Use new cgi source.
This commit is contained in:
parent
57ae058d9a
commit
20cc279b72
158 changed files with 157 additions and 92879 deletions
5
Framework/external/embree/CMakeLists.txt
vendored
5
Framework/external/embree/CMakeLists.txt
vendored
|
|
@ -682,11 +682,6 @@ SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
|
||||||
ADD_SUBDIRECTORY(common)
|
ADD_SUBDIRECTORY(common)
|
||||||
ADD_SUBDIRECTORY(kernels)
|
ADD_SUBDIRECTORY(kernels)
|
||||||
|
|
||||||
IF (EMBREE_TUTORIALS)
|
|
||||||
ADD_SUBDIRECTORY(tutorials)
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
|
|
||||||
##############################################################
|
##############################################################
|
||||||
# Uninstall
|
# Uninstall
|
||||||
##############################################################
|
##############################################################
|
||||||
|
|
|
||||||
|
|
@ -1,85 +0,0 @@
|
||||||
## Copyright 2009-2021 Intel Corporation
|
|
||||||
## SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
include(CMakeDependentOption)
|
|
||||||
|
|
||||||
CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/README.md.in" "${CMAKE_CURRENT_SOURCE_DIR}/README.md")
|
|
||||||
INSTALL(FILES "${CMAKE_CURRENT_SOURCE_DIR}/README.md" DESTINATION "src" COMPONENT examples)
|
|
||||||
|
|
||||||
ADD_SUBDIRECTORY(common/image)
|
|
||||||
CMAKE_DEPENDENT_OPTION(EMBREE_TUTORIALS_GLFW "Enables GLFW usage in tutorials. When disabled tutorial can only render to disk." ON "EMBREE_TUTORIALS" OFF)
|
|
||||||
CMAKE_DEPENDENT_OPTION(EMBREE_BUILD_GLFW_FROM_SOURCE "Builds GLFW from source." OFF "EMBREE_TUTORIALS_GLFW" OFF)
|
|
||||||
|
|
||||||
IF (EMBREE_TUTORIALS)
|
|
||||||
|
|
||||||
IF (EMBREE_TUTORIALS_GLFW)
|
|
||||||
|
|
||||||
# IF (NOT EMBREE_BUILD_GLFW_FROM_SOURCE)
|
|
||||||
# FIND_PACKAGE(glfw3 QUIET)
|
|
||||||
# ENDIF()
|
|
||||||
#
|
|
||||||
# IF(NOT glfw3_FOUND)
|
|
||||||
# CMAKE_MINIMUM_REQUIRED(VERSION 3.14)
|
|
||||||
# IF (NOT EMBREE_BUILD_GLFW_FROM_SOURCE)
|
|
||||||
# MESSAGE("-- glfw3 installation not found. download and build from source")
|
|
||||||
# ELSE()
|
|
||||||
# MESSAGE("-- download and build glfw3 from source")
|
|
||||||
# ENDIF()
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# INCLUDE(FetchContent)
|
|
||||||
# SET(FETCHCONTENT_QUIET ON)
|
|
||||||
#
|
|
||||||
# set(GLFW_BUILD_DOCS OFF CACHE INTERNAL "")
|
|
||||||
# set(GLFW_BUILD_EXAMPLES OFF CACHE INTERNAL "")
|
|
||||||
# set(GLFW_BUILD_TESTS OFF CACHE INTERNAL "")
|
|
||||||
# set(EMBREE_PATCH_GLFW_SOURCE OFF CACHE INTERNAL "Applys an optional patch to GLFW.")
|
|
||||||
#
|
|
||||||
# if (EMBREE_PATCH_GLFW_SOURCE)
|
|
||||||
# # The patch command first resets the glfw repository to a clean state. That
|
|
||||||
# # is because CMake wants to apply the patch again when CMake needs to
|
|
||||||
# # reconfigure, which fails.
|
|
||||||
# set(patch_command git reset --hard && git apply -v "${CMAKE_CURRENT_SOURCE_DIR}/common/glfw/glfw.patch")
|
|
||||||
# endif()
|
|
||||||
#
|
|
||||||
# FetchContent_Declare(
|
|
||||||
# glfw
|
|
||||||
# GIT_REPOSITORY https://github.com/glfw/glfw
|
|
||||||
# GIT_TAG 3.3.8
|
|
||||||
# PATCH_COMMAND ${patch_command}
|
|
||||||
# )
|
|
||||||
#
|
|
||||||
# FetchContent_GetProperties(glfw)
|
|
||||||
# if(NOT glfw_POPULATED)
|
|
||||||
# FetchContent_Populate(glfw)
|
|
||||||
# # We want to build glfw and link statically, so no need to
|
|
||||||
# # install it as part of the Embree install targets.
|
|
||||||
# add_subdirectory(${glfw_SOURCE_DIR} ${glfw_BINARY_DIR} EXCLUDE_FROM_ALL)
|
|
||||||
# endif()
|
|
||||||
#
|
|
||||||
# MARK_AS_ADVANCED(FETCHCONTENT_BASE_DIR)
|
|
||||||
# MARK_AS_ADVANCED(FETCHCONTENT_FULLY_DISCONNECTED)
|
|
||||||
# MARK_AS_ADVANCED(FETCHCONTENT_QUIET)
|
|
||||||
# MARK_AS_ADVANCED(FETCHCONTENT_SOURCE_DIR_GLFW)
|
|
||||||
# MARK_AS_ADVANCED(FETCHCONTENT_UPDATES_DISCONNECTED)
|
|
||||||
# MARK_AS_ADVANCED(FETCHCONTENT_UPDATES_DISCONNECTED_GLFW)
|
|
||||||
# ELSE()
|
|
||||||
# MESSAGE("-- glfw3 installation found.")
|
|
||||||
# ENDIF()
|
|
||||||
|
|
||||||
FIND_PACKAGE(OpenGL)
|
|
||||||
IF (NOT OPENGL_FOUND)
|
|
||||||
MESSAGE(FATAL_ERROR "OpenGL not found! Please either install OpenGL or disable EMBREE_TUTORIALS.")
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
ADD_DEFINITIONS(-DUSE_GLFW)
|
|
||||||
|
|
||||||
# all libraries we have to link against when using a window/gui
|
|
||||||
SET(GUI_LIBRARIES imgui glfw ${OPENGL_LIBRARIES})
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
ADD_SUBDIRECTORY(common)
|
|
||||||
|
|
||||||
ADD_SUBDIRECTORY(pathtracer)
|
|
||||||
|
|
||||||
ENDIF()
|
|
||||||
95
Framework/external/embree/tutorials/Makefile
vendored
95
Framework/external/embree/tutorials/Makefile
vendored
|
|
@ -1,95 +0,0 @@
|
||||||
## Copyright 2009-2021 Intel Corporation
|
|
||||||
## SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
ispc2cpp: common triangle_geometry point_geometry dynamic_scene user_geometry viewer instanced_geometry intersection_filter pathtracer hair_geometry subdivision_geometry displacement_geometry lazy_geometry motion_blur_geometry interpolation_geometry curve_geometry grid_geometry quaternion_motion_blur
|
|
||||||
|
|
||||||
common: FORCE
|
|
||||||
@./ispc2cpp.sh common/tutorial/tutorial_device.isph common/tutorial/tutorial_device.h
|
|
||||||
@./ispc2cpp.sh common/tutorial/tutorial_device.ispc common/tutorial/tutorial_device.cpp
|
|
||||||
@./ispc2cpp.sh common/core/differential_geometry.isph common/core/differential_geometry.h
|
|
||||||
# @./ispc2cpp.sh common/math/random_sampler.isph common/math/random_sampler.h # manual optimizations
|
|
||||||
@./ispc2cpp.sh common/math/sampling.isph common/math/sampling.h
|
|
||||||
@./ispc2cpp.sh common/tutorial/optics.isph common/tutorial/optics.h
|
|
||||||
@./ispc2cpp.sh common/lights/light.isph common/lights/light.h
|
|
||||||
@./ispc2cpp.sh common/lights/light.ispc common/lights/light.cpp
|
|
||||||
@./ispc2cpp.sh common/lights/ambient_light.ispc common/lights/ambient_light.cpp
|
|
||||||
@./ispc2cpp.sh common/lights/directional_light.ispc common/lights/directional_light.cpp
|
|
||||||
@./ispc2cpp.sh common/lights/point_light.ispc common/lights/point_light.cpp
|
|
||||||
@./ispc2cpp.sh common/lights/quad_light.ispc common/lights/quad_light.cpp
|
|
||||||
@./ispc2cpp.sh common/lights/spot_light.ispc common/lights/spot_light.cpp
|
|
||||||
@./ispc2cpp.sh common/texture/texture2d.isph common/texture/texture2d.h
|
|
||||||
@./ispc2cpp.sh common/texture/texture2d.ispc common/texture/texture2d.cpp
|
|
||||||
@./ispc2cpp.sh common/texture/texture_param.isph common/texture/texture_param.h
|
|
||||||
|
|
||||||
triangle_geometry: FORCE
|
|
||||||
@./ispc2cpp.sh triangle_geometry/triangle_geometry_device.isph triangle_geometry/triangle_geometry_device.h
|
|
||||||
@./ispc2cpp.sh triangle_geometry/triangle_geometry_device.ispc triangle_geometry/triangle_geometry_device.cpp
|
|
||||||
point_geometry: FORCE
|
|
||||||
@./ispc2cpp.sh point_geometry/point_geometry_device.isph point_geometry/point_geometry_device.h
|
|
||||||
@./ispc2cpp.sh point_geometry/point_geometry_device.ispc point_geometry/point_geometry_device.cpp
|
|
||||||
dynamic_scene: FORCE
|
|
||||||
@./ispc2cpp.sh dynamic_scene/dynamic_scene_device.isph dynamic_scene/dynamic_scene_device.h
|
|
||||||
@./ispc2cpp.sh dynamic_scene/dynamic_scene_device.ispc dynamic_scene/dynamic_scene_device.cpp
|
|
||||||
user_geometry: FORCE
|
|
||||||
@./ispc2cpp.sh user_geometry/user_geometry_device.isph user_geometry/user_geometry_device.h
|
|
||||||
@./ispc2cpp.sh user_geometry/user_geometry_device.ispc user_geometry/user_geometry_device.cpp
|
|
||||||
viewer: FORCE
|
|
||||||
@./ispc2cpp.sh viewer/viewer_device.isph viewer/viewer_device.h
|
|
||||||
@./ispc2cpp.sh viewer/viewer_device.ispc viewer/viewer_device.cpp
|
|
||||||
instanced_geometry: FORCE
|
|
||||||
@./ispc2cpp.sh instanced_geometry/instanced_geometry_device.isph instanced_geometry/instanced_geometry_device.h
|
|
||||||
@./ispc2cpp.sh instanced_geometry/instanced_geometry_device.ispc instanced_geometry/instanced_geometry_device.cpp
|
|
||||||
multi_instanced_geometry: FORCE
|
|
||||||
@./ispc2cpp.sh multi_instanced_geometry/multi_instanced_geometry_device.isph multi_instanced_geometry/multi_instanced_geometry_device.h
|
|
||||||
@./ispc2cpp.sh multi_instanced_geometry/multi_instanced_geometry_device.ispc multi_instanced_geometry/multi_instanced_geometry_device.cpp
|
|
||||||
intersection_filter: FORCE
|
|
||||||
@./ispc2cpp.sh intersection_filter/intersection_filter_device.isph intersection_filter/intersection_filter_device.h
|
|
||||||
@./ispc2cpp.sh intersection_filter/intersection_filter_device.ispc intersection_filter/intersection_filter_device.cpp
|
|
||||||
pathtracer: FORCE
|
|
||||||
@./ispc2cpp.sh pathtracer/pathtracer_device.isph pathtracer/pathtracer_device.h
|
|
||||||
@./ispc2cpp.sh pathtracer/pathtracer_device.ispc pathtracer/pathtracer_device.cpp
|
|
||||||
hair_geometry: FORCE
|
|
||||||
@./ispc2cpp.sh hair_geometry/hair_geometry_device.isph hair_geometry/hair_geometry_device.h
|
|
||||||
@./ispc2cpp.sh hair_geometry/hair_geometry_device.ispc hair_geometry/hair_geometry_device.cpp
|
|
||||||
subdivision_geometry: FORCE
|
|
||||||
@./ispc2cpp.sh subdivision_geometry/subdivision_geometry_device.ispc subdivision_geometry/subdivision_geometry_device.cpp
|
|
||||||
displacement_geometry: FORCE
|
|
||||||
@./ispc2cpp.sh displacement_geometry/displacement_geometry_device.ispc displacement_geometry/displacement_geometry_device.cpp
|
|
||||||
lazy_geometry: FORCE
|
|
||||||
@./ispc2cpp.sh lazy_geometry/lazy_geometry_device.ispc lazy_geometry/lazy_geometry_device.cpp
|
|
||||||
motion_blur_geometry: FORCE
|
|
||||||
@./ispc2cpp.sh motion_blur_geometry/motion_blur_geometry_device.isph motion_blur_geometry/motion_blur_geometry_device.h
|
|
||||||
@./ispc2cpp.sh motion_blur_geometry/motion_blur_geometry_device.ispc motion_blur_geometry/motion_blur_geometry_device.cpp
|
|
||||||
interpolation_geometry: FORCE
|
|
||||||
@./ispc2cpp.sh interpolation/interpolation_device.isph interpolation/interpolation_device.h
|
|
||||||
@./ispc2cpp.sh interpolation/interpolation_device.ispc interpolation/interpolation_device.cpp
|
|
||||||
curve_geometry: FORCE
|
|
||||||
@./ispc2cpp.sh curve_geometry/curve_geometry_device.isph curve_geometry/curve_geometry_device.h
|
|
||||||
@./ispc2cpp.sh curve_geometry/curve_geometry_device.ispc curve_geometry/curve_geometry_device.cpp
|
|
||||||
grid_geometry: FORCE
|
|
||||||
@./ispc2cpp.sh grid_geometry/grid_geometry_device.isph grid_geometry/grid_geometry_device.h
|
|
||||||
@./ispc2cpp.sh grid_geometry/grid_geometry_device.ispc grid_geometry/grid_geometry_device.cpp
|
|
||||||
quaternion_motion_blur: FORCE
|
|
||||||
@./ispc2cpp.sh quaternion_motion_blur/quaternion_motion_blur_device.isph quaternion_motion_blur/quaternion_motion_blur_device.h
|
|
||||||
@./ispc2cpp.sh quaternion_motion_blur/quaternion_motion_blur_device.ispc quaternion_motion_blur/quaternion_motion_blur_device.cpp
|
|
||||||
|
|
||||||
osp2emb:
|
|
||||||
@./osp2emb.sh ../../ospray/ospray/math/math.ih common/math/math.isph
|
|
||||||
# @./osp2emb.sh ../../ospray/ospray/math/vec.ih common/math/vec.isph # requires manual changes
|
|
||||||
@./osp2emb.sh ../../ospray/ospray/math/sampling.ih common/math/sampling.isph
|
|
||||||
@./osp2emb.sh ../../ospray/ospray/lights/Light.ih common/lights/light.isph
|
|
||||||
@./osp2emb.sh ../../ospray/ospray/lights/Light.ispc common/lights/light.ispc
|
|
||||||
@./osp2emb.sh ../../ospray/ospray/lights/AmbientLight.ispc common/lights/ambient_light.ispc
|
|
||||||
@./osp2emb.sh ../../ospray/ospray/lights/DirectionalLight.ispc common/lights/directional_light.ispc
|
|
||||||
@./osp2emb.sh ../../ospray/ospray/lights/PointLight.ispc common/lights/point_light.ispc
|
|
||||||
@./osp2emb.sh ../../ospray/ospray/lights/QuadLight.ispc common/lights/quad_light.ispc
|
|
||||||
@./osp2emb.sh ../../ospray/ospray/lights/SpotLight.ispc common/lights/spot_light.ispc
|
|
||||||
@./osp2emb.sh ../../ospray/ospray/include/ospray/OSPTexture.h common/texture/texture.h
|
|
||||||
@./osp2emb.sh ../../ospray/ospray/texture/Texture2D.ih common/texture/texture2d.isph
|
|
||||||
@./osp2emb.sh ../../ospray/ospray/texture/Texture2D.ispc common/texture/texture2d.ispc
|
|
||||||
@./osp2emb.sh ../../ospray/ospray/texture/TextureParam.ih common/texture/texture_param.isph
|
|
||||||
@echo "export void dummy() {} // just to avoid linker warning under MacOSX" >> common/lights/light.ispc
|
|
||||||
|
|
||||||
all: osp2emb ispc2cpp
|
|
||||||
|
|
||||||
FORCE:
|
|
||||||
105
Framework/external/embree/tutorials/README.md
vendored
105
Framework/external/embree/tutorials/README.md
vendored
|
|
@ -1,105 +0,0 @@
|
||||||
## Copyright 2009-2021 Intel Corporation
|
|
||||||
## SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
This folder contains sources of the Embree tutorials for illustration
|
|
||||||
purposes of the API. Follow the next sections to compile the
|
|
||||||
tutorials.
|
|
||||||
|
|
||||||
Compilation under Windows using SYCL
|
|
||||||
-------------------------------------
|
|
||||||
|
|
||||||
Install one of the SYCL compilers supported by Embree, see section
|
|
||||||
[Compiling Embree / Windows SYCL Compilation] of the Embree
|
|
||||||
documentation.
|
|
||||||
|
|
||||||
Then open some "x64 Native Tools Command Prompt" of Visual Studio and
|
|
||||||
execute the following line which properly configures the environment to
|
|
||||||
use the DPC++ compiler:
|
|
||||||
|
|
||||||
set "DPCPP_DIR=path_to_dpcpp_compiler"
|
|
||||||
set "PATH=%DPCPP_DIR%\bin;%PATH%"
|
|
||||||
set "PATH=%DPCPP_DIR%\lib;%PATH%"
|
|
||||||
set "CPATH=%DPCPP_DIR%\include;%CPATH%"
|
|
||||||
set "INCLUDE=%DPCPP_DIR%\include;%INCLUDE%"
|
|
||||||
set "LIB=%DPCPP_DIR%\lib;%LIB%"
|
|
||||||
|
|
||||||
Now download and unpack some recent TBB version for Windows, e.g. oneTBB 2021.2.0:
|
|
||||||
|
|
||||||
https://github.com/oneapi-src/oneTBB/releases/download/v2021.2.0/oneapi-tbb-2021.2.0-win.zip
|
|
||||||
|
|
||||||
To compile tutorials contained in this folder first create and enter a
|
|
||||||
build folder inside the tutorial you want to compile. E.g. for the
|
|
||||||
minimal tutorial execute:
|
|
||||||
|
|
||||||
cd minimal
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
|
|
||||||
Then configure the tutorial you would like to compile by pointing to
|
|
||||||
the Embree and TBB installation on your system.
|
|
||||||
|
|
||||||
cmake -G Ninja
|
|
||||||
-D CMAKE_CXX_COMPILER=clang++
|
|
||||||
-D CMAKE_C_COMPILER=clang
|
|
||||||
-D CMAKE_BUILD_TYPE=Release
|
|
||||||
-D embree_DIR=%cd%\..\..\..\lib\cmake\embree-4.3.1\
|
|
||||||
-D TBB_DIR=path_to_tbb\oneapi-tbb-2021.2.0\lib\cmake\tbb ..
|
|
||||||
|
|
||||||
Now you can build the tutorial:
|
|
||||||
|
|
||||||
cmake --build .
|
|
||||||
|
|
||||||
In order to run the tutorial you have to set the PATH to the bin
|
|
||||||
folder in order to find the Embree DLL:
|
|
||||||
|
|
||||||
set PATH=%cd%\..\..\..\bin;%PATH%
|
|
||||||
|
|
||||||
Now you can run the tutorial:
|
|
||||||
|
|
||||||
.\minimal.exe
|
|
||||||
.\minimal_sycl.exe
|
|
||||||
|
|
||||||
|
|
||||||
Compilation under Linux using SYCL
|
|
||||||
-----------------------------------
|
|
||||||
|
|
||||||
Install one of the SYCL compilers supported by Embree, see section
|
|
||||||
[Compiling Embree / Linux SYCL Compilation] of the Embree
|
|
||||||
documentation.
|
|
||||||
|
|
||||||
To properly configure your environment, you have to source the
|
|
||||||
`startup.sh` of the unpacked DPC++ compiler:
|
|
||||||
|
|
||||||
source dpcpp_compiler/startup.sh
|
|
||||||
|
|
||||||
Now download and unpack some recent TBB version for Linux, e.g. oneTBB 2021.2.0:
|
|
||||||
|
|
||||||
wget https://github.com/oneapi-src/oneTBB/releases/download/v2021.2.0/oneapi-tbb-2021.2.0-lin.tgz
|
|
||||||
tar xzf oneapi-tbb-2021.2.0-lin.tgz
|
|
||||||
|
|
||||||
To compile tutorials contained in this folder first create and enter a
|
|
||||||
build folder inside the tutorial you want to compile. E.g. for the
|
|
||||||
minimal tutorial execute:
|
|
||||||
|
|
||||||
cd minimal
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
|
|
||||||
Then configure the tutorial you would like to compile by pointing to
|
|
||||||
the Embree and TBB installation on your system.
|
|
||||||
|
|
||||||
cmake -D CMAKE_BUILD_TYPE=Release \
|
|
||||||
-D CMAKE_CXX_COMPILER=clang++ \
|
|
||||||
-D CMAKE_C_COMPILER=clang \
|
|
||||||
-D embree_DIR=`pwd`/../../../lib/cmake/embree-4.3.1/ \
|
|
||||||
-D TBB_DIR=path_to_tbb/oneapi-tbb-2021.2.0/lib/cmake/tbb/ ..
|
|
||||||
|
|
||||||
Now you can build the tutorial:
|
|
||||||
|
|
||||||
cmake --build .
|
|
||||||
|
|
||||||
Now you can run the tutorial:
|
|
||||||
|
|
||||||
./minimal
|
|
||||||
./minimal_sycl
|
|
||||||
|
|
||||||
105
Framework/external/embree/tutorials/README.md.in
vendored
105
Framework/external/embree/tutorials/README.md.in
vendored
|
|
@ -1,105 +0,0 @@
|
||||||
## Copyright 2009-2021 Intel Corporation
|
|
||||||
## SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
This folder contains sources of the Embree tutorials for illustration
|
|
||||||
purposes of the API. Follow the next sections to compile the
|
|
||||||
tutorials.
|
|
||||||
|
|
||||||
Compilation under Windows using SYCL
|
|
||||||
-------------------------------------
|
|
||||||
|
|
||||||
Install one of the SYCL compilers supported by Embree, see section
|
|
||||||
[Compiling Embree / Windows SYCL Compilation] of the Embree
|
|
||||||
documentation.
|
|
||||||
|
|
||||||
Then open some "x64 Native Tools Command Prompt" of Visual Studio and
|
|
||||||
execute the following line which properly configures the environment to
|
|
||||||
use the DPC++ compiler:
|
|
||||||
|
|
||||||
set "DPCPP_DIR=path_to_dpcpp_compiler"
|
|
||||||
set "PATH=%DPCPP_DIR%\bin;%PATH%"
|
|
||||||
set "PATH=%DPCPP_DIR%\lib;%PATH%"
|
|
||||||
set "CPATH=%DPCPP_DIR%\include;%CPATH%"
|
|
||||||
set "INCLUDE=%DPCPP_DIR%\include;%INCLUDE%"
|
|
||||||
set "LIB=%DPCPP_DIR%\lib;%LIB%"
|
|
||||||
|
|
||||||
Now download and unpack some recent TBB version for Windows, e.g. oneTBB 2021.2.0:
|
|
||||||
|
|
||||||
https://github.com/oneapi-src/oneTBB/releases/download/v2021.2.0/oneapi-tbb-2021.2.0-win.zip
|
|
||||||
|
|
||||||
To compile tutorials contained in this folder first create and enter a
|
|
||||||
build folder inside the tutorial you want to compile. E.g. for the
|
|
||||||
minimal tutorial execute:
|
|
||||||
|
|
||||||
cd minimal
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
|
|
||||||
Then configure the tutorial you would like to compile by pointing to
|
|
||||||
the Embree and TBB installation on your system.
|
|
||||||
|
|
||||||
cmake -G Ninja
|
|
||||||
-D CMAKE_CXX_COMPILER=clang++
|
|
||||||
-D CMAKE_C_COMPILER=clang
|
|
||||||
-D CMAKE_BUILD_TYPE=Release
|
|
||||||
-D embree_DIR=%cd%\..\..\..\lib\cmake\embree-@EMBREE_VERSION@\
|
|
||||||
-D TBB_DIR=path_to_tbb\oneapi-tbb-2021.2.0\lib\cmake\tbb ..
|
|
||||||
|
|
||||||
Now you can build the tutorial:
|
|
||||||
|
|
||||||
cmake --build .
|
|
||||||
|
|
||||||
In order to run the tutorial you have to set the PATH to the bin
|
|
||||||
folder in order to find the Embree DLL:
|
|
||||||
|
|
||||||
set PATH=%cd%\..\..\..\bin;%PATH%
|
|
||||||
|
|
||||||
Now you can run the tutorial:
|
|
||||||
|
|
||||||
.\minimal.exe
|
|
||||||
.\minimal_sycl.exe
|
|
||||||
|
|
||||||
|
|
||||||
Compilation under Linux using SYCL
|
|
||||||
-----------------------------------
|
|
||||||
|
|
||||||
Install one of the SYCL compilers supported by Embree, see section
|
|
||||||
[Compiling Embree / Linux SYCL Compilation] of the Embree
|
|
||||||
documentation.
|
|
||||||
|
|
||||||
To properly configure your environment, you have to source the
|
|
||||||
`startup.sh` of the unpacked DPC++ compiler:
|
|
||||||
|
|
||||||
source dpcpp_compiler/startup.sh
|
|
||||||
|
|
||||||
Now download and unpack some recent TBB version for Linux, e.g. oneTBB 2021.2.0:
|
|
||||||
|
|
||||||
wget https://github.com/oneapi-src/oneTBB/releases/download/v2021.2.0/oneapi-tbb-2021.2.0-lin.tgz
|
|
||||||
tar xzf oneapi-tbb-2021.2.0-lin.tgz
|
|
||||||
|
|
||||||
To compile tutorials contained in this folder first create and enter a
|
|
||||||
build folder inside the tutorial you want to compile. E.g. for the
|
|
||||||
minimal tutorial execute:
|
|
||||||
|
|
||||||
cd minimal
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
|
|
||||||
Then configure the tutorial you would like to compile by pointing to
|
|
||||||
the Embree and TBB installation on your system.
|
|
||||||
|
|
||||||
cmake -D CMAKE_BUILD_TYPE=Release \
|
|
||||||
-D CMAKE_CXX_COMPILER=clang++ \
|
|
||||||
-D CMAKE_C_COMPILER=clang \
|
|
||||||
-D embree_DIR=`pwd`/../../../lib/cmake/embree-@EMBREE_VERSION@/ \
|
|
||||||
-D TBB_DIR=path_to_tbb/oneapi-tbb-2021.2.0/lib/cmake/tbb/ ..
|
|
||||||
|
|
||||||
Now you can build the tutorial:
|
|
||||||
|
|
||||||
cmake --build .
|
|
||||||
|
|
||||||
Now you can run the tutorial:
|
|
||||||
|
|
||||||
./minimal
|
|
||||||
./minimal_sycl
|
|
||||||
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
## Copyright 2009-2021 Intel Corporation
|
|
||||||
## SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
IF (EMBREE_TUTORIALS_GLFW)
|
|
||||||
ADD_SUBDIRECTORY(imgui)
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
ADD_SUBDIRECTORY(tutorial)
|
|
||||||
ADD_SUBDIRECTORY(scenegraph)
|
|
||||||
ADD_SUBDIRECTORY(lights)
|
|
||||||
ADD_SUBDIRECTORY(texture)
|
|
||||||
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#ifndef ISPC_UINT_IS_DEFINED
|
|
||||||
typedef unsigned int64 uint64;
|
|
||||||
typedef unsigned int32 uint32;
|
|
||||||
typedef unsigned int16 uint16;
|
|
||||||
typedef unsigned int8 uint8;
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../../../include/embree4/rtcore.h"
|
|
||||||
#include "../math/vec.h"
|
|
||||||
|
|
||||||
namespace embree {
|
|
||||||
|
|
||||||
struct DifferentialGeometry
|
|
||||||
{
|
|
||||||
unsigned int instIDs[RTC_MAX_INSTANCE_LEVEL_COUNT];
|
|
||||||
unsigned int geomID;
|
|
||||||
unsigned int primID;
|
|
||||||
float u,v;
|
|
||||||
Vec3fa P;
|
|
||||||
Vec3fa Ng;
|
|
||||||
Vec3fa Ns;
|
|
||||||
Vec3fa Tx; //direction along hair
|
|
||||||
Vec3fa Ty;
|
|
||||||
float eps;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace embree
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../../../include/embree4/rtcore.isph"
|
|
||||||
#include "../math/vec.isph"
|
|
||||||
|
|
||||||
struct DifferentialGeometry
|
|
||||||
{
|
|
||||||
unsigned int instIDs[RTC_MAX_INSTANCE_LEVEL_COUNT];
|
|
||||||
unsigned int geomID;
|
|
||||||
unsigned int primID;
|
|
||||||
float u,v;
|
|
||||||
Vec3f P;
|
|
||||||
Vec3f Ng;
|
|
||||||
Vec3f Ns;
|
|
||||||
Vec3f Tx; //direction along hair
|
|
||||||
Vec3f Ty;
|
|
||||||
float eps;
|
|
||||||
};
|
|
||||||
|
|
@ -1,144 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../../../common/sys/platform.h"
|
|
||||||
#include "../../../common/sys/ref.h"
|
|
||||||
#include "../../../common/sys/intrinsics.h"
|
|
||||||
#include "../../../common/sys/sysinfo.h"
|
|
||||||
#include "../../../common/sys/atomic.h"
|
|
||||||
#include "../../../common/sys/vector.h"
|
|
||||||
#include "../../../common/sys/estring.h"
|
|
||||||
|
|
||||||
#include "../../../common/math/emath.h"
|
|
||||||
#include "../../../common/math/vec2.h"
|
|
||||||
#include "../../../common/math/vec3.h"
|
|
||||||
#include "../../../common/math/vec4.h"
|
|
||||||
#include "../../../common/math/bbox.h"
|
|
||||||
#include "../../../common/math/affinespace.h"
|
|
||||||
|
|
||||||
#include "../../../common/simd/simd.h"
|
|
||||||
|
|
||||||
/*! Ray structure. */
|
|
||||||
struct __aligned(16) Ray
|
|
||||||
{
|
|
||||||
/*! Default construction does nothing. */
|
|
||||||
__forceinline Ray() {}
|
|
||||||
|
|
||||||
/*! Constructs a ray from origin, direction, and ray segment. Near
|
|
||||||
* has to be smaller than far. */
|
|
||||||
__forceinline Ray(const embree::Vec3fa& org,
|
|
||||||
const embree::Vec3fa& dir,
|
|
||||||
float tnear = 0.0f,
|
|
||||||
float tfar = embree::inf,
|
|
||||||
float time = 0.0f,
|
|
||||||
int mask = -1,
|
|
||||||
unsigned int geomID = RTC_INVALID_GEOMETRY_ID,
|
|
||||||
unsigned int primID = RTC_INVALID_GEOMETRY_ID)
|
|
||||||
: org(org,tnear), dir(dir,time), tfar(tfar), mask(mask), primID(primID), geomID(geomID)
|
|
||||||
{
|
|
||||||
instID[0] = RTC_INVALID_GEOMETRY_ID;
|
|
||||||
#if defined(RTC_GEOMETRY_INSTANCE_ARRAY)
|
|
||||||
instPrimID[0] = RTC_INVALID_GEOMETRY_ID;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Tests if we hit something. */
|
|
||||||
__forceinline operator bool() const { return geomID != RTC_INVALID_GEOMETRY_ID; }
|
|
||||||
|
|
||||||
public:
|
|
||||||
embree::Vec3ff org; //!< Ray origin + tnear
|
|
||||||
//float tnear; //!< Start of ray segment
|
|
||||||
embree::Vec3ff dir; //!< Ray direction + tfar
|
|
||||||
//float time; //!< Time of this ray for motion blur.
|
|
||||||
float tfar; //!< End of ray segment
|
|
||||||
unsigned int mask; //!< used to mask out objects during traversal
|
|
||||||
unsigned int id; //!< ray ID
|
|
||||||
unsigned int flags; //!< ray flags
|
|
||||||
|
|
||||||
public:
|
|
||||||
embree::Vec3f Ng; //!< Not normalized geometry normal
|
|
||||||
float u; //!< Barycentric u coordinate of hit
|
|
||||||
float v; //!< Barycentric v coordinate of hit
|
|
||||||
unsigned int primID; //!< primitive ID
|
|
||||||
unsigned int geomID; //!< geometry ID
|
|
||||||
unsigned int instID[RTC_MAX_INSTANCE_LEVEL_COUNT]; //!< instance ID
|
|
||||||
#if defined(RTC_GEOMETRY_INSTANCE_ARRAY)
|
|
||||||
unsigned int instPrimID[RTC_MAX_INSTANCE_LEVEL_COUNT]; //!< instance primitive ID
|
|
||||||
#endif
|
|
||||||
|
|
||||||
__forceinline float &tnear() { return org.w; };
|
|
||||||
__forceinline float &time() { return dir.w; };
|
|
||||||
__forceinline float const &tnear() const { return org.w; };
|
|
||||||
__forceinline float const &time() const { return dir.w; };
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
__forceinline void init_Ray(Ray &ray,
|
|
||||||
const embree::Vec3fa& org,
|
|
||||||
const embree::Vec3fa& dir,
|
|
||||||
float tnear = 0.0f,
|
|
||||||
float tfar = embree::inf,
|
|
||||||
float time = 0.0f,
|
|
||||||
int mask = -1,
|
|
||||||
unsigned int geomID = RTC_INVALID_GEOMETRY_ID,
|
|
||||||
unsigned int primID = RTC_INVALID_GEOMETRY_ID)
|
|
||||||
{
|
|
||||||
ray = Ray(org,dir,tnear,tfar,time,mask,geomID,primID);
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef Ray Ray1;
|
|
||||||
|
|
||||||
__forceinline RTCRayHit* RTCRayHit_(Ray& ray) {
|
|
||||||
return (RTCRayHit*)&ray;
|
|
||||||
}
|
|
||||||
|
|
||||||
__forceinline RTCRayHit* RTCRayHit1_(Ray& ray) {
|
|
||||||
return (RTCRayHit*)&ray;
|
|
||||||
}
|
|
||||||
|
|
||||||
__forceinline RTCRay* RTCRay_(Ray& ray) {
|
|
||||||
return (RTCRay*)&ray;
|
|
||||||
}
|
|
||||||
|
|
||||||
__forceinline RTCHit* RTCHit_(Ray& ray)
|
|
||||||
{
|
|
||||||
RTCHit* hit_ptr = (RTCHit*)&(ray.Ng.x);
|
|
||||||
return hit_ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
__forceinline RTCRay* RTCRay1_(Ray& ray) {
|
|
||||||
return (RTCRay*)&ray;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Outputs ray to stream. */
|
|
||||||
__forceinline embree_ostream operator<<(embree_ostream cout, const Ray& ray)
|
|
||||||
{
|
|
||||||
cout << "{ " <<
|
|
||||||
"org = " << ray.org << ", dir = " << ray.dir << ", near = " << ray.tnear() << ", far = " << ray.tfar << ", time = " << ray.time() << ", ";
|
|
||||||
|
|
||||||
for (size_t i=0; i<RTC_MAX_INSTANCE_LEVEL_COUNT; i++)
|
|
||||||
cout << "instID" << i << " = " << ray.instID[i] << ", ";
|
|
||||||
#if defined(RTC_GEOMETRY_INSTANCE_ARRAY)
|
|
||||||
for (size_t i=0; i<RTC_MAX_INSTANCE_LEVEL_COUNT; i++)
|
|
||||||
cout << "instPrimID" << i << " = " << ray.instPrimID[i] << ", ";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return cout << "geomID = " << ray.geomID << ", primID = " << ray.primID << ", " << "u = " << ray.u << ", v = " << ray.v << ", Ng = " << ray.Ng << " }";
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! ray query context passed to intersect/occluded calls */
|
|
||||||
struct RayQueryContext
|
|
||||||
{
|
|
||||||
RTCRayQueryContext context;
|
|
||||||
void* userRayExt; //!< can be used to pass extended ray data to callbacks
|
|
||||||
void* tutorialData;
|
|
||||||
};
|
|
||||||
|
|
||||||
__forceinline void InitIntersectionContext(struct RayQueryContext* context)
|
|
||||||
{
|
|
||||||
rtcInitRayQueryContext(&context->context);
|
|
||||||
context->userRayExt = NULL;
|
|
||||||
}
|
|
||||||
|
|
@ -1,144 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../math/vec.isph"
|
|
||||||
|
|
||||||
struct Ray1
|
|
||||||
{
|
|
||||||
uniform Vec3f org; //!< Ray origin
|
|
||||||
uniform float tnear; //!< Start of ray segment
|
|
||||||
uniform Vec3f dir; //!< Ray direction
|
|
||||||
uniform float time; //!< Time of this ray for motion blur.
|
|
||||||
uniform float tfar; //!< End of ray segment
|
|
||||||
uniform int mask; //!< used to mask out objects during traversal
|
|
||||||
uniform int id; //!< ray ID
|
|
||||||
uniform int flags; //!< ray flags
|
|
||||||
uniform Vec3f Ng; //!< Geometric normal.
|
|
||||||
uniform float u; //!< Barycentric u coordinate of hit
|
|
||||||
uniform float v; //!< Barycentric v coordinate of hit
|
|
||||||
uniform int primID; //!< primitive ID
|
|
||||||
uniform int geomID; //!< geometry ID
|
|
||||||
uniform int instID[RTC_MAX_INSTANCE_LEVEL_COUNT]; //!< instance ID
|
|
||||||
#if defined(RTC_GEOMETRY_INSTANCE_ARRAY)
|
|
||||||
uniform int instPrimID[RTC_MAX_INSTANCE_LEVEL_COUNT]; //!< instance ID
|
|
||||||
#endif
|
|
||||||
varying int align[0]; //!< aligns ray on stack to at least 16 bytes
|
|
||||||
};
|
|
||||||
|
|
||||||
inline uniform RTCRayHit* uniform RTCRayHit1_(uniform Ray1& ray)
|
|
||||||
{
|
|
||||||
uniform RTCRayHit* uniform ray_ptr = (uniform RTCRayHit* uniform)&ray;
|
|
||||||
return ray_ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Ray structure. Contains all information about a ray including
|
|
||||||
* precomputed reciprocal direction. */
|
|
||||||
struct Ray
|
|
||||||
{
|
|
||||||
Vec3f org; //!< Ray origin
|
|
||||||
float tnear; //!< Start of ray segment
|
|
||||||
Vec3f dir; //!< Ray direction
|
|
||||||
float time; //!< Time of this ray for motion blur.
|
|
||||||
float tfar; //!< End of ray segment
|
|
||||||
int mask; //!< used to mask out objects during traversal
|
|
||||||
int id; //!< ray ID
|
|
||||||
int flags; //!< ray flags
|
|
||||||
Vec3f Ng; //!< Geometric normal.
|
|
||||||
float u; //!< Barycentric u coordinate of hit
|
|
||||||
float v; //!< Barycentric v coordinate of hit
|
|
||||||
int primID; //!< primitive ID
|
|
||||||
int geomID; //!< geometry ID
|
|
||||||
int instID[RTC_MAX_INSTANCE_LEVEL_COUNT]; //!< instance ID
|
|
||||||
#if defined(RTC_GEOMETRY_INSTANCE_ARRAY)
|
|
||||||
int instPrimID[RTC_MAX_INSTANCE_LEVEL_COUNT]; //!< instance ID
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
inline varying RTCRayHit* uniform RTCRayHit_(varying Ray& ray)
|
|
||||||
{
|
|
||||||
varying RTCRayHit* uniform ray_ptr = (varying RTCRayHit* uniform)&ray;
|
|
||||||
return ray_ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline varying RTCRay* uniform RTCRay_(varying Ray& ray)
|
|
||||||
{
|
|
||||||
varying RTCRay* uniform ray_ptr = (varying RTCRay* uniform)&ray;
|
|
||||||
return ray_ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline varying RTCHit* uniform RTCHit_(varying Ray& ray)
|
|
||||||
{
|
|
||||||
varying RTCHit* uniform hit_ptr = (varying RTCHit* uniform)&(ray.Ng.x);
|
|
||||||
return hit_ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Constructs a ray from origin, direction, and ray segment. Near
|
|
||||||
* has to be smaller than far. */
|
|
||||||
inline Ray make_Ray(const Vec3f org,
|
|
||||||
const Vec3f dir,
|
|
||||||
const float tnear = 0.0f,
|
|
||||||
const float tfar = inf,
|
|
||||||
const float time = 0.0f,
|
|
||||||
const int mask = -1,
|
|
||||||
const int geomID = -1,
|
|
||||||
const int primID = -1)
|
|
||||||
{
|
|
||||||
Ray ray;
|
|
||||||
ray.org = org;
|
|
||||||
ray.tnear = tnear;
|
|
||||||
ray.dir = dir;
|
|
||||||
ray.time = time;
|
|
||||||
ray.tfar = tfar;
|
|
||||||
ray.mask = mask;
|
|
||||||
ray.geomID = geomID;
|
|
||||||
ray.primID = primID;
|
|
||||||
ray.instID[0] = RTC_INVALID_GEOMETRY_ID;
|
|
||||||
#if defined(RTC_GEOMETRY_INSTANCE_ARRAY)
|
|
||||||
ray.instPrimID[0] = RTC_INVALID_GEOMETRY_ID;
|
|
||||||
#endif
|
|
||||||
return ray;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void init_Ray(Ray &ray,
|
|
||||||
const Vec3f org,
|
|
||||||
const Vec3f dir,
|
|
||||||
const float tnear = 0.0f,
|
|
||||||
const float tfar = inf,
|
|
||||||
const float time = 0.0f,
|
|
||||||
const int mask = -1,
|
|
||||||
const int geomID = -1,
|
|
||||||
const int primID = -1)
|
|
||||||
{
|
|
||||||
ray.org = org;
|
|
||||||
ray.tnear = tnear;
|
|
||||||
ray.dir = dir;
|
|
||||||
ray.time = time;
|
|
||||||
ray.tfar = tfar;
|
|
||||||
ray.mask = mask;
|
|
||||||
ray.geomID = geomID;
|
|
||||||
ray.primID = primID;
|
|
||||||
ray.instID[0] = RTC_INVALID_GEOMETRY_ID;
|
|
||||||
#if defined(RTC_GEOMETRY_INSTANCE_ARRAY)
|
|
||||||
ray.instPrimID[0] = RTC_INVALID_GEOMETRY_ID;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool noHit(const Ray& r) { return r.geomID < 0; }
|
|
||||||
|
|
||||||
inline bool hadHit(const Ray& r) { return r.geomID >= 0; }
|
|
||||||
|
|
||||||
/*! ray query context passed to intersect/occluded calls */
|
|
||||||
struct RayQueryContext
|
|
||||||
{
|
|
||||||
RTCRayQueryContext context;
|
|
||||||
void* userRayExt; //!< can be used to pass extended ray data to callbacks
|
|
||||||
void* tutorialData;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline void InitIntersectionContext(uniform RayQueryContext* uniform context)
|
|
||||||
{
|
|
||||||
rtcInitRayQueryContext(&context->context);
|
|
||||||
context->userRayExt = NULL;
|
|
||||||
}
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../../kernels/config.h"
|
|
||||||
#include "../../common/sys/platform.h"
|
|
||||||
#include "../../common/sys/sysinfo.h"
|
|
||||||
#include "../../common/sys/ref.h"
|
|
||||||
#include "../../common/sys/vector.h"
|
|
||||||
#include "../../common/math/vec2.h"
|
|
||||||
#include "../../common/math/vec3.h"
|
|
||||||
#include "../../common/math/vec4.h"
|
|
||||||
#include "../../common/math/bbox.h"
|
|
||||||
#include "../../common/math/lbbox.h"
|
|
||||||
#include "../../common/math/affinespace.h"
|
|
||||||
#include "../../common/sys/filename.h"
|
|
||||||
#include "../../common/sys/estring.h"
|
|
||||||
#include "../../common/lexers/tokenstream.h"
|
|
||||||
#include "../../common/lexers/streamfilters.h"
|
|
||||||
#include "../../common/lexers/parsestream.h"
|
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
#include <vector>
|
|
||||||
#include <memory>
|
|
||||||
#include <map>
|
|
||||||
#include <set>
|
|
||||||
#include <deque>
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#if defined(EMBREE_SYCL_SUPPORT)
|
|
||||||
// If we use the internal clang frontend of the dpc++ compiler directly __INTEL_LLVM_COMPILER is not set.
|
|
||||||
// I think doing this is fine because normal clang can not compile dpcpp/sycl code anyway.
|
|
||||||
#if defined(__WIN32__) and defined(__clang__) and !defined(__INTEL_LLVM_COMPILER)
|
|
||||||
#define __INTEL_LLVM_COMPILER
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(EMBREE_SYCL_TUTORIAL)
|
|
||||||
# define __SYCL_USE_NON_VARIADIC_SPIRV_OCL_PRINTF__
|
|
||||||
# pragma clang diagnostic push
|
|
||||||
# pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
|
||||||
# pragma clang diagnostic ignored "-W#pragma-messages"
|
|
||||||
# include <sycl/sycl.hpp>
|
|
||||||
# pragma clang diagnostic pop
|
|
||||||
#else
|
|
||||||
# if !defined(SYCL_EXTERNAL)
|
|
||||||
# define SYCL_EXTERNAL
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* include embree API */
|
|
||||||
#include "../../include/embree4/rtcore.h"
|
|
||||||
RTC_NAMESPACE_USE
|
|
||||||
#include "../../kernels/config.h"
|
|
||||||
|
|
||||||
namespace embree
|
|
||||||
{
|
|
||||||
#if defined(EMBREE_SYCL_TUTORIAL) && defined(EMBREE_SYCL_SUPPORT)
|
|
||||||
|
|
||||||
extern sycl::queue *global_gpu_queue;
|
|
||||||
extern sycl::context *global_gpu_context;
|
|
||||||
extern sycl::device *global_gpu_device;
|
|
||||||
|
|
||||||
/* returns function pointer to be usable in SYCL kernel */
|
|
||||||
template<auto F>
|
|
||||||
inline decltype(F) getFunctionPointer() {
|
|
||||||
return rtcGetSYCLDeviceFunctionPointer<F>(*global_gpu_queue);
|
|
||||||
}
|
|
||||||
#define GET_FUNCTION_POINTER(f) getFunctionPointer<f>()
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#define GET_FUNCTION_POINTER(f) f
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#define SYCL_EXTERNAL
|
|
||||||
|
|
||||||
/* include embree API */
|
|
||||||
#include "../../include/embree4/rtcore.isph"
|
|
||||||
RTC_NAMESPACE_USE
|
|
||||||
#include "../../kernels/config.h"
|
|
||||||
|
|
||||||
#define GET_FUNCTION_POINTER(f) f
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,112 +0,0 @@
|
||||||
From 8dfd5804447a1f35c15e650737fee3694bc71f26 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Florian Reibold <florian.reibold@intel.com>
|
|
||||||
Date: Mon, 6 Feb 2023 17:29:44 +0100
|
|
||||||
Subject: [PATCH] fix LoadLibraryA
|
|
||||||
|
|
||||||
---
|
|
||||||
src/null_platform.h | 2 +-
|
|
||||||
src/wgl_context.c | 2 +-
|
|
||||||
src/win32_init.c | 12 ++++++------
|
|
||||||
src/win32_platform.h | 2 +-
|
|
||||||
4 files changed, 9 insertions(+), 9 deletions(-)
|
|
||||||
|
|
||||||
diff --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 72ad11de..5c42fa81 100644
|
|
||||||
--- a/src/wgl_context.c
|
|
||||||
+++ b/src/wgl_context.c
|
|
||||||
@@ -416,7 +416,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 bf703d7e..55b8425b 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)
|
|
||||||
|
|
||||||
--
|
|
||||||
2.38.1.windows.1
|
|
||||||
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
## Copyright 2009-2021 Intel Corporation
|
|
||||||
## SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}" ${CMAKE_MODULE_PATH})
|
|
||||||
INCLUDE(CMakeDependentOption)
|
|
||||||
|
|
||||||
SET(ADDITIONAL_SOURCES)
|
|
||||||
|
|
||||||
## FIND_PACKAGE(OpenImageIO)
|
|
||||||
## MARK_AS_ADVANCED(
|
|
||||||
## OPENIMAGEIO_ROOT
|
|
||||||
## )
|
|
||||||
CMAKE_DEPENDENT_OPTION(EMBREE_TUTORIALS_OPENIMAGEIO "Enables BMP, GIF, PNG, TGA, TIFF image codecs." OFF "EMBREE_TUTORIALS AND OPENIMAGEIO_FOUND" OFF)
|
|
||||||
IF (EMBREE_TUTORIALS_OPENIMAGEIO)
|
|
||||||
ADD_DEFINITIONS(-DUSE_OPENIMAGEIO)
|
|
||||||
INCLUDE_DIRECTORIES(${OPENIMAGEIO_INCLUDE_DIRS})
|
|
||||||
SET(ADDITIONAL_LIBRARIES ${ADDITIONAL_LIBRARIES} ${OPENIMAGEIO_LIBRARIES})
|
|
||||||
SET(ADDITIONAL_SOURCES ${ADDITIONAL_SOURCES} oiio.cpp)
|
|
||||||
ENDIF (EMBREE_TUTORIALS_OPENIMAGEIO)
|
|
||||||
|
|
||||||
FIND_PACKAGE(JPEG)
|
|
||||||
CMAKE_DEPENDENT_OPTION(EMBREE_TUTORIALS_LIBJPEG "Enables JPEG image codec." OFF "EMBREE_TUTORIALS AND JPEG_FOUND" OFF)
|
|
||||||
IF (EMBREE_TUTORIALS_LIBJPEG)
|
|
||||||
ADD_DEFINITIONS(-DEMBREE_TUTORIALS_LIBJPEG)
|
|
||||||
INCLUDE_DIRECTORIES(${JPEG_INCLUDE_DIR})
|
|
||||||
SET(ADDITIONAL_LIBRARIES ${ADDITIONAL_LIBRARIES} ${JPEG_LIBRARIES})
|
|
||||||
SET(ADDITIONAL_SOURCES ${ADDITIONAL_SOURCES} jpeg.cpp)
|
|
||||||
ENDIF (EMBREE_TUTORIALS_LIBJPEG)
|
|
||||||
|
|
||||||
FIND_PACKAGE(PNG)
|
|
||||||
CMAKE_DEPENDENT_OPTION(EMBREE_TUTORIALS_LIBPNG "Enables PNG image codecs." OFF "EMBREE_TUTORIALS AND PNG_FOUND" OFF)
|
|
||||||
IF (EMBREE_TUTORIALS_LIBPNG)
|
|
||||||
ADD_DEFINITIONS(-DEMBREE_TUTORIALS_LIBPNG)
|
|
||||||
INCLUDE_DIRECTORIES(${PNG_INCLUDE_DIR})
|
|
||||||
SET(ADDITIONAL_LIBRARIES ${ADDITIONAL_LIBRARIES} ${PNG_LIBRARIES})
|
|
||||||
ENDIF (EMBREE_TUTORIALS_LIBPNG)
|
|
||||||
|
|
||||||
ADD_LIBRARY(image STATIC
|
|
||||||
image.cpp
|
|
||||||
pfm.cpp
|
|
||||||
ppm.cpp
|
|
||||||
tga.cpp
|
|
||||||
png.cpp
|
|
||||||
stb.cpp
|
|
||||||
exr.cpp
|
|
||||||
${ADDITIONAL_SOURCES}
|
|
||||||
)
|
|
||||||
|
|
||||||
TARGET_LINK_LIBRARIES(image sys math ${ADDITIONAL_LIBRARIES})
|
|
||||||
SET_PROPERTY(TARGET image PROPERTY FOLDER tutorials/common)
|
|
||||||
SET_PROPERTY(TARGET image APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}")
|
|
||||||
|
|
@ -1,70 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#include "image.h"
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <cstring>
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
#define TINYEXR_USE_MINIZ 0
|
|
||||||
//#include "zlib.h"
|
|
||||||
//Or, if your project uses `stb_image[_write].h`, use their
|
|
||||||
//zlib implementation:
|
|
||||||
#define TINYEXR_USE_STB_ZLIB 1
|
|
||||||
#define TINYEXR_IMPLEMENTATION
|
|
||||||
#include "tinyexr.h"
|
|
||||||
|
|
||||||
namespace embree
|
|
||||||
{
|
|
||||||
/*! read PFM file from disk */
|
|
||||||
Ref<Image> loadEXR(const FileName& fileName)
|
|
||||||
{
|
|
||||||
float* rgba; // width * height * RGBA
|
|
||||||
int width;
|
|
||||||
int height;
|
|
||||||
const char* err = NULL; // or nullptr in C++11
|
|
||||||
|
|
||||||
int ret = LoadEXR(&rgba, &width, &height, fileName.str().c_str(), &err);
|
|
||||||
if (ret != TINYEXR_SUCCESS) {
|
|
||||||
if (err) {
|
|
||||||
std::cerr << "ERR: " << err;
|
|
||||||
FreeEXRErrorMessage(err);
|
|
||||||
}
|
|
||||||
THROW_RUNTIME_ERROR("Could not load image " + fileName.str())
|
|
||||||
}
|
|
||||||
|
|
||||||
/* create image and fill with data */
|
|
||||||
Ref<Image> img = new Image4f(width,height,fileName);
|
|
||||||
|
|
||||||
for (ssize_t y=0; y<height; y++) {
|
|
||||||
for (ssize_t x=0; x<width; x++) {
|
|
||||||
float* pix = rgba + (y * width + x) * 4;
|
|
||||||
img->set(x,y,Color4(pix[0],pix[1],pix[2],1.0f));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(rgba);
|
|
||||||
return img;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! store PFM file to disk */
|
|
||||||
void storeEXR(const Ref<Image>& img, const FileName& fileName)
|
|
||||||
{
|
|
||||||
std::vector<Col3f> rgb(img->width * img->height);
|
|
||||||
for (size_t y=0; y<img->height; ++y) {
|
|
||||||
for (size_t x=0; x<img->width; ++x) {
|
|
||||||
Color4 c = img->get(x, y);
|
|
||||||
rgb[y * img->width + x] = Col3f(c.r, c.g, c.b);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const char* err = NULL;
|
|
||||||
int ret = SaveEXR((float*)rgb.data(), img->width, img->height, 3, 0, fileName.str().c_str(), &err);
|
|
||||||
if (ret != TINYEXR_SUCCESS) {
|
|
||||||
if (err) {
|
|
||||||
std::cerr << "ERR: " << err;
|
|
||||||
FreeEXRErrorMessage(err);
|
|
||||||
}
|
|
||||||
THROW_RUNTIME_ERROR("Could not save image " + fileName.str())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,122 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#include "image.h"
|
|
||||||
#include "../../../common/sys/estring.h"
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
|
|
||||||
namespace embree
|
|
||||||
{
|
|
||||||
double compareImages(Ref<Image> image0, Ref<Image> image1)
|
|
||||||
{
|
|
||||||
/* compare image size */
|
|
||||||
const size_t width = image0->width;
|
|
||||||
const size_t height = image0->height;
|
|
||||||
if (image1->width != width) return inf;
|
|
||||||
if (image1->height != height) return inf;
|
|
||||||
|
|
||||||
/* compare both images */
|
|
||||||
double diff = 0.0;
|
|
||||||
for (size_t y=0; y<height; y++)
|
|
||||||
{
|
|
||||||
for (size_t x=0; x<width; x++)
|
|
||||||
{
|
|
||||||
const Color c0 = image0->get(x,y);
|
|
||||||
const Color c1 = image1->get(x,y);
|
|
||||||
diff += sqr(fabs(c0.r - c1.r))/3.0f;
|
|
||||||
diff += sqr(fabs(c0.g - c1.g))/3.0f;
|
|
||||||
diff += sqr(fabs(c0.b - c1.b))/3.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return diff;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! loads an image from a file with auto-detection of format */
|
|
||||||
Ref<Image> loadImageFromDisk(const FileName& fileName)
|
|
||||||
{
|
|
||||||
std::string ext = toLowerCase(fileName.ext());
|
|
||||||
|
|
||||||
#ifdef EMBREE_TUTORIALS_LIBPNG
|
|
||||||
if (ext == "png" ) return loadPNG(fileName);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef EMBREE_TUTORIALS_LIBJPEG
|
|
||||||
if (ext == "jpg" ) return loadJPEG(fileName);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_OPENIMAGEIO
|
|
||||||
if (ext == "bmp" ) return loadOIIO(fileName);
|
|
||||||
if (ext == "gif" ) return loadOIIO(fileName);
|
|
||||||
if (ext == "tga" ) return loadOIIO(fileName);
|
|
||||||
if (ext == "tif" ) return loadOIIO(fileName);
|
|
||||||
if (ext == "tiff") return loadOIIO(fileName);
|
|
||||||
if (ext == "png" ) return loadOIIO(fileName);
|
|
||||||
if (ext == "jpg" ) return loadOIIO(fileName);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (ext == "bmp" ) return loadSTB(fileName);
|
|
||||||
if (ext == "png" ) return loadSTB(fileName);
|
|
||||||
if (ext == "jpg" ) return loadSTB(fileName);
|
|
||||||
|
|
||||||
if (ext == "exr" ) return loadEXR(fileName);
|
|
||||||
|
|
||||||
if (ext == "pfm" ) return loadPFM(fileName);
|
|
||||||
if (ext == "ppm" ) return loadPPM(fileName);
|
|
||||||
if (ext == "tga" ) return loadTGA(fileName);
|
|
||||||
THROW_RUNTIME_ERROR("image format " + ext + " not supported");
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::map<std::string,Ref<Image> > image_cache;
|
|
||||||
|
|
||||||
/*! loads an image from a file with auto-detection of format */
|
|
||||||
Ref<Image> loadImage(const FileName& fileName, bool cache)
|
|
||||||
{
|
|
||||||
if (!cache)
|
|
||||||
return loadImageFromDisk(fileName);
|
|
||||||
|
|
||||||
if (image_cache.find(fileName) == image_cache.end())
|
|
||||||
image_cache[fileName] = loadImageFromDisk(fileName);
|
|
||||||
|
|
||||||
return image_cache[fileName];
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! stores an image to file with auto-detection of format */
|
|
||||||
void storeImage(const Ref<Image>& img, const FileName& fileName)
|
|
||||||
{
|
|
||||||
std::string ext = toLowerCase(fileName.ext());
|
|
||||||
|
|
||||||
#ifdef EMBREE_TUTORIALS_LIBJPEG
|
|
||||||
if (ext == "jpg" ) { storeJPEG(img, fileName); return; }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_OPENIMAGEIO
|
|
||||||
if (ext == "bmp" ) { storeOIIO(img, fileName); return; }
|
|
||||||
if (ext == "gif" ) { storeOIIO(img, fileName); return; }
|
|
||||||
if (ext == "tga" ) { storeOIIO(img, fileName); return; }
|
|
||||||
if (ext == "tif" ) { storeOIIO(img, fileName); return; }
|
|
||||||
if (ext == "tiff") { storeOIIO(img, fileName); return; }
|
|
||||||
if (ext == "png" ) { storeOIIO(img, fileName); return; }
|
|
||||||
if (ext == "jpg" ) { storeOIIO(img, fileName); return; }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (ext == "bmp" ) { storeSTB(img, fileName); return; }
|
|
||||||
if (ext == "png" ) { storeSTB(img, fileName); return; }
|
|
||||||
if (ext == "jpg" ) { storeSTB(img, fileName); return; }
|
|
||||||
|
|
||||||
if (ext == "exr" ) { storeEXR(img, fileName); return; }
|
|
||||||
|
|
||||||
if (ext == "pfm" ) { storePFM(img, fileName); return; }
|
|
||||||
if (ext == "ppm" ) { storePPM(img, fileName); return; }
|
|
||||||
if (ext == "tga" ) { storeTga(img, fileName); return; }
|
|
||||||
THROW_RUNTIME_ERROR("image format " + ext + " not supported");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! template instantiations */
|
|
||||||
template class ImageT<Col3uc>;
|
|
||||||
template class ImageT<Col3f>;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,205 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../../../common/sys/platform.h"
|
|
||||||
#include "../../../common/sys/ref.h"
|
|
||||||
#include "../../../common/sys/filename.h"
|
|
||||||
#include "../../../common/math/color.h"
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace embree
|
|
||||||
{
|
|
||||||
/* virtual interface to image */
|
|
||||||
class Image : public RefCount {
|
|
||||||
public:
|
|
||||||
Image (size_t width, size_t height, const std::string& name) : width(width), height(height), name(name) {}
|
|
||||||
virtual ~Image() {}
|
|
||||||
virtual Color4 get(size_t x, size_t y) const = 0;
|
|
||||||
virtual void set(size_t x, size_t y, const Color4& c) = 0;
|
|
||||||
void set(size_t x, size_t y, const Color& c) { set(x,y,Color4(c.r,c.g,c.b,1.0f)); }
|
|
||||||
void convertToRGBA8(unsigned char *dest)
|
|
||||||
{
|
|
||||||
for (size_t y=0;y<height;y++)
|
|
||||||
for (size_t x=0;x<width;x++)
|
|
||||||
{
|
|
||||||
size_t offset = 4 * (y * width + x);
|
|
||||||
Color4 c = get(x,y);
|
|
||||||
dest[offset+0] = (unsigned char)(c.r * 255.0f);
|
|
||||||
dest[offset+1] = (unsigned char)(c.g * 255.0f);
|
|
||||||
dest[offset+2] = (unsigned char)(c.b * 255.0f);
|
|
||||||
dest[offset+3] = (unsigned char)(c.a * 255.0f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Image (const Image& other) DELETED; // do not implement
|
|
||||||
Image& operator= (const Image& other) DELETED; // do not implement
|
|
||||||
|
|
||||||
public:
|
|
||||||
size_t width,height;
|
|
||||||
std::string name;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* main image class templated over element type */
|
|
||||||
template<typename T>
|
|
||||||
class ImageT : public Image {
|
|
||||||
public:
|
|
||||||
|
|
||||||
/*! create empty image */
|
|
||||||
ImageT (size_t width = 0, size_t height = 0, const std::string& name = "")
|
|
||||||
: Image(width,height,name)
|
|
||||||
{
|
|
||||||
data = new T[width*height];
|
|
||||||
memset(data,0,width*height*sizeof(T));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! create image of constant color */
|
|
||||||
ImageT (size_t width, size_t height, const T& color, const std::string& name = "")
|
|
||||||
: Image(width,height,name)
|
|
||||||
{
|
|
||||||
data = new T[width*height];
|
|
||||||
for (size_t i=0; i<width*height; i++) data[i] = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! initialize image from color data */
|
|
||||||
ImageT (size_t width, size_t height, T* color, const bool copy = true, const std::string& name = "", const bool flip_y = false)
|
|
||||||
: Image(width,height,name)
|
|
||||||
{
|
|
||||||
if (copy)
|
|
||||||
{
|
|
||||||
data = new T[width*height];
|
|
||||||
|
|
||||||
if (flip_y)
|
|
||||||
{
|
|
||||||
const T* in = color + (height-1) * width;
|
|
||||||
T* out = data;
|
|
||||||
|
|
||||||
for (size_t y=0; y<height; y++)
|
|
||||||
{
|
|
||||||
for (size_t x=0; x<width; x++)
|
|
||||||
out[x] = in[x];
|
|
||||||
|
|
||||||
in -= width;
|
|
||||||
out += width;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (size_t i=0; i<width*height; i++)
|
|
||||||
data[i] = color[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
data = color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! image destruction */
|
|
||||||
virtual ~ImageT() {
|
|
||||||
delete[] data; data = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! returns pixel color */
|
|
||||||
__forceinline Color4 get(size_t x, size_t y) const {
|
|
||||||
return Color4(data[y*width+x]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! sets pixel */
|
|
||||||
__forceinline void set(size_t x, size_t y, const Color4& c) {
|
|
||||||
c.set(data[y*width+x]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! returns data pointer of image */
|
|
||||||
__forceinline void* ptr() {
|
|
||||||
return (void*)data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! returns and forgets about data pointer of image */
|
|
||||||
__forceinline void* steal_ptr() {
|
|
||||||
T* ptr = data;
|
|
||||||
data = nullptr;
|
|
||||||
return (void*)ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
T* data;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*! Shortcuts for common image types. */
|
|
||||||
typedef ImageT<Col3uc> Image3uc;
|
|
||||||
typedef ImageT<Col3f> Image3f;
|
|
||||||
typedef ImageT<Col4uc> Image4uc;
|
|
||||||
typedef ImageT<Col4f> Image4f;
|
|
||||||
|
|
||||||
/*! Generate a JPEG encoded image from a RGB8 buffer in memory. */
|
|
||||||
void encodeRGB8_to_JPEG(unsigned char *image, size_t width, size_t height, unsigned char **encoded, unsigned long *capacity);
|
|
||||||
|
|
||||||
/*! compare two images */
|
|
||||||
double compareImages(Ref<Image> image0, Ref<Image> image1);
|
|
||||||
|
|
||||||
/*! Loads image from file. Format is auto detected. */
|
|
||||||
Ref<Image> loadImage(const FileName& filename, bool cache = false);
|
|
||||||
|
|
||||||
/*! Loads image from JPEG file. */
|
|
||||||
Ref<Image> loadJPEG(const FileName& fileName);
|
|
||||||
|
|
||||||
/*! Loads image using OpenImageIO. */
|
|
||||||
Ref<Image> loadOIIO(const FileName& fileName);
|
|
||||||
|
|
||||||
/*! Loads image using stb_image. */
|
|
||||||
Ref<Image> loadSTB(const FileName& fileName);
|
|
||||||
|
|
||||||
/*! Loads image from EXR file. */
|
|
||||||
Ref<Image> loadEXR(const FileName& fileName);
|
|
||||||
|
|
||||||
/*! Loads image from PFM file. */
|
|
||||||
Ref<Image> loadPFM(const FileName& fileName);
|
|
||||||
|
|
||||||
/*! Loads image from PNG file. */
|
|
||||||
Ref<Image> loadPNG(const FileName& fileName);
|
|
||||||
|
|
||||||
/*! Loads image from PPM file. */
|
|
||||||
Ref<Image> loadPPM(const FileName& fileName);
|
|
||||||
|
|
||||||
/*! Loads image from TGA file. */
|
|
||||||
Ref<Image> loadTGA(const FileName& fileName);
|
|
||||||
|
|
||||||
/*! Loads image from TIFF file. */
|
|
||||||
//Ref<Image> loadTIFF(const FileName& fileName);
|
|
||||||
|
|
||||||
/*! Store image to file. Format is auto detected. */
|
|
||||||
void storeImage(const Ref<Image>& image, const FileName& filename);
|
|
||||||
|
|
||||||
/*! Store image to JPEG file. */
|
|
||||||
void storeJPEG(const Ref<Image>& img, const FileName& fileName);
|
|
||||||
|
|
||||||
/*! Store image to file using OpenImageIO. */
|
|
||||||
void storeOIIO(const Ref<Image>& img, const FileName& fileName);
|
|
||||||
|
|
||||||
/*! Store image to file using stb_image. */
|
|
||||||
void storeSTB(const Ref<Image>& img, const FileName& fileName);
|
|
||||||
|
|
||||||
/*! Store image to EXR file. */
|
|
||||||
void storeEXR(const Ref<Image>& img, const FileName& fileName);
|
|
||||||
|
|
||||||
/*! Store image to PFM file. */
|
|
||||||
void storePFM(const Ref<Image>& img, const FileName& fileName);
|
|
||||||
|
|
||||||
/*! Store image to PNG file. */
|
|
||||||
//void storePNG(const Ref<Image>& img, const FileName& fileName);
|
|
||||||
|
|
||||||
/*! Store image to PPM file. */
|
|
||||||
void storePPM(const Ref<Image>& img, const FileName& fileName);
|
|
||||||
|
|
||||||
/*! Store image to TGA file. */
|
|
||||||
void storeTga(const Ref<Image>& img, const FileName& fileName);
|
|
||||||
|
|
||||||
/*! Store image to TIFF file. */
|
|
||||||
//void storeTIFF(const Ref<Image>& img, const FileName& fileName);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,192 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#ifdef EMBREE_TUTORIALS_LIBJPEG
|
|
||||||
|
|
||||||
#include "image.h"
|
|
||||||
#include "jpeglib.h"
|
|
||||||
|
|
||||||
namespace embree
|
|
||||||
{
|
|
||||||
void compress(struct jpeg_compress_struct *cinfo, unsigned char *image)
|
|
||||||
{
|
|
||||||
|
|
||||||
/*! Start compression. */
|
|
||||||
jpeg_start_compress(cinfo, TRUE);
|
|
||||||
|
|
||||||
/*! Pointer to and size of a scanline in the image. */
|
|
||||||
JSAMPROW scanline[1]; size_t bytes = cinfo->image_width * cinfo->input_components;
|
|
||||||
|
|
||||||
/*! Here we use the library state variable 'next_scanline' as the loop index. */
|
|
||||||
while (cinfo->next_scanline < cinfo->image_height) {
|
|
||||||
scanline[0] = &image[cinfo->next_scanline * bytes];
|
|
||||||
jpeg_write_scanlines(cinfo, scanline, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Finish compression. */
|
|
||||||
jpeg_finish_compress(cinfo);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char *decompress(struct jpeg_decompress_struct *cinfo)
|
|
||||||
{
|
|
||||||
/*! Start decompression. */
|
|
||||||
jpeg_start_decompress(cinfo);
|
|
||||||
|
|
||||||
/*! Bytes per row in the scanline buffer. */
|
|
||||||
size_t bytes = cinfo->output_width * cinfo->output_components;
|
|
||||||
|
|
||||||
/*! Allocate scratch space for a single scanline. */
|
|
||||||
JSAMPARRAY scanline = (*cinfo->mem->alloc_sarray)((j_common_ptr) cinfo, JPOOL_IMAGE, bytes, 1);
|
|
||||||
|
|
||||||
/*! Allocate storage for the decompressed image. */
|
|
||||||
unsigned char* image = new unsigned char[cinfo->output_height * bytes];
|
|
||||||
|
|
||||||
/*! Here we use the library state variable 'output_scanline' as the loop index. */
|
|
||||||
while (cinfo->output_scanline < cinfo->output_height) {
|
|
||||||
jpeg_read_scanlines(cinfo, scanline, 1);
|
|
||||||
for (size_t i=0; i<bytes; i++)
|
|
||||||
image[(cinfo->output_scanline - 1) * bytes + i] = scanline[0][i];
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Finish decompression. */
|
|
||||||
jpeg_finish_decompress(cinfo);
|
|
||||||
return(image);
|
|
||||||
}
|
|
||||||
|
|
||||||
void encodeRGB8_to_JPEG(unsigned char *image, size_t width, size_t height, unsigned char **encoded, unsigned long *capacity)
|
|
||||||
{
|
|
||||||
|
|
||||||
#if JPEG_LIB_VERSION >= 80
|
|
||||||
|
|
||||||
/*! Compression parameters and scratch space pointers (allocated by the library). */
|
|
||||||
struct jpeg_compress_struct cinfo;
|
|
||||||
|
|
||||||
/*! The library error handler. */
|
|
||||||
struct jpeg_error_mgr jerror; cinfo.err = jpeg_std_error(&jerror);
|
|
||||||
|
|
||||||
/*! Initialize the JPEG compression object. */
|
|
||||||
jpeg_create_compress(&cinfo);
|
|
||||||
|
|
||||||
/*! Specify the incoming image resolution, color space, and color space components. */
|
|
||||||
cinfo.image_width = width; cinfo.image_height = height; cinfo.in_color_space = JCS_RGB; cinfo.input_components = 3;
|
|
||||||
|
|
||||||
/*! Fill in a sensible set of defaults. */
|
|
||||||
jpeg_set_defaults(&cinfo);
|
|
||||||
|
|
||||||
/*! Set the image quality. */
|
|
||||||
jpeg_set_quality(&cinfo, 90, TRUE);
|
|
||||||
|
|
||||||
/*! Specify the data source. */
|
|
||||||
jpeg_mem_dest(&cinfo, encoded, capacity);
|
|
||||||
|
|
||||||
/*! Compress and write the image into the target buffer. */
|
|
||||||
compress(&cinfo, image);
|
|
||||||
|
|
||||||
/*! At this point 'jerror.num_warnings' could be checked for corrupt-data warnings. */
|
|
||||||
jpeg_destroy_compress(&cinfo);
|
|
||||||
|
|
||||||
#else // JPEG_LIB_VERSION
|
|
||||||
|
|
||||||
THROW_RUNTIME_ERROR("JPEG encoding into a memory buffer requires LibJPEG 8a or higher");
|
|
||||||
|
|
||||||
#endif // JPEG_LIB_VERSION
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<Image> loadJPEG(const FileName &filename)
|
|
||||||
{
|
|
||||||
|
|
||||||
/*! Open the source JPEG file. */
|
|
||||||
FILE *file = fopen(filename.c_str(), "rb"); if (!file) THROW_RUNTIME_ERROR("Unable to open \"" + filename.str() + "\".");
|
|
||||||
|
|
||||||
/*! Decompression parameters and scratch space pointers allocated by the library. */
|
|
||||||
struct jpeg_decompress_struct cinfo;
|
|
||||||
|
|
||||||
/*! The library error handler. */
|
|
||||||
struct jpeg_error_mgr jerror; cinfo.err = jpeg_std_error(&jerror);
|
|
||||||
|
|
||||||
/*! Initialize the JPEG decompression object. */
|
|
||||||
jpeg_create_decompress(&cinfo);
|
|
||||||
|
|
||||||
/*! Specify the data source. */
|
|
||||||
jpeg_stdio_src(&cinfo, file);
|
|
||||||
|
|
||||||
/*! Read file parameters with jpeg_read_header(). */
|
|
||||||
jpeg_read_header(&cinfo, TRUE);
|
|
||||||
|
|
||||||
/*! Specify the color space and color space components of the decompressed image. */
|
|
||||||
cinfo.out_color_space = JCS_RGB; cinfo.output_components = 3;
|
|
||||||
|
|
||||||
/*! Decompress the image into an output buffer and get the image dimensions. */
|
|
||||||
unsigned char *rgb = decompress(&cinfo); size_t width = cinfo.output_width; size_t height = cinfo.output_height;
|
|
||||||
|
|
||||||
/*! Allocate the Embree image. */
|
|
||||||
Ref<Image> image = new Image4uc(width, height, filename);
|
|
||||||
|
|
||||||
/*! Convert the image from unsigned char RGB to unsigned char RGBA. */
|
|
||||||
for (size_t y=0, i=0 ; y < height ; y++) {
|
|
||||||
for (size_t x=0 ; x < width ; x++) {
|
|
||||||
const float r = (float) rgb[i++] / 255.0f;
|
|
||||||
const float g = (float) rgb[i++] / 255.0f;
|
|
||||||
const float b = (float) rgb[i++] / 255.0f;
|
|
||||||
image->set(x, y, Color4(r,g,b,1.0f));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Clean up. */
|
|
||||||
jpeg_destroy_decompress(&cinfo);
|
|
||||||
delete[] rgb;
|
|
||||||
fclose(file);
|
|
||||||
return(image);
|
|
||||||
}
|
|
||||||
|
|
||||||
void storeJPEG(const Ref<Image> &image, const FileName &filename)
|
|
||||||
{
|
|
||||||
|
|
||||||
/*! Open the target JPEG file. */
|
|
||||||
FILE *file = fopen(filename.c_str(), "wb"); if (!file) THROW_RUNTIME_ERROR("Unable to open \"" + filename.str() + "\".");
|
|
||||||
|
|
||||||
/*! Compression parameters and scratch space pointers (allocated by the library). */
|
|
||||||
struct jpeg_compress_struct cinfo;
|
|
||||||
|
|
||||||
/*! The library error handler. */
|
|
||||||
struct jpeg_error_mgr jerror; cinfo.err = jpeg_std_error(&jerror);
|
|
||||||
|
|
||||||
/*! Initialize the JPEG compression object. */
|
|
||||||
jpeg_create_compress(&cinfo);
|
|
||||||
|
|
||||||
/*! Specify the incoming image resolution, color space, and color space components. */
|
|
||||||
cinfo.image_width = image->width; cinfo.image_height = image->height; cinfo.in_color_space = JCS_RGB; cinfo.input_components = 3;
|
|
||||||
|
|
||||||
/*! Fill in a sensible set of defaults. */
|
|
||||||
jpeg_set_defaults(&cinfo);
|
|
||||||
|
|
||||||
/*! Specify the data source. */
|
|
||||||
jpeg_stdio_dest(&cinfo, file);
|
|
||||||
|
|
||||||
/*! Allocate storage for the uncompressed packed image. */
|
|
||||||
unsigned char* rgb = new unsigned char [3 * image->height * image->width];
|
|
||||||
|
|
||||||
/*! Convert the image to unsigned char RGB. */
|
|
||||||
for (size_t y=0, i=0 ; y < image->height ; y++) {
|
|
||||||
for (size_t x=0 ; x < image->width ; x++) {
|
|
||||||
const Color4 pixel = image->get(x, y);
|
|
||||||
rgb[i++] = (unsigned char)(clamp(pixel.r) * 255.0f);
|
|
||||||
rgb[i++] = (unsigned char)(clamp(pixel.g) * 255.0f);
|
|
||||||
rgb[i++] = (unsigned char)(clamp(pixel.b) * 255.0f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Compress and write the image into the target file. */
|
|
||||||
compress(&cinfo, rgb);
|
|
||||||
|
|
||||||
/*! At this point 'jerror.num_warnings' could be checked for corrupt-data warnings. */
|
|
||||||
jpeg_destroy_compress(&cinfo);
|
|
||||||
delete [] rgb;
|
|
||||||
fclose(file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // EMBREE_TUTORIALS_LIBJPEG
|
|
||||||
|
|
||||||
|
|
@ -1,76 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#ifdef USE_OPENIMAGEIO
|
|
||||||
|
|
||||||
#include "image.h"
|
|
||||||
#include <iostream>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
/*! include OpenImageIO headers */
|
|
||||||
#include <OpenImageIO/imageio.h>
|
|
||||||
OIIO_NAMESPACE_USING
|
|
||||||
|
|
||||||
namespace embree
|
|
||||||
{
|
|
||||||
Ref<Image> loadOIIO(const FileName& fileName)
|
|
||||||
{
|
|
||||||
std::unique_ptr<ImageInput> in(ImageInput::open(fileName.str().c_str()));
|
|
||||||
if (!in)
|
|
||||||
THROW_RUNTIME_ERROR("error opening file " + fileName.str());
|
|
||||||
|
|
||||||
const ImageSpec& spec = in->spec();
|
|
||||||
size_t width = spec.width;
|
|
||||||
size_t height = spec.height;
|
|
||||||
size_t channels = spec.nchannels;
|
|
||||||
std::vector<unsigned char> pixels(width*height*channels);
|
|
||||||
in->read_image(TypeDesc::UINT8, pixels.data());
|
|
||||||
in->close();
|
|
||||||
|
|
||||||
Image* out = new Image4uc(width, height, fileName);
|
|
||||||
const float rcpMaxColor = 1.f/255.f;
|
|
||||||
for (size_t y = 0; y < height; y++)
|
|
||||||
{
|
|
||||||
for (size_t x = 0; x < width; x++)
|
|
||||||
{
|
|
||||||
float r = (channels > 0) ? (float(pixels[(y*width+x)*channels+0]) * rcpMaxColor) : 0.f;
|
|
||||||
float g = (channels > 1) ? (float(pixels[(y*width+x)*channels+1]) * rcpMaxColor) : r;
|
|
||||||
float b = (channels > 2) ? (float(pixels[(y*width+x)*channels+2]) * rcpMaxColor) : ((channels == 1) ? r : 0.f);
|
|
||||||
float a = (channels > 3) ? (float(pixels[(y*width+x)*channels+3]) * rcpMaxColor) : 1.f;
|
|
||||||
out->set(x, height-y-1, Color4(r,g,b,a)); // flip image
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
void storeOIIO(const Ref<Image>& img, const FileName& fileName)
|
|
||||||
{
|
|
||||||
std::unique_ptr<ImageOutput> out(ImageOutput::create(fileName.c_str()));
|
|
||||||
if (!out) THROW_RUNTIME_ERROR("unsupported output file format " + fileName.str());
|
|
||||||
|
|
||||||
std::vector<unsigned char> pixels(img->width*img->height*3);
|
|
||||||
const float maxColor = 255.f;
|
|
||||||
for (size_t y = 0; y < img->height; y++)
|
|
||||||
{
|
|
||||||
for (size_t x = 0; x < img->width; x++)
|
|
||||||
{
|
|
||||||
Color4 c = img->get(x, y);
|
|
||||||
pixels[(y*img->width+x)*3+0] = (unsigned char)(clamp(c.r) * maxColor);
|
|
||||||
pixels[(y*img->width+x)*3+1] = (unsigned char)(clamp(c.g) * maxColor);
|
|
||||||
pixels[(y*img->width+x)*3+2] = (unsigned char)(clamp(c.b) * maxColor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImageSpec spec(int(img->width), int(img->height), 3, TypeDesc::UINT8);
|
|
||||||
if (!out->open(fileName.c_str(), spec))
|
|
||||||
{
|
|
||||||
THROW_RUNTIME_ERROR("error opening file " + fileName.str());
|
|
||||||
}
|
|
||||||
out->write_image(TypeDesc::UINT8, pixels.data());
|
|
||||||
out->close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // USE_OPENIMAGEIO
|
|
||||||
|
|
||||||
|
|
@ -1,90 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#include "image.h"
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <cstring>
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
namespace embree
|
|
||||||
{
|
|
||||||
static void skipSpacesAndComments(std::fstream& file)
|
|
||||||
{
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
if (isspace(file.peek())) {
|
|
||||||
file.ignore();
|
|
||||||
} else if (file.peek() == '#') {
|
|
||||||
std::string line; std::getline(file,line);
|
|
||||||
} else break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! read PFM file from disk */
|
|
||||||
Ref<Image> loadPFM(const FileName& fileName)
|
|
||||||
{
|
|
||||||
/* open file for reading */
|
|
||||||
std::fstream file;
|
|
||||||
file.exceptions (std::fstream::failbit | std::fstream::badbit);
|
|
||||||
file.open (fileName.c_str(), std::fstream::in | std::fstream::binary);
|
|
||||||
|
|
||||||
/* read file type */
|
|
||||||
char cty[2]; file.read(cty,2);
|
|
||||||
skipSpacesAndComments(file);
|
|
||||||
std::string type(cty,2);
|
|
||||||
|
|
||||||
/* read width, height, and maximum color value */
|
|
||||||
int width; file >> width;
|
|
||||||
skipSpacesAndComments(file);
|
|
||||||
int height; file >> height;
|
|
||||||
skipSpacesAndComments(file);
|
|
||||||
float maxColor; file >> maxColor;
|
|
||||||
if (maxColor > 0) THROW_RUNTIME_ERROR("Big endian PFM files not supported");
|
|
||||||
float rcpMaxColor = -1.0f/float(maxColor);
|
|
||||||
file.ignore(); // skip space or return
|
|
||||||
|
|
||||||
/* create image and fill with data */
|
|
||||||
Ref<Image> img = new Image4f(width,height,fileName);
|
|
||||||
|
|
||||||
/* image in binary format 16 bit */
|
|
||||||
if (type == "PF")
|
|
||||||
{
|
|
||||||
float rgb[3];
|
|
||||||
for (ssize_t y=height-1; y>=0; y--) {
|
|
||||||
for (ssize_t x=0; x<width; x++) {
|
|
||||||
file.read((char*)rgb,sizeof(rgb));
|
|
||||||
img->set(x,y,Color4(rgb[0]*rcpMaxColor,rgb[1]*rcpMaxColor,rgb[2]*rcpMaxColor,1.0f));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* invalid magic value */
|
|
||||||
else {
|
|
||||||
THROW_RUNTIME_ERROR("Invalid magic value in PFM file");
|
|
||||||
}
|
|
||||||
return img;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! store PFM file to disk */
|
|
||||||
void storePFM(const Ref<Image>& img, const FileName& fileName)
|
|
||||||
{
|
|
||||||
/* open file for writing */
|
|
||||||
std::fstream file;
|
|
||||||
file.exceptions (std::fstream::failbit | std::fstream::badbit);
|
|
||||||
file.open (fileName.c_str(), std::fstream::out | std::fstream::binary);
|
|
||||||
|
|
||||||
/* write file header */
|
|
||||||
file << "PF" << std::endl;
|
|
||||||
file << img->width << " " << img->height << std::endl;
|
|
||||||
file << -1.0f << std::endl;
|
|
||||||
|
|
||||||
/* write image */
|
|
||||||
for (ssize_t y=img->height-1; y>=0; y--) {
|
|
||||||
for (ssize_t x=0; x<(ssize_t)img->width; x++) {
|
|
||||||
const Color4 c = img->get(x,y);
|
|
||||||
file.write((char*)&c,3*sizeof(float));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,135 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#ifdef EMBREE_TUTORIALS_LIBPNG
|
|
||||||
|
|
||||||
#include "image.h"
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <cstring>
|
|
||||||
#include <cstdio>
|
|
||||||
#include <png.h>
|
|
||||||
|
|
||||||
namespace embree
|
|
||||||
{
|
|
||||||
struct AutoCloseFile
|
|
||||||
{
|
|
||||||
FILE* file;
|
|
||||||
AutoCloseFile (FILE* file) : file(file) {}
|
|
||||||
~AutoCloseFile () { if (file) fclose(file); }
|
|
||||||
};
|
|
||||||
|
|
||||||
/*! read PNG file from disk */
|
|
||||||
Ref<Image> loadPNG(const FileName& fileName)
|
|
||||||
{
|
|
||||||
size_t width, height;
|
|
||||||
|
|
||||||
//header for testing if it is a png
|
|
||||||
png_byte header[8];
|
|
||||||
|
|
||||||
//open file as binary
|
|
||||||
FILE* fp = fopen(fileName.c_str(), "rb");
|
|
||||||
if (!fp) THROW_RUNTIME_ERROR("cannot open file "+fileName.str());
|
|
||||||
//ON_SCOPE_EXIT(fclose(fp));
|
|
||||||
AutoCloseFile close_file(fp);
|
|
||||||
|
|
||||||
//read the header
|
|
||||||
if (fread(header, 1, 8, fp) != 8)
|
|
||||||
THROW_RUNTIME_ERROR("invalid PNG file "+fileName.str());
|
|
||||||
|
|
||||||
//test if png
|
|
||||||
int is_png = !png_sig_cmp(header, 0, 8);
|
|
||||||
if (!is_png)
|
|
||||||
THROW_RUNTIME_ERROR("invalid PNG file "+fileName.str());
|
|
||||||
|
|
||||||
//create png struct
|
|
||||||
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
|
||||||
if (!png_ptr) THROW_RUNTIME_ERROR("invalid PNG file "+fileName.str());
|
|
||||||
ON_SCOPE_EXIT(png_destroy_read_struct(&png_ptr, (png_infopp) nullptr, (png_infopp) nullptr));
|
|
||||||
|
|
||||||
//create png info struct
|
|
||||||
png_infop info_ptr = png_create_info_struct(png_ptr);
|
|
||||||
if (!info_ptr)
|
|
||||||
THROW_RUNTIME_ERROR("invalid PNG file "+fileName.str());
|
|
||||||
|
|
||||||
//create png info struct
|
|
||||||
png_infop end_info = png_create_info_struct(png_ptr);
|
|
||||||
if (!end_info)
|
|
||||||
THROW_RUNTIME_ERROR("invalid PNG file "+fileName.str());
|
|
||||||
|
|
||||||
//png error stuff, not sure libpng man suggests this.
|
|
||||||
//if (setjmp(png_jmpbuf(png_ptr))) {
|
|
||||||
/// return (TEXTURE_LOAD_ERROR);
|
|
||||||
//}
|
|
||||||
|
|
||||||
//init png reading
|
|
||||||
png_init_io(png_ptr, fp);
|
|
||||||
|
|
||||||
//let libpng know you already read the first 8 bytes
|
|
||||||
png_set_sig_bytes(png_ptr, 8);
|
|
||||||
|
|
||||||
// read all the info up to the image data
|
|
||||||
png_read_info(png_ptr, info_ptr);
|
|
||||||
|
|
||||||
//variables to pass to get info
|
|
||||||
int bit_depth, color_type;
|
|
||||||
png_uint_32 twidth, theight;
|
|
||||||
|
|
||||||
// get info about png
|
|
||||||
png_get_IHDR(png_ptr, info_ptr, &twidth, &theight, &bit_depth, &color_type,
|
|
||||||
nullptr, nullptr, nullptr);
|
|
||||||
|
|
||||||
//update width and height based on png info
|
|
||||||
width = twidth;
|
|
||||||
height = theight;
|
|
||||||
|
|
||||||
Ref<Image> img = new Image4uc(width,height,fileName);
|
|
||||||
|
|
||||||
// Update the png info struct.
|
|
||||||
png_read_update_info(png_ptr, info_ptr);
|
|
||||||
|
|
||||||
// Row size in bytes.
|
|
||||||
int rowbytes = png_get_rowbytes(png_ptr, info_ptr);
|
|
||||||
|
|
||||||
// Allocate the image_data as a big block, to be given to opengl
|
|
||||||
std::vector<png_byte> data(rowbytes * height);
|
|
||||||
|
|
||||||
// row_pointers is for pointing to image_data for reading the png with libpng
|
|
||||||
std::vector<png_bytep> row_pointers(height);
|
|
||||||
|
|
||||||
// set the individual row_pointers to point at the correct offsets of image_data
|
|
||||||
for (size_t i = 0; i < height; ++i)
|
|
||||||
row_pointers[i] = (unsigned char*) &data[i * rowbytes];
|
|
||||||
|
|
||||||
// read the png into image_data through row_pointers
|
|
||||||
png_read_image(png_ptr, row_pointers.data());
|
|
||||||
|
|
||||||
if (color_type == PNG_COLOR_TYPE_RGB && bit_depth == 8)
|
|
||||||
{
|
|
||||||
for (size_t y=0;y<height;y++)
|
|
||||||
for (size_t x=0;x<width;x++)
|
|
||||||
{
|
|
||||||
unsigned char* texel = data.data() + (y * width + x) * 3;
|
|
||||||
Color4 c( (float)texel[0] * 1.0f/255.0f, (float)texel[1] * 1.0f/255.0f, (float)texel[2] * 1.0f/255.0f, 0.0f );
|
|
||||||
img.ptr->set(x,y,c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (color_type == PNG_COLOR_TYPE_RGBA && bit_depth == 8)
|
|
||||||
{
|
|
||||||
for (size_t y=0;y<height;y++)
|
|
||||||
for (size_t x=0;x<width;x++)
|
|
||||||
{
|
|
||||||
unsigned char *texel = data.data() + (y * width + x) * 4;
|
|
||||||
Color4 c( (float)texel[0] * 1.0f/255.0f, (float)texel[1] * 1.0f/255.0f, (float)texel[2] * 1.0f/255.0f, (float)texel[3] * 1.0f/255.0f );
|
|
||||||
img.ptr->set(x,y,c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
THROW_RUNTIME_ERROR("invalid color type in PNG file "+fileName.str());
|
|
||||||
|
|
||||||
return img;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
@ -1,117 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#include "image.h"
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <cstring>
|
|
||||||
#include <cstdio>
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
namespace embree
|
|
||||||
{
|
|
||||||
static void skipSpacesAndComments(std::fstream& file)
|
|
||||||
{
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
if (isspace(file.peek())) {
|
|
||||||
file.ignore();
|
|
||||||
} else if (file.peek() == '#') {
|
|
||||||
std::string line; std::getline(file,line);
|
|
||||||
} else break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! read PPM file from disk */
|
|
||||||
Ref<Image> loadPPM(const FileName& fileName)
|
|
||||||
{
|
|
||||||
/* open file for reading */
|
|
||||||
std::fstream file;
|
|
||||||
file.exceptions (std::fstream::failbit | std::fstream::badbit);
|
|
||||||
file.open (fileName.c_str(), std::fstream::in | std::fstream::binary);
|
|
||||||
|
|
||||||
/* read file type */
|
|
||||||
char cty[2]; file.read(cty,2);
|
|
||||||
skipSpacesAndComments(file);
|
|
||||||
std::string type(cty,2);
|
|
||||||
|
|
||||||
/* read width, height, and maximum color value */
|
|
||||||
int width; file >> width;
|
|
||||||
skipSpacesAndComments(file);
|
|
||||||
int height; file >> height;
|
|
||||||
skipSpacesAndComments(file);
|
|
||||||
int maxColor; file >> maxColor;
|
|
||||||
if (maxColor <= 0) THROW_RUNTIME_ERROR("Invalid maxColor value in PPM file");
|
|
||||||
float rcpMaxColor = 1.0f/float(maxColor);
|
|
||||||
file.ignore(); // skip space or return
|
|
||||||
|
|
||||||
/* create image and fill with data */
|
|
||||||
Ref<Image> img = new Image4uc(width,height,fileName);
|
|
||||||
|
|
||||||
/* image in text format */
|
|
||||||
if (type == "P3")
|
|
||||||
{
|
|
||||||
int r, g, b;
|
|
||||||
for (ssize_t y=0; y<height; y++) {
|
|
||||||
for (ssize_t x=0; x<width; x++) {
|
|
||||||
file >> r; file >> g; file >> b;
|
|
||||||
img->set(x,y,Color4(float(r)*rcpMaxColor,float(g)*rcpMaxColor,float(b)*rcpMaxColor,1.0f));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* image in binary format 8 bit */
|
|
||||||
else if (type == "P6" && maxColor <= 255)
|
|
||||||
{
|
|
||||||
unsigned char rgb[3];
|
|
||||||
for (ssize_t y=0; y<height; y++) {
|
|
||||||
for (ssize_t x=0; x<width; x++) {
|
|
||||||
file.read((char*)rgb,sizeof(rgb));
|
|
||||||
img->set(x,y,Color4(float(rgb[0])*rcpMaxColor,float(rgb[1])*rcpMaxColor,float(rgb[2])*rcpMaxColor,1.0f));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* image in binary format 16 bit */
|
|
||||||
else if (type == "P6" && maxColor <= 65535)
|
|
||||||
{
|
|
||||||
unsigned short rgb[3];
|
|
||||||
for (ssize_t y=0; y<height; y++) {
|
|
||||||
for (ssize_t x=0; x<width; x++) {
|
|
||||||
file.read((char*)rgb,sizeof(rgb));
|
|
||||||
img->set(x,y,Color4(float(rgb[0])*rcpMaxColor,float(rgb[1])*rcpMaxColor,float(rgb[2])*rcpMaxColor,1.0f));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* invalid magic value */
|
|
||||||
else {
|
|
||||||
THROW_RUNTIME_ERROR("Invalid magic value in PPM file");
|
|
||||||
}
|
|
||||||
return img;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! store PPM file to disk */
|
|
||||||
void storePPM(const Ref<Image>& img, const FileName& fileName)
|
|
||||||
{
|
|
||||||
/* open file for writing */
|
|
||||||
std::fstream file;
|
|
||||||
file.exceptions (std::fstream::failbit | std::fstream::badbit);
|
|
||||||
file.open (fileName.c_str(), std::fstream::out | std::fstream::binary);
|
|
||||||
|
|
||||||
/* write file header */
|
|
||||||
file << "P6" << std::endl;
|
|
||||||
file << img->width << " " << img->height << std::endl;
|
|
||||||
file << 255 << std::endl;
|
|
||||||
|
|
||||||
/* write image */
|
|
||||||
for (size_t y=0; y<img->height; y++) {
|
|
||||||
for (size_t x=0; x<img->width; x++) {
|
|
||||||
const Color4 c = img->get(x,y);
|
|
||||||
file << (unsigned char)(clamp(c.r)*255.0f);
|
|
||||||
file << (unsigned char)(clamp(c.g)*255.0f);
|
|
||||||
file << (unsigned char)(clamp(c.b)*255.0f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,72 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#include "image.h"
|
|
||||||
#include "../../../common/sys/estring.h"
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#define STB_IMAGE_IMPLEMENTATION
|
|
||||||
#include "stb_image.h"
|
|
||||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
|
||||||
#include "stb_image_write.h"
|
|
||||||
|
|
||||||
namespace embree
|
|
||||||
{
|
|
||||||
Ref<Image> loadSTB(const FileName& fileName)
|
|
||||||
{
|
|
||||||
int width, height, channels;
|
|
||||||
unsigned char *pixels = stbi_load(fileName.str().c_str(), &width, &height, &channels, 0);
|
|
||||||
if(pixels == nullptr) {
|
|
||||||
THROW_RUNTIME_ERROR("Could not load " + fileName.str());
|
|
||||||
}
|
|
||||||
|
|
||||||
Image* out = new Image4uc(width, height, fileName);
|
|
||||||
const float rcpMaxColor = 1.f/255.f;
|
|
||||||
for (size_t y = 0; y < height; y++)
|
|
||||||
{
|
|
||||||
for (size_t x = 0; x < width; x++)
|
|
||||||
{
|
|
||||||
float r = (channels > 0) ? (float(pixels[(y*width+x)*channels+0]) * rcpMaxColor) : 0.f;
|
|
||||||
float g = (channels > 1) ? (float(pixels[(y*width+x)*channels+1]) * rcpMaxColor) : r;
|
|
||||||
float b = (channels > 2) ? (float(pixels[(y*width+x)*channels+2]) * rcpMaxColor) : ((channels == 1) ? r : 0.f);
|
|
||||||
float a = (channels > 3) ? (float(pixels[(y*width+x)*channels+3]) * rcpMaxColor) : 1.f;
|
|
||||||
out->set(x, y, Color4(r,g,b,a));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stbi_image_free(pixels);
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
void storeSTB(const Ref<Image>& img, const FileName& fileName)
|
|
||||||
{
|
|
||||||
std::string ext = toLowerCase(fileName.ext());
|
|
||||||
if (ext != "bmp" && ext != "png" && ext != "jpg") {
|
|
||||||
THROW_RUNTIME_ERROR("Could not store image")
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int width = int(img->width);
|
|
||||||
int height = int(img->height);
|
|
||||||
int channels = 3;
|
|
||||||
std::vector<unsigned char> pixels(width*height*channels);
|
|
||||||
const float maxColor = 255.f;
|
|
||||||
for (int y = 0; y < height; y++)
|
|
||||||
{
|
|
||||||
for (int x = 0; x < width; x++)
|
|
||||||
{
|
|
||||||
Color4 c = img->get(x, y);
|
|
||||||
pixels[(y*img->width+x)*channels+0] = (unsigned char)(clamp(c.r) * maxColor);
|
|
||||||
pixels[(y*img->width+x)*channels+1] = (unsigned char)(clamp(c.g) * maxColor);
|
|
||||||
pixels[(y*img->width+x)*channels+2] = (unsigned char)(clamp(c.b) * maxColor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ext == "bmp" ) { stbi_write_bmp(fileName.str().c_str(), width, height, channels, pixels.data()); return; }
|
|
||||||
if (ext == "png" ) { stbi_write_png(fileName.str().c_str(), width, height, channels, pixels.data(), width * channels); return; }
|
|
||||||
if (ext == "jpg" ) { stbi_write_jpg(fileName.str().c_str(), width, height, channels, pixels.data(), 100); return; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,95 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#include "image.h"
|
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
namespace embree
|
|
||||||
{
|
|
||||||
inline void fwrite_uchar (unsigned char v, std::fstream& file) { file.write((const char*)&v,sizeof(v)); }
|
|
||||||
inline void fwrite_ushort(unsigned short v, std::fstream& file) { file.write((const char*)&v,sizeof(v)); }
|
|
||||||
|
|
||||||
void storeTga(const Ref<Image>& img, const FileName& fileName)
|
|
||||||
{
|
|
||||||
/* open file for reading */
|
|
||||||
std::fstream file;
|
|
||||||
file.exceptions (std::fstream::failbit | std::fstream::badbit);
|
|
||||||
file.open (fileName.c_str(), std::fstream::out | std::fstream::binary);
|
|
||||||
|
|
||||||
fwrite_uchar(0x00, file);
|
|
||||||
fwrite_uchar(0x00, file);
|
|
||||||
fwrite_uchar(0x02, file);
|
|
||||||
fwrite_ushort(0x0000, file);
|
|
||||||
fwrite_ushort(0x0000, file);
|
|
||||||
fwrite_uchar(0x00, file);
|
|
||||||
fwrite_ushort(0x0000, file);
|
|
||||||
fwrite_ushort(0x0000, file);
|
|
||||||
fwrite_ushort((unsigned short)img->width , file);
|
|
||||||
fwrite_ushort((unsigned short)img->height, file);
|
|
||||||
fwrite_uchar(0x18, file);
|
|
||||||
fwrite_uchar(0x20, file);
|
|
||||||
|
|
||||||
for (size_t y=0; y<img->height; y++) {
|
|
||||||
for (size_t x=0; x<img->width; x++) {
|
|
||||||
Color c = img->get(x,y);
|
|
||||||
fwrite_uchar((unsigned char)(clamp(c.b)*255.0f), file);
|
|
||||||
fwrite_uchar((unsigned char)(clamp(c.g)*255.0f), file);
|
|
||||||
fwrite_uchar((unsigned char)(clamp(c.r)*255.0f), file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline unsigned char fread_uchar (std::fstream& file) { unsigned char v; file.read((char*)&v,sizeof(v)); return v; }
|
|
||||||
inline unsigned short fread_ushort(std::fstream& file) { unsigned short v; file.read((char*)&v,sizeof(v)); return v; }
|
|
||||||
|
|
||||||
/*! read TGA file from disk */
|
|
||||||
Ref<Image> loadTGA(const FileName& fileName)
|
|
||||||
{
|
|
||||||
/* open file for reading */
|
|
||||||
std::fstream file;
|
|
||||||
file.exceptions (std::fstream::failbit | std::fstream::badbit);
|
|
||||||
file.open (fileName.c_str(), std::fstream::in | std::fstream::binary);
|
|
||||||
|
|
||||||
unsigned char idlength = fread_uchar(file);
|
|
||||||
if (idlength != 0) THROW_RUNTIME_ERROR("unsupported TGA file");
|
|
||||||
|
|
||||||
unsigned char colormaptype = fread_uchar(file);
|
|
||||||
if (colormaptype != 0) THROW_RUNTIME_ERROR("unsupported TGA file");
|
|
||||||
|
|
||||||
unsigned char datatype = fread_uchar(file);
|
|
||||||
if (datatype != 2) THROW_RUNTIME_ERROR("unsupported TGA file");
|
|
||||||
|
|
||||||
unsigned short cmo = fread_ushort(file);
|
|
||||||
unsigned short cml = fread_ushort(file);
|
|
||||||
unsigned char cmd = fread_uchar(file);
|
|
||||||
unsigned short xorg = fread_ushort(file);
|
|
||||||
unsigned short yorg = fread_ushort(file);
|
|
||||||
if (cmo != 0 || cml != 0 || cmd != 0 || xorg != 0 || yorg != 0)
|
|
||||||
THROW_RUNTIME_ERROR("unsupported TGA file");
|
|
||||||
|
|
||||||
unsigned short width = fread_ushort(file);
|
|
||||||
unsigned short height = fread_ushort(file);
|
|
||||||
|
|
||||||
unsigned char bits = fread_uchar(file);
|
|
||||||
if (bits != 3*8) THROW_RUNTIME_ERROR("unsupported TGA file bits per pixel");
|
|
||||||
|
|
||||||
unsigned char desc = fread_uchar(file);
|
|
||||||
if (desc != 0x20) THROW_RUNTIME_ERROR("unsupported TGA file");
|
|
||||||
|
|
||||||
/* create image and fill with data */
|
|
||||||
Ref<Image> img = new Image4f(width,height,fileName);
|
|
||||||
|
|
||||||
/* load image data */
|
|
||||||
for (size_t y=0; y<height; y++) {
|
|
||||||
for (size_t x=0; x<width; x++) {
|
|
||||||
const unsigned char b = fread_uchar(file);
|
|
||||||
const unsigned char g = fread_uchar(file);
|
|
||||||
const unsigned char r = fread_uchar(file);
|
|
||||||
img->set(x,y,Color4(r/255.0f,g/255.0f,b/255.0f,1.0f));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return img;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,18 +0,0 @@
|
||||||
## Copyright 2009-2021 Intel Corporation
|
|
||||||
## SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
ADD_LIBRARY(imgui STATIC
|
|
||||||
imgui.cpp
|
|
||||||
imgui_draw.cpp
|
|
||||||
imgui_widgets.cpp
|
|
||||||
imgui_tables.cpp
|
|
||||||
backends/imgui_impl_glfw.cpp
|
|
||||||
backends/imgui_impl_opengl2.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
TARGET_INCLUDE_DIRECTORIES(imgui PUBLIC . ./backends)
|
|
||||||
TARGET_LINK_LIBRARIES(imgui glfw)
|
|
||||||
SET_PROPERTY(TARGET imgui PROPERTY FOLDER tutorials/common)
|
|
||||||
SET_PROPERTY(TARGET imgui APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}")
|
|
||||||
|
|
||||||
TARGET_COMPILE_DEFINITIONS(imgui PUBLIC IMGUI_DISABLE_SSE)
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2014-2022 Omar Cornut
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
@ -1,686 +0,0 @@
|
||||||
// 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+)
|
|
||||||
|
|
||||||
// Implemented features:
|
|
||||||
// [X] Platform: Clipboard support.
|
|
||||||
// [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.
|
|
||||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
|
||||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
|
||||||
|
|
||||||
// CHANGELOG
|
|
||||||
// (minor and older changes stripped away, please see git history for details)
|
|
||||||
// 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.
|
|
||||||
// 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"
|
|
||||||
#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 <GLFW/glfw3.h>
|
|
||||||
#ifdef _WIN32
|
|
||||||
#undef APIENTRY
|
|
||||||
#define GLFW_EXPOSE_NATIVE_WIN32
|
|
||||||
#include <GLFW/glfw3native.h> // for glfwGetWin32Window
|
|
||||||
#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()
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
|
|
||||||
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;
|
|
||||||
default: return ImGuiKey_None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int ImGui_ImplGlfw_KeyToModifier(int key)
|
|
||||||
{
|
|
||||||
if (key == GLFW_KEY_LEFT_CONTROL || key == GLFW_KEY_RIGHT_CONTROL)
|
|
||||||
return GLFW_MOD_CONTROL;
|
|
||||||
if (key == GLFW_KEY_LEFT_SHIFT || key == GLFW_KEY_RIGHT_SHIFT)
|
|
||||||
return GLFW_MOD_SHIFT;
|
|
||||||
if (key == GLFW_KEY_LEFT_ALT || key == GLFW_KEY_RIGHT_ALT)
|
|
||||||
return GLFW_MOD_ALT;
|
|
||||||
if (key == GLFW_KEY_LEFT_SUPER || key == GLFW_KEY_RIGHT_SUPER)
|
|
||||||
return GLFW_MOD_SUPER;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ImGui_ImplGlfw_UpdateKeyModifiers(int mods)
|
|
||||||
{
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
io.AddKeyEvent(ImGuiMod_Ctrl, (mods & GLFW_MOD_CONTROL) != 0);
|
|
||||||
io.AddKeyEvent(ImGuiMod_Shift, (mods & GLFW_MOD_SHIFT) != 0);
|
|
||||||
io.AddKeyEvent(ImGuiMod_Alt, (mods & GLFW_MOD_ALT) != 0);
|
|
||||||
io.AddKeyEvent(ImGuiMod_Super, (mods & GLFW_MOD_SUPER) != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods)
|
|
||||||
{
|
|
||||||
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
|
|
||||||
if (bd->PrevUserCallbackMousebutton != nullptr && window == bd->Window)
|
|
||||||
bd->PrevUserCallbackMousebutton(window, button, action, mods);
|
|
||||||
|
|
||||||
ImGui_ImplGlfw_UpdateKeyModifiers(mods);
|
|
||||||
|
|
||||||
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 && window == bd->Window)
|
|
||||||
bd->PrevUserCallbackScroll(window, xoffset, yoffset);
|
|
||||||
|
|
||||||
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_VERSION_COMBINED >= 3300) // Eat errors (see #5908)
|
|
||||||
(void)glfwGetError(NULL);
|
|
||||||
#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 && window == bd->Window)
|
|
||||||
bd->PrevUserCallbackKey(window, keycode, scancode, action, mods);
|
|
||||||
|
|
||||||
if (action != GLFW_PRESS && action != GLFW_RELEASE)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Workaround: X11 does not include current pressed/released modifier key in 'mods' flags. https://github.com/glfw/glfw/issues/1630
|
|
||||||
if (int keycode_to_mod = ImGui_ImplGlfw_KeyToModifier(keycode))
|
|
||||||
mods = (action == GLFW_PRESS) ? (mods | keycode_to_mod) : (mods & ~keycode_to_mod);
|
|
||||||
ImGui_ImplGlfw_UpdateKeyModifiers(mods);
|
|
||||||
|
|
||||||
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 && window == bd->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 && window == bd->Window)
|
|
||||||
bd->PrevUserCallbackCursorPos(window, x, y);
|
|
||||||
if (glfwGetInputMode(window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED)
|
|
||||||
return;
|
|
||||||
|
|
||||||
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 && window == bd->Window)
|
|
||||||
bd->PrevUserCallbackCursorEnter(window, entered);
|
|
||||||
if (glfwGetInputMode(window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED)
|
|
||||||
return;
|
|
||||||
|
|
||||||
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 && window == bd->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.
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
// Set platform dependent data in viewport
|
|
||||||
#if defined(_WIN32)
|
|
||||||
ImGui::GetMainViewport()->PlatformHandleRaw = (void*)glfwGetWin32Window(bd->Window);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// 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_VERSION_COMBINED >= 3300) // Eat errors (see #5785)
|
|
||||||
(void)glfwGetError(NULL);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any.
|
|
||||||
if (install_callbacks)
|
|
||||||
ImGui_ImplGlfw_InstallCallbacks(window);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++)
|
|
||||||
glfwDestroyCursor(bd->MouseCursors[cursor_n]);
|
|
||||||
|
|
||||||
io.BackendPlatformName = nullptr;
|
|
||||||
io.BackendPlatformUserData = nullptr;
|
|
||||||
IM_DELETE(bd);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ImGui_ImplGlfw_UpdateMouseData()
|
|
||||||
{
|
|
||||||
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
|
|
||||||
if (glfwGetInputMode(bd->Window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED)
|
|
||||||
{
|
|
||||||
io.AddMousePosEvent(-FLT_MAX, -FLT_MAX);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __EMSCRIPTEN__
|
|
||||||
const bool is_app_focused = true;
|
|
||||||
#else
|
|
||||||
const bool is_app_focused = glfwGetWindowAttrib(bd->Window, GLFW_FOCUSED) != 0;
|
|
||||||
#endif
|
|
||||||
if (is_app_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(bd->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 (is_app_focused && bd->MouseWindow == nullptr)
|
|
||||||
{
|
|
||||||
double mouse_x, mouse_y;
|
|
||||||
glfwGetCursorPos(bd->Window, &mouse_x, &mouse_y);
|
|
||||||
io.AddMousePosEvent((float)mouse_x, (float)mouse_y);
|
|
||||||
bd->LastValidMousePos = ImVec2((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();
|
|
||||||
if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor)
|
|
||||||
{
|
|
||||||
// Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
|
|
||||||
glfwSetInputMode(bd->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(bd->Window, bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow]);
|
|
||||||
glfwSetInputMode(bd->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
|
|
||||||
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
|
|
||||||
double current_time = glfwGetTime();
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(__clang__)
|
|
||||||
#pragma clang diagnostic pop
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
// 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: 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.
|
|
||||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
|
||||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "imgui.h" // IMGUI_IMPL_API
|
|
||||||
|
|
||||||
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();
|
|
||||||
|
|
||||||
// GLFW callbacks (installer)
|
|
||||||
// - 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);
|
|
||||||
|
|
||||||
// GLFW callbacks (individual callbacks to call 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);
|
|
||||||
|
|
@ -1,287 +0,0 @@
|
||||||
// dear imgui: Renderer Backend for OpenGL2 (legacy OpenGL, fixed pipeline)
|
|
||||||
// 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!
|
|
||||||
|
|
||||||
// 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.
|
|
||||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
|
||||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
|
||||||
|
|
||||||
// **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)**
|
|
||||||
// **Prefer using the code in imgui_impl_opengl3.cpp**
|
|
||||||
// This code is mostly provided as a reference to learn how ImGui integration works, because it is shorter to read.
|
|
||||||
// If your code is using GL3+ context or any semi modern OpenGL calls, using this is likely to make everything more
|
|
||||||
// complicated, will require your code to reset every single OpenGL attributes to their initial state, and might
|
|
||||||
// confuse your GPU driver.
|
|
||||||
// The GL2 code is unable to reset attributes or even call e.g. "glUseProgram(0)" because they don't exist in that API.
|
|
||||||
|
|
||||||
// CHANGELOG
|
|
||||||
// (minor and older changes stripped away, please see git history for details)
|
|
||||||
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
|
|
||||||
// 2021-12-08: OpenGL: Fixed mishandling of the the ImDrawCmd::IdxOffset field! This is an old bug but it never had an effect until some internal rendering changes in 1.86.
|
|
||||||
// 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-05-19: OpenGL: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
|
|
||||||
// 2021-01-03: OpenGL: Backup, setup and restore GL_SHADE_MODEL state, disable GL_STENCIL_TEST and disable GL_NORMAL_ARRAY client state to increase compatibility with legacy OpenGL applications.
|
|
||||||
// 2020-01-23: OpenGL: Backup, setup and restore GL_TEXTURE_ENV to increase compatibility with legacy OpenGL applications.
|
|
||||||
// 2019-04-30: OpenGL: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
|
|
||||||
// 2019-02-11: OpenGL: Projecting clipping rectangles correctly using draw_data->FramebufferScale to allow multi-viewports for retina display.
|
|
||||||
// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
|
|
||||||
// 2018-08-03: OpenGL: Disabling/restoring GL_LIGHTING and GL_COLOR_MATERIAL to increase compatibility with legacy OpenGL applications.
|
|
||||||
// 2018-06-08: Misc: Extracted imgui_impl_opengl2.cpp/.h away from the old combined GLFW/SDL+OpenGL2 examples.
|
|
||||||
// 2018-06-08: OpenGL: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.
|
|
||||||
// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplOpenGL2_RenderDrawData() in the .h file so you can call it yourself.
|
|
||||||
// 2017-09-01: OpenGL: Save and restore current polygon mode.
|
|
||||||
// 2016-09-10: OpenGL: Uploading font texture as RGBA32 to increase compatibility with users shaders (not ideal).
|
|
||||||
// 2016-09-05: OpenGL: Fixed save and restore of current scissor rectangle.
|
|
||||||
|
|
||||||
#include "imgui.h"
|
|
||||||
#include "imgui_impl_opengl2.h"
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
|
|
||||||
#include <stddef.h> // intptr_t
|
|
||||||
#else
|
|
||||||
#include <stdint.h> // intptr_t
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Include OpenGL header (without an OpenGL loader) requires a bit of fiddling
|
|
||||||
#if defined(_WIN32) && !defined(APIENTRY)
|
|
||||||
#define APIENTRY __stdcall // It is customary to use APIENTRY for OpenGL function pointer declarations on all platforms. Additionally, the Windows OpenGL header needs APIENTRY.
|
|
||||||
#endif
|
|
||||||
#if defined(_WIN32) && !defined(WINGDIAPI)
|
|
||||||
#define WINGDIAPI __declspec(dllimport) // Some Windows OpenGL headers need this
|
|
||||||
#endif
|
|
||||||
#if defined(__APPLE__)
|
|
||||||
#define GL_SILENCE_DEPRECATION
|
|
||||||
#include <OpenGL/gl.h>
|
|
||||||
#else
|
|
||||||
#include <GL/gl.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct ImGui_ImplOpenGL2_Data
|
|
||||||
{
|
|
||||||
GLuint FontTexture;
|
|
||||||
|
|
||||||
ImGui_ImplOpenGL2_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_ImplOpenGL2_Data* ImGui_ImplOpenGL2_GetBackendData()
|
|
||||||
{
|
|
||||||
return ImGui::GetCurrentContext() ? (ImGui_ImplOpenGL2_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Functions
|
|
||||||
bool ImGui_ImplOpenGL2_Init()
|
|
||||||
{
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
|
|
||||||
|
|
||||||
// Setup backend capabilities flags
|
|
||||||
ImGui_ImplOpenGL2_Data* bd = IM_NEW(ImGui_ImplOpenGL2_Data)();
|
|
||||||
io.BackendRendererUserData = (void*)bd;
|
|
||||||
io.BackendRendererName = "imgui_impl_opengl2";
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGui_ImplOpenGL2_Shutdown()
|
|
||||||
{
|
|
||||||
ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData();
|
|
||||||
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
|
|
||||||
ImGui_ImplOpenGL2_DestroyDeviceObjects();
|
|
||||||
io.BackendRendererName = nullptr;
|
|
||||||
io.BackendRendererUserData = nullptr;
|
|
||||||
IM_DELETE(bd);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGui_ImplOpenGL2_NewFrame()
|
|
||||||
{
|
|
||||||
ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData();
|
|
||||||
IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplOpenGL2_Init()?");
|
|
||||||
|
|
||||||
if (!bd->FontTexture)
|
|
||||||
ImGui_ImplOpenGL2_CreateDeviceObjects();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ImGui_ImplOpenGL2_SetupRenderState(ImDrawData* draw_data, int fb_width, int fb_height)
|
|
||||||
{
|
|
||||||
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers, polygon fill.
|
|
||||||
glEnable(GL_BLEND);
|
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
//glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); // In order to composite our output buffer we need to preserve alpha
|
|
||||||
glDisable(GL_CULL_FACE);
|
|
||||||
glDisable(GL_DEPTH_TEST);
|
|
||||||
glDisable(GL_STENCIL_TEST);
|
|
||||||
glDisable(GL_LIGHTING);
|
|
||||||
glDisable(GL_COLOR_MATERIAL);
|
|
||||||
glEnable(GL_SCISSOR_TEST);
|
|
||||||
glEnableClientState(GL_VERTEX_ARRAY);
|
|
||||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
||||||
glEnableClientState(GL_COLOR_ARRAY);
|
|
||||||
glDisableClientState(GL_NORMAL_ARRAY);
|
|
||||||
glEnable(GL_TEXTURE_2D);
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
||||||
glShadeModel(GL_SMOOTH);
|
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
|
||||||
|
|
||||||
// If you are using this code with non-legacy OpenGL header/contexts (which you should not, prefer using imgui_impl_opengl3.cpp!!),
|
|
||||||
// you may need to backup/reset/restore other state, e.g. for current shader using the commented lines below.
|
|
||||||
// (DO NOT MODIFY THIS FILE! Add the code in your calling function)
|
|
||||||
// GLint last_program;
|
|
||||||
// glGetIntegerv(GL_CURRENT_PROGRAM, &last_program);
|
|
||||||
// glUseProgram(0);
|
|
||||||
// ImGui_ImplOpenGL2_RenderDrawData(...);
|
|
||||||
// glUseProgram(last_program)
|
|
||||||
// There are potentially many more states you could need to clear/setup that we can't access from default headers.
|
|
||||||
// e.g. glBindBuffer(GL_ARRAY_BUFFER, 0), glDisable(GL_TEXTURE_CUBE_MAP).
|
|
||||||
|
|
||||||
// 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.
|
|
||||||
glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height);
|
|
||||||
glMatrixMode(GL_PROJECTION);
|
|
||||||
glPushMatrix();
|
|
||||||
glLoadIdentity();
|
|
||||||
glOrtho(draw_data->DisplayPos.x, draw_data->DisplayPos.x + draw_data->DisplaySize.x, draw_data->DisplayPos.y + draw_data->DisplaySize.y, draw_data->DisplayPos.y, -1.0f, +1.0f);
|
|
||||||
glMatrixMode(GL_MODELVIEW);
|
|
||||||
glPushMatrix();
|
|
||||||
glLoadIdentity();
|
|
||||||
}
|
|
||||||
|
|
||||||
// OpenGL2 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_ImplOpenGL2_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;
|
|
||||||
|
|
||||||
// Backup GL state
|
|
||||||
GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
|
||||||
GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode);
|
|
||||||
GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport);
|
|
||||||
GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box);
|
|
||||||
GLint last_shade_model; glGetIntegerv(GL_SHADE_MODEL, &last_shade_model);
|
|
||||||
GLint last_tex_env_mode; glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &last_tex_env_mode);
|
|
||||||
glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT);
|
|
||||||
|
|
||||||
// Setup desired GL state
|
|
||||||
ImGui_ImplOpenGL2_SetupRenderState(draw_data, fb_width, fb_height);
|
|
||||||
|
|
||||||
// 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];
|
|
||||||
const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data;
|
|
||||||
const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data;
|
|
||||||
glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, pos)));
|
|
||||||
glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, uv)));
|
|
||||||
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, col)));
|
|
||||||
|
|
||||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
|
||||||
{
|
|
||||||
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
|
||||||
if (pcmd->UserCallback)
|
|
||||||
{
|
|
||||||
// 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_ImplOpenGL2_SetupRenderState(draw_data, fb_width, fb_height);
|
|
||||||
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)
|
|
||||||
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
|
|
||||||
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID());
|
|
||||||
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer + pcmd->IdxOffset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Restore modified GL state
|
|
||||||
glDisableClientState(GL_COLOR_ARRAY);
|
|
||||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
||||||
glDisableClientState(GL_VERTEX_ARRAY);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, (GLuint)last_texture);
|
|
||||||
glMatrixMode(GL_MODELVIEW);
|
|
||||||
glPopMatrix();
|
|
||||||
glMatrixMode(GL_PROJECTION);
|
|
||||||
glPopMatrix();
|
|
||||||
glPopAttrib();
|
|
||||||
glPolygonMode(GL_FRONT, (GLenum)last_polygon_mode[0]); glPolygonMode(GL_BACK, (GLenum)last_polygon_mode[1]);
|
|
||||||
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]);
|
|
||||||
glShadeModel(last_shade_model);
|
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, last_tex_env_mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ImGui_ImplOpenGL2_CreateFontsTexture()
|
|
||||||
{
|
|
||||||
// Build texture atlas
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData();
|
|
||||||
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;
|
|
||||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
|
||||||
glGenTextures(1, &bd->FontTexture);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, bd->FontTexture);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
|
||||||
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
|
|
||||||
glBindTexture(GL_TEXTURE_2D, last_texture);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGui_ImplOpenGL2_DestroyFontsTexture()
|
|
||||||
{
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData();
|
|
||||||
if (bd->FontTexture)
|
|
||||||
{
|
|
||||||
glDeleteTextures(1, &bd->FontTexture);
|
|
||||||
io.Fonts->SetTexID(0);
|
|
||||||
bd->FontTexture = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ImGui_ImplOpenGL2_CreateDeviceObjects()
|
|
||||||
{
|
|
||||||
return ImGui_ImplOpenGL2_CreateFontsTexture();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGui_ImplOpenGL2_DestroyDeviceObjects()
|
|
||||||
{
|
|
||||||
ImGui_ImplOpenGL2_DestroyFontsTexture();
|
|
||||||
}
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
// dear imgui: Renderer Backend for OpenGL2 (legacy OpenGL, fixed pipeline)
|
|
||||||
// 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!
|
|
||||||
|
|
||||||
// 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.
|
|
||||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
|
||||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
|
||||||
|
|
||||||
// **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)**
|
|
||||||
// **Prefer using the code in imgui_impl_opengl3.cpp**
|
|
||||||
// This code is mostly provided as a reference to learn how ImGui integration works, because it is shorter to read.
|
|
||||||
// If your code is using GL3+ context or any semi modern OpenGL calls, using this is likely to make everything more
|
|
||||||
// complicated, will require your code to reset every single OpenGL attributes to their initial state, and might
|
|
||||||
// confuse your GPU driver.
|
|
||||||
// The GL2 code is unable to reset attributes or even call e.g. "glUseProgram(0)" because they don't exist in that API.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "imgui.h" // IMGUI_IMPL_API
|
|
||||||
|
|
||||||
IMGUI_IMPL_API bool ImGui_ImplOpenGL2_Init();
|
|
||||||
IMGUI_IMPL_API void ImGui_ImplOpenGL2_Shutdown();
|
|
||||||
IMGUI_IMPL_API void ImGui_ImplOpenGL2_NewFrame();
|
|
||||||
IMGUI_IMPL_API void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data);
|
|
||||||
|
|
||||||
// Called by Init/NewFrame/Shutdown
|
|
||||||
IMGUI_IMPL_API bool ImGui_ImplOpenGL2_CreateFontsTexture();
|
|
||||||
IMGUI_IMPL_API void ImGui_ImplOpenGL2_DestroyFontsTexture();
|
|
||||||
IMGUI_IMPL_API bool ImGui_ImplOpenGL2_CreateDeviceObjects();
|
|
||||||
IMGUI_IMPL_API void ImGui_ImplOpenGL2_DestroyDeviceObjects();
|
|
||||||
|
|
@ -1,890 +0,0 @@
|
||||||
// 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: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bit indices.
|
|
||||||
|
|
||||||
// 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.
|
|
||||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
|
||||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
|
||||||
|
|
||||||
// CHANGELOG
|
|
||||||
// (minor and older changes stripped away, please see git history for details)
|
|
||||||
// 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: Fix 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"
|
|
||||||
#include "imgui_impl_opengl3.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
|
|
||||||
#include <stddef.h> // intptr_t
|
|
||||||
#else
|
|
||||||
#include <stdint.h> // intptr_t
|
|
||||||
#endif
|
|
||||||
#if defined(__APPLE__)
|
|
||||||
#include <TargetConditionals.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// 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
|
|
||||||
|
|
||||||
// GL includes
|
|
||||||
#if defined(IMGUI_IMPL_OPENGL_ES2)
|
|
||||||
#if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV))
|
|
||||||
#include <OpenGLES/ES2/gl.h> // Use GL ES 2
|
|
||||||
#else
|
|
||||||
#include <GLES2/gl2.h> // Use GL ES 2
|
|
||||||
#endif
|
|
||||||
#if defined(__EMSCRIPTEN__)
|
|
||||||
#ifndef GL_GLEXT_PROTOTYPES
|
|
||||||
#define GL_GLEXT_PROTOTYPES
|
|
||||||
#endif
|
|
||||||
#include <GLES2/gl2ext.h>
|
|
||||||
#endif
|
|
||||||
#elif defined(IMGUI_IMPL_OPENGL_ES3)
|
|
||||||
#if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV))
|
|
||||||
#include <OpenGLES/ES3/gl.h> // Use GL ES 3
|
|
||||||
#else
|
|
||||||
#include <GLES3/gl3.h> // 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+ has 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 <stdio.h>
|
|
||||||
#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.
|
|
||||||
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)
|
|
||||||
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 "<major>.<minor>"
|
|
||||||
const char* gl_version = (const char*)glGetString(GL_VERSION);
|
|
||||||
sscanf(gl_version, "%d.%d", &major, &minor);
|
|
||||||
}
|
|
||||||
bd->GlVersion = (GLuint)(major * 100 + minor * 10);
|
|
||||||
|
|
||||||
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
|
|
||||||
*/
|
|
||||||
#else
|
|
||||||
bd->GlVersion = 200; // GLES 2
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef IMGUI_IMPL_OPENGL_DEBUG
|
|
||||||
printf("GL_MAJOR_VERSION = %d\nGL_MINOR_VERSION = %d\nGL_VENDOR = '%s'\nGL_RENDERER = '%s'\n", major, minor, (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;
|
|
||||||
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)
|
|
||||||
glBindSampler(0, 0); // We use combined texture/sampler state. Applications using GL 3.3 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*)IM_OFFSETOF(ImDrawVert, pos)));
|
|
||||||
GL_CALL(glVertexAttribPointer(bd->AttribLocationVtxUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv)));
|
|
||||||
GL_CALL(glVertexAttribPointer(bd->AttribLocationVtxColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)IM_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) { 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
|
|
||||||
glUseProgram(last_program);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, last_texture);
|
|
||||||
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
|
|
||||||
if (bd->GlVersion >= 330)
|
|
||||||
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
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0]);
|
|
||||||
#endif
|
|
||||||
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<char> 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<char> 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(__clang__)
|
|
||||||
#pragma clang diagnostic pop
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
||||||
// 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: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bit indices.
|
|
||||||
|
|
||||||
// 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.
|
|
||||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
|
||||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
|
||||||
|
|
||||||
// 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
|
|
||||||
|
|
||||||
// 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 <TargetConditionals.h>
|
|
||||||
#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
|
|
||||||
|
|
@ -1,794 +0,0 @@
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// 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 <stdint.h>
|
|
||||||
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 <windows.h>
|
|
||||||
#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 <GL/glcorearb.h>.
|
|
||||||
**
|
|
||||||
** 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 <GL/glcorearb.h> and either of <GL/gl.h> or
|
|
||||||
** <GL/glext.h> 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_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 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 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;
|
|
||||||
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 GL3WProcs {
|
|
||||||
GL3WglProc ptr[58];
|
|
||||||
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;
|
|
||||||
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 GL3WProcs 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 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 <stdlib.h>
|
|
||||||
|
|
||||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
#ifndef WIN32_LEAN_AND_MEAN
|
|
||||||
#define WIN32_LEAN_AND_MEAN 1
|
|
||||||
#endif
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
static HMODULE libgl;
|
|
||||||
typedef PROC(__stdcall* GL3WglGetProcAddr)(LPCSTR);
|
|
||||||
static GL3WglGetProcAddr wgl_get_proc_address;
|
|
||||||
|
|
||||||
static int open_libgl(void)
|
|
||||||
{
|
|
||||||
libgl = LoadLibraryExA("opengl32.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
|
|
||||||
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 <dlfcn.h>
|
|
||||||
|
|
||||||
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 <dlfcn.h>
|
|
||||||
|
|
||||||
static void *libgl;
|
|
||||||
static GL3WglProc (*glx_get_proc_address)(const GLubyte *);
|
|
||||||
|
|
||||||
static int open_libgl(void)
|
|
||||||
{
|
|
||||||
libgl = dlopen("libGL.so.1", 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 < 3)
|
|
||||||
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 < 3)
|
|
||||||
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",
|
|
||||||
"glLinkProgram",
|
|
||||||
"glPixelStorei",
|
|
||||||
"glPolygonMode",
|
|
||||||
"glReadPixels",
|
|
||||||
"glScissor",
|
|
||||||
"glShaderSource",
|
|
||||||
"glTexImage2D",
|
|
||||||
"glTexParameteri",
|
|
||||||
"glUniform1i",
|
|
||||||
"glUniformMatrix4fv",
|
|
||||||
"glUseProgram",
|
|
||||||
"glVertexAttribPointer",
|
|
||||||
"glViewport",
|
|
||||||
};
|
|
||||||
|
|
||||||
GL3W_API union GL3WProcs imgl3wProcs;
|
|
||||||
|
|
||||||
static void load_procs(GL3WGetProcAddressProc proc)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
for (i = 0; i < ARRAY_SIZE(proc_names); i++)
|
|
||||||
imgl3wProcs.ptr[i] = proc(proc_names[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,120 +0,0 @@
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// COMPILE-TIME OPTIONS FOR DEAR IMGUI
|
|
||||||
// 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 files 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.
|
|
||||||
// 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 avoid using soon-to-be 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 will be folded into IMGUI_DISABLE_OBSOLETE_FUNCTIONS in a few versions.
|
|
||||||
|
|
||||||
//---- 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 ShowStackToolWindow() will be empty (this was called IMGUI_DISABLE_METRICS_WINDOW before 1.88).
|
|
||||||
|
|
||||||
//---- 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
|
|
||||||
//#define IMGUI_INCLUDE_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 enabled
|
|
||||||
//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
|
|
||||||
//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
|
|
||||||
|
|
||||||
//---- 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 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); }
|
|
||||||
*/
|
|
||||||
|
|
||||||
//---- 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
|
|
||||||
// (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, here or in your own headers files.
|
|
||||||
/*
|
|
||||||
namespace ImGui
|
|
||||||
{
|
|
||||||
void MyFunction(const char* name, const MyMatrix44& v);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
14238
Framework/external/embree/tutorials/common/imgui/imgui.cpp
vendored
14238
Framework/external/embree/tutorials/common/imgui/imgui.cpp
vendored
File diff suppressed because it is too large
Load diff
3078
Framework/external/embree/tutorials/common/imgui/imgui.h
vendored
3078
Framework/external/embree/tutorials/common/imgui/imgui.h
vendored
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,627 +0,0 @@
|
||||||
// [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 <stdlib.h>
|
|
||||||
#define STBRP_SORT qsort
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef STBRP_ASSERT
|
|
||||||
#include <assert.h>
|
|
||||||
#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.
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,44 +0,0 @@
|
||||||
## Copyright 2009-2021 Intel Corporation
|
|
||||||
## SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
ADD_LIBRARY(lights STATIC
|
|
||||||
light.cpp
|
|
||||||
ambient_light.cpp
|
|
||||||
directional_light.cpp
|
|
||||||
point_light.cpp
|
|
||||||
quad_light.cpp
|
|
||||||
spot_light.cpp
|
|
||||||
)
|
|
||||||
TARGET_LINK_LIBRARIES(lights sys math)
|
|
||||||
SET_PROPERTY(TARGET lights PROPERTY FOLDER tutorials/common)
|
|
||||||
SET_PROPERTY(TARGET lights APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}")
|
|
||||||
|
|
||||||
IF (EMBREE_SYCL_SUPPORT)
|
|
||||||
ADD_LIBRARY(lights_sycl STATIC
|
|
||||||
light.cpp
|
|
||||||
ambient_light.cpp
|
|
||||||
directional_light.cpp
|
|
||||||
point_light.cpp
|
|
||||||
quad_light.cpp
|
|
||||||
spot_light.cpp
|
|
||||||
)
|
|
||||||
TARGET_LINK_LIBRARIES(lights_sycl sys math)
|
|
||||||
SET_PROPERTY(TARGET lights_sycl PROPERTY FOLDER tutorials/common)
|
|
||||||
SET_PROPERTY(TARGET lights_sycl APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST} ${CMAKE_CXX_FLAGS_SYCL}")
|
|
||||||
TARGET_COMPILE_DEFINITIONS(lights_sycl PUBLIC EMBREE_SYCL_TUTORIAL)
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
IF (EMBREE_ISPC_SUPPORT)
|
|
||||||
ADD_ISPC_LIBRARY(lights_ispc STATIC
|
|
||||||
light.ispc
|
|
||||||
ambient_light.ispc
|
|
||||||
directional_light.ispc
|
|
||||||
point_light.ispc
|
|
||||||
quad_light.ispc
|
|
||||||
spot_light.ispc
|
|
||||||
)
|
|
||||||
TARGET_LINK_LIBRARIES(lights_ispc sys math)
|
|
||||||
SET_TARGET_PROPERTIES(lights_ispc PROPERTIES LINKER_LANGUAGE CXX)
|
|
||||||
SET_PROPERTY(TARGET lights_ispc PROPERTY FOLDER tutorials/common)
|
|
||||||
SET_PROPERTY(TARGET lights_ispc APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}")
|
|
||||||
ENDIF()
|
|
||||||
|
|
@ -1,84 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#include "light.h"
|
|
||||||
#include "../math/sampling.h"
|
|
||||||
#include "../math/linearspace.h"
|
|
||||||
|
|
||||||
namespace embree {
|
|
||||||
|
|
||||||
struct AmbientLight
|
|
||||||
{
|
|
||||||
Light super; //!< inherited light fields
|
|
||||||
|
|
||||||
Vec3fa radiance; //!< RGB color and intensity of light
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Implementation
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// XXX importance sampling is only done into the positive hemisphere
|
|
||||||
// ==> poor support for translucent materials
|
|
||||||
SYCL_EXTERNAL Light_SampleRes AmbientLight_sample(const Light* super,
|
|
||||||
const DifferentialGeometry& dg,
|
|
||||||
const Vec2f& s)
|
|
||||||
{
|
|
||||||
AmbientLight* self = (AmbientLight*)super;
|
|
||||||
Light_SampleRes res;
|
|
||||||
|
|
||||||
const Vec3fa localDir = cosineSampleHemisphere(s);
|
|
||||||
res.dir = frame(dg.Ns) * localDir;
|
|
||||||
res.pdf = cosineSampleHemispherePDF(localDir);
|
|
||||||
res.dist = inf;
|
|
||||||
res.weight = self->radiance * rcp(res.pdf);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
SYCL_EXTERNAL Light_EvalRes AmbientLight_eval(const Light* super,
|
|
||||||
const DifferentialGeometry& dg,
|
|
||||||
const Vec3fa& dir)
|
|
||||||
{
|
|
||||||
AmbientLight* self = (AmbientLight*)super;
|
|
||||||
Light_EvalRes res;
|
|
||||||
|
|
||||||
res.value = self->radiance;
|
|
||||||
res.dist = inf;
|
|
||||||
res.pdf = cosineSampleHemispherePDF(max(dot(dg.Ns, dir), 0.f));
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void AmbientLight_Constructor(AmbientLight* self,
|
|
||||||
const Vec3fa& radiance)
|
|
||||||
{
|
|
||||||
Light_Constructor(&self->super);
|
|
||||||
self->radiance = radiance;
|
|
||||||
//self->super.sample = GET_FUNCTION_POINTER(AmbientLight_sample);
|
|
||||||
//self->super.eval = GET_FUNCTION_POINTER(AmbientLight_eval);
|
|
||||||
self->super.type = LIGHT_AMBIENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Exports (called from C++)
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
//! Create an ispc-side AmbientLight object
|
|
||||||
extern "C" void *AmbientLight_create()
|
|
||||||
{
|
|
||||||
AmbientLight* self = (AmbientLight*) alignedUSMMalloc(sizeof(AmbientLight),16);
|
|
||||||
AmbientLight_Constructor(self, Vec3fa(1.f));
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Set the parameters of an ispc-side AmbientLight object
|
|
||||||
extern "C" void AmbientLight_set(void* super,
|
|
||||||
const Vec3fa& radiance)
|
|
||||||
{
|
|
||||||
AmbientLight* self = (AmbientLight*)super;
|
|
||||||
self->radiance = radiance;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace embree
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../math/vec.h"
|
|
||||||
|
|
||||||
namespace embree
|
|
||||||
{
|
|
||||||
extern "C" void* AmbientLight_create();
|
|
||||||
|
|
||||||
extern "C" void AmbientLight_set(void* super,
|
|
||||||
const Vec3fa& radiance);
|
|
||||||
|
|
||||||
extern "C" void Light_destroy(Light* light);
|
|
||||||
}
|
|
||||||
|
|
@ -1,80 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#include "light.isph"
|
|
||||||
#include "../math/sampling.isph"
|
|
||||||
#include "../math/linearspace.isph"
|
|
||||||
|
|
||||||
struct AmbientLight
|
|
||||||
{
|
|
||||||
Light super; //!< inherited light fields
|
|
||||||
|
|
||||||
Vec3f radiance; //!< RGB color and intensity of light
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Implementation
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// XXX importance sampling is only done into the positive hemisphere
|
|
||||||
// ==> poor support for translucent materials
|
|
||||||
SYCL_EXTERNAL Light_SampleRes AmbientLight_sample(const uniform Light* uniform super,
|
|
||||||
const DifferentialGeometry& dg,
|
|
||||||
const Vec2f& s)
|
|
||||||
{
|
|
||||||
uniform AmbientLight* uniform self = (uniform AmbientLight* uniform)super;
|
|
||||||
Light_SampleRes res;
|
|
||||||
|
|
||||||
const Vec3f localDir = cosineSampleHemisphere(s);
|
|
||||||
res.dir = frame(dg.Ns) * localDir;
|
|
||||||
res.pdf = cosineSampleHemispherePDF(localDir);
|
|
||||||
res.dist = inf;
|
|
||||||
res.weight = self->radiance * rcp(res.pdf);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
SYCL_EXTERNAL Light_EvalRes AmbientLight_eval(const uniform Light* uniform super,
|
|
||||||
const DifferentialGeometry& dg,
|
|
||||||
const Vec3f& dir)
|
|
||||||
{
|
|
||||||
uniform AmbientLight* uniform self = (uniform AmbientLight* uniform)super;
|
|
||||||
Light_EvalRes res;
|
|
||||||
|
|
||||||
res.value = self->radiance;
|
|
||||||
res.dist = inf;
|
|
||||||
res.pdf = cosineSampleHemispherePDF(max(dot(dg.Ns, dir), 0.f));
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void AmbientLight_Constructor(uniform AmbientLight* uniform self,
|
|
||||||
const uniform Vec3f& radiance)
|
|
||||||
{
|
|
||||||
Light_Constructor(&self->super);
|
|
||||||
self->radiance = radiance;
|
|
||||||
//self->super.sample = GET_FUNCTION_POINTER(AmbientLight_sample);
|
|
||||||
//self->super.eval = GET_FUNCTION_POINTER(AmbientLight_eval);
|
|
||||||
self->super.type = LIGHT_AMBIENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Exports (called from C++)
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
//! Create an ispc-side AmbientLight object
|
|
||||||
export void *uniform AmbientLight_create()
|
|
||||||
{
|
|
||||||
uniform AmbientLight* uniform self = uniform new uniform AmbientLight;
|
|
||||||
AmbientLight_Constructor(self, make_Vec3f(1.f));
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Set the parameters of an ispc-side AmbientLight object
|
|
||||||
export void AmbientLight_set(void* uniform super,
|
|
||||||
const uniform Vec3f& radiance)
|
|
||||||
{
|
|
||||||
uniform AmbientLight* uniform self = (uniform AmbientLight* uniform)super;
|
|
||||||
self->radiance = radiance;
|
|
||||||
}
|
|
||||||
|
|
@ -1,95 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#include "light.h"
|
|
||||||
#include "../math/sampling.h"
|
|
||||||
#include "../math/linearspace.h"
|
|
||||||
|
|
||||||
namespace embree {
|
|
||||||
|
|
||||||
struct DirectionalLight
|
|
||||||
{
|
|
||||||
Light super; //!< inherited light fields
|
|
||||||
|
|
||||||
LinearSpace3fa frame; //!< coordinate frame, with vz == direction *towards* the light source
|
|
||||||
Vec3fa radiance; //!< RGB color and intensity of 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
|
|
||||||
};
|
|
||||||
|
|
||||||
// for very small cones treat as singular light, because float precision is not good enough
|
|
||||||
#define COS_ANGLE_MAX 0.99999988f
|
|
||||||
|
|
||||||
|
|
||||||
// Implementation
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
SYCL_EXTERNAL Light_SampleRes DirectionalLight_sample(const Light* super,
|
|
||||||
const DifferentialGeometry& dg,
|
|
||||||
const Vec2f& s)
|
|
||||||
{
|
|
||||||
const DirectionalLight* self = (DirectionalLight*)super;
|
|
||||||
Light_SampleRes res;
|
|
||||||
|
|
||||||
res.dir = self->frame.vz;
|
|
||||||
res.dist = inf;
|
|
||||||
res.pdf = self->pdf;
|
|
||||||
|
|
||||||
if (self->cosAngle < COS_ANGLE_MAX)
|
|
||||||
res.dir = self->frame * uniformSampleCone(self->cosAngle, s);
|
|
||||||
|
|
||||||
res.weight = self->radiance; // *pdf/pdf cancel
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
SYCL_EXTERNAL Light_EvalRes DirectionalLight_eval(const Light* super,
|
|
||||||
const DifferentialGeometry&,
|
|
||||||
const Vec3fa& dir)
|
|
||||||
{
|
|
||||||
DirectionalLight* self = (DirectionalLight*)super;
|
|
||||||
Light_EvalRes res;
|
|
||||||
res.dist = inf;
|
|
||||||
|
|
||||||
if (self->cosAngle < COS_ANGLE_MAX && dot(self->frame.vz, dir) > self->cosAngle) {
|
|
||||||
res.value = self->radiance * self->pdf;
|
|
||||||
res.pdf = self->pdf;
|
|
||||||
} else {
|
|
||||||
res.value = Vec3fa(0.f);
|
|
||||||
res.pdf = 0.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Exports (called from C++)
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
//! Set the parameters of an ispc-side DirectionalLight object
|
|
||||||
extern "C" void DirectionalLight_set(void* super,
|
|
||||||
const Vec3fa& direction,
|
|
||||||
const Vec3fa& radiance,
|
|
||||||
float cosAngle)
|
|
||||||
{
|
|
||||||
DirectionalLight* self = (DirectionalLight*)super;
|
|
||||||
self->frame = frame(direction);
|
|
||||||
self->radiance = radiance;
|
|
||||||
self->cosAngle = cosAngle;
|
|
||||||
self->pdf = cosAngle < COS_ANGLE_MAX ? uniformSampleConePDF(cosAngle) : inf;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Create an ispc-side DirectionalLight object
|
|
||||||
extern "C" void* DirectionalLight_create()
|
|
||||||
{
|
|
||||||
DirectionalLight* self = (DirectionalLight*) alignedUSMMalloc(sizeof(DirectionalLight),16);
|
|
||||||
Light_Constructor(&self->super);
|
|
||||||
//self->super.sample = GET_FUNCTION_POINTER(DirectionalLight_sample);
|
|
||||||
//self->super.eval = GET_FUNCTION_POINTER(DirectionalLight_eval);
|
|
||||||
self->super.type = LIGHT_DIRECTIONAL;
|
|
||||||
|
|
||||||
DirectionalLight_set(self, Vec3fa(0.f, 0.f, 1.f), Vec3fa(1.f), 1.f);
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace embree
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../math/vec.h"
|
|
||||||
|
|
||||||
namespace embree
|
|
||||||
{
|
|
||||||
extern "C" void* DirectionalLight_create();
|
|
||||||
|
|
||||||
extern "C" void DirectionalLight_set(void* super,
|
|
||||||
const Vec3fa& direction,
|
|
||||||
const Vec3fa& radiance,
|
|
||||||
float cosAngle);
|
|
||||||
}
|
|
||||||
|
|
@ -1,91 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#include "light.isph"
|
|
||||||
#include "../math/sampling.isph"
|
|
||||||
#include "../math/linearspace.isph"
|
|
||||||
|
|
||||||
struct DirectionalLight
|
|
||||||
{
|
|
||||||
Light super; //!< inherited light fields
|
|
||||||
|
|
||||||
LinearSpace3f frame; //!< coordinate frame, with vz == direction *towards* the light source
|
|
||||||
Vec3f radiance; //!< RGB color and intensity of 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
|
|
||||||
};
|
|
||||||
|
|
||||||
// for very small cones treat as singular light, because float precision is not good enough
|
|
||||||
#define COS_ANGLE_MAX 0.99999988f
|
|
||||||
|
|
||||||
|
|
||||||
// Implementation
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
SYCL_EXTERNAL Light_SampleRes DirectionalLight_sample(const uniform Light* uniform super,
|
|
||||||
const DifferentialGeometry& dg,
|
|
||||||
const Vec2f& s)
|
|
||||||
{
|
|
||||||
const DirectionalLight* uniform self = (DirectionalLight* uniform)super;
|
|
||||||
Light_SampleRes res;
|
|
||||||
|
|
||||||
res.dir = self->frame.vz;
|
|
||||||
res.dist = inf;
|
|
||||||
res.pdf = self->pdf;
|
|
||||||
|
|
||||||
if (self->cosAngle < COS_ANGLE_MAX)
|
|
||||||
res.dir = self->frame * uniformSampleCone(self->cosAngle, s);
|
|
||||||
|
|
||||||
res.weight = self->radiance; // *pdf/pdf cancel
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
SYCL_EXTERNAL Light_EvalRes DirectionalLight_eval(const uniform Light* uniform super,
|
|
||||||
const DifferentialGeometry&,
|
|
||||||
const Vec3f& dir)
|
|
||||||
{
|
|
||||||
uniform DirectionalLight* uniform self = (uniform DirectionalLight* uniform)super;
|
|
||||||
Light_EvalRes res;
|
|
||||||
res.dist = inf;
|
|
||||||
|
|
||||||
if (self->cosAngle < COS_ANGLE_MAX && dot(self->frame.vz, dir) > self->cosAngle) {
|
|
||||||
res.value = self->radiance * self->pdf;
|
|
||||||
res.pdf = self->pdf;
|
|
||||||
} else {
|
|
||||||
res.value = make_Vec3f(0.f);
|
|
||||||
res.pdf = 0.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Exports (called from C++)
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
//! Set the parameters of an ispc-side DirectionalLight object
|
|
||||||
export void DirectionalLight_set(void* uniform super,
|
|
||||||
const uniform Vec3f& direction,
|
|
||||||
const uniform Vec3f& radiance,
|
|
||||||
uniform float cosAngle)
|
|
||||||
{
|
|
||||||
uniform DirectionalLight* uniform self = (uniform DirectionalLight* uniform)super;
|
|
||||||
self->frame = frame(direction);
|
|
||||||
self->radiance = radiance;
|
|
||||||
self->cosAngle = cosAngle;
|
|
||||||
self->pdf = cosAngle < COS_ANGLE_MAX ? uniformSampleConePDF(cosAngle) : inf;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Create an ispc-side DirectionalLight object
|
|
||||||
export void* uniform DirectionalLight_create()
|
|
||||||
{
|
|
||||||
uniform DirectionalLight* uniform self = uniform new uniform DirectionalLight;
|
|
||||||
Light_Constructor(&self->super);
|
|
||||||
//self->super.sample = GET_FUNCTION_POINTER(DirectionalLight_sample);
|
|
||||||
//self->super.eval = GET_FUNCTION_POINTER(DirectionalLight_eval);
|
|
||||||
self->super.type = LIGHT_DIRECTIONAL;
|
|
||||||
|
|
||||||
DirectionalLight_set(self, make_Vec3f(0.f, 0.f, 1.f), make_Vec3f(1.f), 1.f);
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#include "light.h"
|
|
||||||
|
|
||||||
namespace embree {
|
|
||||||
|
|
||||||
SYCL_EXTERNAL Light_EvalRes Light_eval(const Light* uniform,
|
|
||||||
const DifferentialGeometry&,
|
|
||||||
const Vec3fa&)
|
|
||||||
{
|
|
||||||
Light_EvalRes res;
|
|
||||||
res.value = Vec3fa(0.f);
|
|
||||||
res.dist = inf;
|
|
||||||
res.pdf = 0.f;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void Light_destroy(Light* light)
|
|
||||||
{
|
|
||||||
alignedUSMFree(light);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void dummy() {} // just to avoid linker warning under MacOSX
|
|
||||||
|
|
||||||
} // namespace embree
|
|
||||||
|
|
@ -1,67 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../device_default.h"
|
|
||||||
#include "../core/differential_geometry.h"
|
|
||||||
|
|
||||||
namespace embree {
|
|
||||||
|
|
||||||
struct Light;
|
|
||||||
|
|
||||||
enum TutorialLightType
|
|
||||||
{
|
|
||||||
LIGHT_AMBIENT,
|
|
||||||
LIGHT_POINT,
|
|
||||||
LIGHT_DIRECTIONAL,
|
|
||||||
LIGHT_SPOT,
|
|
||||||
LIGHT_DISTANT,
|
|
||||||
LIGHT_TRIANGLE,
|
|
||||||
LIGHT_QUAD,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Light_SampleRes
|
|
||||||
{
|
|
||||||
Vec3fa weight; //!< radiance that arrives at the given point divided by pdf
|
|
||||||
Vec3fa dir; //!< direction towards the light source
|
|
||||||
float dist; //!< largest valid t_far value for a shadow ray
|
|
||||||
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 OBJ renderer)
|
|
||||||
typedef Light_SampleRes (*Light_SampleFunc)(const Light* self,
|
|
||||||
const DifferentialGeometry& dg, /*! point to generate the sample for >*/
|
|
||||||
const Vec2f& s); /*! random numbers to generate the sample >*/
|
|
||||||
|
|
||||||
|
|
||||||
struct Light_EvalRes
|
|
||||||
{
|
|
||||||
Vec3fa value; //!< radiance that arrives at the given point (not weighted by pdf)
|
|
||||||
float dist;
|
|
||||||
float pdf; //!< probability density that the direction would have been sampled
|
|
||||||
};
|
|
||||||
|
|
||||||
//! compute the radiance, distance and pdf caused by the light source (pointed to by the given direction)
|
|
||||||
typedef Light_EvalRes (*Light_EvalFunc)(const Light* self,
|
|
||||||
const DifferentialGeometry& dg, /*! point to evaluate illumination for >*/
|
|
||||||
const Vec3fa& dir); /*! direction towards the light source >*/
|
|
||||||
|
|
||||||
|
|
||||||
struct Light
|
|
||||||
{
|
|
||||||
//Light_SampleFunc sample;
|
|
||||||
//Light_EvalFunc eval;
|
|
||||||
TutorialLightType type;
|
|
||||||
};
|
|
||||||
|
|
||||||
SYCL_EXTERNAL Light_EvalRes Light_eval(const Light* self, const DifferentialGeometry& dg, const Vec3fa& dir);
|
|
||||||
|
|
||||||
inline void Light_Constructor(Light* self)
|
|
||||||
{
|
|
||||||
//self->eval = GET_FUNCTION_POINTER(Light_eval);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace embree
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#include "light.isph"
|
|
||||||
|
|
||||||
SYCL_EXTERNAL Light_EvalRes Light_eval(const uniform Light* uniform,
|
|
||||||
const DifferentialGeometry&,
|
|
||||||
const Vec3f&)
|
|
||||||
{
|
|
||||||
Light_EvalRes res;
|
|
||||||
res.value = make_Vec3f(0.f);
|
|
||||||
res.dist = inf;
|
|
||||||
res.pdf = 0.f;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
export void Light_destroy(Light* uniform light)
|
|
||||||
{
|
|
||||||
delete light;
|
|
||||||
}
|
|
||||||
|
|
||||||
export void dummy() {} // just to avoid linker warning under MacOSX
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../device_default.isph"
|
|
||||||
#include "../core/differential_geometry.isph"
|
|
||||||
|
|
||||||
struct Light;
|
|
||||||
|
|
||||||
enum TutorialLightType
|
|
||||||
{
|
|
||||||
LIGHT_AMBIENT,
|
|
||||||
LIGHT_POINT,
|
|
||||||
LIGHT_DIRECTIONAL,
|
|
||||||
LIGHT_SPOT,
|
|
||||||
LIGHT_DISTANT,
|
|
||||||
LIGHT_TRIANGLE,
|
|
||||||
LIGHT_QUAD,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Light_SampleRes
|
|
||||||
{
|
|
||||||
Vec3f weight; //!< radiance that arrives at the given point divided by pdf
|
|
||||||
Vec3f dir; //!< direction towards the light source
|
|
||||||
float dist; //!< largest valid t_far value for a shadow ray
|
|
||||||
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 OBJ renderer)
|
|
||||||
typedef Light_SampleRes (*Light_SampleFunc)(const uniform Light* uniform self,
|
|
||||||
const DifferentialGeometry& dg, /*! point to generate the sample for >*/
|
|
||||||
const Vec2f& s); /*! random numbers to generate the sample >*/
|
|
||||||
|
|
||||||
|
|
||||||
struct Light_EvalRes
|
|
||||||
{
|
|
||||||
Vec3f value; //!< radiance that arrives at the given point (not weighted by pdf)
|
|
||||||
float dist;
|
|
||||||
float pdf; //!< probability density that the direction would have been sampled
|
|
||||||
};
|
|
||||||
|
|
||||||
//! compute the radiance, distance and pdf caused by the light source (pointed to by the given direction)
|
|
||||||
typedef Light_EvalRes (*Light_EvalFunc)(const uniform Light* uniform self,
|
|
||||||
const DifferentialGeometry& dg, /*! point to evaluate illumination for >*/
|
|
||||||
const Vec3f& dir); /*! direction towards the light source >*/
|
|
||||||
|
|
||||||
|
|
||||||
struct Light
|
|
||||||
{
|
|
||||||
//Light_SampleFunc sample;
|
|
||||||
//Light_EvalFunc eval;
|
|
||||||
TutorialLightType type;
|
|
||||||
};
|
|
||||||
|
|
||||||
SYCL_EXTERNAL Light_EvalRes Light_eval(const uniform Light* uniform self, const DifferentialGeometry& dg, const Vec3f& dir);
|
|
||||||
|
|
||||||
inline void Light_Constructor(uniform Light* uniform self)
|
|
||||||
{
|
|
||||||
//self->eval = GET_FUNCTION_POINTER(Light_eval);
|
|
||||||
}
|
|
||||||
|
|
@ -1,134 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#include "light.h"
|
|
||||||
#include "../math/sampling.h"
|
|
||||||
#include "../math/linearspace.h"
|
|
||||||
|
|
||||||
namespace embree {
|
|
||||||
|
|
||||||
struct PointLight
|
|
||||||
{
|
|
||||||
Light super; //!< inherited light fields
|
|
||||||
|
|
||||||
Vec3fa position; //!< light position
|
|
||||||
Vec3fa power; //!< RGB color and intensity of light
|
|
||||||
float radius; //!< defines the size of the SphereLight
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Implementation
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
SYCL_EXTERNAL Light_SampleRes PointLight_sample(const Light* super,
|
|
||||||
const DifferentialGeometry& dg,
|
|
||||||
const Vec2f& s)
|
|
||||||
{
|
|
||||||
const PointLight* self = (PointLight*)super;
|
|
||||||
Light_SampleRes res;
|
|
||||||
|
|
||||||
// extant light vector from the hit point
|
|
||||||
const Vec3fa dir = self->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 res
|
|
||||||
|
|
||||||
// convert from power to radiance by attenuating by distance^2
|
|
||||||
res.weight = self->power * sqr(invdist);
|
|
||||||
const float sinTheta = self->radius * invdist;
|
|
||||||
|
|
||||||
if ((self->radius > 0.f) & (sinTheta > 0.005f)) {
|
|
||||||
// res 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 Vec3fa 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(sqr(self->radius) - (1.f - c*c) * dist2);
|
|
||||||
// TODO scale radiance by actual distance
|
|
||||||
} else { // inside sphere
|
|
||||||
const Vec3fa localDir = cosineSampleHemisphere(s);
|
|
||||||
res.dir = frame(dg.Ns) * localDir;
|
|
||||||
res.pdf = cosineSampleHemispherePDF(localDir);
|
|
||||||
// TODO:
|
|
||||||
res.weight = self->power * rcp(sqr(self->radius));
|
|
||||||
res.dist = self->radius;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
SYCL_EXTERNAL Light_EvalRes PointLight_eval(const Light* super,
|
|
||||||
const DifferentialGeometry& dg,
|
|
||||||
const Vec3fa& dir)
|
|
||||||
{
|
|
||||||
const PointLight* self = (PointLight*)super;
|
|
||||||
Light_EvalRes res;
|
|
||||||
res.value = Vec3fa(0.f);
|
|
||||||
res.dist = inf;
|
|
||||||
res.pdf = 0.f;
|
|
||||||
|
|
||||||
if (self->radius > 0.f) {
|
|
||||||
const Vec3fa A = self->position - dg.P;
|
|
||||||
const float a = dot(dir, dir);
|
|
||||||
const float b = 2.f * dot(dir, A);
|
|
||||||
const float centerDist2 = dot(A, A);
|
|
||||||
const float c = centerDist2 - sqr(self->radius);
|
|
||||||
const float radical = sqr(b) - 4.f*a*c;
|
|
||||||
|
|
||||||
if (radical > 0.f) {
|
|
||||||
const float t_near = (b - sqrt(radical)) / (2.f*a);
|
|
||||||
const float t_far = (b + sqrt(radical)) / (2.f*a);
|
|
||||||
|
|
||||||
if (t_far > 0.0f) {
|
|
||||||
// TODO: handle interior case
|
|
||||||
res.dist = t_near;
|
|
||||||
const float sinTheta2 = sqr(self->radius) * rcp(centerDist2);
|
|
||||||
const float cosTheta = sqrt(1.f - sinTheta2);
|
|
||||||
res.pdf = uniformSampleConePDF(cosTheta);
|
|
||||||
const float invdist = rcp(t_near);
|
|
||||||
res.value = self->power * res.pdf * sqr(invdist);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exports (called from C++)
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
//! Set the parameters of an ispc-side PointLight object
|
|
||||||
extern "C" void PointLight_set(void* super,
|
|
||||||
const Vec3fa& position,
|
|
||||||
const Vec3fa& power,
|
|
||||||
float radius)
|
|
||||||
{
|
|
||||||
PointLight* self = (PointLight*)super;
|
|
||||||
self->position = position;
|
|
||||||
self->power = power;
|
|
||||||
self->radius = radius;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Create an ispc-side PointLight object
|
|
||||||
extern "C" void* PointLight_create()
|
|
||||||
{
|
|
||||||
PointLight* self = (PointLight*) alignedUSMMalloc(sizeof(PointLight),16);
|
|
||||||
Light_Constructor(&self->super);
|
|
||||||
//self->super.sample = GET_FUNCTION_POINTER(PointLight_sample);
|
|
||||||
//self->super.eval = GET_FUNCTION_POINTER(PointLight_eval);
|
|
||||||
self->super.type = LIGHT_POINT;
|
|
||||||
|
|
||||||
PointLight_set(self, Vec3fa(0.f), Vec3fa(1.f), 0.f);
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace embree
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../math/vec.h"
|
|
||||||
|
|
||||||
namespace embree
|
|
||||||
{
|
|
||||||
extern "C" void* PointLight_create();
|
|
||||||
|
|
||||||
extern "C" void PointLight_set(void* super,
|
|
||||||
const Vec3fa& position,
|
|
||||||
const Vec3fa& power,
|
|
||||||
float radius);
|
|
||||||
}
|
|
||||||
|
|
@ -1,130 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#include "light.isph"
|
|
||||||
#include "../math/sampling.isph"
|
|
||||||
#include "../math/linearspace.isph"
|
|
||||||
|
|
||||||
struct PointLight
|
|
||||||
{
|
|
||||||
Light super; //!< inherited light fields
|
|
||||||
|
|
||||||
Vec3f position; //!< light position
|
|
||||||
Vec3f power; //!< RGB color and intensity of light
|
|
||||||
float radius; //!< defines the size of the SphereLight
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Implementation
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
SYCL_EXTERNAL Light_SampleRes PointLight_sample(const uniform Light* uniform super,
|
|
||||||
const DifferentialGeometry& dg,
|
|
||||||
const Vec2f& s)
|
|
||||||
{
|
|
||||||
const PointLight* uniform self = (PointLight* uniform)super;
|
|
||||||
Light_SampleRes res;
|
|
||||||
|
|
||||||
// extant light vector from the hit point
|
|
||||||
const Vec3f dir = self->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 res
|
|
||||||
|
|
||||||
// convert from power to radiance by attenuating by distance^2
|
|
||||||
res.weight = self->power * sqr(invdist);
|
|
||||||
const float sinTheta = self->radius * invdist;
|
|
||||||
|
|
||||||
if ((self->radius > 0.f) & (sinTheta > 0.005f)) {
|
|
||||||
// res 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(sqr(self->radius) - (1.f - c*c) * dist2);
|
|
||||||
// TODO scale radiance by actual distance
|
|
||||||
} else { // inside sphere
|
|
||||||
const Vec3f localDir = cosineSampleHemisphere(s);
|
|
||||||
res.dir = frame(dg.Ns) * localDir;
|
|
||||||
res.pdf = cosineSampleHemispherePDF(localDir);
|
|
||||||
// TODO:
|
|
||||||
res.weight = self->power * rcp(sqr(self->radius));
|
|
||||||
res.dist = self->radius;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
SYCL_EXTERNAL Light_EvalRes PointLight_eval(const uniform Light* uniform super,
|
|
||||||
const DifferentialGeometry& dg,
|
|
||||||
const Vec3f& dir)
|
|
||||||
{
|
|
||||||
const PointLight* uniform self = (PointLight* uniform)super;
|
|
||||||
Light_EvalRes res;
|
|
||||||
res.value = make_Vec3f(0.f);
|
|
||||||
res.dist = inf;
|
|
||||||
res.pdf = 0.f;
|
|
||||||
|
|
||||||
if (self->radius > 0.f) {
|
|
||||||
const Vec3f A = self->position - dg.P;
|
|
||||||
const float a = dot(dir, dir);
|
|
||||||
const float b = 2.f * dot(dir, A);
|
|
||||||
const float centerDist2 = dot(A, A);
|
|
||||||
const float c = centerDist2 - sqr(self->radius);
|
|
||||||
const float radical = sqr(b) - 4.f*a*c;
|
|
||||||
|
|
||||||
if (radical > 0.f) {
|
|
||||||
const float t_near = (b - sqrt(radical)) / (2.f*a);
|
|
||||||
const float t_far = (b + sqrt(radical)) / (2.f*a);
|
|
||||||
|
|
||||||
if (t_far > 0.0f) {
|
|
||||||
// TODO: handle interior case
|
|
||||||
res.dist = t_near;
|
|
||||||
const float sinTheta2 = sqr(self->radius) * rcp(centerDist2);
|
|
||||||
const float cosTheta = sqrt(1.f - sinTheta2);
|
|
||||||
res.pdf = uniformSampleConePDF(cosTheta);
|
|
||||||
const float invdist = rcp(t_near);
|
|
||||||
res.value = self->power * res.pdf * sqr(invdist);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exports (called from C++)
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
//! Set the parameters of an ispc-side PointLight object
|
|
||||||
export void PointLight_set(void* uniform super,
|
|
||||||
const uniform Vec3f& position,
|
|
||||||
const uniform Vec3f& power,
|
|
||||||
uniform float radius)
|
|
||||||
{
|
|
||||||
uniform PointLight* uniform self = (uniform PointLight* uniform)super;
|
|
||||||
self->position = position;
|
|
||||||
self->power = power;
|
|
||||||
self->radius = radius;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Create an ispc-side PointLight object
|
|
||||||
export void* uniform PointLight_create()
|
|
||||||
{
|
|
||||||
uniform PointLight* uniform self = uniform new uniform PointLight;
|
|
||||||
Light_Constructor(&self->super);
|
|
||||||
//self->super.sample = GET_FUNCTION_POINTER(PointLight_sample);
|
|
||||||
//self->super.eval = GET_FUNCTION_POINTER(PointLight_eval);
|
|
||||||
self->super.type = LIGHT_POINT;
|
|
||||||
|
|
||||||
PointLight_set(self, make_Vec3f(0.f), make_Vec3f(1.f), 0.f);
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
@ -1,106 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#include "light.h"
|
|
||||||
|
|
||||||
namespace embree {
|
|
||||||
|
|
||||||
struct QuadLight
|
|
||||||
{
|
|
||||||
Light super; //!< inherited light fields
|
|
||||||
|
|
||||||
Vec3fa position; //!< world-space corner position of the light
|
|
||||||
Vec3fa edge1; //!< vectors to adjacent corners
|
|
||||||
Vec3fa edge2; //!< vectors to adjacent corners
|
|
||||||
Vec3fa radiance; //!< RGB color and intensity of the QuadLight
|
|
||||||
|
|
||||||
Vec3fa nnormal; //!< negated normal, the direction that the QuadLight is not emitting; normalized
|
|
||||||
float ppdf; // probability to sample point on light = 1/area
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Implementation
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
SYCL_EXTERNAL Light_SampleRes QuadLight_sample(const Light* super,
|
|
||||||
const DifferentialGeometry& dg,
|
|
||||||
const Vec2f& s)
|
|
||||||
{
|
|
||||||
const QuadLight* self = (QuadLight*)super;
|
|
||||||
Light_SampleRes res;
|
|
||||||
|
|
||||||
// res position on light with density ppdf = 1/area
|
|
||||||
// TODO: use solid angle sampling
|
|
||||||
const Vec3fa pos = self->position + self->edge1 * s.x + self->edge2 * s.y;
|
|
||||||
|
|
||||||
// extant light vector from the hit point
|
|
||||||
const Vec3fa dir = pos - 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(self->nnormal, res.dir);
|
|
||||||
res.pdf = self->ppdf * (dist * dist) / abs(cosd);
|
|
||||||
|
|
||||||
// emit only to one side
|
|
||||||
res.weight = cosd > 0.f ? self->radiance * rcp(res.pdf) : Vec3fa(0.f);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
SYCL_EXTERNAL Light_EvalRes QuadLight_eval(const Light* super,
|
|
||||||
const DifferentialGeometry& dg,
|
|
||||||
const Vec3fa& dir)
|
|
||||||
|
|
||||||
{
|
|
||||||
Light_EvalRes res;
|
|
||||||
res.value = Vec3fa(0,0,0);
|
|
||||||
res.dist = inf;
|
|
||||||
res.pdf = 0.f;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Exports (called from C++)
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
//! Set the parameters of an ispc-side QuadLight object
|
|
||||||
extern "C" void QuadLight_set(void* super,
|
|
||||||
const Vec3fa& position,
|
|
||||||
const Vec3fa& edge2,
|
|
||||||
const Vec3fa& edge1,
|
|
||||||
const Vec3fa& radiance)
|
|
||||||
{
|
|
||||||
QuadLight* self = (QuadLight*)super;
|
|
||||||
self->position = position;
|
|
||||||
self->edge1 = edge1;
|
|
||||||
self->edge2 = edge2;
|
|
||||||
self->radiance = radiance;
|
|
||||||
|
|
||||||
const Vec3fa ndirection = cross(edge2, edge1);
|
|
||||||
self->ppdf = rcp(length(ndirection));
|
|
||||||
self->nnormal = ndirection * self->ppdf;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Create an ispc-side QuadLight object
|
|
||||||
extern "C" void* QuadLight_create()
|
|
||||||
{
|
|
||||||
QuadLight* self = (QuadLight*) alignedUSMMalloc(sizeof(QuadLight),16);
|
|
||||||
|
|
||||||
Light_Constructor(&self->super);
|
|
||||||
//self->super.sample = GET_FUNCTION_POINTER(QuadLight_sample);
|
|
||||||
self->super.type = LIGHT_QUAD;
|
|
||||||
|
|
||||||
QuadLight_set(self,
|
|
||||||
Vec3fa(0.f),
|
|
||||||
Vec3fa(1.f, 0.f, 0.f),
|
|
||||||
Vec3fa(0.f, 1.f, 0.f),
|
|
||||||
Vec3fa(1.f));
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace embree
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../math/vec.h"
|
|
||||||
|
|
||||||
namespace embree
|
|
||||||
{
|
|
||||||
extern "C" void* QuadLight_create();
|
|
||||||
|
|
||||||
extern "C" void QuadLight_set(void* super,
|
|
||||||
const Vec3fa& position,
|
|
||||||
const Vec3fa& edge2,
|
|
||||||
const Vec3fa& edge1,
|
|
||||||
const Vec3fa& radiance);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,102 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#include "light.isph"
|
|
||||||
|
|
||||||
struct QuadLight
|
|
||||||
{
|
|
||||||
Light super; //!< inherited light fields
|
|
||||||
|
|
||||||
Vec3f position; //!< world-space corner position of the light
|
|
||||||
Vec3f edge1; //!< vectors to adjacent corners
|
|
||||||
Vec3f edge2; //!< vectors to adjacent corners
|
|
||||||
Vec3f radiance; //!< RGB color and intensity of the QuadLight
|
|
||||||
|
|
||||||
Vec3f nnormal; //!< negated normal, the direction that the QuadLight is not emitting; normalized
|
|
||||||
float ppdf; // probability to sample point on light = 1/area
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Implementation
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
SYCL_EXTERNAL Light_SampleRes QuadLight_sample(const uniform Light* uniform super,
|
|
||||||
const DifferentialGeometry& dg,
|
|
||||||
const Vec2f& s)
|
|
||||||
{
|
|
||||||
const QuadLight* uniform self = (QuadLight* uniform)super;
|
|
||||||
Light_SampleRes res;
|
|
||||||
|
|
||||||
// res position on light with density ppdf = 1/area
|
|
||||||
// TODO: use solid angle sampling
|
|
||||||
const Vec3f pos = self->position + self->edge1 * s.x + self->edge2 * s.y;
|
|
||||||
|
|
||||||
// extant light vector from the hit point
|
|
||||||
const Vec3f dir = pos - 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(self->nnormal, res.dir);
|
|
||||||
res.pdf = self->ppdf * (dist * dist) / abs(cosd);
|
|
||||||
|
|
||||||
// emit only to one side
|
|
||||||
res.weight = cosd > 0.f ? self->radiance * rcp(res.pdf) : make_Vec3f(0.f);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
SYCL_EXTERNAL Light_EvalRes QuadLight_eval(const uniform Light* uniform super,
|
|
||||||
const DifferentialGeometry& dg,
|
|
||||||
const Vec3f& dir)
|
|
||||||
|
|
||||||
{
|
|
||||||
Light_EvalRes res;
|
|
||||||
res.value = make_Vec3f(0,0,0);
|
|
||||||
res.dist = inf;
|
|
||||||
res.pdf = 0.f;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Exports (called from C++)
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
//! Set the parameters of an ispc-side QuadLight object
|
|
||||||
export void QuadLight_set(void* uniform super,
|
|
||||||
const uniform Vec3f& position,
|
|
||||||
const uniform Vec3f& edge2,
|
|
||||||
const uniform Vec3f& edge1,
|
|
||||||
const uniform Vec3f& radiance)
|
|
||||||
{
|
|
||||||
uniform QuadLight* uniform self = (uniform QuadLight* uniform)super;
|
|
||||||
self->position = position;
|
|
||||||
self->edge1 = edge1;
|
|
||||||
self->edge2 = edge2;
|
|
||||||
self->radiance = radiance;
|
|
||||||
|
|
||||||
const uniform Vec3f ndirection = cross(edge2, edge1);
|
|
||||||
self->ppdf = rcp(length(ndirection));
|
|
||||||
self->nnormal = ndirection * self->ppdf;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Create an ispc-side QuadLight object
|
|
||||||
export void* uniform QuadLight_create()
|
|
||||||
{
|
|
||||||
uniform QuadLight* uniform self = uniform new uniform QuadLight;
|
|
||||||
|
|
||||||
Light_Constructor(&self->super);
|
|
||||||
//self->super.sample = GET_FUNCTION_POINTER(QuadLight_sample);
|
|
||||||
self->super.type = LIGHT_QUAD;
|
|
||||||
|
|
||||||
QuadLight_set(self,
|
|
||||||
make_Vec3f(0.f),
|
|
||||||
make_Vec3f(1.f, 0.f, 0.f),
|
|
||||||
make_Vec3f(0.f, 1.f, 0.f),
|
|
||||||
make_Vec3f(1.f));
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
@ -1,139 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#include "light.h"
|
|
||||||
#include "../math/sampling.h"
|
|
||||||
#include "../math/linearspace.h"
|
|
||||||
|
|
||||||
namespace embree {
|
|
||||||
|
|
||||||
struct SpotLight
|
|
||||||
{
|
|
||||||
Light super; //!< inherited light fields
|
|
||||||
|
|
||||||
Vec3fa position; //!< Position of the SpotLight
|
|
||||||
LinearSpace3fa frame; //!< coordinate frame, with vz == direction that the SpotLight is emitting
|
|
||||||
Vec3fa power; //!< RGB color and intensity of the SpotLight
|
|
||||||
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 (extended) SpotLight
|
|
||||||
float diskPdf; //!< pdf of disk with radius
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Implementation
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
SYCL_EXTERNAL Light_SampleRes SpotLight_sample(const Light* super,
|
|
||||||
const DifferentialGeometry& dg,
|
|
||||||
const Vec2f& s)
|
|
||||||
{
|
|
||||||
const SpotLight* self = (SpotLight*)super;
|
|
||||||
Light_SampleRes res;
|
|
||||||
|
|
||||||
// extant light vector from the hit point
|
|
||||||
res.dir = self->position - dg.P;
|
|
||||||
|
|
||||||
if (self->radius > 0.0f)
|
|
||||||
res.dir = self->frame * uniformSampleDisk(self->radius, 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(self->frame.vz, res.dir);
|
|
||||||
const float angularAttenuation = clamp((cosAngle - self->cosAngleMax) * self->cosAngleScale);
|
|
||||||
|
|
||||||
if (self->radius > 0.0f)
|
|
||||||
res.pdf = self->diskPdf * dist2 * abs(cosAngle);
|
|
||||||
else
|
|
||||||
res.pdf = inf; // we always take this res
|
|
||||||
|
|
||||||
// convert from power to radiance by attenuating by distance^2; attenuate by angle
|
|
||||||
res.weight = self->power * (sqr(invdist) * angularAttenuation);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
SYCL_EXTERNAL Light_EvalRes SpotLight_eval(const Light* super,
|
|
||||||
const DifferentialGeometry& dg,
|
|
||||||
const Vec3fa& dir)
|
|
||||||
{
|
|
||||||
const SpotLight* self = (SpotLight*)super;
|
|
||||||
Light_EvalRes res;
|
|
||||||
res.value = Vec3fa(0.0f);
|
|
||||||
res.dist = inf;
|
|
||||||
res.pdf = 0.0f;
|
|
||||||
|
|
||||||
if (self->radius > 0.0f) {
|
|
||||||
// intersect disk
|
|
||||||
const float cosAngle = -dot(dir, self->frame.vz);
|
|
||||||
if (cosAngle > self->cosAngleMax) { // inside illuminated cone?
|
|
||||||
const Vec3fa vp = dg.P - self->position;
|
|
||||||
const float dp = dot(vp, self->frame.vz);
|
|
||||||
if (dp > 0.0f) { // in front of light?
|
|
||||||
const float t = dp*rcp(cosAngle);
|
|
||||||
const Vec3fa vd = vp + t * dir;
|
|
||||||
if (dot(vd, vd) < sqr(self->radius)) { // inside disk?
|
|
||||||
const float angularAttenuation = min((cosAngle - self->cosAngleMax) * self->cosAngleScale, 1.f);
|
|
||||||
const float pdf = self->diskPdf * cosAngle;
|
|
||||||
res.value = self->power * (angularAttenuation * pdf); // *sqr(t)/sqr(t) cancels
|
|
||||||
res.dist = t;
|
|
||||||
res.pdf = pdf * sqr(t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Exports (called from C++)
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
//! Set the parameters of an ispc-side SpotLight object
|
|
||||||
extern "C" void SpotLight_set(void* super,
|
|
||||||
const Vec3fa& position,
|
|
||||||
const Vec3fa& direction,
|
|
||||||
const Vec3fa& power,
|
|
||||||
float cosAngleMax,
|
|
||||||
float cosAngleScale,
|
|
||||||
float radius)
|
|
||||||
{
|
|
||||||
SpotLight* self = (SpotLight*)super;
|
|
||||||
self->position = position;
|
|
||||||
self->frame = frame(direction);
|
|
||||||
self->power = power;
|
|
||||||
self->cosAngleMax = cosAngleMax;
|
|
||||||
self->cosAngleScale = cosAngleScale;
|
|
||||||
self->radius = radius;
|
|
||||||
self->diskPdf = uniformSampleDiskPDF(radius);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Create an ispc-side SpotLight object
|
|
||||||
extern "C" void* SpotLight_create()
|
|
||||||
{
|
|
||||||
SpotLight* self = (SpotLight*) alignedUSMMalloc(sizeof(SpotLight),16);
|
|
||||||
|
|
||||||
Light_Constructor(&self->super);
|
|
||||||
//self->super.sample = GET_FUNCTION_POINTER(SpotLight_sample);
|
|
||||||
//self->super.eval = GET_FUNCTION_POINTER(SpotLight_eval);
|
|
||||||
self->super.type = LIGHT_SPOT;
|
|
||||||
|
|
||||||
SpotLight_set(self,
|
|
||||||
Vec3fa(0.f),
|
|
||||||
Vec3fa(0.f, 0.f, 1.f),
|
|
||||||
Vec3fa(1.f),
|
|
||||||
0.f,
|
|
||||||
100.f,
|
|
||||||
0.f);
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace embree
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../math/vec.h"
|
|
||||||
|
|
||||||
namespace embree
|
|
||||||
{
|
|
||||||
extern "C" void* SpotLight_create();
|
|
||||||
|
|
||||||
extern "C" void SpotLight_set(void* super,
|
|
||||||
const Vec3fa& position,
|
|
||||||
const Vec3fa& direction,
|
|
||||||
const Vec3fa& power,
|
|
||||||
float cosAngleMax,
|
|
||||||
float cosAngleScale,
|
|
||||||
float radius);
|
|
||||||
}
|
|
||||||
|
|
@ -1,135 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#include "light.isph"
|
|
||||||
#include "../math/sampling.isph"
|
|
||||||
#include "../math/linearspace.isph"
|
|
||||||
|
|
||||||
struct SpotLight
|
|
||||||
{
|
|
||||||
Light super; //!< inherited light fields
|
|
||||||
|
|
||||||
Vec3f position; //!< Position of the SpotLight
|
|
||||||
LinearSpace3f frame; //!< coordinate frame, with vz == direction that the SpotLight is emitting
|
|
||||||
Vec3f power; //!< RGB color and intensity of the SpotLight
|
|
||||||
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 (extended) SpotLight
|
|
||||||
float diskPdf; //!< pdf of disk with radius
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Implementation
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
SYCL_EXTERNAL Light_SampleRes SpotLight_sample(const uniform Light* uniform super,
|
|
||||||
const DifferentialGeometry& dg,
|
|
||||||
const Vec2f& s)
|
|
||||||
{
|
|
||||||
const SpotLight* uniform self = (SpotLight* uniform)super;
|
|
||||||
Light_SampleRes res;
|
|
||||||
|
|
||||||
// extant light vector from the hit point
|
|
||||||
res.dir = self->position - dg.P;
|
|
||||||
|
|
||||||
if (self->radius > 0.0f)
|
|
||||||
res.dir = self->frame * uniformSampleDisk(self->radius, 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(self->frame.vz, res.dir);
|
|
||||||
const float angularAttenuation = clamp((cosAngle - self->cosAngleMax) * self->cosAngleScale);
|
|
||||||
|
|
||||||
if (self->radius > 0.0f)
|
|
||||||
res.pdf = self->diskPdf * dist2 * abs(cosAngle);
|
|
||||||
else
|
|
||||||
res.pdf = inf; // we always take this res
|
|
||||||
|
|
||||||
// convert from power to radiance by attenuating by distance^2; attenuate by angle
|
|
||||||
res.weight = self->power * (sqr(invdist) * angularAttenuation);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
SYCL_EXTERNAL Light_EvalRes SpotLight_eval(const uniform Light* uniform super,
|
|
||||||
const DifferentialGeometry& dg,
|
|
||||||
const Vec3f& dir)
|
|
||||||
{
|
|
||||||
const SpotLight* uniform self = (SpotLight* uniform)super;
|
|
||||||
Light_EvalRes res;
|
|
||||||
res.value = make_Vec3f(0.0f);
|
|
||||||
res.dist = inf;
|
|
||||||
res.pdf = 0.0f;
|
|
||||||
|
|
||||||
if (self->radius > 0.0f) {
|
|
||||||
// intersect disk
|
|
||||||
const float cosAngle = -dot(dir, self->frame.vz);
|
|
||||||
if (cosAngle > self->cosAngleMax) { // inside illuminated cone?
|
|
||||||
const Vec3f vp = dg.P - self->position;
|
|
||||||
const float dp = dot(vp, self->frame.vz);
|
|
||||||
if (dp > 0.0f) { // in front of light?
|
|
||||||
const float t = dp*rcp(cosAngle);
|
|
||||||
const Vec3f vd = vp + t * dir;
|
|
||||||
if (dot(vd, vd) < sqr(self->radius)) { // inside disk?
|
|
||||||
const float angularAttenuation = min((cosAngle - self->cosAngleMax) * self->cosAngleScale, 1.f);
|
|
||||||
const float pdf = self->diskPdf * cosAngle;
|
|
||||||
res.value = self->power * (angularAttenuation * pdf); // *sqr(t)/sqr(t) cancels
|
|
||||||
res.dist = t;
|
|
||||||
res.pdf = pdf * sqr(t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Exports (called from C++)
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
//! Set the parameters of an ispc-side SpotLight object
|
|
||||||
export void SpotLight_set(void* uniform super,
|
|
||||||
const uniform Vec3f& position,
|
|
||||||
const uniform Vec3f& direction,
|
|
||||||
const uniform Vec3f& power,
|
|
||||||
uniform float cosAngleMax,
|
|
||||||
uniform float cosAngleScale,
|
|
||||||
uniform float radius)
|
|
||||||
{
|
|
||||||
uniform SpotLight* uniform self = (uniform SpotLight* uniform)super;
|
|
||||||
self->position = position;
|
|
||||||
self->frame = frame(direction);
|
|
||||||
self->power = power;
|
|
||||||
self->cosAngleMax = cosAngleMax;
|
|
||||||
self->cosAngleScale = cosAngleScale;
|
|
||||||
self->radius = radius;
|
|
||||||
self->diskPdf = uniformSampleDiskPDF(radius);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Create an ispc-side SpotLight object
|
|
||||||
export void* uniform SpotLight_create()
|
|
||||||
{
|
|
||||||
uniform SpotLight* uniform self = uniform new uniform SpotLight;
|
|
||||||
|
|
||||||
Light_Constructor(&self->super);
|
|
||||||
//self->super.sample = GET_FUNCTION_POINTER(SpotLight_sample);
|
|
||||||
//self->super.eval = GET_FUNCTION_POINTER(SpotLight_eval);
|
|
||||||
self->super.type = LIGHT_SPOT;
|
|
||||||
|
|
||||||
SpotLight_set(self,
|
|
||||||
make_Vec3f(0.f),
|
|
||||||
make_Vec3f(0.f, 0.f, 1.f),
|
|
||||||
make_Vec3f(1.f),
|
|
||||||
0.f,
|
|
||||||
100.f,
|
|
||||||
0.f);
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../../../common/math/affinespace.h"
|
|
||||||
|
|
||||||
namespace embree
|
|
||||||
{
|
|
||||||
__forceinline bool eq (const AffineSpace3fa& a, const AffineSpace3fa& b) { return a == b; }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,135 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "linearspace.isph"
|
|
||||||
|
|
||||||
struct AffineSpace3f
|
|
||||||
{
|
|
||||||
LinearSpace3f l;
|
|
||||||
Vec3f p;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct AffineSpace3fa
|
|
||||||
{
|
|
||||||
LinearSpace3fa l;
|
|
||||||
Vec3fa p;
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// Constructors
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
inline uniform AffineSpace3f make_AffineSpace3f(const uniform LinearSpace3f l) {
|
|
||||||
uniform AffineSpace3f xfm; xfm.l = l; xfm.p = make_Vec3f(0,0,0); return xfm;
|
|
||||||
}
|
|
||||||
inline varying AffineSpace3f make_AffineSpace3f(const varying LinearSpace3f l) {
|
|
||||||
varying AffineSpace3f xfm; xfm.l = l; xfm.p = make_Vec3f(0,0,0); return xfm;
|
|
||||||
}
|
|
||||||
inline uniform AffineSpace3f make_AffineSpace3f(const uniform LinearSpace3f l, const uniform Vec3f p) {
|
|
||||||
uniform AffineSpace3f xfm; xfm.l = l; xfm.p = p; return xfm;
|
|
||||||
}
|
|
||||||
inline varying AffineSpace3f make_AffineSpace3f(const varying LinearSpace3f l, const varying Vec3f p) {
|
|
||||||
varying AffineSpace3f xfm; xfm.l = l; xfm.p = p; return xfm;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uniform AffineSpace3f make_AffineSpace3f(const uniform AffineSpace3fa l) {
|
|
||||||
uniform AffineSpace3f xfm; xfm.l = make_LinearSpace3f(l.l); xfm.p = make_Vec3f(l.p); return xfm;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline varying AffineSpace3f make_AffineSpace3f(const varying AffineSpace3fa l) {
|
|
||||||
varying AffineSpace3f xfm; xfm.l = make_LinearSpace3f(l.l); xfm.p = make_Vec3f(l.p); return xfm;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uniform AffineSpace3f make_AffineSpace3f(const uniform Vec3f x, const uniform Vec3f y, const uniform Vec3f z, const uniform Vec3f p) {
|
|
||||||
uniform AffineSpace3f xfm; xfm.l.vx = x; xfm.l.vy = y; xfm.l.vz = z; xfm.p = p; return xfm;
|
|
||||||
}
|
|
||||||
inline varying AffineSpace3f make_AffineSpace3f(const varying Vec3f x, const varying Vec3f y, const varying Vec3f z, const varying Vec3f p) {
|
|
||||||
varying AffineSpace3f xfm; xfm.l.vx = x; xfm.l.vy = y; xfm.l.vz = z; xfm.p = p; return xfm;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Unary Operators
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
inline uniform AffineSpace3f neg(const uniform AffineSpace3f a) { return make_AffineSpace3f(neg(a.l),neg(a.p)); }
|
|
||||||
inline varying AffineSpace3f neg(const varying AffineSpace3f a) { return make_AffineSpace3f(neg(a.l),neg(a.p)); }
|
|
||||||
|
|
||||||
inline uniform AffineSpace3f rcp( const uniform AffineSpace3f a) { uniform LinearSpace3f il = rcp(a.l); return make_AffineSpace3f(il,neg(il*a.p)); }
|
|
||||||
inline varying AffineSpace3f rcp( const varying AffineSpace3f a) { varying LinearSpace3f il = rcp(a.l); return make_AffineSpace3f(il,neg(il*a.p)); }
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// Binary Operators
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
inline uniform AffineSpace3f operator+(const uniform AffineSpace3f a, const uniform AffineSpace3f b) { return make_AffineSpace3f(a.l+b.l, a.p+b.p); }
|
|
||||||
inline varying AffineSpace3f operator+(const varying AffineSpace3f a, const varying AffineSpace3f b) { return make_AffineSpace3f(a.l+b.l, a.p+b.p); }
|
|
||||||
|
|
||||||
inline uniform AffineSpace3f operator-(const uniform AffineSpace3f a, const uniform AffineSpace3f b) { return make_AffineSpace3f(a.l-b.l, a.p-b.p); }
|
|
||||||
inline varying AffineSpace3f operator-(const varying AffineSpace3f a, const varying AffineSpace3f b) { return make_AffineSpace3f(a.l-b.l, a.p-b.p); }
|
|
||||||
|
|
||||||
inline uniform AffineSpace3f operator*( const uniform float a, const uniform AffineSpace3f b ) { return make_AffineSpace3f(a*b.l,a*b.p); }
|
|
||||||
inline uniform AffineSpace3f operator*( const uniform AffineSpace3f a, const uniform float b ) { return make_AffineSpace3f(a.l*b,a.p*b); }
|
|
||||||
inline uniform AffineSpace3f operator*( const uniform AffineSpace3f a, const uniform AffineSpace3f b ) { return make_AffineSpace3f(a.l*b.l,a.l*b.p+a.p); }
|
|
||||||
|
|
||||||
inline varying AffineSpace3f operator*( const varying float a, const varying AffineSpace3f b ) { return make_AffineSpace3f(a*b.l,a*b.p); }
|
|
||||||
inline varying AffineSpace3f operator*( const varying AffineSpace3f a, const varying float b ) { return make_AffineSpace3f(a.l*b,a.p*b); }
|
|
||||||
inline varying AffineSpace3f operator*( const varying AffineSpace3f a, const varying AffineSpace3f b ) { return make_AffineSpace3f(a.l*b.l,a.l*b.p + a.p); }
|
|
||||||
|
|
||||||
inline varying AffineSpace3f operator*( const varying float a, const uniform AffineSpace3f b ) { return make_AffineSpace3f(a*b.l,a*b.p); }
|
|
||||||
inline varying AffineSpace3f operator*( const uniform AffineSpace3f a, const varying float b ) { return make_AffineSpace3f(a.l*b,a.p*b); }
|
|
||||||
|
|
||||||
inline uniform Vec3f xfmPoint (const uniform AffineSpace3f a, const uniform Vec3f v) { return xfmVector(a.l,v)+a.p; }
|
|
||||||
inline varying Vec3f xfmPoint (const uniform AffineSpace3f a, const varying Vec3f v) { return xfmVector(a.l,v)+a.p; }
|
|
||||||
inline varying Vec3f xfmPoint (const varying AffineSpace3f a, const varying Vec3f v) { return xfmVector(a.l,v)+a.p; }
|
|
||||||
|
|
||||||
inline uniform Vec3f xfmVector(const uniform AffineSpace3f a, const uniform Vec3f v) { return xfmVector(a.l,v); }
|
|
||||||
inline varying Vec3f xfmVector(const uniform AffineSpace3f a, const varying Vec3f v) { return xfmVector(a.l,v); }
|
|
||||||
inline varying Vec3f xfmVector(const varying AffineSpace3f a, const varying Vec3f v) { return xfmVector(a.l,v); }
|
|
||||||
|
|
||||||
inline uniform Vec3f xfmNormal(const uniform AffineSpace3f a, const uniform Vec3f v) { return xfmNormal(a.l,v); }
|
|
||||||
inline varying Vec3f xfmNormal(const uniform AffineSpace3f a, const varying Vec3f v) { return xfmNormal(a.l,v); }
|
|
||||||
inline varying Vec3f xfmNormal(const varying AffineSpace3f a, const varying Vec3f v) { return xfmNormal(a.l,v); }
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// Comparison Operators
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
inline uniform bool eq(const uniform AffineSpace3f a, const uniform AffineSpace3f b) { return eq(a.l,b.l) & eq(a.p,b.p); }
|
|
||||||
inline varying bool eq(const varying AffineSpace3f a, const varying AffineSpace3f b) { return eq(a.l,b.l) & eq(a.p,b.p); }
|
|
||||||
|
|
||||||
inline uniform bool ne(const uniform AffineSpace3f a, const uniform AffineSpace3f b) { return ne(a.l,b.l) | ne(a.p,b.p); }
|
|
||||||
inline varying bool ne(const varying AffineSpace3f a, const varying AffineSpace3f b) { return ne(a.l,b.l) | ne(a.p,b.p); }
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Interpolation
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
inline uniform AffineSpace3f lerp(uniform float factor, const uniform AffineSpace3f& a, const uniform AffineSpace3f& b) {
|
|
||||||
return make_AffineSpace3f(lerp(factor, a.l, b.l), lerp(factor, a.p, b.p));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline varying AffineSpace3f lerp(varying float factor, const uniform AffineSpace3f& a, const uniform AffineSpace3f& b) {
|
|
||||||
return make_AffineSpace3f(lerp(factor, a.l, b.l), lerp(factor, a.p, b.p));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! return scale matrix */
|
|
||||||
inline uniform AffineSpace3f make_AffineSpace3f_scale(const uniform Vec3f& s) {
|
|
||||||
return make_AffineSpace3f(make_LinearSpace3f_scale(s));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! return translation matrix */
|
|
||||||
inline uniform AffineSpace3f make_AffineSpace3f_translate(const uniform Vec3f& p) {
|
|
||||||
return make_AffineSpace3f(make_Vec3f(1,0,0),make_Vec3f(0,1,0),make_Vec3f(0,0,1),p);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! return translation matrix */
|
|
||||||
inline AffineSpace3f make_AffineSpace3f_translate(const Vec3f& p) {
|
|
||||||
return make_AffineSpace3f(make_Vec3f(1,0,0),make_Vec3f(0,1,0),make_Vec3f(0,0,1),p);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! return matrix for rotation around arbitrary axis and point */
|
|
||||||
inline uniform AffineSpace3f make_AffineSpace3f_rotate (const uniform Vec3f& p, const uniform Vec3f& u, const uniform float& r) {
|
|
||||||
return (make_AffineSpace3f_translate(+p) * make_AffineSpace3f(make_LinearSpace3f_rotate(u,r))) * make_AffineSpace3f_translate(neg(p));
|
|
||||||
}
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../math/vec.h"
|
|
||||||
|
|
||||||
namespace embree
|
|
||||||
{
|
|
||||||
Vec3fa closestPointTriangle(Vec3fa const& p, Vec3fa const& a, Vec3fa const& b, Vec3fa const& c)
|
|
||||||
{
|
|
||||||
const Vec3fa ab = b - a;
|
|
||||||
const Vec3fa ac = c - a;
|
|
||||||
const Vec3fa ap = p - a;
|
|
||||||
|
|
||||||
const float d1 = dot(ab, ap);
|
|
||||||
const float d2 = dot(ac, ap);
|
|
||||||
if (d1 <= 0.f && d2 <= 0.f) return a;
|
|
||||||
|
|
||||||
const Vec3fa bp = p - b;
|
|
||||||
const float d3 = dot(ab, bp);
|
|
||||||
const float d4 = dot(ac, bp);
|
|
||||||
if (d3 >= 0.f && d4 <= d3) return b;
|
|
||||||
|
|
||||||
const Vec3fa cp = p - c;
|
|
||||||
const float d5 = dot(ab, cp);
|
|
||||||
const float d6 = dot(ac, cp);
|
|
||||||
if (d6 >= 0.f && d5 <= d6) return c;
|
|
||||||
|
|
||||||
const float vc = d1 * d4 - d3 * d2;
|
|
||||||
if (vc <= 0.f && d1 >= 0.f && d3 <= 0.f)
|
|
||||||
{
|
|
||||||
const float v = d1 / (d1 - d3);
|
|
||||||
return a + v * ab;
|
|
||||||
}
|
|
||||||
|
|
||||||
const float vb = d5 * d2 - d1 * d6;
|
|
||||||
if (vb <= 0.f && d2 >= 0.f && d6 <= 0.f)
|
|
||||||
{
|
|
||||||
const float v = d2 / (d2 - d6);
|
|
||||||
return a + v * ac;
|
|
||||||
}
|
|
||||||
|
|
||||||
const float va = d3 * d6 - d5 * d4;
|
|
||||||
if (va <= 0.f && (d4 - d3) >= 0.f && (d5 - d6) >= 0.f)
|
|
||||||
{
|
|
||||||
const float v = (d4 - d3) / ((d4 - d3) + (d5 - d6));
|
|
||||||
return b + v * (c - b);
|
|
||||||
}
|
|
||||||
|
|
||||||
const float denom = 1.f / (va + vb + vc);
|
|
||||||
const float v = vb * denom;
|
|
||||||
const float w = vc * denom;
|
|
||||||
return a + v * ab + w * ac;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,100 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../math/vec.isph"
|
|
||||||
|
|
||||||
Vec3f closestPointTriangle(Vec3f const& p, Vec3f const& a, Vec3f const& b, Vec3f const& c)
|
|
||||||
{
|
|
||||||
const Vec3f ab = b - a;
|
|
||||||
const Vec3f ac = c - a;
|
|
||||||
const Vec3f ap = p - a;
|
|
||||||
|
|
||||||
const float d1 = dot(ab, ap);
|
|
||||||
const float d2 = dot(ac, ap);
|
|
||||||
if (d1 <= 0.f && d2 <= 0.f) return a;
|
|
||||||
|
|
||||||
const Vec3f bp = p - b;
|
|
||||||
const float d3 = dot(ab, bp);
|
|
||||||
const float d4 = dot(ac, bp);
|
|
||||||
if (d3 >= 0.f && d4 <= d3) return b;
|
|
||||||
|
|
||||||
const Vec3f cp = p - c;
|
|
||||||
const float d5 = dot(ab, cp);
|
|
||||||
const float d6 = dot(ac, cp);
|
|
||||||
if (d6 >= 0.f && d5 <= d6) return c;
|
|
||||||
|
|
||||||
const float vc = d1 * d4 - d3 * d2;
|
|
||||||
if (vc <= 0.f && d1 >= 0.f && d3 <= 0.f)
|
|
||||||
{
|
|
||||||
const float v = d1 / (d1 - d3);
|
|
||||||
return a + v * ab;
|
|
||||||
}
|
|
||||||
|
|
||||||
const float vb = d5 * d2 - d1 * d6;
|
|
||||||
if (vb <= 0.f && d2 >= 0.f && d6 <= 0.f)
|
|
||||||
{
|
|
||||||
const float v = d2 / (d2 - d6);
|
|
||||||
return a + v * ac;
|
|
||||||
}
|
|
||||||
|
|
||||||
const float va = d3 * d6 - d5 * d4;
|
|
||||||
if (va <= 0.f && (d4 - d3) >= 0.f && (d5 - d6) >= 0.f)
|
|
||||||
{
|
|
||||||
const float v = (d4 - d3) / ((d4 - d3) + (d5 - d6));
|
|
||||||
return b + v * (c - b);
|
|
||||||
}
|
|
||||||
|
|
||||||
const float denom = 1.f / (va + vb + vc);
|
|
||||||
const float v = vb * denom;
|
|
||||||
const float w = vc * denom;
|
|
||||||
return a + v * ab + w * ac;
|
|
||||||
}
|
|
||||||
|
|
||||||
uniform Vec3f closestPointTriangle(uniform Vec3f& p, uniform Vec3f& a, uniform Vec3f& b, uniform Vec3f& c)
|
|
||||||
{
|
|
||||||
const uniform Vec3f ab = b - a;
|
|
||||||
const uniform Vec3f ac = c - a;
|
|
||||||
const uniform Vec3f ap = p - a;
|
|
||||||
|
|
||||||
const uniform float d1 = dot(ab, ap);
|
|
||||||
const uniform float d2 = dot(ac, ap);
|
|
||||||
if (d1 <= 0.f && d2 <= 0.f) return a;
|
|
||||||
|
|
||||||
const uniform Vec3f bp = p - b;
|
|
||||||
const uniform float d3 = dot(ab, bp);
|
|
||||||
const uniform float d4 = dot(ac, bp);
|
|
||||||
if (d3 >= 0.f && d4 <= d3) return b;
|
|
||||||
|
|
||||||
const uniform Vec3f cp = p - c;
|
|
||||||
const uniform float d5 = dot(ab, cp);
|
|
||||||
const uniform float d6 = dot(ac, cp);
|
|
||||||
if (d6 >= 0.f && d5 <= d6) return c;
|
|
||||||
|
|
||||||
const uniform float vc = d1 * d4 - d3 * d2;
|
|
||||||
if (vc <= 0.f && d1 >= 0.f && d3 <= 0.f)
|
|
||||||
{
|
|
||||||
const uniform float v = d1 / (d1 - d3);
|
|
||||||
return a + v * ab;
|
|
||||||
}
|
|
||||||
|
|
||||||
const uniform float vb = d5 * d2 - d1 * d6;
|
|
||||||
if (vb <= 0.f && d2 >= 0.f && d6 <= 0.f)
|
|
||||||
{
|
|
||||||
const uniform float v = d2 / (d2 - d6);
|
|
||||||
return a + v * ac;
|
|
||||||
}
|
|
||||||
|
|
||||||
const uniform float va = d3 * d6 - d5 * d4;
|
|
||||||
if (va <= 0.f && (d4 - d3) >= 0.f && (d5 - d6) >= 0.f)
|
|
||||||
{
|
|
||||||
const uniform float v = (d4 - d3) / ((d4 - d3) + (d5 - d6));
|
|
||||||
return b + v * (c - b);
|
|
||||||
}
|
|
||||||
|
|
||||||
const uniform float denom = 1.f / (va + vb + vc);
|
|
||||||
const uniform float v = vb * denom;
|
|
||||||
const uniform float w = vc * denom;
|
|
||||||
return a + v * ab + w * ac;
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../../../common/math/linearspace3.h"
|
|
||||||
|
|
||||||
|
|
@ -1,314 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "vec.isph"
|
|
||||||
#include "quaternion.isph"
|
|
||||||
|
|
||||||
struct LinearSpace3f
|
|
||||||
{
|
|
||||||
Vec3f vx;
|
|
||||||
Vec3f vy;
|
|
||||||
Vec3f vz;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct LinearSpace3fa
|
|
||||||
{
|
|
||||||
Vec3fa vx;
|
|
||||||
Vec3fa vy;
|
|
||||||
Vec3fa vz;
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// Constructors
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
inline uniform LinearSpace3f make_LinearSpace3f(const uniform Vec3f &x, const uniform Vec3f &y, const uniform Vec3f &z) {
|
|
||||||
uniform LinearSpace3f l; l.vx = x; l.vy = y; l.vz = z; return l;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline varying LinearSpace3f make_LinearSpace3f(const varying Vec3f &x, const varying Vec3f &y, const varying Vec3f &z) {
|
|
||||||
varying LinearSpace3f l; l.vx = x; l.vy = y; l.vz = z; return l;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uniform LinearSpace3f make_LinearSpace3f(const uniform LinearSpace3fa &s) {
|
|
||||||
uniform LinearSpace3f l; l.vx = make_Vec3f(s.vx); l.vy = make_Vec3f(s.vy); l.vz = make_Vec3f(s.vz); return l;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline varying LinearSpace3f make_LinearSpace3f(const varying LinearSpace3fa &s) {
|
|
||||||
varying LinearSpace3f l; l.vx = make_Vec3f(s.vx); l.vy = make_Vec3f(s.vy); l.vz = make_Vec3f(s.vz); return l;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! construction from quaternion */
|
|
||||||
inline uniform LinearSpace3f make_LinearSpace3f(const uniform Quaternion3f& q)
|
|
||||||
{
|
|
||||||
uniform LinearSpace3f l;
|
|
||||||
l.vx = make_Vec3f(q.r*q.r + q.i*q.i - q.j*q.j - q.k*q.k, 2.0f*(q.i*q.j + q.r*q.k), 2.0f*(q.i*q.k - q.r*q.j));
|
|
||||||
l.vy = make_Vec3f(2.0f*(q.i*q.j - q.r*q.k), (q.r*q.r - q.i*q.i + q.j*q.j - q.k*q.k), 2.0f*(q.j*q.k + q.r*q.i));
|
|
||||||
l.vz = make_Vec3f(2.0f*(q.i*q.k + q.r*q.j), 2.0f*(q.j*q.k - q.r*q.i), q.r*q.r - q.i*q.i - q.j*q.j + q.k*q.k);
|
|
||||||
return l;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline varying LinearSpace3f make_LinearSpace3f(const varying Quaternion3f& q)
|
|
||||||
{
|
|
||||||
LinearSpace3f l;
|
|
||||||
l.vx = make_Vec3f(q.r*q.r + q.i*q.i - q.j*q.j - q.k*q.k, 2.0f*(q.i*q.j + q.r*q.k), 2.0f*(q.i*q.k - q.r*q.j));
|
|
||||||
l.vy = make_Vec3f(2.0f*(q.i*q.j - q.r*q.k), (q.r*q.r - q.i*q.i + q.j*q.j - q.k*q.k), 2.0f*(q.j*q.k + q.r*q.i));
|
|
||||||
l.vz = make_Vec3f(2.0f*(q.i*q.k + q.r*q.j), 2.0f*(q.j*q.k - q.r*q.i), q.r*q.r - q.i*q.i - q.j*q.j + q.k*q.k);
|
|
||||||
return l;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uniform LinearSpace3f make_LinearSpace3f_identity()
|
|
||||||
{
|
|
||||||
return make_LinearSpace3f(make_Vec3f(1.f,0.f,0.f),
|
|
||||||
make_Vec3f(0.f,1.f,0.f),
|
|
||||||
make_Vec3f(0.f,0.f,1.f));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! return scale matrix */
|
|
||||||
inline uniform LinearSpace3f make_LinearSpace3f_scale(const uniform Vec3f& s)
|
|
||||||
{
|
|
||||||
return make_LinearSpace3f( make_Vec3f( s.x, 0.0f, 0.0f),
|
|
||||||
make_Vec3f(0.0f, s.y, 0.0f),
|
|
||||||
make_Vec3f(0.0f, 0.0f, s.z));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! return matrix for rotation around arbitrary axis */
|
|
||||||
inline uniform LinearSpace3f make_LinearSpace3f_rotate(const uniform Vec3f& _u, const uniform float& r)
|
|
||||||
{
|
|
||||||
uniform Vec3f u = normalize(_u);
|
|
||||||
uniform float s = sin(r), c = cos(r);
|
|
||||||
return make_LinearSpace3f(make_Vec3f(u.x*u.x+(1-u.x*u.x)*c, u.x*u.y*(1-c)+u.z*s, u.x*u.z*(1-c)-u.y*s),
|
|
||||||
make_Vec3f(u.x*u.y*(1-c)-u.z*s, u.y*u.y+(1-u.y*u.y)*c, u.y*u.z*(1-c)+u.x*s),
|
|
||||||
make_Vec3f(u.x*u.z*(1-c)+u.y*s, u.y*u.z*(1-c)-u.x*s, u.z*u.z+(1-u.z*u.z)*c));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! return matrix for rotation around arbitrary axis */
|
|
||||||
inline varying LinearSpace3f make_LinearSpace3f_rotate(const varying Vec3f& _u, const varying float& r)
|
|
||||||
{
|
|
||||||
varying Vec3f u = normalize(_u);
|
|
||||||
varying float s = sin(r), c = cos(r);
|
|
||||||
return make_LinearSpace3f(make_Vec3f(u.x*u.x+(1-u.x*u.x)*c, u.x*u.y*(1-c)+u.z*s, u.x*u.z*(1-c)-u.y*s),
|
|
||||||
make_Vec3f(u.x*u.y*(1-c)-u.z*s, u.y*u.y+(1-u.y*u.y)*c, u.y*u.z*(1-c)+u.x*s),
|
|
||||||
make_Vec3f(u.x*u.z*(1-c)+u.y*s, u.y*u.z*(1-c)-u.x*s, u.z*u.z+(1-u.z*u.z)*c));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! return matrix for rotation around arbitrary axis */
|
|
||||||
inline varying LinearSpace3f make_LinearSpace3f_rotate(const uniform Vec3f& _u, const varying float& r)
|
|
||||||
{
|
|
||||||
varying Vec3f u = normalize(_u);
|
|
||||||
varying float s = sin(r), c = cos(r);
|
|
||||||
return make_LinearSpace3f(make_Vec3f(u.x*u.x+(1-u.x*u.x)*c, u.x*u.y*(1-c)+u.z*s, u.x*u.z*(1-c)-u.y*s),
|
|
||||||
make_Vec3f(u.x*u.y*(1-c)-u.z*s, u.y*u.y+(1-u.y*u.y)*c, u.y*u.z*(1-c)+u.x*s),
|
|
||||||
make_Vec3f(u.x*u.z*(1-c)+u.y*s, u.y*u.z*(1-c)-u.x*s, u.z*u.z+(1-u.z*u.z)*c));
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Unary Operators
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
inline uniform LinearSpace3f neg(const uniform LinearSpace3f &l) { return make_LinearSpace3f(neg(l.vx),neg(l.vy),neg(l.vz)); }
|
|
||||||
inline varying LinearSpace3f neg(const varying LinearSpace3f &l) { return make_LinearSpace3f(neg(l.vx),neg(l.vy),neg(l.vz)); }
|
|
||||||
|
|
||||||
/*! compute the determinant of the matrix */
|
|
||||||
inline uniform float det(const uniform LinearSpace3f &l) { return dot(l.vx,cross(l.vy,l.vz)); }
|
|
||||||
inline varying float det(const varying LinearSpace3f &l) { return dot(l.vx,cross(l.vy,l.vz)); }
|
|
||||||
|
|
||||||
/*! compute transposed matrix */
|
|
||||||
inline uniform LinearSpace3f transposed(const uniform LinearSpace3f &l) {
|
|
||||||
return make_LinearSpace3f(make_Vec3f(l.vx.x,l.vy.x,l.vz.x),
|
|
||||||
make_Vec3f(l.vx.y,l.vy.y,l.vz.y),
|
|
||||||
make_Vec3f(l.vx.z,l.vy.z,l.vz.z));
|
|
||||||
}
|
|
||||||
inline varying LinearSpace3f transposed(const varying LinearSpace3f &l) {
|
|
||||||
return make_LinearSpace3f(make_Vec3f(l.vx.x,l.vy.x,l.vz.x),
|
|
||||||
make_Vec3f(l.vx.y,l.vy.y,l.vz.y),
|
|
||||||
make_Vec3f(l.vx.z,l.vy.z,l.vz.z));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! compute adjoint matrix */
|
|
||||||
inline uniform LinearSpace3f adjoint(const uniform LinearSpace3f &l) {
|
|
||||||
return transposed(make_LinearSpace3f(cross(l.vy,l.vz),cross(l.vz,l.vx),cross(l.vx,l.vy)));
|
|
||||||
}
|
|
||||||
inline varying LinearSpace3f adjoint(const varying LinearSpace3f &l) {
|
|
||||||
return transposed(make_LinearSpace3f(cross(l.vy,l.vz),cross(l.vz,l.vx),cross(l.vx,l.vy)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! calculates orthogonal coordinate frame with z-Vector pointing towards N */
|
|
||||||
inline uniform LinearSpace3f frame(const uniform Vec3f &N)
|
|
||||||
{
|
|
||||||
const uniform Vec3f dx0 = make_Vec3f(0.0f,N.z,-N.y);
|
|
||||||
const uniform Vec3f dx1 = make_Vec3f(-N.z,0.0f,N.x);
|
|
||||||
const uniform Vec3f dx = normalize(dot(dx0,dx0) > dot(dx1,dx1) ? dx0 : dx1);
|
|
||||||
const uniform Vec3f dy = normalize(cross(N,dx));
|
|
||||||
return make_LinearSpace3f(dx,dy,N);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline varying LinearSpace3f frame(const varying Vec3f &N)
|
|
||||||
{
|
|
||||||
const varying Vec3f dx0 = make_Vec3f(0.0f,N.z,-N.y);
|
|
||||||
const varying Vec3f dx1 = make_Vec3f(-N.z,0.0f,N.x);
|
|
||||||
const varying Vec3f dx = normalize(dot(dx0,dx0) > dot(dx1,dx1) ? dx0 : dx1);
|
|
||||||
const varying Vec3f dy = normalize(cross(N,dx));
|
|
||||||
return make_LinearSpace3f(dx,dy,N);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// Binary Operators
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
inline uniform LinearSpace3f operator+(const uniform LinearSpace3f &a, const uniform LinearSpace3f &b) { return make_LinearSpace3f(a.vx+b.vx, a.vy+b.vy, a.vz+b.vz); }
|
|
||||||
inline varying LinearSpace3f operator+(const varying LinearSpace3f &a, const varying LinearSpace3f &b) { return make_LinearSpace3f(a.vx+b.vx, a.vy+b.vy, a.vz+b.vz); }
|
|
||||||
|
|
||||||
inline uniform LinearSpace3f operator-(const uniform LinearSpace3f &a, const uniform LinearSpace3f &b) { return make_LinearSpace3f(a.vx-b.vx, a.vy-b.vy, a.vz-b.vz); }
|
|
||||||
inline varying LinearSpace3f operator-(const varying LinearSpace3f &a, const varying LinearSpace3f &b) { return make_LinearSpace3f(a.vx-b.vx, a.vy-b.vy, a.vz-b.vz); }
|
|
||||||
|
|
||||||
inline uniform Vec3f operator*(const uniform LinearSpace3f &l, const uniform Vec3f &v) { return v.x*l.vx + v.y*l.vy + v.z*l.vz; }
|
|
||||||
inline varying Vec3f operator*(const uniform LinearSpace3f &l, const varying Vec3f &v) { return v.x*l.vx + v.y*l.vy + v.z*l.vz; }
|
|
||||||
inline varying Vec3f operator*(const varying LinearSpace3f &l, const varying Vec3f &v) { return v.x*l.vx + v.y*l.vy + v.z*l.vz; }
|
|
||||||
|
|
||||||
inline uniform LinearSpace3f operator*(const uniform float &a, const uniform LinearSpace3f &b) { return make_LinearSpace3f(a*b.vx, a*b.vy, a*b.vz); }
|
|
||||||
inline uniform LinearSpace3f operator*(const uniform LinearSpace3f &a, const uniform float &b) { return make_LinearSpace3f(a.vx*b, a.vy*b, a.vz*b); }
|
|
||||||
inline uniform LinearSpace3f operator*(const uniform LinearSpace3f &a, const uniform LinearSpace3f &b) { return make_LinearSpace3f(a*b.vx, a*b.vy, a*b.vz); }
|
|
||||||
|
|
||||||
inline varying LinearSpace3f operator*(const varying float &a, const varying LinearSpace3f &b) { return make_LinearSpace3f(a*b.vx, a*b.vy, a*b.vz); }
|
|
||||||
inline varying LinearSpace3f operator*(const varying LinearSpace3f &a, const varying float &b) { return make_LinearSpace3f(a.vx*b, a.vy*b, a.vz*b); }
|
|
||||||
inline varying LinearSpace3f operator*(const varying LinearSpace3f &a, const varying LinearSpace3f &b) { return make_LinearSpace3f(a*b.vx, a*b.vy, a*b.vz); }
|
|
||||||
|
|
||||||
inline varying LinearSpace3f operator*(const varying float &a, const uniform LinearSpace3f &b) { return make_LinearSpace3f(a*b.vx, a*b.vy, a*b.vz); }
|
|
||||||
inline varying LinearSpace3f operator*(const uniform LinearSpace3f &a, const varying float &b) { return make_LinearSpace3f(a.vx*b, a.vy*b, a.vz*b); }
|
|
||||||
|
|
||||||
inline uniform Vec3f xfmVector(const uniform LinearSpace3f l, const uniform Vec3f v) { return v.x*l.vx + v.y*l.vy + v.z*l.vz; }
|
|
||||||
inline varying Vec3f xfmVector(const uniform LinearSpace3f l, const varying Vec3f v) { return v.x*l.vx + v.y*l.vy + v.z*l.vz; }
|
|
||||||
inline varying Vec3f xfmVector(const varying LinearSpace3f l, const varying Vec3f v) { return v.x*l.vx + v.y*l.vy + v.z*l.vz; }
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// Comparison Operators
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
inline uniform bool eq(const uniform LinearSpace3f &a, const uniform LinearSpace3f &b) { return eq(a.vx,b.vx) & eq(a.vy,b.vy) & eq(a.vz,b.vz); }
|
|
||||||
inline varying bool eq(const varying LinearSpace3f &a, const varying LinearSpace3f &b) { return eq(a.vx,b.vx) & eq(a.vy,b.vy) & eq(a.vz,b.vz); }
|
|
||||||
|
|
||||||
inline uniform bool ne(const uniform LinearSpace3f &a, const uniform LinearSpace3f &b) { return ne(a.vx,b.vx) | ne(a.vy,b.vy) | ne(a.vz,b.vz); }
|
|
||||||
inline varying bool ne(const varying LinearSpace3f &a, const varying LinearSpace3f &b) { return ne(a.vx,b.vx) | ne(a.vy,b.vy) | ne(a.vz,b.vz); }
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Unary Operators
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
/*! compute inverse matrix */
|
|
||||||
inline uniform LinearSpace3f rcp(const uniform LinearSpace3f &l) { return rcp(det(l))*adjoint(l); }
|
|
||||||
inline varying LinearSpace3f rcp(const varying LinearSpace3f &l) { return rcp(det(l))*adjoint(l); }
|
|
||||||
|
|
||||||
inline uniform Vec3f xfmNormal(const uniform LinearSpace3f l, const uniform Vec3f v) { return xfmVector(transposed(rcp(l)),v); }
|
|
||||||
inline varying Vec3f xfmNormal(const uniform LinearSpace3f l, const varying Vec3f v) { return xfmVector(transposed(rcp(l)),v); }
|
|
||||||
inline varying Vec3f xfmNormal(const varying LinearSpace3f l, const varying Vec3f v) { return xfmVector(transposed(rcp(l)),v); }
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Interpolation
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
inline uniform LinearSpace3f lerp(uniform float factor, const uniform LinearSpace3f& a, const uniform LinearSpace3f& b) {
|
|
||||||
return make_LinearSpace3f(lerp(factor, a.vx, b.vx), lerp(factor, a.vy, b.vy), lerp(factor, a.vz, b.vz));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline varying LinearSpace3f lerp(varying float factor, const uniform LinearSpace3f& a, const uniform LinearSpace3f& b) {
|
|
||||||
return make_LinearSpace3f(lerp(factor, a.vx, b.vx), lerp(factor, a.vy, b.vy), lerp(factor, a.vz, b.vz));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline varying LinearSpace3f lerp(varying float factor, const varying LinearSpace3f& a, const varying LinearSpace3f& b) {
|
|
||||||
return make_LinearSpace3f(lerp(factor, a.vx, b.vx), lerp(factor, a.vy, b.vy), lerp(factor, a.vz, b.vz));
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Norms
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
inline uniform float norm_1(const uniform LinearSpace3f& l)
|
|
||||||
{
|
|
||||||
uniform float sum = 0;
|
|
||||||
sum += reduce_add(abs(l.vx));
|
|
||||||
sum += reduce_add(abs(l.vy));
|
|
||||||
sum += reduce_add(abs(l.vz));
|
|
||||||
return sum / 9.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uniform Quaternion3f make_Quaternion3f(const uniform LinearSpace3f & l)
|
|
||||||
{
|
|
||||||
uniform Quaternion3f q;
|
|
||||||
const uniform float tr = l.vx.x + l.vy.y + l.vz.z;
|
|
||||||
if (tr > 0)
|
|
||||||
{
|
|
||||||
const uniform float S = sqrt(tr+1.0) * 2;
|
|
||||||
q.r = 0.25 * S;
|
|
||||||
q.i = (l.vy.z - l.vz.y) / S;
|
|
||||||
q.j = (l.vz.x - l.vx.z) / S;
|
|
||||||
q.k = (l.vx.y - l.vy.x) / S;
|
|
||||||
}
|
|
||||||
else if ((l.vx.x > l.vy.y)&(l.vx.x > l.vz.z))
|
|
||||||
{
|
|
||||||
const uniform float S = sqrt(1.0 + l.vx.x - l.vy.y - l.vz.z) * 2;
|
|
||||||
q.r = (l.vy.z - l.vz.y) / S;
|
|
||||||
q.i = 0.25 * S;
|
|
||||||
q.j = (l.vy.x + l.vx.y) / S;
|
|
||||||
q.k = (l.vz.x + l.vx.z) / S;
|
|
||||||
}
|
|
||||||
else if (l.vy.y > l.vz.z)
|
|
||||||
{
|
|
||||||
const uniform float S = sqrt(1.0 + l.vy.y - l.vx.x - l.vz.z) * 2;
|
|
||||||
q.r = (l.vz.x - l.vx.z) / S;
|
|
||||||
q.i = (l.vy.x + l.vx.y) / S;
|
|
||||||
q.j = 0.25 * S;
|
|
||||||
q.k = (l.vz.y + l.vy.z) / S;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const uniform float S = sqrt(1.0 + l.vz.z - l.vx.x - l.vy.y) * 2;
|
|
||||||
q.r = (l.vx.y - l.vy.x) / S;
|
|
||||||
q.i = (l.vz.x + l.vx.z) / S;
|
|
||||||
q.j = (l.vz.y + l.vy.z) / S;
|
|
||||||
q.k = 0.25 * S;
|
|
||||||
}
|
|
||||||
return q;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline varying Quaternion3f make_Quaternion3f(const varying LinearSpace3f & l)
|
|
||||||
{
|
|
||||||
Quaternion3f q;
|
|
||||||
const float tr = l.vx.x + l.vy.y + l.vz.z;
|
|
||||||
if (tr > 0)
|
|
||||||
{
|
|
||||||
const float S = sqrt(tr+1.0) * 2;
|
|
||||||
q.r = 0.25 * S;
|
|
||||||
q.i = (l.vy.z - l.vz.y) / S;
|
|
||||||
q.j = (l.vz.x - l.vx.z) / S;
|
|
||||||
q.k = (l.vx.y - l.vy.x) / S;
|
|
||||||
}
|
|
||||||
else if ((l.vx.x > l.vy.y)&(l.vx.x > l.vz.z))
|
|
||||||
{
|
|
||||||
const float S = sqrt(1.0 + l.vx.x - l.vy.y - l.vz.z) * 2;
|
|
||||||
q.r = (l.vy.z - l.vz.y) / S;
|
|
||||||
q.i = 0.25 * S;
|
|
||||||
q.j = (l.vy.x + l.vx.y) / S;
|
|
||||||
q.k = (l.vz.x + l.vx.z) / S;
|
|
||||||
}
|
|
||||||
else if (l.vy.y > l.vz.z)
|
|
||||||
{
|
|
||||||
const float S = sqrt(1.0 + l.vy.y - l.vx.x - l.vz.z) * 2;
|
|
||||||
q.r = (l.vz.x - l.vx.z) / S;
|
|
||||||
q.i = (l.vy.x + l.vx.y) / S;
|
|
||||||
q.j = 0.25 * S;
|
|
||||||
q.k = (l.vz.y + l.vy.z) / S;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const float S = sqrt(1.0 + l.vz.z - l.vx.x - l.vy.y) * 2;
|
|
||||||
q.r = (l.vx.y - l.vy.x) / S;
|
|
||||||
q.i = (l.vz.x + l.vx.z) / S;
|
|
||||||
q.j = (l.vz.y + l.vy.z) / S;
|
|
||||||
q.k = 0.25 * S;
|
|
||||||
}
|
|
||||||
return q;
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../../../common/math/emath.h"
|
|
||||||
|
|
@ -1,184 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../common.isph"
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
|
||||||
// Constants
|
|
||||||
// ------------------------------------------------------------------
|
|
||||||
|
|
||||||
#define inf (1e100f)
|
|
||||||
#define pos_inf (1e100f)
|
|
||||||
#define neg_inf (-1e100f)
|
|
||||||
|
|
||||||
#define M_PI 3.14159265358979323846f
|
|
||||||
#define pi 3.14159265358979323846f
|
|
||||||
#define two_pi 6.283185307179586232f
|
|
||||||
#define four_pi 12.566370614359172464f
|
|
||||||
|
|
||||||
#define one_over_pi 0.31830988618379069122f
|
|
||||||
#define one_over_two_pi 0.15915494309189534561f
|
|
||||||
#define one_over_four_pi 0.079577471545947672804f
|
|
||||||
#define one_over_two_pi_sqr 0.050660591821168885722f
|
|
||||||
|
|
||||||
/*! c-style reciprocal. required since ispc 1.7 due to type changes in this version */
|
|
||||||
inline float rcpf(const float f) { return rcp(f); }
|
|
||||||
/*! c-style reciprocal. required since ispc 1.7 due to type changes in this version */
|
|
||||||
inline uniform float rcpf(const uniform float f) { return rcp(f); }
|
|
||||||
|
|
||||||
/*! c-style square root. */
|
|
||||||
inline float sqrtf(const float f) { return sqrt(f); }
|
|
||||||
/*! c-style square root */
|
|
||||||
inline uniform float sqrtf(const uniform float f) { return sqrt(f); }
|
|
||||||
|
|
||||||
/*! c-style reciprocal square root. */
|
|
||||||
inline float rsqrtf(const float f) { return rsqrt(f); }
|
|
||||||
/*! c-style reciprocal square root */
|
|
||||||
inline uniform float rsqrtf(const uniform float f) { return rsqrt(f); }
|
|
||||||
|
|
||||||
/*! square. */
|
|
||||||
inline float sqr(const float f) { return f*f; }
|
|
||||||
/*! square. */
|
|
||||||
inline uniform float sqr(const uniform float f) { return f*f; }
|
|
||||||
/*! c-style square. */
|
|
||||||
inline float sqrf(const float f) { return f*f; }
|
|
||||||
/*! c-style square */
|
|
||||||
inline uniform float sqrf(const uniform float f) { return f*f; }
|
|
||||||
|
|
||||||
/*! c-style pow function. */
|
|
||||||
inline float powf(const float a, const float b) { return pow(a,b); }
|
|
||||||
/*! c-style pow function */
|
|
||||||
inline uniform float powf(const uniform float a, const uniform float b) { return pow(a,b); }
|
|
||||||
|
|
||||||
|
|
||||||
/*! c-style cos. */
|
|
||||||
inline float cosf(const float f) { return cos(f); }
|
|
||||||
/*! c-style cos */
|
|
||||||
inline uniform float cosf(const uniform float f) { return cos(f); }
|
|
||||||
|
|
||||||
/*! c-style sin. */
|
|
||||||
inline float sinf(const float f) { return sin(f); }
|
|
||||||
/*! c-style sin */
|
|
||||||
inline uniform float sinf(const uniform float f) { return sin(f); }
|
|
||||||
|
|
||||||
/*! c-style exp. */
|
|
||||||
inline float expf(const float f) { return exp(f); }
|
|
||||||
/*! c-style exp */
|
|
||||||
inline uniform float expf(const uniform float f) { return exp(f); }
|
|
||||||
|
|
||||||
/*! c-style log. */
|
|
||||||
inline float logf(const float f) { return log(f); }
|
|
||||||
/*! c-style log */
|
|
||||||
inline uniform float logf(const uniform float f) { return log(f); }
|
|
||||||
|
|
||||||
/*! c-style abs. */
|
|
||||||
inline float absf(const float f) { return abs(f); }
|
|
||||||
/*! c-style abs */
|
|
||||||
inline uniform float absf(const uniform float f) { return abs(f); }
|
|
||||||
|
|
||||||
|
|
||||||
// inline float clamp(const float f) { return max(min(1.f,f),0.f); }
|
|
||||||
|
|
||||||
inline uniform float rcp_safe(uniform float f) { return rcpf((abs(f) < 1e-8f) ? 1e-8f : f); }
|
|
||||||
inline varying float rcp_safe(varying float f) { return rcpf((abs(f) < 1e-8f) ? 1e-8f : f); }
|
|
||||||
|
|
||||||
inline uniform float sqrt_safe(uniform float f) { return sqrt(max(f, 0.0f)); }
|
|
||||||
inline varying float sqrt_safe(varying float f) { return sqrt(max(f, 0.0f)); }
|
|
||||||
|
|
||||||
inline uniform float clamp (const uniform float v) { return max(0.0f,min(v,1.0f)); }
|
|
||||||
inline varying float clamp (const varying float v) { return max(0.0f,min(v,1.0f)); }
|
|
||||||
|
|
||||||
inline uniform float clamp (const uniform float v, const uniform float lower, const uniform float upper) { return max(lower,min(v,upper)); }
|
|
||||||
inline varying float clamp (const varying float v, const varying float lower, const varying float upper) { return max(lower,min(v,upper)); }
|
|
||||||
|
|
||||||
inline uniform int clamp (const uniform int v, const uniform int lower, const uniform int upper) { return max(lower,min(v,upper)); }
|
|
||||||
inline varying int clamp (const varying int v, const varying int lower, const varying int upper) { return max(lower,min(v,upper)); }
|
|
||||||
|
|
||||||
inline uniform float frac(const uniform float x) { return x - floor(x); }
|
|
||||||
inline varying float frac(const varying float x) { return x - floor(x); }
|
|
||||||
|
|
||||||
inline uniform float deg2rad (const uniform float x) { return x * 1.74532925199432957692e-2f; }
|
|
||||||
inline varying float deg2rad (const varying float x) { return x * 1.74532925199432957692e-2f; }
|
|
||||||
|
|
||||||
inline uniform float rad2deg (const uniform float x) { return x * 5.72957795130823208768e1f; }
|
|
||||||
inline varying float rad2deg (const varying float x) { return x * 5.72957795130823208768e1f; }
|
|
||||||
|
|
||||||
inline float cos2sin(const float f) { return sqrt(max(0.f, 1.f - sqr(f))); }
|
|
||||||
inline float sin2cos(const float f) { return cos2sin(f); }
|
|
||||||
|
|
||||||
inline uniform float nextafter(const uniform float a, const uniform float b)
|
|
||||||
{
|
|
||||||
//! Match the behavior of the C99 math.h function.
|
|
||||||
if (a == b) return(b);
|
|
||||||
|
|
||||||
//! We will compute the smallest representable floating increment or decrement around 'a'.
|
|
||||||
uniform float delta = (b > a) ? 1.0f : -1.0f;
|
|
||||||
|
|
||||||
//! Iteratively compute the positive or negative increment.
|
|
||||||
while (a + 0.5f * delta != a) delta *= 0.5f;
|
|
||||||
|
|
||||||
//! Return the smallest number greater than 'a' or the largest number smaller than 'a'.
|
|
||||||
return(a + delta);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define __define_lerp(TYPE) \
|
|
||||||
inline TYPE lerp(float factor, TYPE a, TYPE b) \
|
|
||||||
{ \
|
|
||||||
return (1-factor)* a + factor * b; \
|
|
||||||
} \
|
|
||||||
inline uniform TYPE lerp(uniform float factor, uniform TYPE a, uniform TYPE b) \
|
|
||||||
{ \
|
|
||||||
return (1-factor)* a + factor * b; \
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
__define_lerp(int8)
|
|
||||||
__define_lerp(int32)
|
|
||||||
__define_lerp(float)
|
|
||||||
__define_lerp(uint8)
|
|
||||||
__define_lerp(uint32)
|
|
||||||
|
|
||||||
#undef __define_lerp
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
|
||||||
// min4/max4, for all types
|
|
||||||
// ------------------------------------------------------------------
|
|
||||||
#define __define_op4T(MM,TYPE) \
|
|
||||||
inline uniform TYPE MM##4(uniform TYPE a, uniform TYPE b, \
|
|
||||||
uniform TYPE c, uniform TYPE d) \
|
|
||||||
{ \
|
|
||||||
return MM(a, MM(b, MM(c, d))); \
|
|
||||||
} \
|
|
||||||
inline varying TYPE MM##4(varying TYPE a, varying TYPE b, \
|
|
||||||
varying TYPE c, varying TYPE d) \
|
|
||||||
{ \
|
|
||||||
return MM(a, MM(b, MM(c, d))); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define __define_op4(MM) \
|
|
||||||
__define_op4T(MM,int8) \
|
|
||||||
__define_op4T(MM,int32) \
|
|
||||||
__define_op4T(MM,uint8) \
|
|
||||||
__define_op4T(MM,uint32) \
|
|
||||||
__define_op4T(MM,float) \
|
|
||||||
__define_op4T(MM,double)
|
|
||||||
|
|
||||||
__define_op4(min)
|
|
||||||
__define_op4(max)
|
|
||||||
|
|
||||||
#undef __define_op4T
|
|
||||||
#undef __define_op4
|
|
||||||
|
|
||||||
#define SIMILAR_EPSILON .00001f
|
|
||||||
inline float similar(float a, float b)
|
|
||||||
{
|
|
||||||
return absf(a - b) <= SIMILAR_EPSILON;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uniform float similar(uniform float a, uniform float b)
|
|
||||||
{
|
|
||||||
return absf(a - b) <= SIMILAR_EPSILON;
|
|
||||||
}
|
|
||||||
#undef SIMILAR_EPSILON
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../../../common/math/quaternion.h"
|
|
||||||
|
|
||||||
|
|
@ -1,124 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "vec.isph"
|
|
||||||
|
|
||||||
struct Quaternion3f
|
|
||||||
{
|
|
||||||
float r, i, j, k;
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// Constructors
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
inline uniform Quaternion3f make_Quaternion3f(const uniform Vec4f& v) {
|
|
||||||
uniform Quaternion3f q; q.r = v.x; q.i = v.y; q.j = v.z; q.k = v.w; return q;
|
|
||||||
}
|
|
||||||
inline varying Quaternion3f make_Quaternion3f(const varying Vec4f& v) {
|
|
||||||
Quaternion3f q; q.r = v.x; q.i = v.y; q.j = v.z; q.k = v.w; return q;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! return quaternion for rotation around arbitrary axis */
|
|
||||||
inline varying Quaternion3f make_Quaternion3f_rotate(const varying Vec3f& u, const varying float r) {
|
|
||||||
Quaternion3f q;
|
|
||||||
Vec3f uu = sin(0.5*r)*normalize(u);
|
|
||||||
|
|
||||||
q.r = cos(0.5*r);
|
|
||||||
q.i = uu.x;
|
|
||||||
q.j = uu.y;
|
|
||||||
q.k = uu.z;
|
|
||||||
return q;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! return quaternion for rotation around arbitrary axis */
|
|
||||||
inline uniform Quaternion3f make_Quaternion3f_rotate(const uniform Vec3f& u, const uniform float r) {
|
|
||||||
uniform Quaternion3f q;
|
|
||||||
uniform Vec3f uu = sin(0.5*r)*normalize(u);
|
|
||||||
|
|
||||||
q.r = cos(0.5*r);
|
|
||||||
q.i = uu.x;
|
|
||||||
q.j = uu.y;
|
|
||||||
q.k = uu.z;
|
|
||||||
return q;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Unary Operators
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// Binary Operators
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
inline uniform Quaternion3f operator*(const uniform float a, const uniform Quaternion3f& q) { return make_Quaternion3f(a * make_Vec4f(q.r, q.i, q.j, q.k)); }
|
|
||||||
inline uniform Quaternion3f operator*(const uniform Quaternion3f& q, const uniform float a) { return make_Quaternion3f(a * make_Vec4f(q.r, q.i, q.j, q.k)); }
|
|
||||||
inline varying Quaternion3f operator*(const varying float a, const uniform Quaternion3f& q) { return make_Quaternion3f(a * make_Vec4f(q.r, q.i, q.j, q.k)); }
|
|
||||||
inline varying Quaternion3f operator*(const uniform Quaternion3f& q, const varying float a) { return make_Quaternion3f(a * make_Vec4f(q.r, q.i, q.j, q.k)); }
|
|
||||||
inline varying Quaternion3f operator*(const varying float a, const varying Quaternion3f& q) { return make_Quaternion3f(a * make_Vec4f(q.r, q.i, q.j, q.k)); }
|
|
||||||
inline varying Quaternion3f operator*(const varying Quaternion3f& q, const varying float a) { return make_Quaternion3f(a * make_Vec4f(q.r, q.i, q.j, q.k)); }
|
|
||||||
inline uniform Quaternion3f operator+(const uniform Quaternion3f& q0, const uniform Quaternion3f& q1) { return make_Quaternion3f(make_Vec4f(q0.r+q1.r, q0.i+q1.i, q0.j+q1.j, q0.k+q1.k)); }
|
|
||||||
inline uniform Quaternion3f operator-(const uniform Quaternion3f& q0, const uniform Quaternion3f& q1) { return make_Quaternion3f(make_Vec4f(q0.r-q1.r, q0.i-q1.i, q0.j-q1.j, q0.k-q1.k)); }
|
|
||||||
inline varying Quaternion3f operator+(const varying Quaternion3f& q0, const varying Quaternion3f& q1) { return make_Quaternion3f(make_Vec4f(q0.r+q1.r, q0.i+q1.i, q0.j+q1.j, q0.k+q1.k)); }
|
|
||||||
inline varying Quaternion3f operator-(const varying Quaternion3f& q0, const varying Quaternion3f& q1) { return make_Quaternion3f(make_Vec4f(q0.r-q1.r, q0.i-q1.i, q0.j-q1.j, q0.k-q1.k)); }
|
|
||||||
|
|
||||||
inline uniform float dot(const uniform Quaternion3f& q0, const uniform Quaternion3f& q1) { return q0.r*q1.r + q0.i*q1.i + q0.j*q1.j + q0.k*q1.k; }
|
|
||||||
inline varying float dot(const varying Quaternion3f& q0, const varying Quaternion3f& q1) { return q0.r*q1.r + q0.i*q1.i + q0.j*q1.j + q0.k*q1.k; }
|
|
||||||
inline uniform Quaternion3f normalize(const uniform Quaternion3f& q) { uniform const float len = sqrt(dot(q, q)); return make_Quaternion3f(make_Vec4f(q.r/len, q.i/len, q.j/len, q.k/len)); }
|
|
||||||
inline varying Quaternion3f normalize(const varying Quaternion3f& q) { varying const float len = sqrt(dot(q, q)); return make_Quaternion3f(make_Vec4f(q.r/len, q.i/len, q.j/len, q.k/len)); }
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// Comparison Operators
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Interpolation
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
inline uniform Quaternion3f lerp(const uniform factor, const uniform Quaternion3f& a, const uniform Quaternion3f& b) {
|
|
||||||
return make_Quaternion3f(lerp(factor, make_Vec4f(a.r, a.i, a.j, a.k), make_Vec4f(b.r, b.i, b.j, b.k)));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline varying Quaternion3f lerp(const varying factor, const uniform Quaternion3f& a, const uniform Quaternion3f& b) {
|
|
||||||
return make_Quaternion3f(lerp(factor, make_Vec4f(a.r, a.i, a.j, a.k), make_Vec4f(b.r, b.i, b.j, b.k)));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uniform Quaternion3f slerp(const uniform float factor, const uniform Quaternion3f& q1, const uniform Quaternion3f& q2)
|
|
||||||
{
|
|
||||||
uniform const float cosTheta = dot(q1, q2);
|
|
||||||
if (cosTheta > .9995f)
|
|
||||||
return normalize((1 - factor) * q1 + factor * q2);
|
|
||||||
else {
|
|
||||||
uniform const float theta = acos(clamp(cosTheta, -1.f, 1.f));
|
|
||||||
uniform const float thetap = theta * factor;
|
|
||||||
uniform Quaternion3f qperp = normalize(q2 - q1 * cosTheta);
|
|
||||||
return q1 * cos(thetap) + qperp * sin(thetap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline varying Quaternion3f slerp(const varying float factor, const uniform Quaternion3f& q1, const uniform Quaternion3f& q2)
|
|
||||||
{
|
|
||||||
uniform const float cosTheta = dot(q1, q2);
|
|
||||||
if (cosTheta > .9995f)
|
|
||||||
return normalize((1 - factor) * q1 + factor * q2);
|
|
||||||
else {
|
|
||||||
const float theta = acos(clamp(cosTheta, -1.f, 1.f));
|
|
||||||
const float thetap = theta * factor;
|
|
||||||
Quaternion3f qperp = normalize(q2 - q1 * cosTheta);
|
|
||||||
return q1 * cos(thetap) + qperp * sin(thetap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline varying Quaternion3f slerp(const varying float factor, const varying Quaternion3f& q1, const varying Quaternion3f& q2)
|
|
||||||
{
|
|
||||||
const float cosTheta = dot(q1, q2);
|
|
||||||
if (cosTheta > .9995f)
|
|
||||||
return normalize((1 - factor) * q1 + factor * q2);
|
|
||||||
else {
|
|
||||||
const float theta = acos(clamp(cosTheta, -1.f, 1.f));
|
|
||||||
const float thetap = theta * factor;
|
|
||||||
Quaternion3f qperp = normalize(q2 - q1 * cosTheta);
|
|
||||||
return q1 * cos(thetap) + qperp * sin(thetap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,114 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../math/vec.h"
|
|
||||||
|
|
||||||
namespace embree {
|
|
||||||
|
|
||||||
struct RandomSampler
|
|
||||||
{
|
|
||||||
unsigned int s;
|
|
||||||
};
|
|
||||||
|
|
||||||
__forceinline unsigned int MurmurHash3_mix(unsigned int hash, unsigned int k)
|
|
||||||
{
|
|
||||||
const unsigned int c1 = 0xcc9e2d51;
|
|
||||||
const unsigned int c2 = 0x1b873593;
|
|
||||||
const unsigned int r1 = 15;
|
|
||||||
const unsigned int r2 = 13;
|
|
||||||
const unsigned int m = 5;
|
|
||||||
const unsigned int n = 0xe6546b64;
|
|
||||||
|
|
||||||
k *= c1;
|
|
||||||
k = (k << r1) | (k >> (32 - r1));
|
|
||||||
k *= c2;
|
|
||||||
|
|
||||||
hash ^= k;
|
|
||||||
hash = ((hash << r2) | (hash >> (32 - r2))) * m + n;
|
|
||||||
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
__forceinline unsigned int MurmurHash3_finalize(unsigned int hash)
|
|
||||||
{
|
|
||||||
hash ^= hash >> 16;
|
|
||||||
hash *= 0x85ebca6b;
|
|
||||||
hash ^= hash >> 13;
|
|
||||||
hash *= 0xc2b2ae35;
|
|
||||||
hash ^= hash >> 16;
|
|
||||||
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
__forceinline unsigned int LCG_next(unsigned int value)
|
|
||||||
{
|
|
||||||
const unsigned int m = 1664525;
|
|
||||||
const unsigned int n = 1013904223;
|
|
||||||
|
|
||||||
return value * m + n;
|
|
||||||
}
|
|
||||||
|
|
||||||
__forceinline void RandomSampler_init(RandomSampler& self, int id)
|
|
||||||
{
|
|
||||||
unsigned int hash = 0;
|
|
||||||
hash = MurmurHash3_mix(hash, id);
|
|
||||||
hash = MurmurHash3_finalize(hash);
|
|
||||||
|
|
||||||
self.s = hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
__forceinline void RandomSampler_init(RandomSampler& self, int pixelId, int sampleId)
|
|
||||||
{
|
|
||||||
unsigned int hash = 0;
|
|
||||||
hash = MurmurHash3_mix(hash, pixelId);
|
|
||||||
hash = MurmurHash3_mix(hash, sampleId);
|
|
||||||
hash = MurmurHash3_finalize(hash);
|
|
||||||
|
|
||||||
self.s = hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
__forceinline void RandomSampler_init(RandomSampler& self, int x, int y, int sampleId)
|
|
||||||
{
|
|
||||||
RandomSampler_init(self, x | (y << 16), sampleId);
|
|
||||||
}
|
|
||||||
|
|
||||||
__forceinline int RandomSampler_getInt(RandomSampler& self) {
|
|
||||||
self.s = LCG_next(self.s); return self.s >> 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
__forceinline unsigned int RandomSampler_getUInt(RandomSampler& self) {
|
|
||||||
self.s = LCG_next(self.s); return self.s;
|
|
||||||
}
|
|
||||||
|
|
||||||
__forceinline float RandomSampler_getFloat(RandomSampler& self) {
|
|
||||||
return (float)RandomSampler_getInt(self) * 4.656612873077392578125e-10f;
|
|
||||||
}
|
|
||||||
|
|
||||||
__forceinline float RandomSampler_get1D(RandomSampler& self) {
|
|
||||||
return RandomSampler_getFloat(self);
|
|
||||||
}
|
|
||||||
|
|
||||||
__forceinline Vec2f RandomSampler_get2D(RandomSampler& self)
|
|
||||||
{
|
|
||||||
const float u = RandomSampler_get1D(self);
|
|
||||||
const float v = RandomSampler_get1D(self);
|
|
||||||
return Vec2f(u,v);
|
|
||||||
}
|
|
||||||
|
|
||||||
__forceinline Vec3fa RandomSampler_get3D(RandomSampler& self)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
const float u = RandomSampler_get1D(self);
|
|
||||||
const float v = RandomSampler_get1D(self);
|
|
||||||
const float w = RandomSampler_get1D(self);
|
|
||||||
return Vec3fa(u,v,w);
|
|
||||||
*/
|
|
||||||
const int u = RandomSampler_getUInt(self);
|
|
||||||
const int v = RandomSampler_getUInt(self);
|
|
||||||
const int w = RandomSampler_getUInt(self);
|
|
||||||
return Vec3fa(srl(Vec3ia(u,v,w), 1)) * 4.656612873077392578125e-10f;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace embree
|
|
||||||
|
|
@ -1,104 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../math/vec.isph"
|
|
||||||
|
|
||||||
struct RandomSampler
|
|
||||||
{
|
|
||||||
unsigned int s;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline unsigned int MurmurHash3_mix(unsigned int hash, unsigned int k)
|
|
||||||
{
|
|
||||||
const unsigned int c1 = 0xcc9e2d51;
|
|
||||||
const unsigned int c2 = 0x1b873593;
|
|
||||||
const unsigned int r1 = 15;
|
|
||||||
const unsigned int r2 = 13;
|
|
||||||
const unsigned int m = 5;
|
|
||||||
const unsigned int 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 unsigned int MurmurHash3_finalize(unsigned int hash)
|
|
||||||
{
|
|
||||||
hash ^= hash >> 16;
|
|
||||||
hash *= 0x85ebca6b;
|
|
||||||
hash ^= hash >> 13;
|
|
||||||
hash *= 0xc2b2ae35;
|
|
||||||
hash ^= hash >> 16;
|
|
||||||
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline unsigned int LCG_next(unsigned int value)
|
|
||||||
{
|
|
||||||
const unsigned int m = 1664525;
|
|
||||||
const unsigned int n = 1013904223;
|
|
||||||
|
|
||||||
return value * m + n;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void RandomSampler_init(RandomSampler& self, int id)
|
|
||||||
{
|
|
||||||
unsigned int hash = 0;
|
|
||||||
hash = MurmurHash3_mix(hash, id);
|
|
||||||
hash = MurmurHash3_finalize(hash);
|
|
||||||
|
|
||||||
self.s = hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void RandomSampler_init(RandomSampler& self, int pixelId, int sampleId)
|
|
||||||
{
|
|
||||||
unsigned int hash = 0;
|
|
||||||
hash = MurmurHash3_mix(hash, pixelId);
|
|
||||||
hash = MurmurHash3_mix(hash, sampleId);
|
|
||||||
hash = MurmurHash3_finalize(hash);
|
|
||||||
|
|
||||||
self.s = hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void RandomSampler_init(RandomSampler& self, int x, int y, int sampleId)
|
|
||||||
{
|
|
||||||
RandomSampler_init(self, x | (y << 16), sampleId);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int RandomSampler_getInt(RandomSampler& self) {
|
|
||||||
self.s = LCG_next(self.s); return self.s >> 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline unsigned int RandomSampler_getUInt(RandomSampler& self) {
|
|
||||||
self.s = LCG_next(self.s); return self.s;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline float RandomSampler_getFloat(RandomSampler& self) {
|
|
||||||
return (float)RandomSampler_getInt(self) * 4.656612873077392578125e-10f;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline float RandomSampler_get1D(RandomSampler& self) {
|
|
||||||
return RandomSampler_getFloat(self);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Vec2f RandomSampler_get2D(RandomSampler& self)
|
|
||||||
{
|
|
||||||
const float u = RandomSampler_get1D(self);
|
|
||||||
const float v = RandomSampler_get1D(self);
|
|
||||||
return make_Vec2f(u,v);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Vec3fa RandomSampler_get3D(RandomSampler& self)
|
|
||||||
{
|
|
||||||
const float u = RandomSampler_get1D(self);
|
|
||||||
const float v = RandomSampler_get1D(self);
|
|
||||||
const float w = RandomSampler_get1D(self);
|
|
||||||
return make_Vec3fa(u,v,w);
|
|
||||||
}
|
|
||||||
|
|
@ -1,159 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
/*! \brief utility library containing sampling functions */
|
|
||||||
|
|
||||||
// convention is to return the sample (Vec3fa) 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 "../math/vec.h"
|
|
||||||
#include "../math/linearspace.h"
|
|
||||||
|
|
||||||
namespace embree {
|
|
||||||
|
|
||||||
struct Sample3f
|
|
||||||
{
|
|
||||||
Vec3fa v;
|
|
||||||
float pdf;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline Sample3f make_Sample3f(const Vec3fa& v, const float pdf) {
|
|
||||||
Sample3f s; s.v = v; s.pdf = pdf; return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(ISPC)
|
|
||||||
inline Sample3f make_Sample3f(const Vec3fa& v, const float pdf) {
|
|
||||||
Sample3f s; s.v = v; s.pdf = pdf; return s;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
inline Vec3fa cartesian(const float phi, const float sinTheta, const float cosTheta)
|
|
||||||
{
|
|
||||||
const float sinPhi = sinf(phi);
|
|
||||||
const float cosPhi = cosf(phi);
|
|
||||||
//sincosf(phi, &sinPhi, &cosPhi);
|
|
||||||
return Vec3fa(cosPhi * sinTheta,
|
|
||||||
sinPhi * sinTheta,
|
|
||||||
cosTheta);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Vec3fa cartesian(const float phi, const float cosTheta)
|
|
||||||
{
|
|
||||||
return cartesian(phi, cos2sin(cosTheta), cosTheta);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// cosine-weighted sampling of hemisphere oriented along the +z-axis
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
inline Vec3fa cosineSampleHemisphere(const Vec2f s)
|
|
||||||
{
|
|
||||||
const float phi = 2.0f * float(M_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 Vec3fa &dir)
|
|
||||||
{
|
|
||||||
return dir.z / float(M_PI);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline float cosineSampleHemispherePDF(float cosTheta)
|
|
||||||
{
|
|
||||||
return cosTheta / float(M_PI);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Cosine weighted hemisphere sampling. Up direction is provided as argument. */
|
|
||||||
inline Sample3f cosineSampleHemisphere(const float u, const float v, const Vec3fa& N)
|
|
||||||
{
|
|
||||||
Vec3fa localDir = cosineSampleHemisphere(Vec2f(u,v));
|
|
||||||
Sample3f s;
|
|
||||||
s.v = frame(N) * localDir;
|
|
||||||
s.pdf = cosineSampleHemispherePDF(localDir);
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// power cosine-weighted sampling of hemisphere oriented along the +z-axis
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
inline Vec3fa 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) * (0.5f / float(M_PI)) * pow(cosTheta, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline float powerCosineSampleHemispherePDF(const Vec3fa& dir, const float n) // TODO: order of arguments
|
|
||||||
{
|
|
||||||
return (n + 1.0f) * (0.5f / float(M_PI)) * pow(dir.z, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// sampling of cone of directions oriented along the +z-axis
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
inline Vec3fa 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));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline float _uniformSampleConePDF(const float cosAngle)
|
|
||||||
{
|
|
||||||
return rcp(float(two_pi)*(1.0f - cosAngle));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// sampling of disk
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
inline Vec3fa uniformSampleDisk(const float radius, const Vec2f &s)
|
|
||||||
{
|
|
||||||
const float r = sqrtf(s.x) * radius;
|
|
||||||
const float phi =float(two_pi) * s.y;
|
|
||||||
const float sinPhi = sinf(phi);
|
|
||||||
const float cosPhi = cosf(phi);
|
|
||||||
//sincosf(phi, &sinPhi, &cosPhi);
|
|
||||||
return Vec3fa(r * cosPhi, r * sinPhi, 0.f);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline float uniformSampleDiskPDF(const float radius)
|
|
||||||
{
|
|
||||||
return rcp(float(M_PI) * sqr(radius));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline float _uniformSampleDiskPDF(const float radius)
|
|
||||||
{
|
|
||||||
return rcp(float(M_PI) * sqr(radius));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// sampling of triangle abc
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
inline Vec3fa uniformSampleTriangle(const Vec3fa &a, const Vec3fa &b, const Vec3fa &c, const Vec2f &s)
|
|
||||||
{
|
|
||||||
const float su = sqrtf(s.x);
|
|
||||||
return c + (1.0f - su) * (a-c) + (s.y*su) * (b-c);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline float uniformSampleTrianglePDF(const Vec3fa &a, const Vec3fa &b, const Vec3fa &c)
|
|
||||||
{
|
|
||||||
return 2.0f * rcp(abs(length(cross(a-c, b-c))));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace embree
|
|
||||||
|
|
@ -1,155 +0,0 @@
|
||||||
// Copyright 2009-2021 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 "../math/vec.isph"
|
|
||||||
#include "../math/linearspace.isph"
|
|
||||||
|
|
||||||
struct Sample3f
|
|
||||||
{
|
|
||||||
Vec3f v;
|
|
||||||
float pdf;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline uniform Sample3f make_Sample3f(const uniform Vec3f& v, const uniform float pdf) {
|
|
||||||
uniform Sample3f s; s.v = v; s.pdf = pdf; return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(ISPC)
|
|
||||||
inline Sample3f make_Sample3f(const Vec3f& v, const float pdf) {
|
|
||||||
Sample3f s; s.v = v; s.pdf = pdf; return s;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
inline Vec3f cartesian(const float phi, const float sinTheta, const float cosTheta)
|
|
||||||
{
|
|
||||||
const float sinPhi = sinf(phi);
|
|
||||||
const float cosPhi = cosf(phi);
|
|
||||||
//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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// cosine-weighted sampling of hemisphere oriented along the +z-axis
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
inline Vec3f cosineSampleHemisphere(const Vec2f s)
|
|
||||||
{
|
|
||||||
const float phi = 2.0f * M_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 / M_PI;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline float cosineSampleHemispherePDF(float cosTheta)
|
|
||||||
{
|
|
||||||
return cosTheta / M_PI;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Cosine weighted hemisphere sampling. Up direction is provided as argument. */
|
|
||||||
inline Sample3f cosineSampleHemisphere(const float u, const float v, const Vec3f& N)
|
|
||||||
{
|
|
||||||
Vec3f localDir = cosineSampleHemisphere(make_Vec2f(u,v));
|
|
||||||
Sample3f s;
|
|
||||||
s.v = frame(N) * localDir;
|
|
||||||
s.pdf = cosineSampleHemispherePDF(localDir);
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// power cosine-weighted sampling of hemisphere oriented along the +z-axis
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
inline Vec3f powerCosineSampleHemisphere(const float n, const Vec2f &s)
|
|
||||||
{
|
|
||||||
const float phi = 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) * (0.5f / M_PI) * pow(cosTheta, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline float powerCosineSampleHemispherePDF(const Vec3f& dir, const float n) // TODO: order of arguments
|
|
||||||
{
|
|
||||||
return (n + 1.0f) * (0.5f / M_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 = 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(two_pi*(1.0f - cosAngle));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uniform float uniformSampleConePDF(const uniform float cosAngle)
|
|
||||||
{
|
|
||||||
return rcp(two_pi*(1.0f - cosAngle));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// uniform sampling of disk
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
inline Vec3f uniformSampleDisk(const float radius, const Vec2f &s)
|
|
||||||
{
|
|
||||||
const float r = sqrtf(s.x) * radius;
|
|
||||||
const float phi = two_pi * s.y;
|
|
||||||
const float sinPhi = sinf(phi);
|
|
||||||
const float cosPhi = cosf(phi);
|
|
||||||
//sincos(phi, &sinPhi, &cosPhi);
|
|
||||||
return make_Vec3f(r * cosPhi, r * sinPhi, 0.f);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline float uniformSampleDiskPDF(const float radius)
|
|
||||||
{
|
|
||||||
return rcp(M_PI * sqr(radius));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uniform float uniformSampleDiskPDF(const uniform float radius)
|
|
||||||
{
|
|
||||||
return rcp(M_PI * sqr(radius));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// uniform sampling of triangle abc
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
inline Vec3f uniformSampleTriangle(const Vec3f &a, const Vec3f &b, const Vec3f &c, const Vec2f &s)
|
|
||||||
{
|
|
||||||
const float su = sqrtf(s.x);
|
|
||||||
return c + (1.0f - su) * (a-c) + (s.y*su) * (b-c);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline float uniformSampleTrianglePDF(const Vec3f &a, const Vec3f &b, const Vec3f &c)
|
|
||||||
{
|
|
||||||
return 2.0f * rcp(abs(length(cross(a-c, b-c))));
|
|
||||||
}
|
|
||||||
|
|
@ -1,87 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../../../common/math/vec2.h"
|
|
||||||
#include "../../../common/math/vec3.h"
|
|
||||||
#include "../../../common/math/vec4.h"
|
|
||||||
|
|
||||||
namespace embree {
|
|
||||||
|
|
||||||
__forceinline Vec3f neg(const Vec3f& a ) { return -a; }
|
|
||||||
__forceinline Vec3fa neg(const Vec3fa& a) { return -a; }
|
|
||||||
__forceinline bool eq (const Vec3fa& a, const Vec3fa& b) { return a == b; }
|
|
||||||
__forceinline bool ne (const Vec3fa& a, const Vec3fa& b) { return a != b; }
|
|
||||||
|
|
||||||
// FIXME: change order of lerp arguments, then remove this function
|
|
||||||
template<typename V>
|
|
||||||
__forceinline V lerpr(float t, const V& v0, const V& v1) {
|
|
||||||
return (1.0f-t)*v0 + t*v1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// -------------------------------------------------------
|
|
||||||
// sRGB conversion functions
|
|
||||||
// -------------------------------------------------------
|
|
||||||
#define APPROXIMATE_SRGB
|
|
||||||
|
|
||||||
inline float linear_to_srgb(const float f)
|
|
||||||
{
|
|
||||||
const float c = max(f, 0.f);
|
|
||||||
#ifdef APPROXIMATE_SRGB
|
|
||||||
return pow(c, 1.f/2.2f);
|
|
||||||
#else
|
|
||||||
return c <= 0.0031308f ? 12.92f*c : pow(c, 1.f/2.4f)*1.055f - 0.055f;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Vec4f linear_to_srgba(const Vec4f c)
|
|
||||||
{
|
|
||||||
return Vec4f(linear_to_srgb(c.x),
|
|
||||||
linear_to_srgb(c.y),
|
|
||||||
linear_to_srgb(c.z),
|
|
||||||
max(c.w, 0.f)); // alpha is never gamma-corrected
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uint32_t linear_to_srgba8(const Vec4f c)
|
|
||||||
{
|
|
||||||
#if 1
|
|
||||||
Vec4f l = 255.f * min(linear_to_srgba(c), Vec4f(1.f));
|
|
||||||
return
|
|
||||||
((uint32_t)l.x << 0) |
|
|
||||||
((uint32_t)l.y << 8) |
|
|
||||||
((uint32_t)l.z << 16) |
|
|
||||||
((uint32_t)l.w << 24);
|
|
||||||
#else
|
|
||||||
// TODO use ISPC's float_to_srgb8 once it is fixed (issue #1198)
|
|
||||||
return
|
|
||||||
(float_to_srgb8(c.x) << 0) |
|
|
||||||
(float_to_srgb8(c.y) << 8) |
|
|
||||||
(float_to_srgb8(c.z) << 16) |
|
|
||||||
((uint32_t)clamp(c.w, 0.f, 1.f) << 24); // alpha is never gamma-corrected
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
inline float srgb_to_linear(const float f)
|
|
||||||
{
|
|
||||||
const float c = max(f, 0.f);
|
|
||||||
#ifdef APPROXIMATE_SRGB
|
|
||||||
return pow(c, 2.2f);
|
|
||||||
#else
|
|
||||||
return c <= 0.04045f ? c/12.92f : pow((c + 0.055f)/1.055f, 2.4f);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Vec4f srgba_to_linear(const Vec4f c)
|
|
||||||
{
|
|
||||||
return Vec4f(srgb_to_linear(c.x),
|
|
||||||
srgb_to_linear(c.y),
|
|
||||||
srgb_to_linear(c.z),
|
|
||||||
max(c.w, 0.f)); // alpha is never gamma-corrected
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO implement srgba8_to_linear with a 256 entry LUT
|
|
||||||
|
|
||||||
#undef APPROXIMATE_SRGB
|
|
||||||
|
|
||||||
} // namespace embree
|
|
||||||
|
|
@ -1,986 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "math.isph"
|
|
||||||
|
|
||||||
#define __define_ispc_vector2(TYPE,ABB) \
|
|
||||||
struct Vec2##ABB { \
|
|
||||||
TYPE x; TYPE y; \
|
|
||||||
}; \
|
|
||||||
|
|
||||||
#define __define_ispc_vector3(TYPE,ABB) \
|
|
||||||
struct Vec3##ABB { \
|
|
||||||
TYPE x,y,z; \
|
|
||||||
}; \
|
|
||||||
struct Vec3##ABB##a { \
|
|
||||||
TYPE x,y,z,w; \
|
|
||||||
}; \
|
|
||||||
|
|
||||||
#define __define_ispc_vector4(TYPE,ABB) \
|
|
||||||
struct Vec4##ABB { \
|
|
||||||
TYPE x,y,z,w; \
|
|
||||||
}; \
|
|
||||||
|
|
||||||
__define_ispc_vector2(int,i);
|
|
||||||
__define_ispc_vector2(unsigned int,ui);
|
|
||||||
__define_ispc_vector2(unsigned int8,uc);
|
|
||||||
__define_ispc_vector2(float,f);
|
|
||||||
|
|
||||||
__define_ispc_vector3(int,i);
|
|
||||||
__define_ispc_vector3(unsigned int,ui);
|
|
||||||
__define_ispc_vector3(unsigned int8,uc);
|
|
||||||
__define_ispc_vector3(float,f);
|
|
||||||
|
|
||||||
__define_ispc_vector4(int,i);
|
|
||||||
__define_ispc_vector4(unsigned int,ui);
|
|
||||||
__define_ispc_vector4(unsigned int8,uc);
|
|
||||||
__define_ispc_vector4(float,f);
|
|
||||||
|
|
||||||
#undef __define_ispc_vector2
|
|
||||||
#undef __define_ispc_vector3
|
|
||||||
#undef __define_ispc_vector4
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*! defines all constructors "make_Vec2[T]" for 2-vector type */
|
|
||||||
#define __define_ispc_constructors2(UV,TYPE,ABB,ITYPE,IABB) \
|
|
||||||
inline UV Vec2##ABB make_Vec2##ABB(const UV ITYPE x, \
|
|
||||||
const UV ITYPE y) \
|
|
||||||
{ \
|
|
||||||
UV Vec2##ABB ret; \
|
|
||||||
ret.x = x; \
|
|
||||||
ret.y = y; \
|
|
||||||
return ret; \
|
|
||||||
} \
|
|
||||||
inline UV Vec2##ABB make_Vec2##ABB(const UV ITYPE x) \
|
|
||||||
{ \
|
|
||||||
UV Vec2##ABB ret; \
|
|
||||||
ret.x = x; \
|
|
||||||
ret.y = x; \
|
|
||||||
return ret; \
|
|
||||||
} \
|
|
||||||
|
|
||||||
/*! defines all constructors "make_Vec3[T]" and "make_Vec3[T]a" for
|
|
||||||
3-vector type */
|
|
||||||
#define __define_ispc_constructors3(UV,TYPE,ABB,ITYPE,IABB) \
|
|
||||||
inline UV Vec3##ABB make_Vec3##ABB(const UV ITYPE x) \
|
|
||||||
{ \
|
|
||||||
UV Vec3##ABB ret; \
|
|
||||||
ret.x = x; \
|
|
||||||
ret.y = x; \
|
|
||||||
ret.z = x; \
|
|
||||||
return ret; \
|
|
||||||
} \
|
|
||||||
inline UV Vec3##ABB make_Vec3##ABB(const UV Vec3##IABB v) \
|
|
||||||
{ \
|
|
||||||
UV Vec3##ABB ret; \
|
|
||||||
ret.x = v.x; \
|
|
||||||
ret.y = v.y; \
|
|
||||||
ret.z = v.z; \
|
|
||||||
return ret; \
|
|
||||||
} \
|
|
||||||
inline UV Vec3##ABB make_Vec3##ABB(const UV Vec3##IABB##a v) \
|
|
||||||
{ \
|
|
||||||
UV Vec3##ABB ret; \
|
|
||||||
ret.x = v.x; \
|
|
||||||
ret.y = v.y; \
|
|
||||||
ret.z = v.z; \
|
|
||||||
return ret; \
|
|
||||||
} \
|
|
||||||
inline UV Vec3##ABB make_Vec3##ABB(const UV ITYPE x, \
|
|
||||||
const UV ITYPE y, \
|
|
||||||
const UV ITYPE z) \
|
|
||||||
{ \
|
|
||||||
UV Vec3##ABB ret; \
|
|
||||||
ret.x = x; \
|
|
||||||
ret.y = y; \
|
|
||||||
ret.z = z; \
|
|
||||||
return ret; \
|
|
||||||
} \
|
|
||||||
inline UV Vec3##ABB make_Vec3##ABB(const UV Vec4##IABB v) \
|
|
||||||
{ \
|
|
||||||
UV Vec3##ABB ret; \
|
|
||||||
ret.x = v.x; \
|
|
||||||
ret.y = v.y; \
|
|
||||||
ret.z = v.z; \
|
|
||||||
return ret; \
|
|
||||||
} \
|
|
||||||
/* the '3a' variants */ \
|
|
||||||
inline UV Vec3##ABB##a make_Vec3##ABB##a(const UV ITYPE x) \
|
|
||||||
{ \
|
|
||||||
UV Vec3##ABB##a ret; \
|
|
||||||
ret.x = x; \
|
|
||||||
ret.y = x; \
|
|
||||||
ret.z = x; \
|
|
||||||
ret.w = 0; \
|
|
||||||
return ret; \
|
|
||||||
} \
|
|
||||||
inline UV Vec3##ABB##a make_Vec3##ABB##a(const UV Vec3##IABB &v) \
|
|
||||||
{ \
|
|
||||||
UV Vec3##ABB##a ret; \
|
|
||||||
ret.x = v.x; \
|
|
||||||
ret.y = v.y; \
|
|
||||||
ret.z = v.z; \
|
|
||||||
ret.w = 0; \
|
|
||||||
return ret; \
|
|
||||||
} \
|
|
||||||
inline UV Vec3##ABB##a make_Vec3##ABB##a(const UV Vec3##IABB##a v) \
|
|
||||||
{ \
|
|
||||||
UV Vec3##ABB##a ret; \
|
|
||||||
ret.x = v.x; \
|
|
||||||
ret.y = v.y; \
|
|
||||||
ret.z = v.z; \
|
|
||||||
ret.w = v.w; \
|
|
||||||
return ret; \
|
|
||||||
} \
|
|
||||||
inline UV Vec3##ABB##a make_Vec3##ABB##a(const UV ITYPE x, \
|
|
||||||
const UV ITYPE y, \
|
|
||||||
const UV ITYPE z) \
|
|
||||||
{ \
|
|
||||||
UV Vec3##ABB##a ret; \
|
|
||||||
ret.x = x; \
|
|
||||||
ret.y = y; \
|
|
||||||
ret.z = z; \
|
|
||||||
ret.w = 0; \
|
|
||||||
return ret; \
|
|
||||||
} \
|
|
||||||
inline UV Vec3##ABB##a make_Vec3##ABB##a(const UV ITYPE x, \
|
|
||||||
const UV ITYPE y, \
|
|
||||||
const UV ITYPE z, \
|
|
||||||
const UV ITYPE w) \
|
|
||||||
{ \
|
|
||||||
UV Vec3##ABB##a ret; \
|
|
||||||
ret.x = x; \
|
|
||||||
ret.y = y; \
|
|
||||||
ret.z = z; \
|
|
||||||
ret.w = w; \
|
|
||||||
return ret; \
|
|
||||||
} \
|
|
||||||
inline UV Vec3##ABB##a make_Vec3##ABB##a(const UV Vec3##IABB &v, \
|
|
||||||
const UV ITYPE w) \
|
|
||||||
{ \
|
|
||||||
UV Vec3##ABB##a ret; \
|
|
||||||
ret.x = v.x; \
|
|
||||||
ret.y = v.y; \
|
|
||||||
ret.z = v.z; \
|
|
||||||
ret.w = w; \
|
|
||||||
return ret; \
|
|
||||||
} \
|
|
||||||
inline UV Vec3##ABB##a make_Vec3##ABB##a(const UV Vec4##IABB v) \
|
|
||||||
{ \
|
|
||||||
UV Vec3##ABB##a ret; \
|
|
||||||
ret.x = v.x; \
|
|
||||||
ret.y = v.y; \
|
|
||||||
ret.z = v.z; \
|
|
||||||
ret.w = v.w; \
|
|
||||||
return ret; \
|
|
||||||
} \
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*! defines all constructors "make_Vec4[T]" for 4-vector type */
|
|
||||||
#define __define_ispc_constructors4(UV,TYPE,ABB,ITYPE,IABB) \
|
|
||||||
/*! construct Vec4 from a single scalar */ \
|
|
||||||
inline UV Vec4##ABB make_Vec4##ABB(const UV ITYPE f) \
|
|
||||||
{ \
|
|
||||||
UV Vec4##ABB ret; \
|
|
||||||
ret.x = f; \
|
|
||||||
ret.y = f; \
|
|
||||||
ret.z = f; \
|
|
||||||
ret.w = f; \
|
|
||||||
return ret; \
|
|
||||||
} \
|
|
||||||
/*! construct Vec4 from a 4 scalars */ \
|
|
||||||
inline UV Vec4##ABB make_Vec4##ABB(const UV ITYPE x, \
|
|
||||||
const UV ITYPE y, \
|
|
||||||
const UV ITYPE z, \
|
|
||||||
const UV ITYPE w) \
|
|
||||||
{ \
|
|
||||||
UV Vec4##ABB ret; \
|
|
||||||
ret.x = x; \
|
|
||||||
ret.y = y; \
|
|
||||||
ret.z = z; \
|
|
||||||
ret.w = w; \
|
|
||||||
return ret; \
|
|
||||||
} \
|
|
||||||
/*! construct Vec4 from another Vec4 (of another type) */ \
|
|
||||||
inline UV Vec4##ABB make_Vec4##ABB(const UV Vec4##IABB v) \
|
|
||||||
{ \
|
|
||||||
UV Vec4##ABB ret; \
|
|
||||||
ret.x = v.x; \
|
|
||||||
ret.y = v.y; \
|
|
||||||
ret.z = v.z; \
|
|
||||||
ret.w = v.w; \
|
|
||||||
return ret; \
|
|
||||||
} \
|
|
||||||
|
|
||||||
|
|
||||||
#define __define_ispc_lift_constructors4(UV,TYPE,ABB) \
|
|
||||||
/*! lift Vec4 from Vec3; fill in with 0es */ \
|
|
||||||
inline UV Vec4##ABB make_Vec4##ABB(const UV Vec3##ABB v) \
|
|
||||||
{ \
|
|
||||||
UV Vec4##ABB ret; \
|
|
||||||
ret.x = (TYPE)v.x; \
|
|
||||||
ret.y = (TYPE)v.y; \
|
|
||||||
ret.z = (TYPE)v.z; \
|
|
||||||
ret.w = (TYPE)0; \
|
|
||||||
return ret; \
|
|
||||||
} \
|
|
||||||
|
|
||||||
#define __define_ispc_constructors_uv_t(UV,OTYPE,OABB,ITYPE,IABB) \
|
|
||||||
__define_ispc_constructors2(UV,OTYPE,OABB,ITYPE,IABB) \
|
|
||||||
__define_ispc_constructors3(UV,OTYPE,OABB,ITYPE,IABB) \
|
|
||||||
__define_ispc_constructors4(UV,OTYPE,OABB,ITYPE,IABB) \
|
|
||||||
|
|
||||||
#define __define_ispc_constructors_uv(UV,TYPE,ABB) \
|
|
||||||
__define_ispc_constructors_uv_t(UV,TYPE,ABB,int,i) \
|
|
||||||
__define_ispc_constructors_uv_t(UV,TYPE,ABB,unsigned int,ui) \
|
|
||||||
__define_ispc_constructors_uv_t(UV,TYPE,ABB,unsigned int8,uc) \
|
|
||||||
__define_ispc_constructors_uv_t(UV,TYPE,ABB,float,f) \
|
|
||||||
__define_ispc_lift_constructors4(UV,TYPE,ABB) \
|
|
||||||
|
|
||||||
#define __define_ispc_constructors(UV) \
|
|
||||||
__define_ispc_constructors_uv(UV,unsigned int,ui) \
|
|
||||||
__define_ispc_constructors_uv(UV,unsigned int8,uc) \
|
|
||||||
__define_ispc_constructors_uv(UV,int,i) \
|
|
||||||
__define_ispc_constructors_uv(UV,float,f) \
|
|
||||||
|
|
||||||
__define_ispc_constructors(uniform);
|
|
||||||
__define_ispc_constructors(varying);
|
|
||||||
|
|
||||||
#undef __define_ispc_constructors2
|
|
||||||
#undef __define_ispc_constructors3
|
|
||||||
#undef __define_ispc_constructors3a
|
|
||||||
#undef __define_ispc_constructors4
|
|
||||||
#undef __define_ispc_lift_constructors4
|
|
||||||
#undef __define_ispc_constructors_uv
|
|
||||||
#undef __define_ispc_constructors
|
|
||||||
|
|
||||||
|
|
||||||
// =======================================================
|
|
||||||
// define 'lifted' binary operators (min/max/...)
|
|
||||||
|
|
||||||
#define __lift_binaryFct(FCT,T) \
|
|
||||||
/* ********************************************************* */ \
|
|
||||||
/* ---- Vec2 ---- */ \
|
|
||||||
/* ********************************************************* */ \
|
|
||||||
/* uniform Vec2 FCT(uniform Vec2, uniform Vec2) */ \
|
|
||||||
inline uniform Vec2##T FCT(const uniform Vec2##T a, \
|
|
||||||
const uniform Vec2##T b) \
|
|
||||||
{ return make_Vec2##T(FCT(a.x,b.x),FCT(a.y,b.y)); } \
|
|
||||||
/* Vec2 FCT(Vec2, Vec2) */ \
|
|
||||||
inline varying Vec2##T FCT(const varying Vec2##T a, \
|
|
||||||
const varying Vec2##T b) \
|
|
||||||
{ return make_Vec2##T(FCT(a.x,b.x),FCT(a.y,b.y)); } \
|
|
||||||
/* Vec2 FCT(Vec2, uniform Vec2) */ \
|
|
||||||
inline varying Vec2##T FCT(const varying Vec2##T a, \
|
|
||||||
const uniform Vec2##T b) \
|
|
||||||
{ return make_Vec2##T(FCT(a.x,b.x),FCT(a.y,b.y)); } \
|
|
||||||
/* Vec2 FCT(uniform Vec2, Vec2) */ \
|
|
||||||
inline varying Vec2##T FCT(const uniform Vec2##T a, \
|
|
||||||
const varying Vec2##T b) \
|
|
||||||
{ return make_Vec2##T(FCT(a.x,b.x),FCT(a.y,b.y)); } \
|
|
||||||
\
|
|
||||||
/* ********************************************************* */ \
|
|
||||||
/* ---- Vec3 ---- */ \
|
|
||||||
/* ********************************************************* */ \
|
|
||||||
/* uniform Vec3 FCT(uniform Vec3, uniform Vec3) */ \
|
|
||||||
inline uniform Vec3##T FCT(const uniform Vec3##T a, \
|
|
||||||
const uniform Vec3##T b) \
|
|
||||||
{ return make_Vec3##T(FCT(a.x,b.x),FCT(a.y,b.y),FCT(a.z,b.z)); } \
|
|
||||||
/* Vec3 FCT(Vec3, Vec3) */ \
|
|
||||||
inline varying Vec3##T FCT(const varying Vec3##T a, \
|
|
||||||
const varying Vec3##T b) \
|
|
||||||
{ return make_Vec3##T(FCT(a.x,b.x),FCT(a.y,b.y),FCT(a.z,b.z)); } \
|
|
||||||
/* Vec3 FCT(uniformVec3, Vec3) */ \
|
|
||||||
inline varying Vec3##T FCT(const uniform Vec3##T a, \
|
|
||||||
const varying Vec3##T b) \
|
|
||||||
{ return make_Vec3##T(FCT(a.x,b.x),FCT(a.y,b.y),FCT(a.z,b.z)); } \
|
|
||||||
/* Vec3 FCT(Vec3, uniformVec3) */ \
|
|
||||||
inline varying Vec3##T FCT(const varying Vec3##T a, \
|
|
||||||
const uniform Vec3##T b) \
|
|
||||||
{ return make_Vec3##T(FCT(a.x,b.x),FCT(a.y,b.y),FCT(a.z,b.z)); } \
|
|
||||||
\
|
|
||||||
/* ********************************************************* */ \
|
|
||||||
/* ---- Vec3a (from 3a and 3a) ---- */ \
|
|
||||||
/* ********************************************************* */ \
|
|
||||||
/* uniform Vec3a FCT(uniform Vec3a, uniform Vec3a) */ \
|
|
||||||
inline uniform Vec3##T##a FCT(const uniform Vec3##T##a a, \
|
|
||||||
const uniform Vec3##T##a b) \
|
|
||||||
{ return make_Vec3##T##a(FCT(a.x,b.x),FCT(a.y,b.y),FCT(a.z,b.z),FCT(a.w,b.w)); } \
|
|
||||||
/* Vec3a FCT(Vec3a, Vec3a) */ \
|
|
||||||
inline varying Vec3##T##a FCT(const varying Vec3##T##a a, \
|
|
||||||
const varying Vec3##T##a b) \
|
|
||||||
{ return make_Vec3##T##a(FCT(a.x,b.x),FCT(a.y,b.y),FCT(a.z,b.z),FCT(a.w,b.w)); } \
|
|
||||||
\
|
|
||||||
/* ********************************************************* */ \
|
|
||||||
/* ---- Vec3a (from 3 and 3a) ---- */ \
|
|
||||||
/* ********************************************************* */ \
|
|
||||||
/* uniform Vec3a FCT(uniform Vec3a, uniform Vec3a) */ \
|
|
||||||
inline uniform Vec3##T##a FCT(const uniform Vec3##T a, \
|
|
||||||
const uniform Vec3##T##a b) \
|
|
||||||
{ return make_Vec3##T##a(FCT(a.x,b.x),FCT(a.y,b.y),FCT(a.z,b.z)); } \
|
|
||||||
/* Vec3a FCT(Vec3a, Vec3a) */ \
|
|
||||||
inline varying Vec3##T##a FCT(const varying Vec3##T a, \
|
|
||||||
const varying Vec3##T##a b) \
|
|
||||||
{ return make_Vec3##T##a(FCT(a.x,b.x),FCT(a.y,b.y),FCT(a.z,b.z)); } \
|
|
||||||
\
|
|
||||||
/* ********************************************************* */ \
|
|
||||||
/* ---- Vec3a (from 3a and 3) ---- */ \
|
|
||||||
/* ********************************************************* */ \
|
|
||||||
/* uniform Vec3a FCT(uniform Vec3a, uniform Vec3a) */ \
|
|
||||||
inline uniform Vec3##T##a FCT(const uniform Vec3##T##a a, \
|
|
||||||
const uniform Vec3##T b) \
|
|
||||||
{ return make_Vec3##T##a(FCT(a.x,b.x),FCT(a.y,b.y),FCT(a.z,b.z)); } \
|
|
||||||
/* Vec3a FCT(Vec3a, Vec3a) */ \
|
|
||||||
inline varying Vec3##T##a FCT(const varying Vec3##T##a a, \
|
|
||||||
const varying Vec3##T b) \
|
|
||||||
{ return make_Vec3##T##a(FCT(a.x,b.x),FCT(a.y,b.y),FCT(a.z,b.z)); } \
|
|
||||||
\
|
|
||||||
/* ********************************************************* */ \
|
|
||||||
/* ---- Vec4 ---- */ \
|
|
||||||
/* ********************************************************* */ \
|
|
||||||
/* uniform Vec4 FCT(uniform Vec4, uniform Vec4) */ \
|
|
||||||
inline uniform Vec4##T FCT(const uniform Vec4##T a, \
|
|
||||||
const uniform Vec4##T b) \
|
|
||||||
{ return make_Vec4##T(FCT(a.x,b.x),FCT(a.y,b.y), \
|
|
||||||
FCT(a.z,b.z),FCT(a.w,b.w)); } \
|
|
||||||
/* Vec4 FCT(Vec4, Vec4) */ \
|
|
||||||
inline varying Vec4##T FCT(const varying Vec4##T a, \
|
|
||||||
const varying Vec4##T b) \
|
|
||||||
{ return make_Vec4##T(FCT(a.x,b.x),FCT(a.y,b.y), \
|
|
||||||
FCT(a.z,b.z),FCT(a.w,b.w)); } \
|
|
||||||
|
|
||||||
__lift_binaryFct(min,f)
|
|
||||||
__lift_binaryFct(max,f)
|
|
||||||
__lift_binaryFct(min,i)
|
|
||||||
__lift_binaryFct(max,i)
|
|
||||||
__lift_binaryFct(min,ui)
|
|
||||||
__lift_binaryFct(max,ui)
|
|
||||||
|
|
||||||
#undef __lift_binaryFct
|
|
||||||
|
|
||||||
// =======================================================
|
|
||||||
|
|
||||||
// for now, let's implement those manually - should eventually do those via a macro!
|
|
||||||
|
|
||||||
inline uniform Vec3f neg(const uniform Vec3f v)
|
|
||||||
{ return make_Vec3f(-v.x,-v.y,-v.z); }
|
|
||||||
inline Vec3f neg(const Vec3f v)
|
|
||||||
{ return make_Vec3f(-v.x,-v.y,-v.z); }
|
|
||||||
inline uniform Vec3f negate(const uniform Vec3f &a)
|
|
||||||
{ return(make_Vec3f(-a.x, -a.y, -a.z)); }
|
|
||||||
inline varying Vec3f negate(const varying Vec3f &a)
|
|
||||||
{ return(make_Vec3f(-a.x, -a.y, -a.z)); }
|
|
||||||
|
|
||||||
|
|
||||||
#define __define_binary_operator_typed(opname,op,abb,type) \
|
|
||||||
/* Vec2##abb */ \
|
|
||||||
inline uniform Vec2##abb opname (const uniform Vec2##abb a, \
|
|
||||||
const uniform Vec2##abb b) { \
|
|
||||||
return make_Vec2##abb(a.x op b.x, a.y op b.y); \
|
|
||||||
} \
|
|
||||||
inline Vec2##abb opname (const Vec2##abb a, const Vec2##abb b) { \
|
|
||||||
return make_Vec2##abb(a.x op b.x, a.y op b.y); \
|
|
||||||
} \
|
|
||||||
inline uniform Vec2##abb opname (const uniform Vec2##abb a, \
|
|
||||||
const uniform type b) { \
|
|
||||||
return make_Vec2##abb(a.x op b, a.y op b); \
|
|
||||||
} \
|
|
||||||
inline Vec2##abb opname (const Vec2##abb a, const type b) { \
|
|
||||||
return make_Vec2##abb(a.x op b, a.y op b); \
|
|
||||||
} \
|
|
||||||
inline uniform Vec2##abb opname (const uniform type a, \
|
|
||||||
const uniform Vec2##abb b) { \
|
|
||||||
return make_Vec2##abb(a op b.x, a op b.y); \
|
|
||||||
} \
|
|
||||||
inline Vec2##abb opname (const type a, const Vec2##abb b) { \
|
|
||||||
return make_Vec2##abb(a op b.x, a op b.y); \
|
|
||||||
} \
|
|
||||||
/* Vec3##abb */ \
|
|
||||||
inline uniform Vec3##abb opname (const uniform Vec3##abb a, \
|
|
||||||
const uniform Vec3##abb b) { \
|
|
||||||
return make_Vec3##abb(a.x op b.x, a.y op b.y, a.z op b.z); \
|
|
||||||
} \
|
|
||||||
inline Vec3##abb opname (const Vec3##abb a, const Vec3##abb b) { \
|
|
||||||
return make_Vec3##abb(a.x op b.x, a.y op b.y, a.z op b.z); \
|
|
||||||
} \
|
|
||||||
inline uniform Vec3##abb opname (const uniform Vec3##abb a, \
|
|
||||||
const uniform type b) { \
|
|
||||||
return make_Vec3##abb(a.x op b, a.y op b, a.z op b); \
|
|
||||||
} \
|
|
||||||
inline Vec3##abb opname (const Vec3##abb a, const type b) { \
|
|
||||||
return make_Vec3##abb(a.x op b, a.y op b, a.z op b); \
|
|
||||||
} \
|
|
||||||
inline uniform Vec3##abb opname (const uniform type a, \
|
|
||||||
const uniform Vec3##abb b) { \
|
|
||||||
return make_Vec3##abb(a op b.x, a op b.y, a op b.z); \
|
|
||||||
} \
|
|
||||||
inline Vec3##abb opname (const type a, const Vec3##abb b) { \
|
|
||||||
return make_Vec3##abb(a op b.x, a op b.y, a op b.z); \
|
|
||||||
} \
|
|
||||||
/* Vec3##abb##a */ \
|
|
||||||
inline uniform Vec3##abb##a opname (const uniform Vec3##abb##a a, \
|
|
||||||
const uniform Vec3##abb##a b) { \
|
|
||||||
return make_Vec3##abb##a(a.x op b.x, a.y op b.y, a.z op b.z, a.w op b.w); \
|
|
||||||
} \
|
|
||||||
inline Vec3##abb##a opname (const Vec3##abb##a a, const Vec3##abb##a b) { \
|
|
||||||
return make_Vec3##abb##a(a.x op b.x, a.y op b.y, a.z op b.z, a.w op b.w); \
|
|
||||||
} \
|
|
||||||
inline uniform Vec3##abb##a opname (const uniform Vec3##abb##a a, \
|
|
||||||
const uniform type b) { \
|
|
||||||
return make_Vec3##abb##a(a.x op b, a.y op b, a.z op b, a.w op b); \
|
|
||||||
} \
|
|
||||||
inline Vec3##abb##a opname (const Vec3##abb##a a, const type b) { \
|
|
||||||
return make_Vec3##abb##a(a.x op b, a.y op b, a.z op b, a.w op b); \
|
|
||||||
} \
|
|
||||||
inline uniform Vec3##abb##a opname (const uniform type a, \
|
|
||||||
const uniform Vec3##abb##a b) { \
|
|
||||||
return make_Vec3##abb##a(a op b.x, a op b.y, a op b.z, a op b.w); \
|
|
||||||
} \
|
|
||||||
inline Vec3##abb##a opname (const type a, const Vec3##abb##a b) { \
|
|
||||||
return make_Vec3##abb##a(a op b.x, a op b.y, a op b.z, a op b.w); \
|
|
||||||
} \
|
|
||||||
/* Vec4##abb */ \
|
|
||||||
inline uniform Vec4##abb opname (const uniform Vec4##abb a, \
|
|
||||||
const uniform Vec4##abb b) { \
|
|
||||||
return make_Vec4##abb(a.x op b.x, a.y op b.y, a.z op b.z, a.w op b.w); \
|
|
||||||
} \
|
|
||||||
inline Vec4##abb opname (const Vec4##abb a, const Vec4##abb b) { \
|
|
||||||
return make_Vec4##abb(a.x op b.x, a.y op b.y, a.z op b.z, a.w op b.w); \
|
|
||||||
} \
|
|
||||||
inline uniform Vec4##abb opname (const uniform Vec4##abb a, \
|
|
||||||
const uniform type b) { \
|
|
||||||
return make_Vec4##abb(a.x op b, a.y op b, a.z op b, a.w op b); \
|
|
||||||
} \
|
|
||||||
inline Vec4##abb opname (const Vec4##abb a, const type b) { \
|
|
||||||
return make_Vec4##abb(a.x op b, a.y op b, a.z op b, a.w op b); \
|
|
||||||
} \
|
|
||||||
inline uniform Vec4##abb opname (const uniform type a, \
|
|
||||||
const uniform Vec4##abb b) { \
|
|
||||||
return make_Vec4##abb(a op b.x, a op b.y, a op b.z, a op b.w); \
|
|
||||||
} \
|
|
||||||
inline Vec4##abb opname (const type a, const Vec4##abb b) { \
|
|
||||||
return make_Vec4##abb(a op b.x, a op b.y, a op b.z, a op b.w); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define __define_binary_operator(opname,op) \
|
|
||||||
__define_binary_operator_typed(opname,op,f,float) \
|
|
||||||
__define_binary_operator_typed(opname,op,i,int32) \
|
|
||||||
__define_binary_operator_typed(opname,op,ui,uint32)
|
|
||||||
|
|
||||||
|
|
||||||
// define 'regular' operators
|
|
||||||
__define_binary_operator( operator+, + );
|
|
||||||
__define_binary_operator( operator-, - );
|
|
||||||
__define_binary_operator( operator*, * );
|
|
||||||
__define_binary_operator( operator/, / );
|
|
||||||
|
|
||||||
// define old functional operators as used in the embree path tracer, deprecated
|
|
||||||
__define_binary_operator( add, + );
|
|
||||||
__define_binary_operator( sub, - );
|
|
||||||
__define_binary_operator( mul, * );
|
|
||||||
|
|
||||||
#undef __define_binary_operator
|
|
||||||
|
|
||||||
inline float reduce_mul(const Vec3f v)
|
|
||||||
{ return v.x * v.y * v.z; }
|
|
||||||
inline uniform float reduce_mul(const uniform Vec3f v)
|
|
||||||
{ return v.x * v.y * v.z; }
|
|
||||||
|
|
||||||
inline float reduce_max(const Vec3f v)
|
|
||||||
{ return max(max(v.x,v.y),v.z); }
|
|
||||||
|
|
||||||
inline float reduce_add(const Vec3f v)
|
|
||||||
{ return v.x+v.y+v.z; }
|
|
||||||
|
|
||||||
inline uniform float reduce_add(const uniform Vec3f v)
|
|
||||||
{ return v.x+v.y+v.z; }
|
|
||||||
|
|
||||||
inline float reduce_avg(const Vec3f v)
|
|
||||||
{ return (v.x+v.y+v.z)*(1.0f/3.0f); }
|
|
||||||
|
|
||||||
inline float luminance(const Vec3f& c)
|
|
||||||
{ return 0.212671f*c.x + 0.715160f*c.y + 0.072169f*c.z; }
|
|
||||||
|
|
||||||
inline uniform bool eq(const uniform Vec2f a, const uniform Vec2f b)
|
|
||||||
{ return a.x==b.x && a.y==b.y; }
|
|
||||||
inline bool eq(const Vec2f a, const Vec2f b)
|
|
||||||
{ return a.x==b.x & a.y==b.y; }
|
|
||||||
inline uniform bool eq(const uniform Vec3f a, const uniform Vec3f b)
|
|
||||||
{ return a.x==b.x && a.y==b.y && a.z==b.z; }
|
|
||||||
inline bool eq(const Vec3f a, const Vec3f b)
|
|
||||||
{ return a.x==b.x & a.y==b.y & a.z==b.z; }
|
|
||||||
inline uniform bool eq(const uniform Vec3fa a, const uniform Vec3fa b)
|
|
||||||
{ return a.x==b.x && a.y==b.y && a.z==b.z; }
|
|
||||||
inline bool eq(const Vec3fa a, const Vec3fa b)
|
|
||||||
{ return a.x==b.x & a.y==b.y & a.z==b.z; }
|
|
||||||
|
|
||||||
inline uniform bool ne(const uniform Vec2f a, const uniform Vec2f b)
|
|
||||||
{ return !eq(a,b); }
|
|
||||||
inline bool ne(const Vec2f a, const Vec2f b)
|
|
||||||
{ return !eq(a,b); }
|
|
||||||
inline uniform bool ne(const uniform Vec3f a, const uniform Vec3f b)
|
|
||||||
{ return !eq(a,b); }
|
|
||||||
inline bool ne(const Vec3f a, const Vec3f b)
|
|
||||||
{ return !eq(a,b); }
|
|
||||||
inline uniform bool ne(const uniform Vec3fa a, const uniform Vec3fa b)
|
|
||||||
{ return !eq(a,b); }
|
|
||||||
inline bool ne(const Vec3fa a, const Vec3fa b)
|
|
||||||
{ return !eq(a,b); }
|
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
|
||||||
// dot product
|
|
||||||
// ------------------------------------------------------------------
|
|
||||||
/*! computes 3D dot product for *all-uniform* Vec3fs */
|
|
||||||
inline uniform float dot(const uniform Vec3f a, const uniform Vec3f b)
|
|
||||||
{ return a.x*b.x+a.y*b.y+a.z*b.z; }
|
|
||||||
/*! computes 3D dot product for Vec3fs that produce varying results */
|
|
||||||
inline float dot(const Vec3f a, const Vec3f b)
|
|
||||||
{ return a.x*b.x+a.y*b.y+a.z*b.z; }
|
|
||||||
|
|
||||||
inline uniform float length(const uniform Vec3f a) { return sqrtf(dot(a,a)); }
|
|
||||||
inline varying float length(const varying Vec3f a) { return sqrtf(dot(a,a)); }
|
|
||||||
|
|
||||||
inline uniform float distance(const uniform Vec3f a, const uniform Vec3f b) { return length(a - b); }
|
|
||||||
inline varying float distance(const varying Vec3f a, const varying Vec3f b) { return length(a - b); }
|
|
||||||
|
|
||||||
|
|
||||||
inline uniform float dot(const uniform Vec3fa a, const uniform Vec3fa b) { return a.x*b.x+a.y*b.y+a.z*b.z; }
|
|
||||||
inline varying float dot(const varying Vec3fa a, const varying Vec3fa b) { return a.x*b.x+a.y*b.y+a.z*b.z; }
|
|
||||||
|
|
||||||
inline uniform float length(const uniform Vec3fa a) { return sqrtf(dot(a,a)); }
|
|
||||||
inline varying float length(const varying Vec3fa a) { return sqrtf(dot(a,a)); }
|
|
||||||
|
|
||||||
inline uniform float distance(const uniform Vec3fa a, const uniform Vec3fa b) { return length(a - b); }
|
|
||||||
inline varying float distance(const varying Vec3fa a, const varying Vec3fa b) { return length(a - b); }
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
|
||||||
// cross product
|
|
||||||
// ------------------------------------------------------------------
|
|
||||||
/*! computes 3D cross product for *all-uniform* Vec3fs */
|
|
||||||
inline uniform Vec3f cross(const uniform Vec3f &a, const uniform Vec3f &b)
|
|
||||||
{ return make_Vec3f(a.y*b.z-a.z*b.y,
|
|
||||||
a.z*b.x-a.x*b.z,
|
|
||||||
a.x*b.y-a.y*b.x); }
|
|
||||||
/*! computes 3D cross product for Vec3fs that produce varying results */
|
|
||||||
inline Vec3f cross(const Vec3f &a, const Vec3f &b)
|
|
||||||
{ return make_Vec3f(a.y*b.z-a.z*b.y,
|
|
||||||
a.z*b.x-a.x*b.z,
|
|
||||||
a.x*b.y-a.y*b.x); }
|
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
|
||||||
// normalize
|
|
||||||
// ------------------------------------------------------------------
|
|
||||||
/*! compute and return normalized version of uniform Vec3f passed to this fct */
|
|
||||||
inline uniform Vec3f normalize(const uniform Vec3f &v)
|
|
||||||
{ return v * (1.f/sqrt(dot(v,v))); }
|
|
||||||
/*! compute and return normalized version of varying Vec3f passed to this fct */
|
|
||||||
inline Vec3f normalize(const Vec3f v)
|
|
||||||
{ return v * (1.f/sqrt(dot(v,v))); }
|
|
||||||
/*! compute and return normalized version of varying Vec3f passed to this fct */
|
|
||||||
inline Vec3f normalize(const Vec3f v, float &len)
|
|
||||||
{ len = sqrtf(dot(v,v)); return v * rcpf(len); }
|
|
||||||
|
|
||||||
inline Vec3f safe_normalize(const Vec3f v)
|
|
||||||
{ return v * (1.f/sqrt(max(1e-6f,dot(v,v)))); }
|
|
||||||
|
|
||||||
/*! differentiated normalization */
|
|
||||||
inline varying Vec3f dnormalize(const varying Vec3f& p, const varying Vec3f& dp)
|
|
||||||
{
|
|
||||||
const float pp = dot(p,p);
|
|
||||||
const float pdp = dot(p,dp);
|
|
||||||
return (pp*dp-pdp*p)*rcp(pp)*rsqrt(pp);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline uniform Vec3fa normalize(const uniform Vec3fa &v) { return v * (1.f/sqrt(dot(v,v))); }
|
|
||||||
inline varying Vec3fa normalize(const varying Vec3fa v) { return v * (1.f/sqrt(dot(v,v))); }
|
|
||||||
|
|
||||||
inline varying Vec3fa dnormalize(const varying Vec3fa& p, const varying Vec3fa& dp)
|
|
||||||
{
|
|
||||||
const float pp = dot(p,p);
|
|
||||||
const float pdp = dot(p,dp);
|
|
||||||
return (pp*dp-pdp*p)*rcp(pp)*rsqrt(pp);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define __lift_unary_fct(F) \
|
|
||||||
inline uniform Vec2f F(const uniform Vec2f v) \
|
|
||||||
{ return make_Vec2f(F(v.x),F(v.y)); } \
|
|
||||||
inline Vec2f F(const Vec2f v) \
|
|
||||||
{ return make_Vec2f(F(v.x),F(v.y)); } \
|
|
||||||
inline uniform Vec3f F(const uniform Vec3f v) \
|
|
||||||
{ return make_Vec3f(F(v.x),F(v.y),F(v.z)); } \
|
|
||||||
inline Vec3f F(const Vec3f v) \
|
|
||||||
{ return make_Vec3f(F(v.x),F(v.y),F(v.z)); } \
|
|
||||||
inline uniform Vec3fa F(const uniform Vec3fa v) \
|
|
||||||
{ return make_Vec3fa(F(v.x),F(v.y),F(v.z),F(v.w)); } \
|
|
||||||
inline Vec3fa F(const Vec3fa v) \
|
|
||||||
{ return make_Vec3fa(F(v.x),F(v.y),F(v.z),F(v.w)); } \
|
|
||||||
inline uniform Vec4f F(const uniform Vec4f v) \
|
|
||||||
{ return make_Vec4f(F(v.x),F(v.y),F(v.z),F(v.w)); } \
|
|
||||||
inline Vec4f F(const Vec4f v) \
|
|
||||||
{ return make_Vec4f(F(v.x),F(v.y),F(v.z),F(v.w)); }
|
|
||||||
|
|
||||||
__lift_unary_fct(absf)
|
|
||||||
__lift_unary_fct(rcpf)
|
|
||||||
__lift_unary_fct(expf)
|
|
||||||
__lift_unary_fct(logf)
|
|
||||||
|
|
||||||
__lift_unary_fct(floor)
|
|
||||||
__lift_unary_fct(abs)
|
|
||||||
__lift_unary_fct(rcp)
|
|
||||||
__lift_unary_fct(exp)
|
|
||||||
__lift_unary_fct(frac)
|
|
||||||
__lift_unary_fct(sqr)
|
|
||||||
|
|
||||||
#undef __lift_unary_fct
|
|
||||||
|
|
||||||
/*! make RGBA from RGB */
|
|
||||||
inline Vec4f make_Vec4f(const Vec3f rgb, const float a)
|
|
||||||
{ return make_Vec4f(rgb.x,rgb.y,rgb.z,a); }
|
|
||||||
|
|
||||||
/*! make RGBA from RGB */
|
|
||||||
inline uniform Vec4f make_Vec4f(const uniform Vec3f rgb, const uniform float a)
|
|
||||||
{ return make_Vec4f(rgb.x,rgb.y,rgb.z,a); }
|
|
||||||
|
|
||||||
// // ------------------------------------------------------------------
|
|
||||||
// // vector functions (abs,rcp,...):
|
|
||||||
// // ------------------------------------------------------------------
|
|
||||||
// /*! return vector of absolute values of input vector */
|
|
||||||
// inline uniform Vec3f abs(const uniform Vec3f v)
|
|
||||||
// { return make_Vec3f(abs(v.x),abs(v.y),abs(v.z)); }
|
|
||||||
// /*! return vector of absolute values of input vector */
|
|
||||||
// inline Vec3f abs(const Vec3f v)
|
|
||||||
// { return make_Vec3f(abs(v.x),abs(v.y),abs(v.z)); }
|
|
||||||
// /*! return vector of reciprocals of input vector */
|
|
||||||
// inline uniform Vec3f rcp(const uniform Vec3f v)
|
|
||||||
// { return make_Vec3f(rcp(v.x),rcp(v.y),rcp(v.z)); }
|
|
||||||
// /*! return vector of reciprocals of input vector */
|
|
||||||
// inline Vec3f rcp(const Vec3f v)
|
|
||||||
// { return make_Vec3f(rcp(v.x),rcp(v.y),rcp(v.z)); }
|
|
||||||
|
|
||||||
#define __define_lerp2(ABB) \
|
|
||||||
inline uniform Vec2##ABB lerp(uniform float factor, const uniform Vec2##ABB a, const uniform Vec2##ABB b) \
|
|
||||||
{ \
|
|
||||||
return make_Vec2##ABB(lerp(factor, a.x, b.x), lerp(factor, a.y, b.y)); \
|
|
||||||
} \
|
|
||||||
inline Vec2##ABB lerp(float factor, const Vec2##ABB a, const Vec2##ABB b) \
|
|
||||||
{ \
|
|
||||||
return make_Vec2##ABB(lerp(factor, a.x, b.x), lerp(factor, a.y, b.y)); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define __define_lerp3(ABB) \
|
|
||||||
inline uniform Vec3##ABB lerp(uniform float factor, const uniform Vec3##ABB a, const uniform Vec3##ABB b) \
|
|
||||||
{ \
|
|
||||||
return make_Vec3##ABB(lerp(factor, a.x, b.x), lerp(factor, a.y, b.y), lerp(factor, a.z, b.z)); \
|
|
||||||
} \
|
|
||||||
inline Vec3##ABB lerp(float factor, const Vec3##ABB a, const Vec3##ABB b) \
|
|
||||||
{ \
|
|
||||||
return make_Vec3##ABB(lerp(factor, a.x, b.x), lerp(factor, a.y, b.y), lerp(factor, a.z, b.z)); \
|
|
||||||
} \
|
|
||||||
|
|
||||||
#define __define_lerp3a(ABB) \
|
|
||||||
inline uniform Vec3##ABB##a lerp(uniform float factor, const uniform Vec3##ABB##a a, const uniform Vec3##ABB##a b) \
|
|
||||||
{ \
|
|
||||||
return make_Vec3##ABB##a(lerp(factor, a.x, b.x), lerp(factor, a.y, b.y), lerp(factor, a.z, b.z), lerp(factor, a.w, b.w)); \
|
|
||||||
} \
|
|
||||||
inline Vec3##ABB##a lerp(float factor, const Vec3##ABB##a a, const Vec3##ABB##a b) \
|
|
||||||
{ \
|
|
||||||
return make_Vec3##ABB##a(lerp(factor, a.x, b.x), lerp(factor, a.y, b.y), lerp(factor, a.z, b.z), lerp(factor, a.w, b.w)); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define __define_lerp4(ABB) \
|
|
||||||
inline uniform Vec4##ABB lerp(uniform float factor, const uniform Vec4##ABB a, const uniform Vec4##ABB b) \
|
|
||||||
{ \
|
|
||||||
return make_Vec4##ABB(lerp(factor, a.x, b.x), lerp(factor, a.y, b.y), lerp(factor, a.z, b.z), lerp(factor, a.w, b.w)); \
|
|
||||||
} \
|
|
||||||
inline Vec4##ABB lerp(float factor, const Vec4##ABB a, const Vec4##ABB b) \
|
|
||||||
{ \
|
|
||||||
return make_Vec4##ABB(lerp(factor, a.x, b.x), lerp(factor, a.y, b.y), lerp(factor, a.z, b.z), lerp(factor, a.w, b.w)); \
|
|
||||||
}
|
|
||||||
|
|
||||||
__define_lerp2(f)
|
|
||||||
__define_lerp2(i)
|
|
||||||
__define_lerp2(ui)
|
|
||||||
__define_lerp2(uc)
|
|
||||||
__define_lerp3(f)
|
|
||||||
__define_lerp3(i)
|
|
||||||
__define_lerp3(ui)
|
|
||||||
__define_lerp3(uc)
|
|
||||||
//__define_lerp3a(i)
|
|
||||||
//__define_lerp3a(ui)
|
|
||||||
//__define_lerp3a(uc)
|
|
||||||
__define_lerp4(f)
|
|
||||||
__define_lerp4(i)
|
|
||||||
__define_lerp4(ui)
|
|
||||||
__define_lerp4(uc)
|
|
||||||
|
|
||||||
#undef __define_lerp2
|
|
||||||
#undef __define_lerp3
|
|
||||||
#undef __define_lerp4
|
|
||||||
|
|
||||||
inline Vec2i make_Vec2i(const Vec2f &a)
|
|
||||||
{ return make_Vec2i((int)a.x, (int)a.y); }
|
|
||||||
|
|
||||||
inline Vec2i integer_cast(const Vec2f &a)
|
|
||||||
{ return make_Vec2i(a); }
|
|
||||||
|
|
||||||
inline Vec2f clamp(const Vec2f &a, const uniform Vec2f &b, const uniform Vec2f &c)
|
|
||||||
{ return(make_Vec2f(clamp(a.x, b.x, c.x), clamp(a.y, b.y, c.y))); }
|
|
||||||
|
|
||||||
|
|
||||||
inline uniform Vec3i operator*(const uniform Vec3i &a, const uniform int b)
|
|
||||||
{ return(make_Vec3i(a.x * b, a.y * b, a.z * b)); }
|
|
||||||
|
|
||||||
inline uniform Vec3i operator+(const uniform Vec3i &a, const uniform Vec3i &b)
|
|
||||||
{ return(make_Vec3i(a.x + b.x, a.y + b.y, a.z + b.z)); }
|
|
||||||
|
|
||||||
inline Vec3i operator+(const varying Vec3i &a, const varying Vec3i &b)
|
|
||||||
{ return(make_Vec3i(a.x + b.x, a.y + b.y, a.z + b.z)); }
|
|
||||||
|
|
||||||
// Workaround for compiler bug.
|
|
||||||
inline Vec3i operator+(const uniform Vec3i &a, const varying Vec3i &b)
|
|
||||||
{ return(make_Vec3i(a.x + b.x, a.y + b.y, a.z + b.z)); }
|
|
||||||
|
|
||||||
inline Vec3i operator+(const varying Vec3i &a, const varying int32 b)
|
|
||||||
{ return(make_Vec3i(a.x + b, a.y + b, a.z + b)); }
|
|
||||||
|
|
||||||
inline uniform Vec3i operator+(const uniform Vec3i &a, const uniform int b)
|
|
||||||
{ return(make_Vec3i(a.x + b, a.y + b, a.z + b)); }
|
|
||||||
|
|
||||||
inline uniform Vec3i operator-(const uniform Vec3i &a, const uniform int b)
|
|
||||||
{ return(make_Vec3i(a.x - b, a.y - b, a.z - b)); }
|
|
||||||
|
|
||||||
inline Vec3i operator-(const varying Vec3i &a, const uniform Vec3i &b)
|
|
||||||
{ return(make_Vec3i(a.x - b.x, a.y - b.y, a.z - b.z)); }
|
|
||||||
|
|
||||||
inline Vec3i operator-(const varying Vec3i &a, const varying Vec3i &b)
|
|
||||||
{ return(make_Vec3i(a.x - b.x, a.y - b.y, a.z - b.z)); }
|
|
||||||
|
|
||||||
inline Vec3i operator-(const varying Vec3i &a, const varying int32 b)
|
|
||||||
{ return(make_Vec3i(a.x - b, a.y - b, a.z - b)); }
|
|
||||||
|
|
||||||
inline uniform Vec3i operator/(const uniform Vec3i &a, const uniform int b)
|
|
||||||
{ return(make_Vec3i(a.x / b, a.y / b, a.z / b)); }
|
|
||||||
|
|
||||||
inline Vec3f float_cast(const Vec3i &a)
|
|
||||||
{ return make_Vec3f(a); }
|
|
||||||
|
|
||||||
inline Vec3i integer_cast(const Vec3f &a)
|
|
||||||
{ return make_Vec3i(a); }
|
|
||||||
|
|
||||||
inline Vec3i operator>>(const Vec3i &a, const int b)
|
|
||||||
{ return(make_Vec3i(a.x >> b, a.y >> b, a.z >> b)); }
|
|
||||||
|
|
||||||
inline Vec3i operator<<(const Vec3i &a, const int b)
|
|
||||||
{ return(make_Vec3i(a.x << b, a.y << b, a.z << b)); }
|
|
||||||
|
|
||||||
inline Vec3i bitwise_AND(const Vec3i &a, const int b)
|
|
||||||
{ return(make_Vec3i(a.x & b, a.y & b, a.z &b)); }
|
|
||||||
|
|
||||||
inline Vec3f powf(const Vec3f v, const float f)
|
|
||||||
{ return make_Vec3f(powf(v.x,f),powf(v.y,f),powf(v.z,f)); }
|
|
||||||
|
|
||||||
inline uniform Vec3f powf(const uniform Vec3f v, const uniform float f)
|
|
||||||
{ return make_Vec3f(powf(v.x,f),powf(v.y,f),powf(v.z,f)); }
|
|
||||||
|
|
||||||
inline Vec3f clamp(const Vec3f &a, const uniform Vec3f &b, const uniform Vec3f &c)
|
|
||||||
{ return(make_Vec3f(clamp(a.x, b.x, c.x), clamp(a.y, b.y, c.y), clamp(a.z, b.z, c.z))); }
|
|
||||||
|
|
||||||
inline Vec3f clamp(const Vec3f &a, const Vec3f &b, const Vec3f &c)
|
|
||||||
{ return(make_Vec3f(clamp(a.x, b.x, c.x), clamp(a.y, b.y, c.y), clamp(a.z, b.z, c.z))); }
|
|
||||||
|
|
||||||
inline Vec3i clamp(const Vec3i &a, const uniform Vec3i &b, const uniform Vec3i &c)
|
|
||||||
{ return(make_Vec3i(clamp(a.x, b.x, c.x), clamp(a.y, b.y, c.y), clamp(a.z, b.z, c.z))); }
|
|
||||||
|
|
||||||
//! The next machine representable number from 'a' in the direction of 'b'.
|
|
||||||
inline uniform Vec3f nextafter(const uniform Vec3i &a, const uniform Vec3i &b)
|
|
||||||
{ return(make_Vec3f(nextafter(a.x, b.x), nextafter(a.y, b.y), nextafter(a.z, b.z))); }
|
|
||||||
|
|
||||||
inline varying float reduce_min(const varying Vec3f &a)
|
|
||||||
{ return min(min(a.x, a.y), a.z); }
|
|
||||||
|
|
||||||
inline uniform float reduce_min(const uniform Vec3f &a)
|
|
||||||
{ return min(min(a.x, a.y), a.z); }
|
|
||||||
|
|
||||||
inline uniform float reduce_min(const uniform Vec3i &a)
|
|
||||||
{ return min(min(a.x, a.y), a.z); }
|
|
||||||
|
|
||||||
inline varying float reduce_min(const varying Vec3i &a)
|
|
||||||
{ return min(min(a.x, a.y), a.z); }
|
|
||||||
|
|
||||||
inline varying float reduce_min(const varying Vec4f &a)
|
|
||||||
{ return min(min(a.x, a.y), min(a.z, a.w)); }
|
|
||||||
|
|
||||||
inline uniform float reduce_min(const uniform Vec4f &a)
|
|
||||||
{ return min(min(a.x, a.y), min(a.z, a.w)); }
|
|
||||||
|
|
||||||
inline uniform float reduce_max(const uniform Vec3i &a)
|
|
||||||
{ return max(max(a.x, a.y), a.z); }
|
|
||||||
|
|
||||||
inline varying float reduce_max(const varying Vec3i &a)
|
|
||||||
{ return max(max(a.x, a.y), a.z); }
|
|
||||||
|
|
||||||
inline varying float reduce_max(const varying Vec3f &a)
|
|
||||||
{ return max(max(a.x, a.y), a.z); }
|
|
||||||
|
|
||||||
inline uniform float reduce_max(const uniform Vec3f &a)
|
|
||||||
{ return max(max(a.x, a.y), a.z); }
|
|
||||||
|
|
||||||
inline varying float reduce_max(const varying Vec4f &a)
|
|
||||||
{ return max(max(a.x, a.y), max(a.z, a.w)); }
|
|
||||||
|
|
||||||
inline uniform float reduce_max(const uniform Vec4f &a)
|
|
||||||
{ return max(max(a.x, a.y), max(a.z, a.w)); }
|
|
||||||
|
|
||||||
inline uniform float reduce_add(const uniform Vec3f &a)
|
|
||||||
{ return a.x+a.y+a.z; }
|
|
||||||
|
|
||||||
inline uniform float reduce_avg(const uniform Vec3f &a)
|
|
||||||
{ return reduce_add(a)*(1.0f/3.0f); }
|
|
||||||
|
|
||||||
inline uniform float luminance(const uniform Vec3f& c)
|
|
||||||
{ return 0.212671f*c.x + 0.715160f*c.y + 0.072169f*c.z; }
|
|
||||||
|
|
||||||
inline varying Vec3f pow(const varying Vec3f &a, const varying float b)
|
|
||||||
{ return make_Vec3f(pow(a.x, b), pow(a.y, b), pow(a.z, b)); }
|
|
||||||
|
|
||||||
inline varying Vec4f pow(const varying Vec4f &a, const varying float b)
|
|
||||||
{ return make_Vec4f(pow(a.x, b), pow(a.y, b), pow(a.z, b), pow(a.w, b)); }
|
|
||||||
|
|
||||||
inline uniform bool isnan(uniform Vec3f v)
|
|
||||||
{ return isnan(v.x+v.y+v.z); }
|
|
||||||
|
|
||||||
inline bool isnan(Vec3f v)
|
|
||||||
{ return isnan(v.x+v.y+v.z); }
|
|
||||||
|
|
||||||
inline uniform bool isnan(uniform Vec3fa v)
|
|
||||||
{ return isnan(v.x+v.y+v.z); }
|
|
||||||
|
|
||||||
inline bool isnan(Vec3fa v)
|
|
||||||
{ return isnan(v.x+v.y+v.z); }
|
|
||||||
|
|
||||||
typedef Vec3fa Vec3ff;
|
|
||||||
typedef Vec3f Vec3f_;
|
|
||||||
|
|
||||||
inline uniform Vec3f make_Vec3f_(uniform float w) { uniform Vec3f r; r.x = w; r.y = w; r.z = w; return r; }
|
|
||||||
inline varying Vec3f make_Vec3f_(varying float w) { varying Vec3f r; r.x = w; r.y = w; r.z = w; return r; }
|
|
||||||
|
|
||||||
inline uniform Vec3f make_Vec3f_(uniform Vec3f v) { uniform Vec3f r; r.x = v.x; r.y = v.y; r.z = v.z; return r; }
|
|
||||||
inline varying Vec3f make_Vec3f_(varying Vec3f v) { varying Vec3f r; r.x = v.x; r.y = v.y; r.z = v.z; return r; }
|
|
||||||
|
|
||||||
inline uniform Vec3f make_Vec3f_(uniform Vec3fa v) { uniform Vec3f r; r.x = v.x; r.y = v.y; r.z = v.z; return r; }
|
|
||||||
inline varying Vec3f make_Vec3f_(varying Vec3fa v) { varying Vec3f r; r.x = v.x; r.y = v.y; r.z = v.z; return r; }
|
|
||||||
|
|
||||||
inline uniform Vec3ff make_Vec3ff(uniform float w) { uniform Vec3ff r; r.x = w; r.y = w; r.z = w; r.w = w; return r; }
|
|
||||||
inline varying Vec3ff make_Vec3ff(varying float w) { varying Vec3ff r; r.x = w; r.y = w; r.z = w; r.w = w; return r; }
|
|
||||||
|
|
||||||
inline uniform Vec3ff make_Vec3ff(uniform Vec3f v) { uniform Vec3ff r; r.x = v.x; r.y = v.y; r.z = v.z; r.w = 0.0f; return r; }
|
|
||||||
inline varying Vec3ff make_Vec3ff(varying Vec3f v) { varying Vec3ff r; r.x = v.x; r.y = v.y; r.z = v.z; r.w = 0.0f; return r; }
|
|
||||||
|
|
||||||
inline uniform Vec3ff make_Vec3ff(uniform Vec3fa v) { uniform Vec3ff r; r.x = v.x; r.y = v.y; r.z = v.z; r.w = 0.0f; return r; }
|
|
||||||
inline varying Vec3ff make_Vec3ff(varying Vec3fa v) { varying Vec3ff r; r.x = v.x; r.y = v.y; r.z = v.z; r.w = 0.0f; return r; }
|
|
||||||
|
|
||||||
inline uniform Vec3ff make_Vec3ff(uniform Vec3f v, uniform float w) { uniform Vec3ff r; r.x = v.x; r.y = v.y; r.z = v.z; r.w = w; return r; }
|
|
||||||
inline varying Vec3ff make_Vec3ff(varying Vec3f v, varying float w) { varying Vec3ff r; r.x = v.x; r.y = v.y; r.z = v.z; r.w = w; return r; }
|
|
||||||
|
|
||||||
inline uniform Vec3ff make_Vec3ff(uniform Vec3fa v, uniform float w) { uniform Vec3ff r; r.x = v.x; r.y = v.y; r.z = v.z; r.w = w; return r; }
|
|
||||||
inline varying Vec3ff make_Vec3ff(varying Vec3fa v, varying float w) { varying Vec3ff r; r.x = v.x; r.y = v.y; r.z = v.z; r.w = w; return r; }
|
|
||||||
|
|
||||||
inline uniform Vec3ff make_Vec3ff(uniform float x, uniform float y, uniform float z, uniform float w) { uniform Vec3ff r; r.x = x; r.y = y; r.z = z; r.w = w; return r; }
|
|
||||||
inline varying Vec3ff make_Vec3ff(varying float x, varying float y, varying float z, varying float w) { varying Vec3ff r; r.x = x; r.y = y; r.z = z; r.w = w; return r; }
|
|
||||||
|
|
||||||
inline void out(uniform Vec3f v) { print("(%,%,%)",v.x,v.y,v.z); }
|
|
||||||
inline void out(Vec3f v) { print("\n(%\n %\n %)",v.x,v.y,v.z); }
|
|
||||||
inline void out(uniform Vec3i v) { print("(%,%,%)",v.x,v.y,v.z); }
|
|
||||||
inline void out(Vec3i v) { print("\n(%\n %\n %)",v.x,v.y,v.z); }
|
|
||||||
|
|
||||||
|
|
||||||
// -------------------------------------------------------
|
|
||||||
// set/get functions for vectors
|
|
||||||
// should eventually get moved to macros so they work for all types
|
|
||||||
// -------------------------------------------------------
|
|
||||||
|
|
||||||
/*! set vector 'v's value in dimension 'd' to 'f' */
|
|
||||||
inline void set(uniform Vec3f &v, const uniform uint32 dim, const uniform float f)
|
|
||||||
{ (&v.x)[dim] = f; }
|
|
||||||
|
|
||||||
/*! get vector 'v's value in dimension 'd' */
|
|
||||||
inline uniform float get(const uniform Vec3f &v, const uniform uint32 dim)
|
|
||||||
{ return (&v.x)[dim]; }
|
|
||||||
inline float get(const Vec3f &v, const uniform uint32 dim)
|
|
||||||
{ return (&v.x)[dim]; }
|
|
||||||
|
|
||||||
|
|
||||||
// -------------------------------------------------------
|
|
||||||
// sRGB conversion functions
|
|
||||||
// -------------------------------------------------------
|
|
||||||
#define APPROXIMATE_SRGB
|
|
||||||
|
|
||||||
inline float linear_to_srgb(const float f)
|
|
||||||
{
|
|
||||||
const float c = max(f, 0.f);
|
|
||||||
#ifdef APPROXIMATE_SRGB
|
|
||||||
return pow(c, 1.f/2.2f);
|
|
||||||
#else
|
|
||||||
return c <= 0.0031308f ? 12.92f*c : pow(c, 1.f/2.4f)*1.055f - 0.055f;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Vec4f linear_to_srgba(const Vec4f c)
|
|
||||||
{
|
|
||||||
return make_Vec4f(linear_to_srgb(c.x),
|
|
||||||
linear_to_srgb(c.y),
|
|
||||||
linear_to_srgb(c.z),
|
|
||||||
max(c.w, 0.f)); // alpha is never gamma-corrected
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uint32 linear_to_srgba8(const Vec4f c)
|
|
||||||
{
|
|
||||||
#if 1
|
|
||||||
Vec4f l = 255.f * min(linear_to_srgba(c), make_Vec4f(1.f));
|
|
||||||
return
|
|
||||||
((uint32)l.x << 0) |
|
|
||||||
((uint32)l.y << 8) |
|
|
||||||
((uint32)l.z << 16) |
|
|
||||||
((uint32)l.w << 24);
|
|
||||||
#else
|
|
||||||
// TODO use ISPC's float_to_srgb8 once it is fixed (issue #1198)
|
|
||||||
return
|
|
||||||
(float_to_srgb8(c.x) << 0) |
|
|
||||||
(float_to_srgb8(c.y) << 8) |
|
|
||||||
(float_to_srgb8(c.z) << 16) |
|
|
||||||
((uint32)clamp(c.w, 0.f, 1.f) << 24); // alpha is never gamma-corrected
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
inline float srgb_to_linear(const float f)
|
|
||||||
{
|
|
||||||
const float c = max(f, 0.f);
|
|
||||||
#ifdef APPROXIMATE_SRGB
|
|
||||||
return pow(c, 2.2f);
|
|
||||||
#else
|
|
||||||
return c <= 0.04045f ? c/12.92f : pow((c + 0.055f)/1.055f, 2.4f);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Vec4f srgba_to_linear(const Vec4f c)
|
|
||||||
{
|
|
||||||
return make_Vec4f(srgb_to_linear(c.x),
|
|
||||||
srgb_to_linear(c.y),
|
|
||||||
srgb_to_linear(c.z),
|
|
||||||
max(c.w, 0.f)); // alpha is never gamma-corrected
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO implement srgba8_to_linear with a 256 entry LUT
|
|
||||||
|
|
||||||
#undef APPROXIMATE_SRGB
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
## Copyright 2009-2021 Intel Corporation
|
|
||||||
## SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
ADD_LIBRARY(scenegraph STATIC
|
|
||||||
xml_parser.cpp
|
|
||||||
xml_loader.cpp
|
|
||||||
xml_writer.cpp
|
|
||||||
obj_loader.cpp
|
|
||||||
ply_loader.cpp
|
|
||||||
corona_loader.cpp
|
|
||||||
texture.cpp
|
|
||||||
scenegraph.cpp
|
|
||||||
geometry_creation.cpp)
|
|
||||||
|
|
||||||
TARGET_LINK_LIBRARIES(scenegraph sys math lexers image embree)
|
|
||||||
SET_PROPERTY(TARGET scenegraph PROPERTY FOLDER tutorials/common)
|
|
||||||
SET_PROPERTY(TARGET scenegraph APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}")
|
|
||||||
|
|
@ -1,299 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#include "corona_loader.h"
|
|
||||||
#include "xml_parser.h"
|
|
||||||
#include "obj_loader.h"
|
|
||||||
|
|
||||||
namespace embree
|
|
||||||
{
|
|
||||||
class CoronaLoader
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
static Ref<SceneGraph::Node> load(const FileName& fileName, const AffineSpace3fa& space);
|
|
||||||
CoronaLoader(const FileName& fileName, const AffineSpace3fa& space);
|
|
||||||
|
|
||||||
private:
|
|
||||||
template<typename T> T load(const Ref<XML>& xml) { assert(false); return T(zero); }
|
|
||||||
Ref<SceneGraph::MaterialNode> loadMaterial(const Ref<XML>& xml);
|
|
||||||
void loadMaterialDefinition(const Ref<XML>& xml);
|
|
||||||
std::shared_ptr<Texture> loadMap(const Ref<XML>& xml);
|
|
||||||
void loadMapDefinition(const Ref<XML>& xml);
|
|
||||||
Ref<SceneGraph::Node> loadMaterialLibrary(const FileName& fileName);
|
|
||||||
Ref<SceneGraph::Node> loadObject(const Ref<XML>& xml);
|
|
||||||
std::pair<Ref<SceneGraph::MaterialNode>, avector<AffineSpace3fa> > loadInstances(const Ref<XML>& xml);
|
|
||||||
Ref<SceneGraph::Node> loadGroupNode(const Ref<XML>& xml);
|
|
||||||
Ref<SceneGraph::Node> loadNode(const Ref<XML>& xml);
|
|
||||||
|
|
||||||
private:
|
|
||||||
FileName path;
|
|
||||||
std::map<std::string,Ref<SceneGraph::MaterialNode> > materialMap;
|
|
||||||
std::map<std::string,std::shared_ptr<Texture>> textureMap;
|
|
||||||
std::map<std::string,std::shared_ptr<Texture>> textureFileMap;
|
|
||||||
public:
|
|
||||||
Ref<SceneGraph::Node> root;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<> FileName CoronaLoader::load<FileName>(const Ref<XML>& xml)
|
|
||||||
{
|
|
||||||
if (xml->body.size() != 1) THROW_RUNTIME_ERROR(xml->loc.str()+": wrong FileName body");
|
|
||||||
return xml->body[0].Identifier();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<> std::string CoronaLoader::load<std::string>(const Ref<XML>& xml)
|
|
||||||
{
|
|
||||||
if (xml->body.size() != 1) THROW_RUNTIME_ERROR(xml->loc.str()+": wrong string body");
|
|
||||||
return xml->body[0].Identifier();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<> int CoronaLoader::load<int>(const Ref<XML>& xml) {
|
|
||||||
if (xml->body.size() < 1) THROW_RUNTIME_ERROR(xml->loc.str()+": wrong int body");
|
|
||||||
return xml->body[0].Int();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<> float CoronaLoader::load<float>(const Ref<XML>& xml) {
|
|
||||||
if (xml->body.size() < 1) THROW_RUNTIME_ERROR(xml->loc.str()+": wrong float body");
|
|
||||||
return xml->body[0].Float();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<> Vec3f CoronaLoader::load<Vec3f>(const Ref<XML>& xml) {
|
|
||||||
if (xml->body.size() < 3) THROW_RUNTIME_ERROR(xml->loc.str()+": wrong float3 body");
|
|
||||||
return Vec3f(xml->body[0].Float(),xml->body[1].Float(),xml->body[2].Float());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<> Vec3fa CoronaLoader::load<Vec3fa>(const Ref<XML>& xml) {
|
|
||||||
if (xml->body.size() < 3) THROW_RUNTIME_ERROR(xml->loc.str()+": wrong float3 body");
|
|
||||||
return Vec3fa(xml->body[0].Float(),xml->body[1].Float(),xml->body[2].Float());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<> AffineSpace3fa CoronaLoader::load<AffineSpace3fa>(const Ref<XML>& xml)
|
|
||||||
{
|
|
||||||
if (xml->body.size() != 12) THROW_RUNTIME_ERROR(xml->loc.str()+": wrong AffineSpace body");
|
|
||||||
return AffineSpace3fa(LinearSpace3fa(xml->body[0].Float(),xml->body[1].Float(),xml->body[ 2].Float(),
|
|
||||||
xml->body[4].Float(),xml->body[5].Float(),xml->body[ 6].Float(),
|
|
||||||
xml->body[8].Float(),xml->body[9].Float(),xml->body[10].Float()),
|
|
||||||
Vec3fa(xml->body[3].Float(),xml->body[7].Float(),xml->body[11].Float()));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<SceneGraph::MaterialNode> CoronaLoader::loadMaterial(const Ref<XML>& xml)
|
|
||||||
{
|
|
||||||
if (xml->name != "material")
|
|
||||||
THROW_RUNTIME_ERROR(xml->loc.str()+": invalid material: "+xml->name);
|
|
||||||
|
|
||||||
/* native material */
|
|
||||||
if (xml->parm("class") == "Native")
|
|
||||||
{
|
|
||||||
/* we convert into an OBJ material */
|
|
||||||
Ref<OBJMaterial> objmaterial = new OBJMaterial;
|
|
||||||
for (auto& child : xml->children)
|
|
||||||
{
|
|
||||||
if (child->name == "diffuse") {
|
|
||||||
objmaterial->Kd = load<Vec3fa>(child);
|
|
||||||
if (child->children.size() && child->children[0]->name == "map")
|
|
||||||
objmaterial->_map_Kd = loadMap(child->children[0]);
|
|
||||||
}
|
|
||||||
else if (child->name == "reflect") {
|
|
||||||
objmaterial->Ks = load<Vec3fa>(child->child("color"));
|
|
||||||
objmaterial->Ni = load<float >(child->child("ior"));
|
|
||||||
objmaterial->Ns = load<float >(child->child("glossiness"));
|
|
||||||
}
|
|
||||||
else if (child->name == "translucency") {
|
|
||||||
objmaterial->Kt = load<Vec3fa>(child->child("color"));
|
|
||||||
}
|
|
||||||
else if (child->name == "opacity") {
|
|
||||||
objmaterial->d = load<Vec3fa>(child).x;
|
|
||||||
if (child->children.size() && child->children[0]->name == "map")
|
|
||||||
objmaterial->_map_d = loadMap(child->children[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return objmaterial.dynamicCast<SceneGraph::MaterialNode>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* reference by name */
|
|
||||||
else if (xml->parm("class") == "Reference")
|
|
||||||
{
|
|
||||||
const std::string name = load<std::string>(xml);
|
|
||||||
return materialMap[name];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* else return default material */
|
|
||||||
else
|
|
||||||
return new OBJMaterial;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoronaLoader::loadMaterialDefinition(const Ref<XML>& xml)
|
|
||||||
{
|
|
||||||
if (xml->name != "materialDefinition")
|
|
||||||
THROW_RUNTIME_ERROR(xml->loc.str()+": invalid material definition: "+xml->name);
|
|
||||||
if (xml->children.size() != 1)
|
|
||||||
THROW_RUNTIME_ERROR(xml->loc.str()+": invalid material definition");
|
|
||||||
|
|
||||||
const std::string name = xml->parm("name");
|
|
||||||
materialMap[name] = loadMaterial(xml->children[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<Texture> CoronaLoader::loadMap(const Ref<XML>& xml)
|
|
||||||
{
|
|
||||||
/* process map node */
|
|
||||||
if (xml->name == "map")
|
|
||||||
{
|
|
||||||
std::string mapClass = xml->parm("class");
|
|
||||||
|
|
||||||
/* load textures */
|
|
||||||
if (mapClass == "Texture")
|
|
||||||
{
|
|
||||||
const FileName src = load<FileName>(xml->child("image"));
|
|
||||||
|
|
||||||
/* load images only once */
|
|
||||||
if (textureFileMap.find(src) != textureFileMap.end())
|
|
||||||
return textureFileMap[src];
|
|
||||||
|
|
||||||
try {
|
|
||||||
return Texture::load(path+src);
|
|
||||||
} catch (const std::runtime_error& e) {
|
|
||||||
std::cerr << "failed to load " << path+src << ": " << e.what() << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (mapClass == "Reference") {
|
|
||||||
const std::string name = load<std::string>(xml);
|
|
||||||
return textureMap[name];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* recurse into every unknown node to find some texture */
|
|
||||||
for (auto& child : xml->children) {
|
|
||||||
std::shared_ptr<Texture> texture = loadMap(child);
|
|
||||||
if (texture) return texture;
|
|
||||||
}
|
|
||||||
return std::shared_ptr<Texture>();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoronaLoader::loadMapDefinition(const Ref<XML>& xml)
|
|
||||||
{
|
|
||||||
if (xml->name != "mapDefinition")
|
|
||||||
THROW_RUNTIME_ERROR(xml->loc.str()+": invalid map definition: "+xml->name);
|
|
||||||
if (xml->children.size() != 1)
|
|
||||||
THROW_RUNTIME_ERROR(xml->loc.str()+": invalid map definition");
|
|
||||||
|
|
||||||
const std::string name = xml->parm("name");
|
|
||||||
std::shared_ptr<Texture> texture = loadMap(xml->children[0]);
|
|
||||||
if (texture) textureMap[name] = texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<SceneGraph::Node> CoronaLoader::loadMaterialLibrary(const FileName& fileName)
|
|
||||||
{
|
|
||||||
Ref<XML> xml = parseXML(path+fileName,"/.-",false);
|
|
||||||
if (xml->name != "mtlLib")
|
|
||||||
THROW_RUNTIME_ERROR(xml->loc.str()+": invalid material library");
|
|
||||||
|
|
||||||
for (auto& child : xml->children)
|
|
||||||
{
|
|
||||||
if (child->name == "materialDefinition") {
|
|
||||||
loadMaterialDefinition(child);
|
|
||||||
}
|
|
||||||
else if (child->name == "mapDefinition")
|
|
||||||
loadMapDefinition(child);
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<SceneGraph::Node> CoronaLoader::loadObject(const Ref<XML>& xml)
|
|
||||||
{
|
|
||||||
if (xml->name != "object")
|
|
||||||
THROW_RUNTIME_ERROR(xml->loc.str()+": invalid object node");
|
|
||||||
if (xml->parm("class") != "file")
|
|
||||||
THROW_RUNTIME_ERROR(xml->loc.str()+": invalid object class");
|
|
||||||
const FileName fileName = load<FileName>(xml);
|
|
||||||
return SceneGraph::load(path+fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<Ref<SceneGraph::MaterialNode>, avector<AffineSpace3fa> > CoronaLoader::loadInstances(const Ref<XML>& xml)
|
|
||||||
{
|
|
||||||
if (xml->name != "instance")
|
|
||||||
THROW_RUNTIME_ERROR(xml->loc.str()+": invalid instance node");
|
|
||||||
|
|
||||||
/* create default material */
|
|
||||||
Ref<SceneGraph::MaterialNode> material = new OBJMaterial;
|
|
||||||
|
|
||||||
avector<AffineSpace3fa> xfms;
|
|
||||||
for (size_t i=0; i<xml->children.size(); i++)
|
|
||||||
{
|
|
||||||
Ref<XML> child = xml->children[i];
|
|
||||||
if (child->name == "material" ) material = loadMaterial(child);
|
|
||||||
else if (child->name == "transform") xfms.push_back(load<AffineSpace3fa>(child));
|
|
||||||
else THROW_RUNTIME_ERROR(child->loc.str()+": unknown node: "+child->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::make_pair(material,xfms);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<SceneGraph::Node> CoronaLoader::loadGroupNode(const Ref<XML>& xml)
|
|
||||||
{
|
|
||||||
if (xml->children.size() < 1)
|
|
||||||
THROW_RUNTIME_ERROR(xml->loc.str()+": invalid group node");
|
|
||||||
|
|
||||||
/* load instances */
|
|
||||||
auto p = loadInstances(xml->children[0]);
|
|
||||||
Ref<SceneGraph::MaterialNode> material = p.first;
|
|
||||||
avector<AffineSpace3fa>& xfms = p.second;
|
|
||||||
|
|
||||||
/* load meshes */
|
|
||||||
Ref<SceneGraph::GroupNode> objects = new SceneGraph::GroupNode;
|
|
||||||
for (size_t i=1; i<xml->children.size(); i++)
|
|
||||||
objects->add(loadObject(xml->children[i]));
|
|
||||||
|
|
||||||
/* force material */
|
|
||||||
objects->setMaterial(material);
|
|
||||||
|
|
||||||
/* create instances */
|
|
||||||
Ref<SceneGraph::GroupNode> instances = new SceneGraph::GroupNode;
|
|
||||||
for (size_t i=0; i<xfms.size(); i++)
|
|
||||||
instances->add(new SceneGraph::TransformNode(xfms[i],objects.cast<SceneGraph::Node>()));
|
|
||||||
|
|
||||||
return instances.cast<SceneGraph::Node>();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<SceneGraph::Node> CoronaLoader::loadNode(const Ref<XML>& xml)
|
|
||||||
{
|
|
||||||
if (xml->name == "conffile" ) return nullptr;
|
|
||||||
else if (xml->name == "mtllib" ) return loadMaterialLibrary(load<FileName>(xml));
|
|
||||||
else if (xml->name == "camera" ) return nullptr;
|
|
||||||
else if (xml->name == "environment" ) return nullptr;
|
|
||||||
else if (xml->name == "geometryGroup") return loadGroupNode(xml);
|
|
||||||
else if (xml->name == "renderElement") return nullptr;
|
|
||||||
else THROW_RUNTIME_ERROR(xml->loc.str()+": unknown tag: "+xml->name);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<SceneGraph::Node> CoronaLoader::load(const FileName& fileName, const AffineSpace3fa& space) {
|
|
||||||
CoronaLoader loader(fileName,space); return loader.root;
|
|
||||||
}
|
|
||||||
|
|
||||||
CoronaLoader::CoronaLoader(const FileName& fileName, const AffineSpace3fa& space)
|
|
||||||
{
|
|
||||||
path = fileName.path();
|
|
||||||
Ref<XML> xml = parseXML(fileName,"/.-",false);
|
|
||||||
if (xml->name == "scene")
|
|
||||||
{
|
|
||||||
Ref<SceneGraph::GroupNode> group = new SceneGraph::GroupNode;
|
|
||||||
for (size_t i=0; i<xml->children.size(); i++) {
|
|
||||||
group->add(loadNode(xml->children[i]));
|
|
||||||
}
|
|
||||||
root = group.cast<SceneGraph::Node>();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
THROW_RUNTIME_ERROR(xml->loc.str()+": invalid scene tag");
|
|
||||||
|
|
||||||
if (space == AffineSpace3fa(one))
|
|
||||||
return;
|
|
||||||
|
|
||||||
root = new SceneGraph::TransformNode(space,root);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! read from disk */
|
|
||||||
Ref<SceneGraph::Node> SceneGraph::loadCorona(const FileName& fileName, const AffineSpace3fa& space) {
|
|
||||||
return CoronaLoader::load(fileName,space);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "scenegraph.h"
|
|
||||||
|
|
||||||
namespace embree
|
|
||||||
{
|
|
||||||
namespace SceneGraph
|
|
||||||
{
|
|
||||||
Ref<SceneGraph::Node> loadCorona(const FileName& fileName, const AffineSpace3fa& space = one);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,693 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#include "geometry_creation.h"
|
|
||||||
|
|
||||||
namespace embree
|
|
||||||
{
|
|
||||||
Ref<SceneGraph::Node> SceneGraph::createTrianglePlane (const Vec3fa& p0, const Vec3fa& dx, const Vec3fa& dy, size_t width, size_t height, Ref<MaterialNode> material)
|
|
||||||
{
|
|
||||||
Ref<SceneGraph::TriangleMeshNode> mesh = new SceneGraph::TriangleMeshNode(material,BBox1f(0,1),1);
|
|
||||||
mesh->positions[0].resize((width+1)*(height+1));
|
|
||||||
mesh->triangles.resize(2*width*height);
|
|
||||||
|
|
||||||
for (size_t y=0; y<=height; y++) {
|
|
||||||
for (size_t x=0; x<=width; x++) {
|
|
||||||
Vec3fa p = p0+float(x)/float(width)*dx+float(y)/float(height)*dy;
|
|
||||||
size_t i = y*(width+1)+x;
|
|
||||||
mesh->positions[0][i].x = p.x;
|
|
||||||
mesh->positions[0][i].y = p.y;
|
|
||||||
mesh->positions[0][i].z = p.z;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (size_t y=0; y<height; y++) {
|
|
||||||
for (size_t x=0; x<width; x++) {
|
|
||||||
size_t i = 2*y*width+2*x;
|
|
||||||
size_t p00 = (y+0)*(width+1)+(x+0);
|
|
||||||
size_t p01 = (y+0)*(width+1)+(x+1);
|
|
||||||
size_t p10 = (y+1)*(width+1)+(x+0);
|
|
||||||
size_t p11 = (y+1)*(width+1)+(x+1);
|
|
||||||
mesh->triangles[i+0].v0 = unsigned(p00); mesh->triangles[i+0].v1 = unsigned(p01); mesh->triangles[i+0].v2 = unsigned(p10);
|
|
||||||
mesh->triangles[i+1].v0 = unsigned(p11); mesh->triangles[i+1].v1 = unsigned(p10); mesh->triangles[i+1].v2 = unsigned(p01);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return mesh.dynamicCast<SceneGraph::Node>();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<SceneGraph::Node> SceneGraph::createQuadPlane (const Vec3fa& p0, const Vec3fa& dx, const Vec3fa& dy, size_t width, size_t height, Ref<MaterialNode> material)
|
|
||||||
{
|
|
||||||
Ref<SceneGraph::QuadMeshNode> mesh = new SceneGraph::QuadMeshNode(material,BBox1f(0,1),1);
|
|
||||||
mesh->positions[0].resize((width+1)*(height+1));
|
|
||||||
mesh->quads.resize(width*height);
|
|
||||||
|
|
||||||
for (size_t y=0; y<=height; y++) {
|
|
||||||
for (size_t x=0; x<=width; x++) {
|
|
||||||
Vec3fa p = p0+float(x)/float(width)*dx+float(y)/float(height)*dy;
|
|
||||||
size_t i = y*(width+1)+x;
|
|
||||||
mesh->positions[0][i].x = p.x;
|
|
||||||
mesh->positions[0][i].y = p.y;
|
|
||||||
mesh->positions[0][i].z = p.z;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (size_t y=0; y<height; y++) {
|
|
||||||
for (size_t x=0; x<width; x++) {
|
|
||||||
size_t i = y*width+x;
|
|
||||||
size_t p00 = (y+0)*(width+1)+(x+0);
|
|
||||||
size_t p01 = (y+0)*(width+1)+(x+1);
|
|
||||||
size_t p10 = (y+1)*(width+1)+(x+0);
|
|
||||||
size_t p11 = (y+1)*(width+1)+(x+1);
|
|
||||||
mesh->quads[i].v0 = unsigned(p00);
|
|
||||||
mesh->quads[i].v1 = unsigned(p01);
|
|
||||||
mesh->quads[i].v2 = unsigned(p11);
|
|
||||||
mesh->quads[i].v3 = unsigned(p10);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return mesh.dynamicCast<SceneGraph::Node>();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<SceneGraph::Node> SceneGraph::createGridPlane (const Vec3fa& p0, const Vec3fa& dx, const Vec3fa& dy, size_t width, size_t height, Ref<MaterialNode> material)
|
|
||||||
{
|
|
||||||
Ref<SceneGraph::GridMeshNode> mesh = new SceneGraph::GridMeshNode(material,BBox1f(0,1),1);
|
|
||||||
mesh->positions[0].resize((width+1)*(height+1));
|
|
||||||
mesh->grids.push_back(SceneGraph::GridMeshNode::Grid(0,(unsigned)width+1,(unsigned)width+1,(unsigned)height+1));
|
|
||||||
|
|
||||||
for (size_t y=0; y<=height; y++) {
|
|
||||||
for (size_t x=0; x<=width; x++) {
|
|
||||||
Vec3fa p = p0+float(x)/float(width)*dx+float(y)/float(height)*dy;
|
|
||||||
size_t i = y*(width+1)+x;
|
|
||||||
mesh->positions[0][i].x = p.x;
|
|
||||||
mesh->positions[0][i].y = p.y;
|
|
||||||
mesh->positions[0][i].z = p.z;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return mesh.dynamicCast<SceneGraph::Node>();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<SceneGraph::Node> SceneGraph::createSubdivPlane (const Vec3fa& p0, const Vec3fa& dx, const Vec3fa& dy, size_t width, size_t height, float tessellationRate, Ref<MaterialNode> material)
|
|
||||||
{
|
|
||||||
Ref<SceneGraph::SubdivMeshNode> mesh = new SceneGraph::SubdivMeshNode(material,BBox1f(0,1),1);
|
|
||||||
mesh->tessellationRate = tessellationRate;
|
|
||||||
mesh->positions[0].resize((width+1)*(height+1));
|
|
||||||
mesh->position_indices.resize(4*width*height);
|
|
||||||
mesh->verticesPerFace.resize(width*height);
|
|
||||||
|
|
||||||
for (size_t y=0; y<=height; y++) {
|
|
||||||
for (size_t x=0; x<=width; x++) {
|
|
||||||
Vec3fa p = p0+float(x)/float(width)*dx+float(y)/float(height)*dy;
|
|
||||||
size_t i = y*(width+1)+x;
|
|
||||||
mesh->positions[0][i].x = p.x;
|
|
||||||
mesh->positions[0][i].y = p.y;
|
|
||||||
mesh->positions[0][i].z = p.z;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (size_t y=0; y<height; y++) {
|
|
||||||
for (size_t x=0; x<width; x++) {
|
|
||||||
size_t i = y*width+x;
|
|
||||||
size_t p00 = (y+0)*(width+1)+(x+0);
|
|
||||||
size_t p01 = (y+0)*(width+1)+(x+1);
|
|
||||||
size_t p10 = (y+1)*(width+1)+(x+0);
|
|
||||||
size_t p11 = (y+1)*(width+1)+(x+1);
|
|
||||||
mesh->position_indices[4*i+0] = unsigned(p00);
|
|
||||||
mesh->position_indices[4*i+1] = unsigned(p01);
|
|
||||||
mesh->position_indices[4*i+2] = unsigned(p11);
|
|
||||||
mesh->position_indices[4*i+3] = unsigned(p10);
|
|
||||||
mesh->verticesPerFace[i] = 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mesh->position_subdiv_mode = RTC_SUBDIVISION_MODE_PIN_CORNERS;
|
|
||||||
return mesh.dynamicCast<SceneGraph::Node>();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<SceneGraph::Node> SceneGraph::createTriangleSphere (const Vec3fa& center, const float radius, size_t N, Ref<MaterialNode> material)
|
|
||||||
{
|
|
||||||
unsigned numPhi = unsigned(N);
|
|
||||||
unsigned numTheta = 2*numPhi;
|
|
||||||
unsigned numVertices = numTheta*(numPhi+1);
|
|
||||||
Ref<SceneGraph::TriangleMeshNode> mesh = new SceneGraph::TriangleMeshNode(material,BBox1f(0,1),1);
|
|
||||||
mesh->positions[0].resize(numVertices);
|
|
||||||
|
|
||||||
/* create sphere geometry */
|
|
||||||
const float rcpNumTheta = rcp(float(numTheta));
|
|
||||||
const float rcpNumPhi = rcp(float(numPhi));
|
|
||||||
for (unsigned int phi=0; phi<=numPhi; phi++)
|
|
||||||
{
|
|
||||||
for (unsigned int theta=0; theta<numTheta; theta++)
|
|
||||||
{
|
|
||||||
const float phif = phi*float(pi)*rcpNumPhi;
|
|
||||||
const float thetaf = theta*2.0f*float(pi)*rcpNumTheta;
|
|
||||||
mesh->positions[0][phi*numTheta+theta].x = center.x + radius*sin(phif)*sin(thetaf);
|
|
||||||
mesh->positions[0][phi*numTheta+theta].y = center.y + radius*cos(phif);
|
|
||||||
mesh->positions[0][phi*numTheta+theta].z = center.z + radius*sin(phif)*cos(thetaf);
|
|
||||||
}
|
|
||||||
if (phi == 0) continue;
|
|
||||||
|
|
||||||
if (phi == 1)
|
|
||||||
{
|
|
||||||
for (unsigned int theta=1; theta<=numTheta; theta++)
|
|
||||||
{
|
|
||||||
unsigned int p00 = numTheta-1;
|
|
||||||
unsigned int p10 = phi*numTheta+theta-1;
|
|
||||||
unsigned int p11 = phi*numTheta+theta%numTheta;
|
|
||||||
mesh->triangles.push_back(TriangleMeshNode::Triangle(p10,p00,p11));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (phi == numPhi)
|
|
||||||
{
|
|
||||||
for (unsigned int theta=1; theta<=numTheta; theta++)
|
|
||||||
{
|
|
||||||
unsigned int p00 = (phi-1)*numTheta+theta-1;
|
|
||||||
unsigned int p01 = (phi-1)*numTheta+theta%numTheta;
|
|
||||||
unsigned int p10 = numPhi*numTheta;
|
|
||||||
mesh->triangles.push_back(TriangleMeshNode::Triangle(p10,p00,p01));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (unsigned int theta=1; theta<=numTheta; theta++)
|
|
||||||
{
|
|
||||||
unsigned int p00 = (phi-1)*numTheta+theta-1;
|
|
||||||
unsigned int p01 = (phi-1)*numTheta+theta%numTheta;
|
|
||||||
unsigned int p10 = phi*numTheta+theta-1;
|
|
||||||
unsigned int p11 = phi*numTheta+theta%numTheta;
|
|
||||||
mesh->triangles.push_back(TriangleMeshNode::Triangle(p10,p00,p11));
|
|
||||||
mesh->triangles.push_back(TriangleMeshNode::Triangle(p01,p11,p00));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return mesh.dynamicCast<SceneGraph::Node>();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<SceneGraph::Node> SceneGraph::createQuadSphere (const Vec3fa& center, const float radius, size_t N, Ref<MaterialNode> material)
|
|
||||||
{
|
|
||||||
unsigned numPhi = unsigned(N);
|
|
||||||
unsigned numTheta = 2*numPhi;
|
|
||||||
unsigned numVertices = numTheta*(numPhi+1);
|
|
||||||
Ref<SceneGraph::QuadMeshNode> mesh = new SceneGraph::QuadMeshNode(material,BBox1f(0,1),1);
|
|
||||||
mesh->positions[0].resize(numVertices);
|
|
||||||
|
|
||||||
/* create sphere geometry */
|
|
||||||
const float rcpNumTheta = rcp(float(numTheta));
|
|
||||||
const float rcpNumPhi = rcp(float(numPhi));
|
|
||||||
for (unsigned int phi=0; phi<=numPhi; phi++)
|
|
||||||
{
|
|
||||||
for (unsigned int theta=0; theta<numTheta; theta++)
|
|
||||||
{
|
|
||||||
const float phif = phi*float(pi)*rcpNumPhi;
|
|
||||||
const float thetaf = theta*2.0f*float(pi)*rcpNumTheta;
|
|
||||||
mesh->positions[0][phi*numTheta+theta].x = center.x + radius*sin(phif)*sin(thetaf);
|
|
||||||
mesh->positions[0][phi*numTheta+theta].y = center.y + radius*cos(phif);
|
|
||||||
mesh->positions[0][phi*numTheta+theta].z = center.z + radius*sin(phif)*cos(thetaf);
|
|
||||||
}
|
|
||||||
if (phi == 0) continue;
|
|
||||||
|
|
||||||
if (phi == 1)
|
|
||||||
{
|
|
||||||
for (unsigned int theta=1; theta<=numTheta; theta++)
|
|
||||||
{
|
|
||||||
unsigned int p00 = numTheta-1;
|
|
||||||
unsigned int p10 = phi*numTheta+theta-1;
|
|
||||||
unsigned int p11 = phi*numTheta+theta%numTheta;
|
|
||||||
mesh->quads.push_back(QuadMeshNode::Quad(p10,p00,p11,p11));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (phi == numPhi)
|
|
||||||
{
|
|
||||||
for (unsigned int theta=1; theta<=numTheta; theta++)
|
|
||||||
{
|
|
||||||
unsigned int p00 = (phi-1)*numTheta+theta-1;
|
|
||||||
unsigned int p01 = (phi-1)*numTheta+theta%numTheta;
|
|
||||||
unsigned int p10 = numPhi*numTheta;
|
|
||||||
mesh->quads.push_back(QuadMeshNode::Quad(p10,p00,p01,p01));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (unsigned int theta=1; theta<=numTheta; theta++)
|
|
||||||
{
|
|
||||||
unsigned int p00 = (phi-1)*numTheta+theta-1;
|
|
||||||
unsigned int p01 = (phi-1)*numTheta+theta%numTheta;
|
|
||||||
unsigned int p10 = phi*numTheta+theta-1;
|
|
||||||
unsigned int p11 = phi*numTheta+theta%numTheta;
|
|
||||||
mesh->quads.push_back(QuadMeshNode::Quad(p10,p00,p01,p11));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return mesh.dynamicCast<SceneGraph::Node>();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<SceneGraph::Node> SceneGraph::createGridSphere (const Vec3fa& center, const float radius, size_t N, Ref<MaterialNode> material)
|
|
||||||
{
|
|
||||||
size_t grid_size = (N+1)*(N+1);
|
|
||||||
Ref<SceneGraph::GridMeshNode> mesh = new SceneGraph::GridMeshNode(material,BBox1f(0,1),1);
|
|
||||||
mesh->positions[0].resize(grid_size*6);
|
|
||||||
|
|
||||||
for (size_t i=0; i<6; i++)
|
|
||||||
{
|
|
||||||
mesh->grids.push_back(SceneGraph::GridMeshNode::Grid(unsigned(i*grid_size),unsigned(N+1),unsigned(N+1),unsigned(N+1)));
|
|
||||||
Vec3fa p0, dx, dy;
|
|
||||||
switch (i) {
|
|
||||||
case 0: p0 = Vec3fa(-0.5f,-0.5f,-0.5f); dx = Vec3fa(+1,0, 0); dy = Vec3fa(0,1,0); break;
|
|
||||||
case 1: p0 = Vec3fa(+0.5f,-0.5f,-0.5f); dx = Vec3fa( 0,0,+1); dy = Vec3fa(0,1,0); break;
|
|
||||||
case 2: p0 = Vec3fa(+0.5f,-0.5f,+0.5f); dx = Vec3fa(-1,0, 0); dy = Vec3fa(0,1,0); break;
|
|
||||||
case 3: p0 = Vec3fa(-0.5f,-0.5f,+0.5f); dx = Vec3fa( 0,0,-1); dy = Vec3fa(0,1,0); break;
|
|
||||||
case 4: p0 = Vec3fa(-0.5f,-0.5f,-0.5f); dx = Vec3fa( 0,0,+1); dy = Vec3fa(1,0,0); break;
|
|
||||||
case 5: p0 = Vec3fa(-0.5f,+0.5f,-0.5f); dx = Vec3fa( 1,0, 0); dy = Vec3fa(0,0,1); break;
|
|
||||||
default: assert(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t y=0; y<=N; y++) {
|
|
||||||
for (size_t x=0; x<=N; x++) {
|
|
||||||
size_t j = i*grid_size + y*(N+1) + x;
|
|
||||||
Vec3fa p = p0+float(x)/float(N)*dx+float(y)/float(N)*dy;
|
|
||||||
mesh->positions[0][j] = center + radius*normalize(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return mesh.dynamicCast<SceneGraph::Node>();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<SceneGraph::Node> SceneGraph::createSubdivSphere (const Vec3fa& center, const float radius, size_t N, float tessellationRate, Ref<MaterialNode> material)
|
|
||||||
{
|
|
||||||
unsigned numPhi = unsigned(N);
|
|
||||||
unsigned numTheta = 2*numPhi;
|
|
||||||
unsigned numVertices = numTheta*(numPhi+1);
|
|
||||||
Ref<SceneGraph::SubdivMeshNode> mesh = new SceneGraph::SubdivMeshNode(material,BBox1f(0,1),1);
|
|
||||||
mesh->tessellationRate = tessellationRate;
|
|
||||||
mesh->positions[0].resize(numVertices);
|
|
||||||
|
|
||||||
/* create sphere geometry */
|
|
||||||
const float rcpNumTheta = rcp((float)numTheta);
|
|
||||||
const float rcpNumPhi = rcp((float)numPhi);
|
|
||||||
for (unsigned int phi=0; phi<=numPhi; phi++)
|
|
||||||
{
|
|
||||||
for (unsigned int theta=0; theta<numTheta; theta++)
|
|
||||||
{
|
|
||||||
const float phif = phi*float(pi)*rcpNumPhi;
|
|
||||||
const float thetaf = theta*2.0f*float(pi)*rcpNumTheta;
|
|
||||||
mesh->positions[0][phi*numTheta+theta].x = center.x + radius*sin(phif)*sin(thetaf);
|
|
||||||
mesh->positions[0][phi*numTheta+theta].y = center.y + radius*cos(phif);
|
|
||||||
mesh->positions[0][phi*numTheta+theta].z = center.z + radius*sin(phif)*cos(thetaf);
|
|
||||||
}
|
|
||||||
if (phi == 0) continue;
|
|
||||||
|
|
||||||
if (phi == 1)
|
|
||||||
{
|
|
||||||
for (unsigned int theta=1; theta<=numTheta; theta++)
|
|
||||||
{
|
|
||||||
unsigned int p00 = numTheta-1;
|
|
||||||
unsigned int p10 = phi*numTheta+theta-1;
|
|
||||||
unsigned int p11 = phi*numTheta+theta%numTheta;
|
|
||||||
mesh->verticesPerFace.push_back(3);
|
|
||||||
mesh->position_indices.push_back(p10);
|
|
||||||
mesh->position_indices.push_back(p00);
|
|
||||||
mesh->position_indices.push_back(p11);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (phi == numPhi)
|
|
||||||
{
|
|
||||||
for (unsigned int theta=1; theta<=numTheta; theta++)
|
|
||||||
{
|
|
||||||
unsigned int p00 = (phi-1)*numTheta+theta-1;
|
|
||||||
unsigned int p01 = (phi-1)*numTheta+theta%numTheta;
|
|
||||||
unsigned int p10 = numPhi*numTheta;
|
|
||||||
mesh->verticesPerFace.push_back(3);
|
|
||||||
mesh->position_indices.push_back(p10);
|
|
||||||
mesh->position_indices.push_back(p00);
|
|
||||||
mesh->position_indices.push_back(p01);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (unsigned int theta=1; theta<=numTheta; theta++)
|
|
||||||
{
|
|
||||||
unsigned int p00 = (phi-1)*numTheta+theta-1;
|
|
||||||
unsigned int p01 = (phi-1)*numTheta+theta%numTheta;
|
|
||||||
unsigned int p10 = phi*numTheta+theta-1;
|
|
||||||
unsigned int p11 = phi*numTheta+theta%numTheta;
|
|
||||||
mesh->verticesPerFace.push_back(4);
|
|
||||||
mesh->position_indices.push_back(p10);
|
|
||||||
mesh->position_indices.push_back(p00);
|
|
||||||
mesh->position_indices.push_back(p01);
|
|
||||||
mesh->position_indices.push_back(p11);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return mesh.dynamicCast<SceneGraph::Node>();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<SceneGraph::Node> SceneGraph::createSphereShapedHair(const Vec3fa& center, const float radius, Ref<MaterialNode> material)
|
|
||||||
{
|
|
||||||
Ref<SceneGraph::HairSetNode> mesh = new SceneGraph::HairSetNode(RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE,material,BBox1f(0,1),1);
|
|
||||||
mesh->hairs.push_back(SceneGraph::HairSetNode::Hair(0,0));
|
|
||||||
mesh->positions[0].push_back(Vec3ff(center+Vec3fa(-radius,0,0),radius));
|
|
||||||
mesh->positions[0].push_back(Vec3ff(center+Vec3fa(0,0,0),radius));
|
|
||||||
mesh->positions[0].push_back(Vec3ff(center+Vec3fa(0,0,0),radius));
|
|
||||||
mesh->positions[0].push_back(Vec3ff(center+Vec3fa(+radius,0,0),radius));
|
|
||||||
return mesh.dynamicCast<SceneGraph::Node>();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<SceneGraph::Node> SceneGraph::createSphere (const Vec3fa& center, const float radius, Ref<MaterialNode> material)
|
|
||||||
{
|
|
||||||
RTCGeometryType type = RTC_GEOMETRY_TYPE_SPHERE_POINT;
|
|
||||||
Ref<SceneGraph::PointSetNode> mesh = new SceneGraph::PointSetNode(type, material, BBox1f(0,1), 1);
|
|
||||||
mesh->positions[0].resize(1);
|
|
||||||
mesh->positions[0][0].x = center.x;
|
|
||||||
mesh->positions[0][0].y = center.y;
|
|
||||||
mesh->positions[0][0].z = center.z;
|
|
||||||
mesh->positions[0][0].w = radius;
|
|
||||||
return mesh.dynamicCast<SceneGraph::Node>();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<SceneGraph::Node> SceneGraph::createPointSphere (const Vec3fa& center, const float radius, const float pointRadius,
|
|
||||||
size_t N, PointSubtype subtype, Ref<MaterialNode> material)
|
|
||||||
{
|
|
||||||
unsigned numPhi = unsigned(N);
|
|
||||||
unsigned numTheta = 2 * numPhi;
|
|
||||||
unsigned numVertices = numTheta * (numPhi + 1);
|
|
||||||
|
|
||||||
RTCGeometryType type;
|
|
||||||
switch (subtype) {
|
|
||||||
case SPHERE:
|
|
||||||
type = RTC_GEOMETRY_TYPE_SPHERE_POINT;
|
|
||||||
break;
|
|
||||||
case DISC:
|
|
||||||
type = RTC_GEOMETRY_TYPE_DISC_POINT;
|
|
||||||
break;
|
|
||||||
case ORIENTED_DISC:
|
|
||||||
type = RTC_GEOMETRY_TYPE_ORIENTED_DISC_POINT;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<SceneGraph::PointSetNode> mesh = new SceneGraph::PointSetNode(type, material, BBox1f(0,1), 1);
|
|
||||||
mesh->positions[0].resize(numVertices);
|
|
||||||
if (subtype == ORIENTED_DISC) {
|
|
||||||
mesh->normals.push_back(avector<Vec3fa>());
|
|
||||||
mesh->normals[0].resize(numVertices);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* create sphere geometry */
|
|
||||||
const float rcpNumTheta = rcp(float(numTheta));
|
|
||||||
const float rcpNumPhi = rcp(float(numPhi));
|
|
||||||
for (unsigned int phi = 0; phi <= numPhi; phi++)
|
|
||||||
{
|
|
||||||
for (unsigned int theta = 0; theta < numTheta; theta++)
|
|
||||||
{
|
|
||||||
const float phif = phi * float(pi) * rcpNumPhi;
|
|
||||||
const float thetaf = theta * 2.0f * float(pi) * rcpNumTheta;
|
|
||||||
mesh->positions[0][phi * numTheta + theta].x = center.x + radius * sin(phif) * sin(thetaf);
|
|
||||||
mesh->positions[0][phi * numTheta + theta].y = center.y + radius * cos(phif);
|
|
||||||
mesh->positions[0][phi * numTheta + theta].z = center.z + radius * sin(phif) * cos(thetaf);
|
|
||||||
mesh->positions[0][phi * numTheta + theta].w = pointRadius;
|
|
||||||
if (subtype == ORIENTED_DISC)
|
|
||||||
mesh->normals[0][phi * numTheta + theta] =
|
|
||||||
normalize(mesh->positions[0][phi * numTheta + theta] - center);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return mesh.dynamicCast<SceneGraph::Node>();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<SceneGraph::Node> SceneGraph::createHairyPlane (int hash, const Vec3fa& pos, const Vec3fa& dx, const Vec3fa& dy, const float len, const float r, size_t numHairs, CurveSubtype subtype, Ref<MaterialNode> material)
|
|
||||||
{
|
|
||||||
RandomSampler sampler;
|
|
||||||
RandomSampler_init(sampler,hash);
|
|
||||||
|
|
||||||
RTCGeometryType type = (subtype == ROUND_CURVE) ? RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE : RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE;
|
|
||||||
Ref<SceneGraph::HairSetNode> mesh = new SceneGraph::HairSetNode(type,material,BBox1f(0,1),1);
|
|
||||||
|
|
||||||
if (numHairs == 1) {
|
|
||||||
const Vec3fa p0 = pos;
|
|
||||||
const Vec3fa p1 = p0 + len*Vec3fa(1,0,0);
|
|
||||||
const Vec3fa p2 = p0 + len*Vec3fa(0,1,1);
|
|
||||||
const Vec3fa p3 = p0 + len*Vec3fa(0,1,0);
|
|
||||||
mesh->hairs.push_back(HairSetNode::Hair(0,0));
|
|
||||||
mesh->positions[0].push_back(Vec3ff(p0,r));
|
|
||||||
mesh->positions[0].push_back(Vec3ff(p1,r));
|
|
||||||
mesh->positions[0].push_back(Vec3ff(p2,r));
|
|
||||||
mesh->positions[0].push_back(Vec3ff(p3,r));
|
|
||||||
return mesh.dynamicCast<SceneGraph::Node>();
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec3fa dz = cross(dx,dy);
|
|
||||||
for (size_t i=0; i<numHairs; i++)
|
|
||||||
{
|
|
||||||
const Vec3fa p0 = pos + RandomSampler_getFloat(sampler)*dx + RandomSampler_getFloat(sampler)*dy;
|
|
||||||
const Vec3fa p1 = p0 + len*normalize(dx);
|
|
||||||
const Vec3fa p2 = p0 + len*(normalize(dz)+normalize(dy));
|
|
||||||
const Vec3fa p3 = p0 + len*normalize(dz);
|
|
||||||
mesh->hairs.push_back(HairSetNode::Hair(unsigned(4*i),unsigned(i)));
|
|
||||||
mesh->positions[0].push_back(Vec3ff(p0,r));
|
|
||||||
mesh->positions[0].push_back(Vec3ff(p1,r));
|
|
||||||
mesh->positions[0].push_back(Vec3ff(p2,r));
|
|
||||||
mesh->positions[0].push_back(Vec3ff(p3,r));
|
|
||||||
}
|
|
||||||
return mesh.dynamicCast<SceneGraph::Node>();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<SceneGraph::Node> SceneGraph::createGarbageTriangleMesh (int hash, size_t numTriangles, bool mblur, Ref<MaterialNode> material)
|
|
||||||
{
|
|
||||||
RandomSampler sampler;
|
|
||||||
RandomSampler_init(sampler,hash);
|
|
||||||
Ref<SceneGraph::TriangleMeshNode> mesh = new SceneGraph::TriangleMeshNode(material,BBox1f(0,1),mblur?2:1);
|
|
||||||
|
|
||||||
mesh->triangles.resize(numTriangles);
|
|
||||||
for (size_t i=0; i<numTriangles; i++) {
|
|
||||||
const unsigned v0 = (RandomSampler_getInt(sampler) % 32 == 0) ? RandomSampler_getUInt(sampler) : unsigned(3*i+0);
|
|
||||||
const unsigned v1 = (RandomSampler_getInt(sampler) % 32 == 0) ? RandomSampler_getUInt(sampler) : unsigned(3*i+1);
|
|
||||||
const unsigned v2 = (RandomSampler_getInt(sampler) % 32 == 0) ? RandomSampler_getUInt(sampler) : unsigned(3*i+2);
|
|
||||||
mesh->triangles[i] = TriangleMeshNode::Triangle(v0,v1,v2);
|
|
||||||
}
|
|
||||||
|
|
||||||
mesh->positions[0].resize(3*numTriangles);
|
|
||||||
for (size_t i=0; i<3*numTriangles; i++) {
|
|
||||||
const float x = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float y = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float z = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float w = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
mesh->positions[0][i] = Vec3ff(x,y,z,w);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mblur)
|
|
||||||
{
|
|
||||||
mesh->positions[1].resize(3*numTriangles);
|
|
||||||
for (size_t i=0; i<3*numTriangles; i++) {
|
|
||||||
const float x = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float y = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float z = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float w = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
mesh->positions[1][i] = Vec3ff(x,y,z,w);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return mesh.dynamicCast<SceneGraph::Node>();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<SceneGraph::Node> SceneGraph::createGarbageQuadMesh (int hash, size_t numQuads, bool mblur, Ref<MaterialNode> material)
|
|
||||||
{
|
|
||||||
RandomSampler sampler;
|
|
||||||
RandomSampler_init(sampler,hash);
|
|
||||||
Ref<SceneGraph::QuadMeshNode> mesh = new SceneGraph::QuadMeshNode(material,BBox1f(0,1),mblur?2:1);
|
|
||||||
|
|
||||||
mesh->quads.resize(numQuads);
|
|
||||||
for (size_t i=0; i<numQuads; i++) {
|
|
||||||
const unsigned v0 = (RandomSampler_getInt(sampler) % 32 == 0) ? RandomSampler_getUInt(sampler) : unsigned(4*i+0);
|
|
||||||
const unsigned v1 = (RandomSampler_getInt(sampler) % 32 == 0) ? RandomSampler_getUInt(sampler) : unsigned(4*i+1);
|
|
||||||
const unsigned v2 = (RandomSampler_getInt(sampler) % 32 == 0) ? RandomSampler_getUInt(sampler) : unsigned(4*i+2);
|
|
||||||
const unsigned v3 = (RandomSampler_getInt(sampler) % 32 == 0) ? RandomSampler_getUInt(sampler) : unsigned(4*i+3);
|
|
||||||
mesh->quads[i] = QuadMeshNode::Quad(v0,v1,v2,v3);
|
|
||||||
}
|
|
||||||
|
|
||||||
mesh->positions[0].resize(4*numQuads);
|
|
||||||
for (size_t i=0; i<4*numQuads; i++) {
|
|
||||||
const float x = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float y = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float z = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float w = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
mesh->positions[0][i] = Vec3fa(Vec3ff(x,y,z,w));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mblur)
|
|
||||||
{
|
|
||||||
mesh->positions[1].resize(4*numQuads);
|
|
||||||
for (size_t i=0; i<4*numQuads; i++) {
|
|
||||||
const float x = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float y = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float z = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float w = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
mesh->positions[1][i] = Vec3fa(Vec3ff(x,y,z,w));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return mesh.dynamicCast<SceneGraph::Node>();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<SceneGraph::Node> SceneGraph::createGarbageGridMesh (int hash, size_t numGrids, bool mblur, Ref<MaterialNode> material)
|
|
||||||
{
|
|
||||||
RandomSampler sampler;
|
|
||||||
RandomSampler_init(sampler,hash);
|
|
||||||
Ref<SceneGraph::GridMeshNode> mesh = new SceneGraph::GridMeshNode(material,BBox1f(0,1),mblur?2:1);
|
|
||||||
|
|
||||||
mesh->grids.resize(numGrids);
|
|
||||||
for (size_t i=0; i<numGrids; i++) {
|
|
||||||
const unsigned v0 = (RandomSampler_getInt(sampler) % 32 == 0) ? RandomSampler_getUInt(sampler) : unsigned(4*i+0);
|
|
||||||
mesh->grids[i] = GridMeshNode::Grid(v0,2,2,2);
|
|
||||||
}
|
|
||||||
|
|
||||||
mesh->positions[0].resize(4*numGrids);
|
|
||||||
for (size_t i=0; i<4*numGrids; i++) {
|
|
||||||
const float x = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float y = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float z = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float w = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
mesh->positions[0][i] = Vec3fa(Vec3ff(x,y,z,w));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mblur)
|
|
||||||
{
|
|
||||||
mesh->positions[1].resize(4*numGrids);
|
|
||||||
for (size_t i=0; i<4*numGrids; i++) {
|
|
||||||
const float x = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float y = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float z = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float w = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
mesh->positions[1][i] = Vec3fa(Vec3ff(x,y,z,w));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return mesh.dynamicCast<SceneGraph::Node>();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<SceneGraph::Node> SceneGraph::createGarbageLineSegments (int hash, size_t numLineSegments, bool mblur, Ref<MaterialNode> material)
|
|
||||||
{
|
|
||||||
RandomSampler sampler;
|
|
||||||
RandomSampler_init(sampler,hash);
|
|
||||||
Ref<SceneGraph::HairSetNode> mesh = new SceneGraph::HairSetNode(RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE,material,BBox1f(0,1),mblur?2:1);
|
|
||||||
|
|
||||||
mesh->hairs.resize(numLineSegments);
|
|
||||||
for (size_t i=0; i<numLineSegments; i++) {
|
|
||||||
mesh->hairs[i].vertex = (RandomSampler_getInt(sampler) % 32 == 0) ? RandomSampler_getUInt(sampler) : unsigned(2*i);
|
|
||||||
mesh->hairs[i].id = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
mesh->positions[0].resize(2*numLineSegments);
|
|
||||||
for (size_t i=0; i<2*numLineSegments; i++) {
|
|
||||||
const float x = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float y = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float z = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float r = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
mesh->positions[0][i] = Vec3ff(x,y,z,r);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mblur)
|
|
||||||
{
|
|
||||||
mesh->positions[1].resize(2*numLineSegments);
|
|
||||||
for (size_t i=0; i<2*numLineSegments; i++) {
|
|
||||||
const float x = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float y = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float z = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float r = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
mesh->positions[1][i] = Vec3ff(x,y,z,r);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return mesh.dynamicCast<SceneGraph::Node>();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<SceneGraph::Node> SceneGraph::createGarbageHair (int hash, size_t numHairs, bool mblur, Ref<MaterialNode> material)
|
|
||||||
{
|
|
||||||
RandomSampler sampler;
|
|
||||||
RandomSampler_init(sampler,hash);
|
|
||||||
Ref<SceneGraph::HairSetNode> mesh = new SceneGraph::HairSetNode(RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE,material,BBox1f(0,1),mblur?2:1);
|
|
||||||
|
|
||||||
mesh->hairs.resize(numHairs);
|
|
||||||
for (size_t i=0; i<numHairs; i++) {
|
|
||||||
const unsigned v0 = (RandomSampler_getInt(sampler) % 32 == 0) ? RandomSampler_getUInt(sampler) : unsigned(4*i);
|
|
||||||
mesh->hairs[i] = HairSetNode::Hair(v0,0);
|
|
||||||
}
|
|
||||||
|
|
||||||
mesh->positions[0].resize(4*numHairs);
|
|
||||||
for (size_t i=0; i<4*numHairs; i++) {
|
|
||||||
const float x = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float y = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float z = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float r = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
mesh->positions[0][i] = Vec3ff(x,y,z,r);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mblur)
|
|
||||||
{
|
|
||||||
mesh->positions[1].resize(4*numHairs);
|
|
||||||
for (size_t i=0; i<4*numHairs; i++) {
|
|
||||||
const float x = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float y = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float z = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float r = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
mesh->positions[1][i] = Vec3ff(x,y,z,r);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return mesh.dynamicCast<SceneGraph::Node>();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<SceneGraph::Node> SceneGraph::createGarbageSubdivMesh (int hash, size_t numFaces, bool mblur, Ref<MaterialNode> material)
|
|
||||||
{
|
|
||||||
RandomSampler sampler;
|
|
||||||
RandomSampler_init(sampler,hash);
|
|
||||||
Ref<SceneGraph::SubdivMeshNode> mesh = new SceneGraph::SubdivMeshNode(material,BBox1f(0,1),mblur?2:1);
|
|
||||||
|
|
||||||
for (size_t i=0; i<numFaces; i++)
|
|
||||||
{
|
|
||||||
const unsigned f = RandomSampler_getInt(sampler) % 20;
|
|
||||||
mesh->verticesPerFace.push_back(f);
|
|
||||||
for (size_t j=0; j<f; j++)
|
|
||||||
{
|
|
||||||
mesh->position_indices.push_back((RandomSampler_getInt(sampler) % 32 == 0) ? RandomSampler_getUInt(sampler) : unsigned(mesh->numPositions()));
|
|
||||||
|
|
||||||
const float x = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float y = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float z = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float w = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
mesh->positions[0].push_back(Vec3fa(Vec3ff(x,y,z,w)));
|
|
||||||
|
|
||||||
if (mblur)
|
|
||||||
{
|
|
||||||
const float x = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float y = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float z = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float w = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
mesh->positions[1].push_back(Vec3fa(Vec3ff(x,y,z,w)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return mesh.dynamicCast<SceneGraph::Node>();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Ref<SceneGraph::Node> SceneGraph::createGarbagePointSet(int hash, size_t numPoints, bool mblur, Ref<MaterialNode> material)
|
|
||||||
{
|
|
||||||
RandomSampler sampler;
|
|
||||||
RandomSampler_init(sampler,hash);
|
|
||||||
|
|
||||||
Ref<SceneGraph::PointSetNode> mesh = new SceneGraph::PointSetNode(RTC_GEOMETRY_TYPE_SPHERE_POINT, material,BBox1f(0,1),mblur?2:1);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < numPoints; i++)
|
|
||||||
{
|
|
||||||
const float x = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float y = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float z = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float r = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
mesh->positions[0].push_back(Vec3ff(x, y, z, r));
|
|
||||||
|
|
||||||
if (mblur)
|
|
||||||
{
|
|
||||||
const float x = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float y = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float z = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
const float r = cast_i2f(RandomSampler_getUInt(sampler));
|
|
||||||
mesh->positions[1].push_back(Vec3ff(x, y, z, r));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return mesh.dynamicCast<SceneGraph::Node>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "scenegraph.h"
|
|
||||||
|
|
||||||
namespace embree
|
|
||||||
{
|
|
||||||
namespace SceneGraph
|
|
||||||
{
|
|
||||||
Ref<Node> createTrianglePlane (const Vec3fa& p0, const Vec3fa& dx, const Vec3fa& dy, size_t width, size_t height, Ref<MaterialNode> material = nullptr);
|
|
||||||
Ref<Node> createQuadPlane (const Vec3fa& p0, const Vec3fa& dx, const Vec3fa& dy, size_t width, size_t height, Ref<MaterialNode> material = nullptr);
|
|
||||||
Ref<Node> createGridPlane (const Vec3fa& p0, const Vec3fa& dx, const Vec3fa& dy, size_t width, size_t height, Ref<MaterialNode> material = nullptr);
|
|
||||||
Ref<Node> createSubdivPlane (const Vec3fa& p0, const Vec3fa& dx, const Vec3fa& dy, size_t width, size_t height, float tessellationRate, Ref<MaterialNode> material = nullptr);
|
|
||||||
|
|
||||||
Ref<Node> createSphere (const Vec3fa& center, const float radius, Ref<MaterialNode> materiall = nullptr);
|
|
||||||
Ref<Node> createTriangleSphere(const Vec3fa& center, const float radius, size_t numPhi, Ref<MaterialNode> material = nullptr);
|
|
||||||
Ref<Node> createQuadSphere (const Vec3fa& center, const float radius, size_t numPhi, Ref<MaterialNode> material = nullptr);
|
|
||||||
Ref<Node> createGridSphere (const Vec3fa& center, const float radius, size_t size, Ref<MaterialNode> material = nullptr);
|
|
||||||
Ref<Node> createSubdivSphere (const Vec3fa& center, const float radius, size_t numPhi, float tessellationRate, Ref<MaterialNode> material = nullptr);
|
|
||||||
Ref<Node> createSphereShapedHair(const Vec3fa& center, const float radius, Ref<MaterialNode> material = nullptr);
|
|
||||||
Ref<Node> createPointSphere (const Vec3fa& center, const float radius, const float pointRadius, size_t numPhi, PointSubtype subtype, Ref<MaterialNode> materiall = nullptr);
|
|
||||||
|
|
||||||
Ref<Node> createHairyPlane (int hash, const Vec3fa& pos, const Vec3fa& dx, const Vec3fa& dy, const float len, const float r, size_t numHairs, CurveSubtype subtype, Ref<MaterialNode> material = nullptr);
|
|
||||||
|
|
||||||
Ref<Node> createGarbageTriangleMesh (int hash, size_t numTriangles, bool mblur, Ref<MaterialNode> material = nullptr);
|
|
||||||
Ref<Node> createGarbageQuadMesh (int hash, size_t numQuads, bool mblur, Ref<MaterialNode> material = nullptr);
|
|
||||||
Ref<Node> createGarbageGridMesh (int hash, size_t numGrids, bool mblur, Ref<MaterialNode> material = nullptr);
|
|
||||||
Ref<Node> createGarbageHair (int hash, size_t numHairs, bool mblur, Ref<MaterialNode> material = nullptr);
|
|
||||||
Ref<Node> createGarbageLineSegments (int hash, size_t numLineSegments, bool mblur, Ref<MaterialNode> material = nullptr);
|
|
||||||
Ref<Node> createGarbageSubdivMesh (int hash, size_t numFaces, bool mblur, Ref<MaterialNode> material = nullptr);
|
|
||||||
Ref<Node> createGarbagePointSet(int hash, size_t numPoints, bool mblur, Ref<MaterialNode> material = nullptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,199 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../default.h"
|
|
||||||
|
|
||||||
namespace embree
|
|
||||||
{
|
|
||||||
namespace SceneGraph
|
|
||||||
{
|
|
||||||
enum LightType
|
|
||||||
{
|
|
||||||
LIGHT_AMBIENT,
|
|
||||||
LIGHT_POINT,
|
|
||||||
LIGHT_DIRECTIONAL,
|
|
||||||
LIGHT_SPOT,
|
|
||||||
LIGHT_DISTANT,
|
|
||||||
LIGHT_TRIANGLE,
|
|
||||||
LIGHT_QUAD,
|
|
||||||
};
|
|
||||||
|
|
||||||
class Light
|
|
||||||
{
|
|
||||||
ALIGNED_CLASS_(16)
|
|
||||||
|
|
||||||
public:
|
|
||||||
Light(LightType type) : type(type) {}
|
|
||||||
|
|
||||||
LightType getType() const { return type; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
LightType type;
|
|
||||||
};
|
|
||||||
|
|
||||||
class AmbientLight : public Light
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
AmbientLight (const Vec3fa& L)
|
|
||||||
: Light(LIGHT_AMBIENT), L(L) {}
|
|
||||||
|
|
||||||
AmbientLight transform(const AffineSpace3fa& space) const {
|
|
||||||
return AmbientLight(L);
|
|
||||||
}
|
|
||||||
|
|
||||||
static AmbientLight lerp(const AmbientLight& light0, const AmbientLight& light1, const float f) {
|
|
||||||
return AmbientLight(embree::lerp(light0.L,light1.L,f));
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
Vec3fa L; //!< radiance of ambient light
|
|
||||||
};
|
|
||||||
|
|
||||||
class PointLight : public Light
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PointLight (const Vec3fa& P, const Vec3fa& I)
|
|
||||||
: Light(LIGHT_POINT), P(P), I(I) {}
|
|
||||||
|
|
||||||
PointLight transform(const AffineSpace3fa& space) const {
|
|
||||||
return PointLight(xfmPoint(space,P),I);
|
|
||||||
}
|
|
||||||
|
|
||||||
static PointLight lerp(const PointLight& light0, const PointLight& light1, const float f)
|
|
||||||
{
|
|
||||||
return PointLight(embree::lerp(light0.P,light1.P,f),
|
|
||||||
embree::lerp(light0.I,light1.I,f));
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
Vec3fa P; //!< position of point light
|
|
||||||
Vec3fa I; //!< radiant intensity of point light
|
|
||||||
};
|
|
||||||
|
|
||||||
class DirectionalLight : public Light
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DirectionalLight (const Vec3fa& D, const Vec3fa& E)
|
|
||||||
: Light(LIGHT_DIRECTIONAL), D(D), E(E) {}
|
|
||||||
|
|
||||||
DirectionalLight transform(const AffineSpace3fa& space) const {
|
|
||||||
return DirectionalLight(xfmVector(space,D),E);
|
|
||||||
}
|
|
||||||
|
|
||||||
static DirectionalLight lerp(const DirectionalLight& light0, const DirectionalLight& light1, const float f)
|
|
||||||
{
|
|
||||||
return DirectionalLight(embree::lerp(light0.D,light1.D,f),
|
|
||||||
embree::lerp(light0.E,light1.E,f));
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
Vec3fa D; //!< Light direction
|
|
||||||
Vec3fa E; //!< Irradiance (W/m^2)
|
|
||||||
};
|
|
||||||
|
|
||||||
class SpotLight : public Light
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SpotLight (const Vec3fa& P, const Vec3fa& D, const Vec3fa& I, float angleMin, float angleMax)
|
|
||||||
: Light(LIGHT_SPOT), P(P), D(D), I(I), angleMin(angleMin), angleMax(angleMax) {}
|
|
||||||
|
|
||||||
SpotLight transform(const AffineSpace3fa& space) const {
|
|
||||||
return SpotLight(xfmPoint(space,P),xfmVector(space,D),I,angleMin,angleMax);
|
|
||||||
}
|
|
||||||
|
|
||||||
static SpotLight lerp(const SpotLight& light0, const SpotLight& light1, const float f)
|
|
||||||
{
|
|
||||||
return SpotLight(embree::lerp(light0.P,light1.P,f),
|
|
||||||
embree::lerp(light0.D,light1.D,f),
|
|
||||||
embree::lerp(light0.I,light1.I,f),
|
|
||||||
embree::lerp(light0.angleMin,light1.angleMin,f),
|
|
||||||
embree::lerp(light0.angleMax,light1.angleMax,f));
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
Vec3fa P; //!< Position of the spot light
|
|
||||||
Vec3fa D; //!< Light direction of the spot light
|
|
||||||
Vec3fa I; //!< Radiant intensity (W/sr)
|
|
||||||
float angleMin, angleMax; //!< Linear falloff region
|
|
||||||
};
|
|
||||||
|
|
||||||
class DistantLight : public Light
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DistantLight (const Vec3fa& D, const Vec3fa& L, const float halfAngle)
|
|
||||||
: Light(LIGHT_DISTANT), D(D), L(L), halfAngle(halfAngle), radHalfAngle(deg2rad(halfAngle)), cosHalfAngle(cos(deg2rad(halfAngle))) {}
|
|
||||||
|
|
||||||
DistantLight transform(const AffineSpace3fa& space) const {
|
|
||||||
return DistantLight(xfmVector(space,D),L,halfAngle);
|
|
||||||
}
|
|
||||||
|
|
||||||
static DistantLight lerp(const DistantLight& light0, const DistantLight& light1, const float f)
|
|
||||||
{
|
|
||||||
return DistantLight(embree::lerp(light0.D,light1.D,f),
|
|
||||||
embree::lerp(light0.L,light1.L,f),
|
|
||||||
embree::lerp(light0.halfAngle,light1.halfAngle,f));
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
Vec3fa D; //!< Light direction
|
|
||||||
Vec3fa L; //!< Radiance (W/(m^2*sr))
|
|
||||||
float halfAngle; //!< Half illumination angle
|
|
||||||
float radHalfAngle; //!< Half illumination angle in radians
|
|
||||||
float cosHalfAngle; //!< Cosine of half illumination angle
|
|
||||||
};
|
|
||||||
|
|
||||||
class TriangleLight : public Light
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TriangleLight (const Vec3fa& v0, const Vec3fa& v1, const Vec3fa& v2, const Vec3fa& L)
|
|
||||||
: Light(LIGHT_TRIANGLE), v0(v0), v1(v1), v2(v2), L(L) {}
|
|
||||||
|
|
||||||
TriangleLight transform(const AffineSpace3fa& space) const {
|
|
||||||
return TriangleLight(xfmPoint(space,v0),xfmPoint(space,v1),xfmPoint(space,v2),L);
|
|
||||||
}
|
|
||||||
|
|
||||||
static TriangleLight lerp(const TriangleLight& light0, const TriangleLight& light1, const float f)
|
|
||||||
{
|
|
||||||
return TriangleLight(embree::lerp(light0.v0,light1.v0,f),
|
|
||||||
embree::lerp(light0.v1,light1.v1,f),
|
|
||||||
embree::lerp(light0.v2,light1.v2,f),
|
|
||||||
embree::lerp(light0.L,light1.L,f));
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
Vec3fa v0;
|
|
||||||
Vec3fa v1;
|
|
||||||
Vec3fa v2;
|
|
||||||
Vec3fa L;
|
|
||||||
};
|
|
||||||
|
|
||||||
class QuadLight : public Light
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
QuadLight (const Vec3fa& v0, const Vec3fa& v1, const Vec3fa& v2, const Vec3fa& v3, const Vec3fa& L)
|
|
||||||
: Light(LIGHT_QUAD), v0(v0), v1(v1), v2(v2), v3(v3), L(L) {}
|
|
||||||
|
|
||||||
QuadLight transform(const AffineSpace3fa& space) const {
|
|
||||||
return QuadLight(xfmPoint(space,v0),xfmPoint(space,v1),xfmPoint(space,v2),xfmPoint(space,v3),L);
|
|
||||||
}
|
|
||||||
|
|
||||||
static QuadLight lerp(const QuadLight& light0, const QuadLight& light1, const float f)
|
|
||||||
{
|
|
||||||
return QuadLight(embree::lerp(light0.v0,light1.v0,f),
|
|
||||||
embree::lerp(light0.v1,light1.v1,f),
|
|
||||||
embree::lerp(light0.v2,light1.v2,f),
|
|
||||||
embree::lerp(light0.v3,light1.v3,f),
|
|
||||||
embree::lerp(light0.L,light1.L,f));
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
Vec3fa v0;
|
|
||||||
Vec3fa v1;
|
|
||||||
Vec3fa v2;
|
|
||||||
Vec3fa v3;
|
|
||||||
Vec3fa L;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,260 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#if defined (CPPTUTORIAL) && !defined(_MATERIALS_H_CPPTUTORIAL) || !defined(_MATERIALS_H_)
|
|
||||||
|
|
||||||
#if defined (CPPTUTORIAL)
|
|
||||||
#define _MATERIALS_H_CPPTUTORIAL
|
|
||||||
#else
|
|
||||||
#define _MATERIALS_H_
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//#pragma once
|
|
||||||
|
|
||||||
#if !defined(ISPC)
|
|
||||||
#include "texture.h"
|
|
||||||
#include "scenegraph.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(ISPC)
|
|
||||||
namespace embree
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ISPC) || defined(CPPTUTORIAL)
|
|
||||||
#define MATERIAL_BASE_CLASS
|
|
||||||
#define PREFIX(x) ISPC##x
|
|
||||||
#else
|
|
||||||
#define MATERIAL_BASE_CLASS : public SceneGraph::MaterialNode
|
|
||||||
#define PREFIX(x) x
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(CPPTUTORIAL)
|
|
||||||
enum MaterialType
|
|
||||||
{
|
|
||||||
MATERIAL_OBJ,
|
|
||||||
MATERIAL_THIN_DIELECTRIC,
|
|
||||||
MATERIAL_METAL,
|
|
||||||
MATERIAL_VELVET,
|
|
||||||
MATERIAL_DIELECTRIC,
|
|
||||||
MATERIAL_METALLIC_PAINT,
|
|
||||||
MATERIAL_MATTE,
|
|
||||||
MATERIAL_MIRROR,
|
|
||||||
MATERIAL_REFLECTIVE_METAL,
|
|
||||||
MATERIAL_HAIR
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct PREFIX(Material)
|
|
||||||
{
|
|
||||||
#if !defined(ISPC) && !defined(CPPTUTORIAL)
|
|
||||||
Material (MaterialType type)
|
|
||||||
: type(type) {}
|
|
||||||
#endif
|
|
||||||
#if !defined(ISPC)
|
|
||||||
__aligned(16)
|
|
||||||
#endif
|
|
||||||
int type;
|
|
||||||
int align[3];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PREFIX(MatteMaterial) MATERIAL_BASE_CLASS
|
|
||||||
{
|
|
||||||
#if !defined(ISPC) && !defined(CPPTUTORIAL)
|
|
||||||
MatteMaterial (const Vec3fa& reflectance)
|
|
||||||
: base(MATERIAL_MATTE), reflectance(reflectance) {}
|
|
||||||
virtual Material* material() { return &base; }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
PREFIX(Material) base;
|
|
||||||
Vec3fa reflectance;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PREFIX(MirrorMaterial) MATERIAL_BASE_CLASS
|
|
||||||
{
|
|
||||||
#if !defined(ISPC) && !defined(CPPTUTORIAL)
|
|
||||||
MirrorMaterial (const Vec3fa& reflectance)
|
|
||||||
: base(MATERIAL_MIRROR), reflectance(reflectance) {}
|
|
||||||
virtual Material* material() { return &base; }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
PREFIX(Material) base;
|
|
||||||
Vec3fa reflectance;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PREFIX(ThinDielectricMaterial) MATERIAL_BASE_CLASS
|
|
||||||
{
|
|
||||||
#if !defined(ISPC) && !defined(CPPTUTORIAL)
|
|
||||||
ThinDielectricMaterial (const Vec3fa& transmission, const float eta, const float thickness)
|
|
||||||
: base(MATERIAL_THIN_DIELECTRIC), transmission(transmission), transmissionFactor(log(transmission)*thickness), eta(eta), thickness(thickness) {}
|
|
||||||
virtual Material* material() { return &base; }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
PREFIX(Material) base;
|
|
||||||
Vec3fa transmission;
|
|
||||||
Vec3fa transmissionFactor;
|
|
||||||
float eta;
|
|
||||||
float thickness;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PREFIX(OBJMaterial) MATERIAL_BASE_CLASS
|
|
||||||
{
|
|
||||||
#if !defined(ISPC) && !defined(CPPTUTORIAL)
|
|
||||||
OBJMaterial (const std::string name = "")
|
|
||||||
: SceneGraph::MaterialNode(name), base(MATERIAL_OBJ), illum(0), d(1.f), Ns(1.f), Ni(1.f), Ka(0.f), Kd(1.f), Ks(0.f), Kt(1.0f),
|
|
||||||
map_d(nullptr), map_Ka(nullptr), map_Kd(nullptr), map_Ks(nullptr), map_Kt(nullptr), map_Ns(nullptr), map_Displ(nullptr) {}
|
|
||||||
|
|
||||||
OBJMaterial (float d, const Vec3fa& Kd, const Vec3fa& Ks, const float Ns, const std::string name = "")
|
|
||||||
: base(MATERIAL_OBJ), illum(0), d(d), Ns(Ns), Ni(1.f), Ka(0.f), Kd(Kd), Ks(Ks), Kt(1.0f),
|
|
||||||
map_d(nullptr), map_Ka(nullptr), map_Kd(nullptr), map_Ks(nullptr), map_Kt(nullptr), map_Ns(nullptr), map_Displ(nullptr) {}
|
|
||||||
|
|
||||||
OBJMaterial (float d, const std::shared_ptr<Texture> map_d,
|
|
||||||
const Vec3fa& Ka, const std::shared_ptr<Texture> map_Ka,
|
|
||||||
const Vec3fa& Kd, const std::shared_ptr<Texture> map_Kd,
|
|
||||||
const Vec3fa& Ks, const std::shared_ptr<Texture> map_Ks,
|
|
||||||
const Vec3fa& Kt, const std::shared_ptr<Texture> map_Kt,
|
|
||||||
const float Ns, const std::shared_ptr<Texture> map_Ns,
|
|
||||||
const std::shared_ptr<Texture> map_Displ)
|
|
||||||
: base(MATERIAL_OBJ), illum(0), d(d), Ns(Ns), Ni(1.f), Ka(Ka), Kd(Kd), Ks(Ks), Kt(Kt),
|
|
||||||
map_d(nullptr), map_Ka(nullptr), map_Kd(nullptr), map_Ks(nullptr), map_Kt(nullptr), map_Ns(nullptr), map_Displ(nullptr),
|
|
||||||
_map_d(map_d), _map_Ka(map_Ka), _map_Kd(map_Kd), _map_Ks(map_Ks), _map_Kt(map_Kt), _map_Ns(map_Ns), _map_Displ(map_Displ) {}
|
|
||||||
|
|
||||||
virtual Material* material()
|
|
||||||
{
|
|
||||||
map_d = _map_d.get();
|
|
||||||
map_Ka = _map_Ka.get();
|
|
||||||
map_Kd = _map_Kd.get();
|
|
||||||
map_Ks = _map_Ks.get();
|
|
||||||
map_Kt = _map_Kt.get();
|
|
||||||
map_Ns = _map_Ns.get();
|
|
||||||
map_Displ = _map_Displ.get();
|
|
||||||
return &base;
|
|
||||||
}
|
|
||||||
|
|
||||||
~OBJMaterial() { // FIXME: destructor never called
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
PREFIX(Material) base;
|
|
||||||
int illum; /*< illumination model */
|
|
||||||
float d; /*< dissolve factor, 1=opaque, 0=transparent */
|
|
||||||
float Ns; /*< specular exponent */
|
|
||||||
float Ni; /*< optical density for the surface (index of refraction) */
|
|
||||||
|
|
||||||
Vec3fa Ka; /*< ambient reflectivity */
|
|
||||||
Vec3fa Kd; /*< diffuse reflectivity */
|
|
||||||
Vec3fa Ks; /*< specular reflectivity */
|
|
||||||
Vec3fa Kt; /*< transmission filter */
|
|
||||||
|
|
||||||
const Texture* map_d; /*< d texture */
|
|
||||||
const Texture* map_Ka; /*< Ka texture */
|
|
||||||
const Texture* map_Kd; /*< Kd texture */
|
|
||||||
const Texture* map_Ks; /*< Ks texture */
|
|
||||||
const Texture* map_Kt; /*< Kt texture */
|
|
||||||
const Texture* map_Ns; /*< Ns texture */
|
|
||||||
const Texture* map_Displ; /*< Displ texture */
|
|
||||||
|
|
||||||
#if !defined(ISPC) && !defined(CPPTUTORIAL)
|
|
||||||
std::shared_ptr<Texture> _map_d; /*< d texture */
|
|
||||||
std::shared_ptr<Texture> _map_Ka; /*< Ka texture */
|
|
||||||
std::shared_ptr<Texture> _map_Kd; /*< Kd texture */
|
|
||||||
std::shared_ptr<Texture> _map_Ks; /*< Ks texture */
|
|
||||||
std::shared_ptr<Texture> _map_Kt; /*< Kt texture */
|
|
||||||
std::shared_ptr<Texture> _map_Ns; /*< Ns texture */
|
|
||||||
std::shared_ptr<Texture> _map_Displ; /*< Displ texture */
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PREFIX(MetalMaterial) MATERIAL_BASE_CLASS
|
|
||||||
{
|
|
||||||
#if !defined(ISPC) && !defined(CPPTUTORIAL)
|
|
||||||
MetalMaterial (const Vec3fa& reflectance, const Vec3fa& eta, const Vec3fa& k)
|
|
||||||
: base(MATERIAL_REFLECTIVE_METAL), reflectance(reflectance), eta(eta), k(k), roughness(0.0f) {}
|
|
||||||
|
|
||||||
MetalMaterial (const Vec3fa& reflectance, const Vec3fa& eta, const Vec3fa& k, const float roughness)
|
|
||||||
: base(MATERIAL_METAL), reflectance(reflectance), eta(eta), k(k), roughness(roughness) {}
|
|
||||||
|
|
||||||
virtual Material* material() { return &base; }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
PREFIX(Material) base;
|
|
||||||
Vec3fa reflectance;
|
|
||||||
Vec3fa eta;
|
|
||||||
Vec3fa k;
|
|
||||||
float roughness;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef PREFIX(MetalMaterial) PREFIX(ReflectiveMetalMaterial);
|
|
||||||
|
|
||||||
struct PREFIX(VelvetMaterial) MATERIAL_BASE_CLASS
|
|
||||||
{
|
|
||||||
#if !defined(ISPC) && !defined(CPPTUTORIAL)
|
|
||||||
VelvetMaterial (const Vec3fa& reflectance, const float backScattering, const Vec3fa& horizonScatteringColor, const float horizonScatteringFallOff)
|
|
||||||
: base(MATERIAL_VELVET), reflectance(reflectance), horizonScatteringColor(horizonScatteringColor), backScattering(backScattering), horizonScatteringFallOff(horizonScatteringFallOff) {}
|
|
||||||
|
|
||||||
virtual Material* material() { return &base; }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
PREFIX(Material) base;
|
|
||||||
Vec3fa reflectance;
|
|
||||||
Vec3fa horizonScatteringColor;
|
|
||||||
float backScattering;
|
|
||||||
float horizonScatteringFallOff;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PREFIX(DielectricMaterial) MATERIAL_BASE_CLASS
|
|
||||||
{
|
|
||||||
#if !defined(ISPC) && !defined(CPPTUTORIAL)
|
|
||||||
DielectricMaterial (const Vec3fa& transmissionOutside, const Vec3fa& transmissionInside, const float etaOutside, const float etaInside)
|
|
||||||
: base(MATERIAL_DIELECTRIC), transmissionOutside(transmissionOutside), transmissionInside(transmissionInside), etaOutside(etaOutside), etaInside(etaInside) {}
|
|
||||||
|
|
||||||
virtual Material* material() { return &base; }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
PREFIX(Material) base;
|
|
||||||
Vec3fa transmissionOutside;
|
|
||||||
Vec3fa transmissionInside;
|
|
||||||
float etaOutside;
|
|
||||||
float etaInside;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PREFIX(MetallicPaintMaterial) MATERIAL_BASE_CLASS
|
|
||||||
{
|
|
||||||
#if !defined(ISPC) && !defined(CPPTUTORIAL)
|
|
||||||
MetallicPaintMaterial (const Vec3fa& shadeColor, const Vec3fa& glitterColor, float glitterSpread, float eta)
|
|
||||||
: base(MATERIAL_METALLIC_PAINT), shadeColor(shadeColor), glitterColor(glitterColor), glitterSpread(glitterSpread), eta(eta) {}
|
|
||||||
|
|
||||||
virtual Material* material() { return &base; }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
PREFIX(Material) base;
|
|
||||||
Vec3fa shadeColor;
|
|
||||||
Vec3fa glitterColor;
|
|
||||||
float glitterSpread;
|
|
||||||
float eta;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PREFIX(HairMaterial) MATERIAL_BASE_CLASS
|
|
||||||
{
|
|
||||||
#if !defined(ISPC) && !defined(CPPTUTORIAL)
|
|
||||||
HairMaterial (const Vec3fa& Kr, const Vec3fa& Kt, float nx, float ny)
|
|
||||||
: base(MATERIAL_HAIR), Kr(Kr), Kt(Kt), nx(nx), ny(ny) {}
|
|
||||||
|
|
||||||
virtual Material* material() { return &base; }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
PREFIX(Material) base;
|
|
||||||
Vec3fa Kr;
|
|
||||||
Vec3fa Kt;
|
|
||||||
float nx;
|
|
||||||
float ny;
|
|
||||||
};
|
|
||||||
|
|
||||||
#undef MATERIAL_BASE_CLASS
|
|
||||||
#undef PREFIX
|
|
||||||
|
|
||||||
#if !defined(ISPC)
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,652 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#include "obj_loader.h"
|
|
||||||
#include "texture.h"
|
|
||||||
|
|
||||||
namespace embree
|
|
||||||
{
|
|
||||||
/*! Three-index vertex, indexing start at 0, -1 means invalid vertex. */
|
|
||||||
struct Vertex {
|
|
||||||
unsigned int v, vt, vn;
|
|
||||||
Vertex() {};
|
|
||||||
Vertex(unsigned int v) : v(v), vt(v), vn(v) {};
|
|
||||||
Vertex(unsigned int v, unsigned int vt, unsigned int vn) : v(v), vt(vt), vn(vn) {};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Crease {
|
|
||||||
float w;
|
|
||||||
unsigned int a, b;
|
|
||||||
Crease() : w(0), a(-1), b(-1) {};
|
|
||||||
Crease(float w, unsigned int a, unsigned int b) : w(w), a(a), b(b) {};
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline bool operator < ( const Vertex& a, const Vertex& b ) {
|
|
||||||
if (a.v != b.v) return a.v < b.v;
|
|
||||||
if (a.vn != b.vn) return a.vn < b.vn;
|
|
||||||
if (a.vt != b.vt) return a.vt < b.vt;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Fill space at the end of the token with 0s. */
|
|
||||||
static inline const char* trimEnd(const char* token)
|
|
||||||
{
|
|
||||||
if (*token == 0) return token;
|
|
||||||
char* pe = (char*) token;
|
|
||||||
while (*pe) pe++;
|
|
||||||
pe--;
|
|
||||||
while ((*pe == ' ' || *pe == '\t' || *pe == '\r') && pe >= token) *pe-- = 0;
|
|
||||||
return token;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Determine if character is a separator. */
|
|
||||||
static inline bool isSep(const char c) {
|
|
||||||
return (c == ' ') || (c == '\t');
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Parse separator. */
|
|
||||||
static inline const char* parseSep(const char*& token) {
|
|
||||||
size_t sep = strspn(token, " \t");
|
|
||||||
if (!sep) THROW_RUNTIME_ERROR("separator expected");
|
|
||||||
return token+=sep;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Parse optional separator. */
|
|
||||||
static inline const char* parseSepOpt(const char*& token) {
|
|
||||||
return token+=strspn(token, " \t");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Read float from a string. */
|
|
||||||
static inline float getFloat(const char*& token) {
|
|
||||||
token += strspn(token, " \t");
|
|
||||||
float n = (float)atof(token);
|
|
||||||
token += strcspn(token, " \t\r");
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Read int from a string. */
|
|
||||||
static inline int getInt(const char*& token) {
|
|
||||||
token += strspn(token, " \t");
|
|
||||||
int n = atoi(token);
|
|
||||||
token += strcspn(token, " \t\r");
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Read Vec2f from a string. */
|
|
||||||
static inline Vec2f getVec2f(const char*& token) {
|
|
||||||
float x = getFloat(token);
|
|
||||||
float y = getFloat(token);
|
|
||||||
return Vec2f(x,y);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Read Vec3f from a string. */
|
|
||||||
static inline Vec3f getVec3f(const char*& token) {
|
|
||||||
float x = getFloat(token);
|
|
||||||
token += strspn(token, " \t");
|
|
||||||
if (*token == 0) return Vec3f(x);
|
|
||||||
float y = getFloat(token);
|
|
||||||
float z = getFloat(token);
|
|
||||||
return Vec3f(x,y,z);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Read Vec3fa from a string. */
|
|
||||||
static inline Vec3fa getVec3fa(const char*& token) {
|
|
||||||
float x = getFloat(token);
|
|
||||||
token += strspn(token, " \t");
|
|
||||||
if (*token == 0) return Vec3f(x);
|
|
||||||
float y = getFloat(token);
|
|
||||||
float z = getFloat(token);
|
|
||||||
return Vec3fa(x,y,z);
|
|
||||||
}
|
|
||||||
|
|
||||||
class OBJLoader
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
/*! Constructor. */
|
|
||||||
OBJLoader(const FileName& fileName, const bool subdivMode, const bool combineIntoSingleObject);
|
|
||||||
|
|
||||||
/*! output model */
|
|
||||||
Ref<SceneGraph::GroupNode> group;
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
/*! file to load */
|
|
||||||
FileName path;
|
|
||||||
|
|
||||||
/*! load only quads and ignore triangles */
|
|
||||||
bool subdivMode;
|
|
||||||
|
|
||||||
/*! Geometry buffer. */
|
|
||||||
avector<Vec3fa> v;
|
|
||||||
avector<Vec3fa> vn;
|
|
||||||
std::vector<Vec2f> vt;
|
|
||||||
std::vector<Crease> ec;
|
|
||||||
|
|
||||||
std::vector<std::vector<Vertex> > curGroup;
|
|
||||||
std::vector<avector<Vec3ff> > curGroupHair;
|
|
||||||
|
|
||||||
/*! Material handling. */
|
|
||||||
std::string curMaterialName;
|
|
||||||
Ref<SceneGraph::MaterialNode> curMaterial;
|
|
||||||
std::map<std::string, Ref<SceneGraph::MaterialNode> > material;
|
|
||||||
std::map<std::string, std::shared_ptr<Texture>> textureMap;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void loadMTL(const FileName& fileName);
|
|
||||||
unsigned int fix_v (int index);
|
|
||||||
unsigned int fix_vt(int index);
|
|
||||||
unsigned int fix_vn(int index);
|
|
||||||
void flushFaceGroup();
|
|
||||||
void flushTriGroup();
|
|
||||||
void flushHairGroup();
|
|
||||||
Vertex getUInt3(const char*& token);
|
|
||||||
uint32_t getVertex(std::map<Vertex,uint32_t>& vertexMap, Ref<SceneGraph::TriangleMeshNode> mesh, const Vertex& i);
|
|
||||||
std::shared_ptr<Texture> loadTexture(const FileName& fname);
|
|
||||||
};
|
|
||||||
|
|
||||||
OBJLoader::OBJLoader(const FileName &fileName, const bool subdivMode, const bool combineIntoSingleObject)
|
|
||||||
: group(new SceneGraph::GroupNode), path(fileName.path()), subdivMode(subdivMode)
|
|
||||||
{
|
|
||||||
/* open file */
|
|
||||||
std::ifstream cin;
|
|
||||||
cin.open(fileName.c_str());
|
|
||||||
if (!cin.is_open()) {
|
|
||||||
THROW_RUNTIME_ERROR("cannot open " + fileName.str());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* generate default material */
|
|
||||||
Ref<SceneGraph::MaterialNode> defaultMaterial = new OBJMaterial("default");
|
|
||||||
curMaterialName = "default";
|
|
||||||
curMaterial = defaultMaterial;
|
|
||||||
|
|
||||||
while (cin.peek() != -1)
|
|
||||||
{
|
|
||||||
/* load next multiline */
|
|
||||||
std::string line; std::getline(cin,line);
|
|
||||||
while (!line.empty() && line[line.size()-1] == '\\') {
|
|
||||||
line[line.size()-1] = ' ';
|
|
||||||
std::string next_line; std::getline(cin,next_line);
|
|
||||||
if (next_line.empty()) break;
|
|
||||||
line += next_line;
|
|
||||||
}
|
|
||||||
const char* token = trimEnd(line.c_str() + strspn(line.c_str(), " \t"));
|
|
||||||
if (token[0] == 0) continue;
|
|
||||||
|
|
||||||
/*! parse position */
|
|
||||||
if (token[0] == 'v' && isSep(token[1])) {
|
|
||||||
v.push_back(getVec3f(token += 2)); continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* parse normal */
|
|
||||||
if (token[0] == 'v' && token[1] == 'n' && isSep(token[2])) {
|
|
||||||
vn.push_back(getVec3f(token += 3));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* parse texcoord */
|
|
||||||
if (token[0] == 'v' && token[1] == 't' && isSep(token[2])) { vt.push_back(getVec2f(token += 3)); continue; }
|
|
||||||
|
|
||||||
/*! parse face */
|
|
||||||
if (token[0] == 'f' && isSep(token[1]))
|
|
||||||
{
|
|
||||||
parseSep(token += 1);
|
|
||||||
|
|
||||||
std::vector<Vertex> face;
|
|
||||||
while (token[0]) {
|
|
||||||
Vertex vtx = getUInt3(token);
|
|
||||||
face.push_back(vtx);
|
|
||||||
parseSepOpt(token);
|
|
||||||
}
|
|
||||||
curGroup.push_back(face);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! parse corona hair */
|
|
||||||
if (!strncmp(token,"hair",4) && isSep(token[4]))
|
|
||||||
{
|
|
||||||
parseSep(token += 4);
|
|
||||||
bool plane = !strncmp(token,"plane",5) && isSep(token[5]);
|
|
||||||
if (plane) {
|
|
||||||
parseSep(token += 5);
|
|
||||||
}
|
|
||||||
else if (!strncmp(token,"cylinder",8) && isSep(token[8])) {
|
|
||||||
parseSep(token += 8);
|
|
||||||
}
|
|
||||||
else continue;
|
|
||||||
|
|
||||||
unsigned int N = getInt(token);
|
|
||||||
avector<Vec3ff> hair;
|
|
||||||
for (unsigned int i=0; i<3*N+1; i++) {
|
|
||||||
hair.push_back((Vec3ff)getVec3fa(token));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (unsigned int i=0; i<N+1; i++)
|
|
||||||
{
|
|
||||||
float r = getFloat(token);
|
|
||||||
MAYBE_UNUSED float t = (float)getInt(token);
|
|
||||||
if (i != 0) hair[3*i-1].w = r;
|
|
||||||
hair[3*i+0].w = r;
|
|
||||||
if (i != N) hair[3*i+1].w = r;
|
|
||||||
}
|
|
||||||
curGroupHair.push_back(hair);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! parse edge crease */
|
|
||||||
if (token[0] == 'e' && token[1] == 'c' && isSep(token[2]))
|
|
||||||
{
|
|
||||||
parseSep(token += 2);
|
|
||||||
float w = getFloat(token);
|
|
||||||
parseSepOpt(token);
|
|
||||||
unsigned int a = fix_v(getInt(token));
|
|
||||||
parseSepOpt(token);
|
|
||||||
unsigned int b = fix_v(getInt(token));
|
|
||||||
parseSepOpt(token);
|
|
||||||
ec.push_back(Crease(w, a, b));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! use material */
|
|
||||||
if (!strncmp(token, "usemtl", 6) && isSep(token[6]))
|
|
||||||
{
|
|
||||||
if (!combineIntoSingleObject) flushFaceGroup();
|
|
||||||
std::string name(parseSep(token += 6));
|
|
||||||
if (material.find(name) == material.end()) {
|
|
||||||
curMaterial = defaultMaterial;
|
|
||||||
curMaterialName = "default";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
curMaterial = material[name];
|
|
||||||
curMaterialName = name;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* load material library */
|
|
||||||
if (!strncmp(token, "mtllib", 6) && isSep(token[6])) {
|
|
||||||
loadMTL(path + std::string(parseSep(token += 6)));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ignore unknown stuff
|
|
||||||
}
|
|
||||||
flushFaceGroup();
|
|
||||||
|
|
||||||
cin.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ExtObjMaterial
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
enum Type { NONE, MATTE, GLASS, METAL, METALLIC_PAINT };
|
|
||||||
|
|
||||||
Ref<SceneGraph::MaterialNode> select() const
|
|
||||||
{
|
|
||||||
std::shared_ptr<Texture> nulltex;
|
|
||||||
if (type == NONE) {
|
|
||||||
return new OBJMaterial(d,map_d,Ka,map_Ka,Kd,map_Kd,Ks,map_Ks,Kt,map_Kt,Ns,map_Ns,map_Displ);
|
|
||||||
} else if (type == MATTE) {
|
|
||||||
if (coat_eta != 1.0f) return new MetallicPaintMaterial (Kd,zero,0.0f,eta.x);
|
|
||||||
else return new OBJMaterial(1.0f,nulltex,zero,nulltex,Kd,map_Kd,Ks,nulltex,zero,nulltex,1.0f/(1E-6f+roughness),nulltex,nulltex);
|
|
||||||
} else if (type == GLASS) {
|
|
||||||
return new ThinDielectricMaterial(Vec3fa(1.0f),eta.x,0.1f);
|
|
||||||
} else if (type == METAL) {
|
|
||||||
if (roughness == 0.0f) {
|
|
||||||
if (eta == Vec3fa(1.0f) && k == Vec3fa(0.0f)) return new MirrorMaterial(Kd);
|
|
||||||
else return new MetalMaterial(Kd,eta,k);
|
|
||||||
}
|
|
||||||
else return new MetalMaterial(Kd,eta,k,roughness);
|
|
||||||
} else if (type == METALLIC_PAINT) {
|
|
||||||
return new MetallicPaintMaterial (Kd,Ks,0.0f,coat_eta);
|
|
||||||
}
|
|
||||||
return new MatteMaterial(Vec3fa(0.5f));
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
Type type = NONE;
|
|
||||||
|
|
||||||
int illum = 0; /*< illumination model */
|
|
||||||
float d = 1.0f; /*< dissolve factor, 1=opaque, 0=transparent */
|
|
||||||
float Ns = 1.0f; /*< specular exponent */
|
|
||||||
float Ni = 1.0f; /*< optical density for the surface (index of refraction) */
|
|
||||||
|
|
||||||
Vec3fa Ka = zero; /*< ambient reflectivity */
|
|
||||||
Vec3fa Kd = one; /*< diffuse reflectivity */
|
|
||||||
Vec3fa Ks = zero; /*< specular reflectivity */
|
|
||||||
Vec3fa Kt = zero; /*< transmission filter */
|
|
||||||
|
|
||||||
std::shared_ptr<Texture> map_d; /*< d texture */
|
|
||||||
std::shared_ptr<Texture> map_Ka; /*< Ka texture */
|
|
||||||
std::shared_ptr<Texture> map_Kd; /*< Kd texture */
|
|
||||||
std::shared_ptr<Texture> map_Ks; /*< Ks texture */
|
|
||||||
std::shared_ptr<Texture> map_Kt; /*< Kt texture */
|
|
||||||
std::shared_ptr<Texture> map_Ns; /*< Ns texture */
|
|
||||||
std::shared_ptr<Texture> map_Displ; /*< Displ texture */
|
|
||||||
|
|
||||||
float roughness = zero;
|
|
||||||
std::shared_ptr<Texture> roughnessMap;
|
|
||||||
float coat_eta = one;
|
|
||||||
float coat_roughness = zero;
|
|
||||||
std::shared_ptr<Texture> coat_roughnessMap;
|
|
||||||
float bump = zero;
|
|
||||||
Vec3f eta = Vec3f(1.4f);
|
|
||||||
Vec3f k = Vec3f(3.0f);
|
|
||||||
};
|
|
||||||
|
|
||||||
std::shared_ptr<Texture> OBJLoader::loadTexture(const FileName& fname)
|
|
||||||
{
|
|
||||||
if (textureMap.find(fname.str()) != textureMap.end())
|
|
||||||
return textureMap[fname.str()];
|
|
||||||
|
|
||||||
return std::shared_ptr<Texture>(Texture::load(path+fname));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* load material file */
|
|
||||||
void OBJLoader::loadMTL(const FileName &fileName)
|
|
||||||
{
|
|
||||||
std::ifstream cin;
|
|
||||||
cin.open(fileName.c_str());
|
|
||||||
if (!cin.is_open()) {
|
|
||||||
std::cerr << "cannot open " << fileName.str() << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string name;
|
|
||||||
ExtObjMaterial cur;
|
|
||||||
|
|
||||||
while (cin.peek() != -1)
|
|
||||||
{
|
|
||||||
/* load next multiline */
|
|
||||||
std::string line; std::getline(cin,line);
|
|
||||||
while (!line.empty() && line[line.size()-1] == '\\') {
|
|
||||||
line[line.size()-1] = ' ';
|
|
||||||
std::string next_line; std::getline(cin,next_line);
|
|
||||||
if (next_line.empty()) break;
|
|
||||||
line += next_line;
|
|
||||||
}
|
|
||||||
const char* token = trimEnd(line.c_str() + strspn(line.c_str(), " \t"));
|
|
||||||
|
|
||||||
if (token[0] == 0 ) continue; // ignore empty lines
|
|
||||||
if (token[0] == '#') continue; // ignore comments
|
|
||||||
|
|
||||||
if (!strncmp(token, "newmtl", 6))
|
|
||||||
{
|
|
||||||
if (name != "") {
|
|
||||||
material[name] = cur.select();
|
|
||||||
material[name]->name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
parseSep(token+=6);
|
|
||||||
name = token;
|
|
||||||
cur = ExtObjMaterial();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (name == "") THROW_RUNTIME_ERROR("invalid material file: newmtl expected first");
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (!strncmp(token, "illum", 5)) { parseSep(token += 5); continue; }
|
|
||||||
|
|
||||||
if (!strncmp(token, "d", 1)) { parseSep(token += 1); cur.d = getFloat(token); continue; }
|
|
||||||
if (!strncmp(token, "Ns", 2)) { parseSep(token += 2); cur.Ns = getFloat(token); continue; }
|
|
||||||
if (!strncmp(token, "Ni", 2)) { parseSep(token += 2); cur.Ni = getFloat(token); continue; }
|
|
||||||
|
|
||||||
if (!strncmp(token, "map_d", 5) || !strncmp(token, "d_map", 5)) {
|
|
||||||
parseSep(token += 5);
|
|
||||||
cur.map_d = loadTexture(FileName(token));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strncmp(token, "map_Ka", 6) || !strncmp(token, "Ka_map", 6)) {
|
|
||||||
parseSep(token += 6);
|
|
||||||
cur.map_Ka = loadTexture(FileName(token));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strncmp(token, "map_Kd", 6) || !strncmp(token, "Kd_map", 6)) {
|
|
||||||
parseSep(token += 6);
|
|
||||||
cur.map_Kd = loadTexture(FileName(token));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strncmp(token, "map_Ks", 6) || !strncmp(token, "Ks_map", 6)) {
|
|
||||||
parseSep(token += 6);
|
|
||||||
cur.map_Ks = loadTexture(FileName(token));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strncmp(token, "map_Kt", 6) || !strncmp(token, "Kt_map", 6)) {
|
|
||||||
parseSep(token += 6);
|
|
||||||
cur.map_Kt = loadTexture(FileName(token));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strncmp(token, "map_Tf", 6) || !strncmp(token, "Tf_map", 6)) {
|
|
||||||
parseSep(token += 6);
|
|
||||||
cur.map_Kt = loadTexture(FileName(token));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strncmp(token, "map_Ns", 6) || !strncmp(token, "Ns_map", 6)) {
|
|
||||||
parseSep(token += 6);
|
|
||||||
cur.map_Ns = loadTexture(FileName(token));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strncmp(token, "map_Displ", 9) || !strncmp(token, "Displ_map", 9)) {
|
|
||||||
parseSep(token += 9);
|
|
||||||
cur.map_Displ = loadTexture(FileName(token));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!strncmp(token, "Ka", 2)) { parseSep(token += 2); cur.Ka = getVec3f(token); continue; }
|
|
||||||
if (!strncmp(token, "Kd", 2)) { parseSep(token += 2); cur.Kd = getVec3f(token); continue; }
|
|
||||||
if (!strncmp(token, "Ks", 2)) { parseSep(token += 2); cur.Ks = getVec3f(token); continue; }
|
|
||||||
if (!strncmp(token, "Kt", 2)) { parseSep(token += 2); cur.Kt = getVec3f(token); continue; }
|
|
||||||
if (!strncmp(token, "Tf", 2)) { parseSep(token += 2); cur.Kt = getVec3f(token); continue; }
|
|
||||||
|
|
||||||
/* extended OBJ */
|
|
||||||
if (!strncmp(token, "type", 4)) {
|
|
||||||
parseSep(token += 4); std::string type = token;
|
|
||||||
if (type == "matte") cur.type = ExtObjMaterial::MATTE;
|
|
||||||
else if (type == "glass") cur.type = ExtObjMaterial::GLASS;
|
|
||||||
else if (type == "metal") cur.type = ExtObjMaterial::METAL;
|
|
||||||
else if (type == "metallicPaint") cur.type = ExtObjMaterial::METALLIC_PAINT;
|
|
||||||
else if (type == "principled") cur.type = ExtObjMaterial::NONE;
|
|
||||||
else if (type == "luminous") cur.type = ExtObjMaterial::NONE;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* OSPRay principled material extensions */
|
|
||||||
if (!strncmp(token, "baseColor", 9)) { parseSep(token += 9); cur.Kd = getVec3f(token); continue; }
|
|
||||||
if (!strncmp(token, "ior", 3)) { parseSep(token += 3); cur.Ni = getFloat(token); continue; }
|
|
||||||
if (!strncmp(token, "map_baseColor", 13)) { parseSep(token += 13); cur.map_Kd = loadTexture(FileName(token)); continue; }
|
|
||||||
if (!strncmp(token, "map_specular", 12)) { parseSep(token += 12); cur.map_Ks = loadTexture(FileName(token)); continue; }
|
|
||||||
if (!strncmp(token, "map_normal.scale", 16)) { parseSep(token += 16); continue; }
|
|
||||||
if (!strncmp(token, "map_normal", 10)) { parseSep(token += 10); cur.map_Displ = loadTexture(FileName(token)); continue; }
|
|
||||||
if (!strncmp(token, "transmissionColor",17)) { parseSep(token += 17); cur.Kt = getVec3f(token); continue; }
|
|
||||||
if (!strncmp(token, "transmission", 12)) { parseSep(token += 12); cur.Kt = Vec3f(getFloat(token)); continue; }
|
|
||||||
|
|
||||||
if (!strncmp(token, "roughnessMap", 12)) { parseSep(token += 12); cur.roughnessMap = loadTexture(FileName(token)); continue; }
|
|
||||||
if (!strncmp(token, "roughness", 9)) { parseSep(token += 9); cur.roughness = getFloat(token); cur.Ns = 1.0f/(cur.roughness+1E-6f); continue; }
|
|
||||||
if (!strncmp(token, "colorMap", 8)) { parseSep(token += 8); cur.map_Kd = loadTexture(FileName(token)); continue; }
|
|
||||||
if (!strncmp(token, "color", 5)) { parseSep(token += 5); cur.Kd = getVec3f(token); continue; }
|
|
||||||
if (!strncmp(token, "coat.color", 10)) { parseSep(token += 10); cur.Kd = getVec3f(token); continue; }
|
|
||||||
if (!strncmp(token, "coat.eta", 8)) { parseSep(token += 8); cur.coat_eta = getFloat(token); continue; }
|
|
||||||
if (!strncmp(token, "coat.roughnessMap",17)) { parseSep(token += 17); cur.coat_roughnessMap = loadTexture(FileName(token)); continue; }
|
|
||||||
if (!strncmp(token, "coat.roughness", 14)) { parseSep(token += 14); cur.coat_roughness = getFloat(token); continue; }
|
|
||||||
if (!strncmp(token, "bumpMap", 7)) { parseSep(token += 7); cur.map_Displ = loadTexture(FileName(token)); continue; }
|
|
||||||
if (!strncmp(token, "bump", 4)) { parseSep(token += 4); cur.bump = getFloat(token); continue; }
|
|
||||||
if (!strncmp(token, "eta", 3)) { parseSep(token += 3); cur.eta = getVec3f(token); continue; }
|
|
||||||
if (!strncmp(token, "k", 1)) { parseSep(token += 1); cur.k = getVec3f(token); continue; }
|
|
||||||
}
|
|
||||||
catch (const std::runtime_error& e) {
|
|
||||||
std::cerr << "Error: " << e.what() << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (name != "") {
|
|
||||||
material[name] = cur.select();
|
|
||||||
material[name]->name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
cin.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! handles relative indices and starts indexing from 0 */
|
|
||||||
unsigned int OBJLoader::fix_v (int index) { return (index > 0 ? index - 1 : (index == 0 ? 0 : (int) v .size() + index)); }
|
|
||||||
unsigned int OBJLoader::fix_vt(int index) { return (index > 0 ? index - 1 : (index == 0 ? 0 : (int) vt.size() + index)); }
|
|
||||||
unsigned int OBJLoader::fix_vn(int index) { return (index > 0 ? index - 1 : (index == 0 ? 0 : (int) vn.size() + index)); }
|
|
||||||
|
|
||||||
/*! Parse differently formatted triplets like: n0, n0/n1/n2, n0//n2, n0/n1. */
|
|
||||||
/*! All indices are converted to C-style (from 0). Missing entries are assigned -1. */
|
|
||||||
Vertex OBJLoader::getUInt3(const char*& token)
|
|
||||||
{
|
|
||||||
Vertex v(-1);
|
|
||||||
v.v = fix_v(atoi(token));
|
|
||||||
token += strcspn(token, "/ \t\r");
|
|
||||||
if (token[0] != '/') return(v);
|
|
||||||
token++;
|
|
||||||
|
|
||||||
// it is i//n
|
|
||||||
if (token[0] == '/') {
|
|
||||||
token++;
|
|
||||||
v.vn = fix_vn(atoi(token));
|
|
||||||
token += strcspn(token, " \t\r");
|
|
||||||
return(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
// it is i/t/n or i/t
|
|
||||||
v.vt = fix_vt(atoi(token));
|
|
||||||
token += strcspn(token, "/ \t\r");
|
|
||||||
if (token[0] != '/') return(v);
|
|
||||||
token++;
|
|
||||||
|
|
||||||
// it is i/t/n
|
|
||||||
v.vn = fix_vn(atoi(token));
|
|
||||||
token += strcspn(token, " \t\r");
|
|
||||||
return(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t OBJLoader::getVertex(std::map<Vertex,uint32_t>& vertexMap, Ref<SceneGraph::TriangleMeshNode> mesh, const Vertex& i)
|
|
||||||
{
|
|
||||||
const std::map<Vertex, uint32_t>::iterator& entry = vertexMap.find(i);
|
|
||||||
if (entry != vertexMap.end()) return(entry->second);
|
|
||||||
|
|
||||||
if (i.v >= v.size()) std::cout << "WARNING: corrupted OBJ file" << std::endl;
|
|
||||||
else mesh->positions[0].push_back(v[i.v]);
|
|
||||||
|
|
||||||
if (i.vn != -1) {
|
|
||||||
while (mesh->normals[0].size() < mesh->positions[0].size()) mesh->normals[0].push_back(zero); // some vertices might not had a normal
|
|
||||||
|
|
||||||
if (i.vn >= vn.size()) std::cout << "WARNING: corrupted OBJ file" << std::endl;
|
|
||||||
else mesh->normals[0][mesh->positions[0].size()-1] = vn[i.vn];
|
|
||||||
}
|
|
||||||
if (i.vt != -1) {
|
|
||||||
while (mesh->texcoords.size() < mesh->positions[0].size()) mesh->texcoords.push_back(zero); // some vertices might not had a texture coordinate
|
|
||||||
|
|
||||||
if (i.vt >= vt.size()) std::cout << "WARNING: corrupted OBJ file" << std::endl;
|
|
||||||
else mesh->texcoords[mesh->positions[0].size()-1] = vt[i.vt];
|
|
||||||
}
|
|
||||||
return (vertexMap[i] = (unsigned int)(mesh->positions[0].size()) - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OBJLoader::flushFaceGroup()
|
|
||||||
{
|
|
||||||
flushTriGroup();
|
|
||||||
flushHairGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! end current facegroup and append to mesh */
|
|
||||||
void OBJLoader::flushTriGroup()
|
|
||||||
{
|
|
||||||
if (curGroup.empty()) return;
|
|
||||||
|
|
||||||
if (subdivMode)
|
|
||||||
{
|
|
||||||
Ref<SceneGraph::SubdivMeshNode> mesh = new SceneGraph::SubdivMeshNode(curMaterial,BBox1f(0,1),1);
|
|
||||||
mesh->normals.resize(1);
|
|
||||||
group->add(mesh.cast<SceneGraph::Node>());
|
|
||||||
|
|
||||||
for (size_t i=0; i<v.size(); i++) mesh->positions[0].push_back(v[i]);
|
|
||||||
for (size_t i=0; i<vn.size(); i++) mesh->normals[0].push_back(vn[i]);
|
|
||||||
for (size_t i=0; i<vt.size(); i++) mesh->texcoords.push_back(vt[i]);
|
|
||||||
|
|
||||||
for (size_t i=0; i<ec.size(); ++i) {
|
|
||||||
assert(((size_t)ec[i].a < v.size()) && ((size_t)ec[i].b < v.size()));
|
|
||||||
mesh->edge_creases.push_back(Vec2i(ec[i].a, ec[i].b));
|
|
||||||
mesh->edge_crease_weights.push_back(ec[i].w);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t j=0; j<curGroup.size(); j++)
|
|
||||||
{
|
|
||||||
const std::vector<Vertex>& face = curGroup[j];
|
|
||||||
mesh->verticesPerFace.push_back(int(face.size()));
|
|
||||||
for (size_t i=0; i<face.size(); i++)
|
|
||||||
mesh->position_indices.push_back(face[i].v);
|
|
||||||
}
|
|
||||||
if (mesh->normals[0].size() == 0)
|
|
||||||
mesh->normals.clear();
|
|
||||||
mesh->verify();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Ref<SceneGraph::TriangleMeshNode> mesh = new SceneGraph::TriangleMeshNode(curMaterial,BBox1f(0,1),1);
|
|
||||||
mesh->normals.resize(1);
|
|
||||||
group->add(mesh.cast<SceneGraph::Node>());
|
|
||||||
// merge three indices into one
|
|
||||||
std::map<Vertex, uint32_t> vertexMap;
|
|
||||||
for (size_t j=0; j<curGroup.size(); j++)
|
|
||||||
{
|
|
||||||
/* iterate over all faces */
|
|
||||||
const std::vector<Vertex>& face = curGroup[j];
|
|
||||||
|
|
||||||
/* triangulate the face with a triangle fan */
|
|
||||||
Vertex i0 = face[0], i1 = Vertex(-1), i2 = face[1];
|
|
||||||
for (size_t k=2; k < face.size(); k++)
|
|
||||||
{
|
|
||||||
i1 = i2; i2 = face[k];
|
|
||||||
uint32_t v0,v1,v2;
|
|
||||||
v0 = getVertex(vertexMap, mesh, i0);
|
|
||||||
v1 = getVertex(vertexMap, mesh, i1);
|
|
||||||
v2 = getVertex(vertexMap, mesh, i2);
|
|
||||||
assert(v0 < mesh->numVertices());
|
|
||||||
assert(v1 < mesh->numVertices());
|
|
||||||
assert(v2 < mesh->numVertices());
|
|
||||||
mesh->triangles.push_back(SceneGraph::TriangleMeshNode::Triangle(v0,v1,v2));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* there may be vertices without normals or texture coordinates, thus we have to make these arrays the same size here */
|
|
||||||
if (mesh->normals[0].size()) while (mesh->normals[0].size() < mesh->numVertices()) mesh->normals[0].push_back(zero);
|
|
||||||
if (mesh->texcoords.size()) while (mesh->texcoords.size() < mesh->numVertices()) mesh->texcoords.push_back(zero);
|
|
||||||
|
|
||||||
if (mesh->normals[0].size() == 0)
|
|
||||||
mesh->normals.clear();
|
|
||||||
mesh->verify();
|
|
||||||
}
|
|
||||||
|
|
||||||
curGroup.clear();
|
|
||||||
ec.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void OBJLoader::flushHairGroup()
|
|
||||||
{
|
|
||||||
if (curGroupHair.empty()) return;
|
|
||||||
|
|
||||||
avector<Vec3ff> vertices;
|
|
||||||
std::vector<SceneGraph::HairSetNode::Hair> curves;
|
|
||||||
|
|
||||||
for (size_t i=0; i<curGroupHair.size(); i++) {
|
|
||||||
for (size_t j=0; j<curGroupHair[i].size(); j++) {
|
|
||||||
if (j%3 == 0) curves.push_back(SceneGraph::HairSetNode::Hair((unsigned int)vertices.size(),(unsigned int)i));
|
|
||||||
vertices.push_back(curGroupHair[i][j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<SceneGraph::HairSetNode> mesh = new SceneGraph::HairSetNode(vertices,curves,curMaterial,RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE);
|
|
||||||
group->add(mesh.cast<SceneGraph::Node>());
|
|
||||||
mesh->verify();
|
|
||||||
curGroupHair.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<SceneGraph::Node> loadOBJ(const FileName& fileName, const bool subdivMode, const bool combineIntoSingleObject) {
|
|
||||||
OBJLoader loader(fileName,subdivMode,combineIntoSingleObject);
|
|
||||||
return loader.group.cast<SceneGraph::Node>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "scenegraph.h"
|
|
||||||
|
|
||||||
namespace embree
|
|
||||||
{
|
|
||||||
Ref<SceneGraph::Node> loadOBJ(const FileName& fileName,
|
|
||||||
const bool subdivMode = false,
|
|
||||||
const bool combineIntoSingleObject = false);
|
|
||||||
}
|
|
||||||
|
|
@ -1,332 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#include "ply_loader.h"
|
|
||||||
#include <list>
|
|
||||||
|
|
||||||
namespace embree
|
|
||||||
{
|
|
||||||
namespace SceneGraph
|
|
||||||
{
|
|
||||||
/*! PLY type */
|
|
||||||
struct Type {
|
|
||||||
enum Tag { PTY_CHAR, PTY_UCHAR, PTY_SHORT, PTY_USHORT, PTY_INT, PTY_UINT, PTY_FLOAT, PTY_DOUBLE, PTY_LIST, PTY_NONE } ty, index, data;
|
|
||||||
Type() : ty(PTY_NONE), index(PTY_NONE), data(PTY_NONE) {}
|
|
||||||
Type(Tag ty) : ty(ty), index(PTY_NONE), data(PTY_NONE) {}
|
|
||||||
Type(Tag ty, Tag index, Tag data) : ty(ty), index(index), data(data) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*! an element stored in the PLY file, such as vertex, face, etc. */
|
|
||||||
struct Element {
|
|
||||||
std::string name;
|
|
||||||
size_t size; /// number of data items of the element
|
|
||||||
std::vector<std::string> properties; /// list of all properties of the element (e.g. x, y, z) (not strictly necessary)
|
|
||||||
std::map<std::string,Type> type; /// mapping of property name to type
|
|
||||||
std::map<std::string,std::vector<float> > data; /// data array properties (all represented as floats)
|
|
||||||
std::map<std::string,std::vector<std::vector<size_t> > > list; /// list properties (integer lists supported only)
|
|
||||||
};
|
|
||||||
|
|
||||||
/*! mesh structure that reflects the PLY file format */
|
|
||||||
struct Mesh {
|
|
||||||
std::vector<std::string> order; /// order of all elements in file (not strictly necessary)
|
|
||||||
std::map<std::string,Element> elements; /// all elements of the file, e.g. vertex, face, ...
|
|
||||||
};
|
|
||||||
|
|
||||||
/* returns the size of a type in bytes */
|
|
||||||
size_t sizeOfType(Type::Tag ty)
|
|
||||||
{
|
|
||||||
switch (ty) {
|
|
||||||
case Type::PTY_CHAR : return 1;
|
|
||||||
case Type::PTY_UCHAR : return 1;
|
|
||||||
case Type::PTY_SHORT : return 2;
|
|
||||||
case Type::PTY_USHORT : return 2;
|
|
||||||
case Type::PTY_INT : return 4;
|
|
||||||
case Type::PTY_UINT : return 4;
|
|
||||||
case Type::PTY_FLOAT : return 4;
|
|
||||||
case Type::PTY_DOUBLE : return 8;
|
|
||||||
default : throw std::runtime_error("invalid type");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* compute the type of a string */
|
|
||||||
Type::Tag typeTagOfString(const std::string& ty) {
|
|
||||||
if (ty == "char") return Type::PTY_CHAR;
|
|
||||||
if (ty == "int8") return Type::PTY_CHAR;
|
|
||||||
if (ty == "uchar") return Type::PTY_UCHAR;
|
|
||||||
if (ty == "uint8") return Type::PTY_UCHAR;
|
|
||||||
if (ty == "short") return Type::PTY_SHORT;
|
|
||||||
if (ty == "int16") return Type::PTY_SHORT;
|
|
||||||
if (ty == "ushort") return Type::PTY_USHORT;
|
|
||||||
if (ty == "uint16") return Type::PTY_USHORT;
|
|
||||||
if (ty == "int") return Type::PTY_INT;
|
|
||||||
if (ty == "int32") return Type::PTY_INT;
|
|
||||||
if (ty == "uint") return Type::PTY_UINT;
|
|
||||||
if (ty == "uint32") return Type::PTY_UINT;
|
|
||||||
if (ty == "float") return Type::PTY_FLOAT;
|
|
||||||
if (ty == "float32") return Type::PTY_FLOAT;
|
|
||||||
if (ty == "double") return Type::PTY_DOUBLE;
|
|
||||||
throw std::runtime_error("invalid type " + ty);
|
|
||||||
return Type::PTY_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* compute the type of a string */
|
|
||||||
std::string stringOfTypeTag(Type::Tag ty) {
|
|
||||||
if (ty == Type::PTY_CHAR) return "char";
|
|
||||||
if (ty == Type::PTY_UCHAR) return "uchar";
|
|
||||||
if (ty == Type::PTY_SHORT) return "short";
|
|
||||||
if (ty == Type::PTY_USHORT) return "ushort";
|
|
||||||
if (ty == Type::PTY_INT) return "int";
|
|
||||||
if (ty == Type::PTY_UINT) return "uint";
|
|
||||||
if (ty == Type::PTY_FLOAT) return "float";
|
|
||||||
if (ty == Type::PTY_DOUBLE) return "double";
|
|
||||||
if (ty == Type::PTY_LIST) return "list";
|
|
||||||
throw std::runtime_error("invalid type");
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
/* compute the type of a string */
|
|
||||||
std::string stringOfType(Type ty) {
|
|
||||||
if (ty.ty == Type::PTY_LIST) return "list " + stringOfTypeTag(ty.index) + " " + stringOfTypeTag(ty.data);
|
|
||||||
else return stringOfTypeTag(ty.ty);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* PLY parser class */
|
|
||||||
struct PlyParser
|
|
||||||
{
|
|
||||||
std::fstream fs;
|
|
||||||
Mesh mesh;
|
|
||||||
Ref<SceneGraph::Node> scene;
|
|
||||||
|
|
||||||
/* storage format of data in file */
|
|
||||||
enum Format { ASCII, BINARY_BIG_ENDIAN, BINARY_LITTLE_ENDIAN } format;
|
|
||||||
|
|
||||||
/* constructor parses the input stream */
|
|
||||||
PlyParser(const FileName& fileName) : format(ASCII)
|
|
||||||
{
|
|
||||||
/* open file */
|
|
||||||
fs.open (fileName.c_str(), std::fstream::in | std::fstream::binary);
|
|
||||||
if (!fs.is_open()) throw std::runtime_error("cannot open file : " + fileName.str());
|
|
||||||
|
|
||||||
/* check for file signature */
|
|
||||||
std::string signature; getline(fs,signature);
|
|
||||||
if (signature != "ply") throw std::runtime_error("invalid PLY file signature: " + signature);
|
|
||||||
|
|
||||||
/* read header */
|
|
||||||
std::list<std::string> header;
|
|
||||||
while (true) {
|
|
||||||
std::string line; getline(fs,line);
|
|
||||||
if (line == "end_header") break;
|
|
||||||
if (line.find_first_of('#') == 0) continue;
|
|
||||||
if (line == "") continue;
|
|
||||||
header.push_back(line);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* parse header */
|
|
||||||
parseHeader(header);
|
|
||||||
|
|
||||||
/* now parse all elements */
|
|
||||||
for (std::vector<std::string>::iterator i = mesh.order.begin(); i!=mesh.order.end(); i++)
|
|
||||||
parseElementData(mesh.elements[*i]);
|
|
||||||
|
|
||||||
/* create triangle mesh */
|
|
||||||
scene = import();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* parse the PLY header */
|
|
||||||
void parseHeader(std::list<std::string>& header)
|
|
||||||
{
|
|
||||||
while (!header.empty())
|
|
||||||
{
|
|
||||||
std::stringstream line(header.front());
|
|
||||||
header.pop_front();
|
|
||||||
|
|
||||||
std::string tag; line >> tag;
|
|
||||||
|
|
||||||
/* ignore comments */
|
|
||||||
if (tag == "comment") {
|
|
||||||
}
|
|
||||||
|
|
||||||
/* parse format */
|
|
||||||
else if (tag == "format")
|
|
||||||
{
|
|
||||||
std::string fmt; line >> fmt;
|
|
||||||
if (fmt == "ascii") format = ASCII;
|
|
||||||
else if (fmt == "binary_big_endian") format = BINARY_BIG_ENDIAN;
|
|
||||||
else if (fmt == "binary_little_endian") format = BINARY_LITTLE_ENDIAN;
|
|
||||||
else throw std::runtime_error("invalid PLY file format: " + fmt);
|
|
||||||
std::string version; line >> version;
|
|
||||||
if (version != "1.0") throw std::runtime_error("invalid PLY file version: " + version);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* parse end of header tag */
|
|
||||||
else if (tag == "end_header")
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* parse elements */
|
|
||||||
else if (tag == "element") parseElementDescr(line,header);
|
|
||||||
|
|
||||||
/* report unknown tags */
|
|
||||||
else throw std::runtime_error("unknown tag in PLY file: " + tag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* parses a PLY element description */
|
|
||||||
void parseElementDescr(std::stringstream& cin, std::list<std::string>& header)
|
|
||||||
{
|
|
||||||
Element elt;
|
|
||||||
std::string name; cin >> name;
|
|
||||||
size_t num; cin >> num;
|
|
||||||
mesh.order.push_back(name);
|
|
||||||
elt.name = name;
|
|
||||||
elt.size = num;
|
|
||||||
|
|
||||||
/* parse all properties */
|
|
||||||
while (!header.empty())
|
|
||||||
{
|
|
||||||
std::stringstream line(header.front());
|
|
||||||
std::string tag; line >> tag;
|
|
||||||
if (tag != "property") break;
|
|
||||||
header.pop_front();
|
|
||||||
|
|
||||||
Type ty = parseType(line);
|
|
||||||
std::string name; line >> name;
|
|
||||||
elt.type[name] = ty;
|
|
||||||
elt.properties.push_back(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
mesh.elements[name] = elt;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* parses a PLY type */
|
|
||||||
Type parseType(std::stringstream& cin)
|
|
||||||
{
|
|
||||||
std::string ty; cin >> ty;
|
|
||||||
if (ty == "list") {
|
|
||||||
std::string ty0; cin >> ty0;
|
|
||||||
std::string ty1; cin >> ty1;
|
|
||||||
return Type(Type::PTY_LIST,typeTagOfString(ty0),typeTagOfString(ty1));
|
|
||||||
} else return Type(typeTagOfString(ty));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* parses data of a PLY element */
|
|
||||||
void parseElementData(Element& elt)
|
|
||||||
{
|
|
||||||
/* allocate data for all properties */
|
|
||||||
for (std::vector<std::string>::iterator i=elt.properties.begin(); i!=elt.properties.end(); i++) {
|
|
||||||
if (elt.type[*i].ty == Type::PTY_LIST) elt.list[*i] = std::vector<std::vector<size_t> >();
|
|
||||||
else elt.data[*i] = std::vector<float>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* parse all elements */
|
|
||||||
for (size_t e=0; e<elt.size; e++)
|
|
||||||
{
|
|
||||||
/* load all properties of the element */
|
|
||||||
for (std::vector<std::string>::iterator i=elt.properties.begin(); i!=elt.properties.end(); i++) {
|
|
||||||
Type ty = elt.type[*i];
|
|
||||||
if (ty.ty == Type::PTY_LIST) loadPropertyList(elt.list[*i],ty.index,ty.data);
|
|
||||||
else loadPropertyData(elt.data[*i],ty.ty);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* load bytes from file and take care of little and big endian encoding */
|
|
||||||
void readBytes(void* dst, int num) {
|
|
||||||
if (format == BINARY_LITTLE_ENDIAN) fs.read((char*)dst,num);
|
|
||||||
else if (format == BINARY_BIG_ENDIAN) for (int i=0; i<num; i++) fs.read((char*)dst+num-i-1,1);
|
|
||||||
else throw std::runtime_error("internal error on PLY loader");
|
|
||||||
}
|
|
||||||
|
|
||||||
int read_ascii_int () { int i; fs >> i; return i; }
|
|
||||||
float read_ascii_float() { float f; fs >> f; return f; }
|
|
||||||
signed char read_char () { if (format == ASCII) return read_ascii_int(); signed char r = 0; readBytes(&r,1); return r; }
|
|
||||||
unsigned char read_uchar () { if (format == ASCII) return read_ascii_int(); unsigned char r = 0; readBytes(&r,1); return r; }
|
|
||||||
signed short read_short () { if (format == ASCII) return read_ascii_int(); signed short r = 0; readBytes(&r,2); return r; }
|
|
||||||
unsigned short read_ushort() { if (format == ASCII) return read_ascii_int(); unsigned short r = 0; readBytes(&r,2); return r; }
|
|
||||||
signed int read_int () { if (format == ASCII) return read_ascii_int(); signed int r = 0; readBytes(&r,4); return r; }
|
|
||||||
unsigned int read_uint () { if (format == ASCII) return read_ascii_int(); unsigned int r = 0; readBytes(&r,4); return r; }
|
|
||||||
float read_float () { if (format == ASCII) return read_ascii_float(); float r = 0; readBytes(&r,4); return r; }
|
|
||||||
double read_double() { if (format == ASCII) return read_ascii_float(); double r = 0; readBytes(&r,8); return r; }
|
|
||||||
|
|
||||||
/* load an integer type */
|
|
||||||
size_t loadInteger(Type::Tag ty)
|
|
||||||
{
|
|
||||||
switch (ty) {
|
|
||||||
case Type::PTY_CHAR : return read_char(); break;
|
|
||||||
case Type::PTY_UCHAR : return read_uchar(); break;
|
|
||||||
case Type::PTY_SHORT : return read_short(); break;
|
|
||||||
case Type::PTY_USHORT : return read_ushort(); break;
|
|
||||||
case Type::PTY_INT : return read_int(); break;
|
|
||||||
case Type::PTY_UINT : return read_uint(); break;
|
|
||||||
default : throw std::runtime_error("invalid type"); return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* load a list */
|
|
||||||
void loadPropertyList(std::vector<std::vector<size_t> >& vec,Type::Tag index_ty,Type::Tag data_ty)
|
|
||||||
{
|
|
||||||
std::vector<size_t> lst;
|
|
||||||
size_t num = loadInteger(index_ty);
|
|
||||||
for (size_t i=0; i<num; i++) lst.push_back(loadInteger(data_ty));
|
|
||||||
vec.push_back(lst);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* load a data element */
|
|
||||||
void loadPropertyData(std::vector<float>& vec, Type::Tag ty)
|
|
||||||
{
|
|
||||||
switch (ty) {
|
|
||||||
case Type::PTY_CHAR : vec.push_back(float(read_char())); break;
|
|
||||||
case Type::PTY_UCHAR : vec.push_back(float(read_uchar())); break;
|
|
||||||
case Type::PTY_SHORT : vec.push_back(float(read_short())); break;
|
|
||||||
case Type::PTY_USHORT : vec.push_back(float(read_ushort())); break;
|
|
||||||
case Type::PTY_INT : vec.push_back(float(read_int())); break;
|
|
||||||
case Type::PTY_UINT : vec.push_back(float(read_uint())); break;
|
|
||||||
case Type::PTY_FLOAT : vec.push_back(float(read_float())); break;
|
|
||||||
case Type::PTY_DOUBLE : vec.push_back(float(read_double())); break;
|
|
||||||
default : throw std::runtime_error("invalid type");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<SceneGraph::Node> import()
|
|
||||||
{
|
|
||||||
Ref<SceneGraph::MaterialNode> material = new OBJMaterial;
|
|
||||||
Ref<SceneGraph::TriangleMeshNode> mesh_o = new SceneGraph::TriangleMeshNode(material,BBox1f(0,1),1);
|
|
||||||
|
|
||||||
/* convert all vertices */
|
|
||||||
const Element& vertices = mesh.elements.at("vertex");
|
|
||||||
const std::vector<float>& posx = vertices.data.at("x");
|
|
||||||
const std::vector<float>& posy = vertices.data.at("y");
|
|
||||||
const std::vector<float>& posz = vertices.data.at("z");
|
|
||||||
|
|
||||||
mesh_o->positions[0].resize(vertices.size);
|
|
||||||
for (size_t i=0; i<vertices.size; i++) {
|
|
||||||
mesh_o->positions[0][i].x = posx[i];
|
|
||||||
mesh_o->positions[0][i].y = posy[i];
|
|
||||||
mesh_o->positions[0][i].z = posz[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* convert all faces */
|
|
||||||
const Element& faces = mesh.elements.at("face");
|
|
||||||
const std::vector<std::vector<size_t> >& polygons = faces.list.at("vertex_indices");
|
|
||||||
|
|
||||||
for (size_t j=0; j<polygons.size(); j++)
|
|
||||||
{
|
|
||||||
const std::vector<size_t>& face = polygons[j];
|
|
||||||
if (face.size() < 3) continue;
|
|
||||||
|
|
||||||
/* triangulate the face with a triangle fan */
|
|
||||||
size_t i0 = face[0], i1 = 0, i2 = face[1];
|
|
||||||
for (size_t k=2; k<face.size(); k++) {
|
|
||||||
i1 = i2; i2 = face[k];
|
|
||||||
mesh_o->triangles.push_back(SceneGraph::TriangleMeshNode::Triangle((unsigned int)i0, (unsigned int)i1, (unsigned int)i2));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return mesh_o.dynamicCast<SceneGraph::Node>();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ref<Node> loadPLY(const FileName& fileName) {
|
|
||||||
return PlyParser(fileName).scene;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "scenegraph.h"
|
|
||||||
|
|
||||||
namespace embree
|
|
||||||
{
|
|
||||||
namespace SceneGraph
|
|
||||||
{
|
|
||||||
Ref<Node> loadPLY(const FileName& fileName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,91 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#include "texture.h"
|
|
||||||
|
|
||||||
namespace embree
|
|
||||||
{
|
|
||||||
bool isPowerOf2 (unsigned int x)
|
|
||||||
{
|
|
||||||
while (((x % 2) == 0) && x > 1)
|
|
||||||
x /= 2;
|
|
||||||
return (x == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::map<std::string,std::shared_ptr<Texture>> texture_cache;
|
|
||||||
|
|
||||||
void Texture::clearTextureCache() {
|
|
||||||
texture_cache.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
Texture::Texture ()
|
|
||||||
: width(-1), height(-1), format(INVALID), bytesPerTexel(0), width_mask(0), height_mask(0), data(nullptr) {}
|
|
||||||
|
|
||||||
Texture::Texture(Ref<Image> img, const std::string fileName)
|
|
||||||
: width(unsigned(img->width)), height(unsigned(img->height)), format(RGBA8), bytesPerTexel(4), width_mask(0), height_mask(0), data(nullptr), fileName(fileName)
|
|
||||||
{
|
|
||||||
width_mask = isPowerOf2(width) ? width-1 : 0;
|
|
||||||
height_mask = isPowerOf2(height) ? height-1 : 0;
|
|
||||||
|
|
||||||
data = alignedUSMMalloc(4*width*height,16);
|
|
||||||
img->convertToRGBA8((unsigned char*)data);
|
|
||||||
}
|
|
||||||
|
|
||||||
Texture::Texture (unsigned width, unsigned height, const Format format, const char* in)
|
|
||||||
: width(width), height(height), format(format), bytesPerTexel(getFormatBytesPerTexel(format)), width_mask(0), height_mask(0), data(nullptr)
|
|
||||||
{
|
|
||||||
width_mask = isPowerOf2(width) ? width-1 : 0;
|
|
||||||
height_mask = isPowerOf2(height) ? height-1 : 0;
|
|
||||||
|
|
||||||
data = alignedUSMMalloc(bytesPerTexel*width*height,16);
|
|
||||||
if (in) {
|
|
||||||
for (size_t i=0; i<bytesPerTexel*width*height; i++)
|
|
||||||
((char*)data)[i] = in[i];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
memset(data,0 ,bytesPerTexel*width*height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Texture::~Texture () {
|
|
||||||
alignedUSMFree(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* Texture::format_to_string(const Format format)
|
|
||||||
{
|
|
||||||
switch (format) {
|
|
||||||
case RGBA8 : return "RGBA8";
|
|
||||||
case RGB8 : return "RGB8";
|
|
||||||
case FLOAT32: return "FLOAT32";
|
|
||||||
default : THROW_RUNTIME_ERROR("invalid texture format");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Texture::Format Texture::string_to_format(const std::string& str)
|
|
||||||
{
|
|
||||||
if (str == "RGBA8") return RGBA8;
|
|
||||||
else if (str == "RGB8") return RGB8;
|
|
||||||
else if (str == "FLOAT32") return FLOAT32;
|
|
||||||
else THROW_RUNTIME_ERROR("invalid texture format string");
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned Texture::getFormatBytesPerTexel(const Format format)
|
|
||||||
{
|
|
||||||
switch (format) {
|
|
||||||
case RGBA8 : return 4;
|
|
||||||
case RGB8 : return 3;
|
|
||||||
case FLOAT32: return 4;
|
|
||||||
default : THROW_RUNTIME_ERROR("invalid texture format");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! read png texture from disk */
|
|
||||||
std::shared_ptr<Texture> Texture::load(const FileName& fileName)
|
|
||||||
{
|
|
||||||
if (texture_cache.find(fileName.str()) != texture_cache.end())
|
|
||||||
return texture_cache[fileName.str()];
|
|
||||||
|
|
||||||
std::shared_ptr<Texture> tex(new Texture(loadImage(fileName),fileName));
|
|
||||||
return texture_cache[fileName.str()] = tex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,71 +0,0 @@
|
||||||
// Copyright 2009-2021 Intel Corporation
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#if defined(ISPC)
|
|
||||||
|
|
||||||
enum TEXTURE_FORMAT {
|
|
||||||
Texture_RGBA8 = 1,
|
|
||||||
Texture_RGB8 = 2,
|
|
||||||
Texture_FLOAT32 = 3,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Texture {
|
|
||||||
int width;
|
|
||||||
int height;
|
|
||||||
int format;
|
|
||||||
int bytesPerTexel;
|
|
||||||
int width_mask;
|
|
||||||
int height_mask;
|
|
||||||
void* data;
|
|
||||||
};
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#include "../default.h"
|
|
||||||
#include "../image/image.h"
|
|
||||||
|
|
||||||
namespace embree
|
|
||||||
{
|
|
||||||
struct Texture // FIXME: should be derived from SceneGraph::Node
|
|
||||||
{
|
|
||||||
ALIGNED_STRUCT_USM_(16);
|
|
||||||
|
|
||||||
enum Format {
|
|
||||||
INVALID = 0,
|
|
||||||
RGBA8 = 1,
|
|
||||||
RGB8 = 2,
|
|
||||||
FLOAT32 = 3,
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
Texture ();
|
|
||||||
Texture (Ref<Image> image, const std::string fileName);
|
|
||||||
Texture (unsigned width, unsigned height, const Format format, const char* in = nullptr);
|
|
||||||
~Texture ();
|
|
||||||
|
|
||||||
private:
|
|
||||||
Texture (const Texture& other) DELETED; // do not implement
|
|
||||||
Texture& operator= (const Texture& other) DELETED; // do not implement
|
|
||||||
|
|
||||||
public:
|
|
||||||
static const char* format_to_string(const Format format);
|
|
||||||
static Format string_to_format(const std::string& str);
|
|
||||||
static unsigned getFormatBytesPerTexel(const Format format);
|
|
||||||
|
|
||||||
static std::shared_ptr<Texture> load(const FileName& fileName);
|
|
||||||
static void clearTextureCache();
|
|
||||||
|
|
||||||
public:
|
|
||||||
unsigned width;
|
|
||||||
unsigned height;
|
|
||||||
Format format;
|
|
||||||
unsigned bytesPerTexel;
|
|
||||||
unsigned width_mask;
|
|
||||||
unsigned height_mask;
|
|
||||||
void* data;
|
|
||||||
std::string fileName;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
File diff suppressed because it is too large
Load diff
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue