Compare commits
75
Commits
v3.2.2
...
experimental
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
86dbc8a437 | ||
|
|
4c93274a31 | ||
|
|
bd7ea15f50 | ||
|
|
1df9591a8c | ||
|
|
23753277fa | ||
|
|
95053e8c6e | ||
|
|
0ff0a6909b | ||
|
|
40e445ade8 | ||
|
|
8c08b5c5b5 | ||
|
|
a07e9b0c5c | ||
|
|
0f4f821f76 | ||
|
|
cf4d9e9f62 | ||
|
|
d25f7b0ac2 | ||
|
|
15caf3fd1b | ||
|
|
0eb47c2c6b | ||
|
|
9de546d581 | ||
|
|
33bd19d2a3 | ||
|
|
4e1a7741fb | ||
|
|
e2f4851405 | ||
|
|
7662e7b260 | ||
|
|
4a12bfed63 | ||
|
|
1bf492e704 | ||
|
|
8e3fc16de5 | ||
|
|
d110857224 | ||
|
|
09a6013b79 | ||
|
|
60254acc8a | ||
|
|
6c6aa92560 | ||
|
|
79c9f4a1b8 | ||
|
|
ae20787a43 | ||
|
|
a8fda51877 | ||
|
|
17a17f7e18 | ||
|
|
b27a31f572 | ||
|
|
a7772b05aa | ||
|
|
03f24bbba5 | ||
|
|
d2db02fa10 | ||
|
|
80c0fae902 | ||
|
|
fd6eca502f | ||
|
|
a1c750b5a2 | ||
|
|
226f9e1fb5 | ||
|
|
ef9dd1951d | ||
|
|
a6527de9c9 | ||
|
|
9805370657 | ||
|
|
ff669ab8f4 | ||
|
|
4efa364c7b | ||
|
|
ca932f7669 | ||
|
|
7297e6ffff | ||
|
|
b04f338936 | ||
|
|
bb4cd86ea4 | ||
|
|
ba404619cc | ||
|
|
a88881677e | ||
|
|
7b7c88337d | ||
|
|
a9b96ac13f | ||
|
|
0e27f93cb2 | ||
|
|
4e725e928b | ||
|
|
d9fd88e841 | ||
|
|
abf293aa0a | ||
|
|
b71f37e1f6 | ||
|
|
0eabcdddd3 | ||
|
|
7b8fa2e8a2 | ||
|
|
a72873c854 | ||
|
|
d5e09d228d | ||
|
|
60b0c0154f | ||
|
|
5a7230da1f | ||
|
|
a8dc2540de | ||
|
|
03f654c62e | ||
|
|
7aeb056b32 | ||
|
|
4262431328 | ||
|
|
11d5e26d82 | ||
|
|
3ae221bf73 | ||
|
|
f3b787a0ea | ||
|
|
0ec8f6a299 | ||
|
|
4be6966f63 | ||
|
|
49fab5e8e0 | ||
|
|
a8ee444842 | ||
|
|
d710ab6245 |
+17
-2
@@ -269,6 +269,11 @@ nightly-linux-skx-x64-RelWithDebInfo-ICC18-ISPC1.9.2-AVX512SKX-TBB2017:
|
||||
tags: [docker, skx]
|
||||
only: [schedules]
|
||||
|
||||
nightly-linux-x64-RelWithDebInfo-ICC19-ISPC1.9.2-AVX2-TBB2017:
|
||||
image: embreedocker/centos:6.0
|
||||
script: "scripts/test.py platform:x64 build:RelWithDebInfo compiler:ICC19 ispc:ispc1.9.2 isa:AVX2 tasking:TBB2017 intensity:4"
|
||||
tags: [docker] # avx2
|
||||
only: [schedules]
|
||||
|
||||
# Testing on different Linux distributions
|
||||
|
||||
@@ -460,8 +465,18 @@ nightly-linux-x64-RelWithDebInfo-CLANG4-ISPC1.9.2-AVX2-TBB2017-INSTANCE:
|
||||
# Release Builds
|
||||
####################################################################
|
||||
|
||||
release-windows-x64-Release-ICC17-ISPC1.9.2-TBB2017-PACKAGE-ZIP:
|
||||
script: "python scripts\\test.py platform:x64 build:Release compiler:ICC17 ispc:ispc1.9.2 isas:SSE2-SSE42-AVX-AVX2-AVX512SKX tasking:TBB2017 intensity:4 package:ZIP"
|
||||
release-windows-x64-Release-ICC17-VC12-ISPC1.9.2-TBB2017-PACKAGE-ZIP:
|
||||
script: "python scripts\\test.py platform:x64 build:Release compiler:ICC17-VC12 ispc:ispc1.9.2 isas:SSE2-SSE42-AVX-AVX2-AVX512SKX tasking:TBB2017 intensity:4 package:ZIP"
|
||||
tags: [win7, icc17]
|
||||
only: [web]
|
||||
artifacts:
|
||||
name: "$env:CI_JOB_NAME"
|
||||
paths: [build/*.zip]
|
||||
when: always
|
||||
expire_in: 2 mos
|
||||
|
||||
release-windows-x64-Release-ICC17-VC14-ISPC1.9.2-TBB2017-PACKAGE-ZIP:
|
||||
script: "python scripts\\test.py platform:x64 build:Release compiler:ICC17-VC14 ispc:ispc1.9.2 isas:SSE2-SSE42-AVX-AVX2-AVX512SKX tasking:TBB2017 intensity:4 package:ZIP"
|
||||
tags: [win7, icc17]
|
||||
only: [web]
|
||||
artifacts:
|
||||
|
||||
+18
-1
@@ -1,9 +1,26 @@
|
||||
Version History
|
||||
---------------
|
||||
|
||||
### New Features in Embree 3.3.0
|
||||
- Added support for motion blur time range per geometry. This way geometries
|
||||
can appear and disappear during the camera shutter and time steps do not have
|
||||
to start and end at camera shutter interval boundaries.
|
||||
- Fixed crash with pathtracer when using --triangle-sphere command line.
|
||||
- Fixed crash with pathtracer when using --shader ao command line.
|
||||
- Fixed tutorials showing a black window on macOS 10.14 until moved.
|
||||
|
||||
### New Features in Embree 3.2.4
|
||||
- Fixed compile issues with ICC 2019.
|
||||
- Released ZIP files for Windows are now provided in a
|
||||
version linked against Visual Studio 2013 and Visual Studio 2015.
|
||||
|
||||
### New Features in Embree 3.2.3
|
||||
- Fixed crash when using curves with RTC_SCENE_FLAG_DYNAMIC
|
||||
combined with RTC_BUILD_QUALITY_MEDIUM.
|
||||
|
||||
### New Features in Embree 3.2.2
|
||||
- Fixed intersection distance for unnormalized rays with line segments.
|
||||
- Removed libmmd.dll depdendency
|
||||
- Removed libmmd.dll dependency in release builds for Windows.
|
||||
- Fixed detection of AppleClang compiler under MacOSX.
|
||||
|
||||
### New Features in Embree 3.2.1
|
||||
|
||||
+3
-3
@@ -15,8 +15,8 @@
|
||||
## ======================================================================== ##
|
||||
|
||||
SET(EMBREE_VERSION_MAJOR 3)
|
||||
SET(EMBREE_VERSION_MINOR 2)
|
||||
SET(EMBREE_VERSION_PATCH 2)
|
||||
SET(EMBREE_VERSION_MINOR 3)
|
||||
SET(EMBREE_VERSION_PATCH 0)
|
||||
SET(EMBREE_VERSION_NOTE "")
|
||||
|
||||
SET(EMBREE_VERSION ${EMBREE_VERSION_MAJOR}.${EMBREE_VERSION_MINOR}.${EMBREE_VERSION_PATCH})
|
||||
@@ -75,7 +75,7 @@ IF(COMMAND cmake_policy)
|
||||
cmake_policy(SET CMP0003 NEW)
|
||||
endif()
|
||||
if (POLICY CMP0042)
|
||||
cmake_policy(SET CMP0042 OLD)
|
||||
cmake_policy(SET CMP0042 NEW)
|
||||
endif()
|
||||
ENDIF(COMMAND cmake_policy)
|
||||
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@
|
||||
|
||||
set(CTEST_PROJECT_NAME "Embree")
|
||||
set(CTEST_NIGHTLY_START_TIME "22:00:00 UTC")
|
||||
set(TEST_MODELS_HASH a1b183a3b76eb40c4c2e6a2d4dc5ca08090d8400)
|
||||
set(TEST_MODELS_HASH ba1bd24186ccdf939d2e749a514f81718f3a2b20)
|
||||
|
||||
IF (NOT CTEST_DROP_SITE)
|
||||
set(CTEST_DROP_METHOD "http")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
% Embree: High Performance Ray Tracing Kernels 3.2.2
|
||||
% Embree: High Performance Ray Tracing Kernels 3.3.0
|
||||
% Intel Corporation
|
||||
|
||||
Embree Overview
|
||||
@@ -85,9 +85,9 @@ Windows MSI Installer
|
||||
---------------------
|
||||
|
||||
You can install the Embree library using the Windows MSI installer
|
||||
[embree-3.2.2-x64.msi](https://github.com/embree/embree/releases/download/v3.2.2/embree-3.2.2.x64.msi). This
|
||||
[embree-3.3.0-x64.vc12.msi](https://github.com/embree/embree/releases/download/v3.3.0/embree-3.3.0.x64.vc12.msi). This
|
||||
will install the 64-bit Embree version by default in `Program
|
||||
Files\Intel\Embree v3.2.2 x64`.
|
||||
Files\Intel\Embree v3.3.0 x64`.
|
||||
|
||||
You have to set the path to the `bin` folders manually to your `PATH`
|
||||
environment variable for applications to find Embree.
|
||||
@@ -95,23 +95,25 @@ environment variable for applications to find Embree.
|
||||
To compile applications with Embree using CMake, please have a look at
|
||||
the `find_embree` tutorial. To compile this tutorial, you need to set
|
||||
the `embree_DIR` CMake variable of this tutorial to `Program
|
||||
Files\Intel\Embree v3.2.2 x64`.
|
||||
Files\Intel\Embree v3.3.0 x64`.
|
||||
|
||||
To uninstall Embree, open `Programs and Features` by clicking the
|
||||
`Start button`, clicking `Control Panel`, clicking `Programs`, and
|
||||
then clicking `Programs and Features`. Select `Embree
|
||||
3.2.2 x64` and uninstall it.
|
||||
3.3.0 x64` and uninstall it.
|
||||
|
||||
Windows ZIP File
|
||||
-----------------
|
||||
|
||||
Embree is also delivered as a ZIP file
|
||||
[embree-3.2.2.x64.windows.zip](https://github.com/embree/embree/releases/download/v3.2.2/embree-3.2.2.x64.windows.zip). After
|
||||
unpacking this ZIP file, you should set the path to the `lib` folder
|
||||
manually to your `PATH` environment variable for applications to find
|
||||
Embree. To compile applications with Embree, you also have to set the
|
||||
`Include Directories` path in Visual Studio to the `include` folder of
|
||||
the Embree installation.
|
||||
Embree linked against Visual Studio 2013
|
||||
[embree-3.3.0.x64.vc12.windows.zip](https://github.com/embree/embree/releases/download/v3.3.0/embree-3.3.0.x64.vc12.windows.zip)
|
||||
and Visual Studio 2015
|
||||
[embree-3.3.0.x64.vc14.windows.zip](https://github.com/embree/embree/releases/download/v3.3.0/embree-3.3.0.x64.vc14.windows.zip)
|
||||
are provided as a ZIP file. After unpacking this ZIP file, you should
|
||||
set the path to the `lib` folder manually to your `PATH` environment
|
||||
variable for applications to find Embree. To compile applications with
|
||||
Embree, you also have to set the `Include Directories` path in Visual
|
||||
Studio to the `include` folder of the Embree installation.
|
||||
|
||||
If you plan to ship Embree with your application, best use the Embree
|
||||
version from this ZIP file.
|
||||
@@ -120,17 +122,17 @@ Linux RPMs
|
||||
----------
|
||||
|
||||
Uncompress the `tar.gz` file
|
||||
[embree-3.2.2.x86_64.rpm.tar.gz](https://github.com/embree/embree/releases/download/v3.2.2/embree-3.2.2.x86_64.rpm.tar.gz)
|
||||
[embree-3.3.0.x86_64.rpm.tar.gz](https://github.com/embree/embree/releases/download/v3.3.0/embree-3.3.0.x86_64.rpm.tar.gz)
|
||||
to obtain the individual RPM files:
|
||||
|
||||
tar xzf embree-3.2.2.x86_64.rpm.tar.gz
|
||||
tar xzf embree-3.3.0.x86_64.rpm.tar.gz
|
||||
|
||||
To install Embree using the RPM packages on your Linux system, type
|
||||
the following:
|
||||
|
||||
sudo rpm --install embree3-lib-3.2.2-1.x86_64.rpm
|
||||
sudo rpm --install embree3-devel-3.2.2-1.noarch.rpm
|
||||
sudo rpm --install embree3-examples-3.2.2-1.x86_64.rpm
|
||||
sudo rpm --install embree3-lib-3.3.0-1.x86_64.rpm
|
||||
sudo rpm --install embree3-devel-3.3.0-1.noarch.rpm
|
||||
sudo rpm --install embree3-examples-3.3.0-1.x86_64.rpm
|
||||
|
||||
You also have to install the Intel® Threading Building Blocks (TBB)
|
||||
using `yum`:
|
||||
@@ -142,13 +144,13 @@ filed into DEB files using the `alien` tool:
|
||||
|
||||
sudo apt-get install alien dpkg-dev debhelper build-essential
|
||||
|
||||
sudo alien embree3-lib-3.2.2-1.x86_64.rpm
|
||||
sudo alien embree3-devel-3.2.2-1.noarch.rpm
|
||||
sudo alien embree3-examples-3.2.2-1.x86_64.rpm
|
||||
sudo alien embree3-lib-3.3.0-1.x86_64.rpm
|
||||
sudo alien embree3-devel-3.3.0-1.noarch.rpm
|
||||
sudo alien embree3-examples-3.3.0-1.x86_64.rpm
|
||||
|
||||
sudo dpkg -i embree3-lib_3.2.2-2_amd64.deb
|
||||
sudo dpkg -i embree3-devel_3.2.2-2_all.deb
|
||||
sudo dpkg -i embree3-examples_3.2.2-2_amd64.deb
|
||||
sudo dpkg -i embree3-lib_3.3.0-2_amd64.deb
|
||||
sudo dpkg -i embree3-devel_3.3.0-2_all.deb
|
||||
sudo dpkg -i embree3-examples_3.3.0-2_amd64.deb
|
||||
|
||||
Also install the Intel® Threading Building Blocks (TBB) using `apt-get`:
|
||||
|
||||
@@ -174,20 +176,20 @@ the tutorials to start them.
|
||||
|
||||
To uninstall Embree, just execute the following:
|
||||
|
||||
sudo rpm --erase embree3-lib-3.2.2-1.x86_64
|
||||
sudo rpm --erase embree3-devel-3.2.2-1.noarch
|
||||
sudo rpm --erase embree3-examples-3.2.2-1.x86_64
|
||||
sudo rpm --erase embree3-lib-3.3.0-1.x86_64
|
||||
sudo rpm --erase embree3-devel-3.3.0-1.noarch
|
||||
sudo rpm --erase embree3-examples-3.3.0-1.x86_64
|
||||
|
||||
Linux tar.gz Files
|
||||
------------------
|
||||
|
||||
The Linux version of Embree is also delivered as a `tar.gz` file:
|
||||
[embree-3.2.2.x86_64.linux.tar.gz](https://github.com/embree/embree/releases/download/v3.2.2/embree-3.2.2.x86_64.linux.tar.gz). Unpack this file using `tar` and source the provided `embree-vars.sh` (if you
|
||||
[embree-3.3.0.x86_64.linux.tar.gz](https://github.com/embree/embree/releases/download/v3.3.0/embree-3.3.0.x86_64.linux.tar.gz). Unpack this file using `tar` and source the provided `embree-vars.sh` (if you
|
||||
are using the bash shell) or `embree-vars.csh` (if you are using the
|
||||
C shell) to set up the environment properly:
|
||||
|
||||
tar xzf embree-3.2.2.x86_64.linux.tar.gz
|
||||
source embree-3.2.2.x86_64.linux/embree-vars.sh
|
||||
tar xzf embree-3.3.0.x86_64.linux.tar.gz
|
||||
source embree-3.3.0.x86_64.linux/embree-vars.sh
|
||||
|
||||
If you want to ship Embree with your application, best use the Embree
|
||||
version provided in the `tar.gz` file.
|
||||
@@ -200,7 +202,7 @@ macOS PKG Installer
|
||||
|
||||
To install the Embree library on your macOS system use the
|
||||
provided package installer inside
|
||||
[embree-3.2.2.x86_64.dmg](https://github.com/embree/embree/releases/download/v3.2.2/embree-3.2.2.x86_64.dmg). This
|
||||
[embree-3.3.0.x86_64.dmg](https://github.com/embree/embree/releases/download/v3.3.0/embree-3.3.0.x86_64.dmg). This
|
||||
will install Embree by default into `/opt/local/lib` and
|
||||
`/opt/local/include` directories. The Embree tutorials are installed
|
||||
into the `/Applications/Embree3` directory.
|
||||
@@ -222,12 +224,12 @@ macOS tar.gz file
|
||||
-----------------
|
||||
|
||||
The macOS version of Embree is also delivered as a `tar.gz` file:
|
||||
[embree-3.2.2.x86_64.macosx.tar.gz](https://github.com/embree/embree/releases/download/v3.2.2/embree-3.2.2.x86_64.macosx.tar.gz). Unpack this file using `tar` and source the provided `embree-vars.sh` (if you
|
||||
[embree-3.3.0.x86_64.macosx.tar.gz](https://github.com/embree/embree/releases/download/v3.3.0/embree-3.3.0.x86_64.macosx.tar.gz). Unpack this file using `tar` and source the provided `embree-vars.sh` (if you
|
||||
are using the bash shell) or `embree-vars.csh` (if you are using the
|
||||
C shell) to set up the environment properly:
|
||||
|
||||
tar xzf embree-3.2.2.x64.macosx.tar.gz
|
||||
source embree-3.2.2.x64.macosx/embree-vars.sh
|
||||
tar xzf embree-3.3.0.x64.macosx.tar.gz
|
||||
source embree-3.3.0.x64.macosx/embree-vars.sh
|
||||
|
||||
If you want to ship Embree with your application, please use the Embree
|
||||
library of the provided `tar.gz` file. The library name of that Embree
|
||||
@@ -698,14 +700,19 @@ assign a geometry ID) or using the `rtcAttachGeometryById` function
|
||||
to a single scene at a time.
|
||||
|
||||
All geometry types support multi-segment motion blur with an arbitrary
|
||||
number of equidistant time steps (in the range of 2 to 129). Each
|
||||
geometry can have a different number of time steps. The motion blur
|
||||
geometry is defined by linearly interpolating the geometries of
|
||||
neighboring time steps. To construct a motion blur geometry, first the
|
||||
number of time steps of the geometry must be specified using the
|
||||
number of equidistant time steps (in the range of 2 to 129) inside a
|
||||
user specified time range. Each geometry can have a different number
|
||||
of time steps and a different time range. The motion blur geometry is
|
||||
defined by linearly interpolating the geometries of neighboring time
|
||||
steps. To construct a motion blur geometry, first the number of time
|
||||
steps of the geometry must be specified using the
|
||||
`rtcSetGeometryTimeStepCount` function, and then a vertex buffer for
|
||||
each time step must be bound, e.g. using the
|
||||
`rtcSetSharedGeometryBuffer` function.
|
||||
`rtcSetSharedGeometryBuffer` function. Optionally, a time range
|
||||
defining the start (and end time) of the first (and last) time step
|
||||
can be set using the `rtcSetGeometryTimeRange` function. This feature
|
||||
will also allow geometries to appear and disappear during the camera
|
||||
shutter time if the time range is a sub range of [0,1].
|
||||
|
||||
The API supports per-geometry filter callback functions (see
|
||||
`rtcSetGeometryIntersectFilterFunction` and
|
||||
@@ -1233,6 +1240,11 @@ Embree API Reference
|
||||
```
|
||||
|
||||
|
||||
## rtcSetGeometryTimeRange
|
||||
``` {include=src/api/rtcSetGeometryTimeRange.md}
|
||||
```
|
||||
|
||||
|
||||
## rtcSetGeometryVertexAttributeCount
|
||||
``` {include=src/api/rtcSetGeometryVertexAttributeCount.md}
|
||||
```
|
||||
|
||||
@@ -51,13 +51,10 @@ IF (WIN32)
|
||||
SET(TBB_ARCH ia32)
|
||||
ENDIF()
|
||||
|
||||
IF (MSVC10)
|
||||
SET(TBB_VCVER vc10)
|
||||
ELSEIF (MSVC11)
|
||||
SET(TBB_VCVER vc11)
|
||||
ELSEIF (MSVC12)
|
||||
# precompiled TBB packages currently only support VC12 and VC14
|
||||
IF (MSVC12)
|
||||
SET(TBB_VCVER vc12)
|
||||
ELSE()
|
||||
ELSEIF(MSVC14)
|
||||
SET(TBB_VCVER vc14)
|
||||
ENDIF()
|
||||
|
||||
|
||||
@@ -120,6 +120,7 @@ ELSE()
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wformat -Wformat-security") # enables string format vulnerability warnings
|
||||
IF (NOT APPLE)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIE") # enables support for more secure position independent execution
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftls-model=local-dynamic") # otherwise ICC2019 cannot compile code with -fPIE enabled
|
||||
ENDIF()
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") # generate position independent code suitable for shared libraries
|
||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") # generate position independent code suitable for shared libraries
|
||||
|
||||
@@ -159,15 +159,21 @@ IF(WIN32)
|
||||
|
||||
IF (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
SET(ARCH x64)
|
||||
SET(CPACK_PACKAGE_NAME "${CPACK_PACKAGE_NAME} x64")
|
||||
SET(CPACK_PACKAGE_NAME "${CPACK_PACKAGE_NAME} x64")
|
||||
ELSE()
|
||||
SET(ARCH win32)
|
||||
SET(CPACK_PACKAGE_NAME "${CPACK_PACKAGE_NAME} Win32")
|
||||
SET(CPACK_PACKAGE_NAME "${CPACK_PACKAGE_NAME} Win32")
|
||||
ENDIF()
|
||||
|
||||
IF (MSVC12)
|
||||
SET(VCVER vc12)
|
||||
ELSEIF(MSVC14) # also for VC15, which is toolset v141
|
||||
SET(VCVER vc14)
|
||||
ENDIF()
|
||||
|
||||
IF (NOT EMBREE_ZIP_MODE)
|
||||
SET(CPACK_GENERATOR WIX)
|
||||
SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}.${ARCH}")
|
||||
SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}.${ARCH}.${VCVER}")
|
||||
SET(CPACK_PACKAGE_INSTALL_DIRECTORY "Intel\\\\Embree${EMBREE_VERSION_MAJOR} ${ARCH}")
|
||||
SET(CPACK_WIX_PRODUCT_GUID "331BD5A9-DAD6-486B-A435-18AAB80${EMBREE_VERSION_NUMBER}")
|
||||
SET(CPACK_WIX_UPGRADE_GUID "331BD5A9-DAD6-486B-A435-18AAB80${EMBREE_VERSION_MAJOR}0000") # upgrade as long as major version is the same
|
||||
@@ -177,7 +183,7 @@ IF(WIN32)
|
||||
ENDIF()
|
||||
ELSE()
|
||||
SET(CPACK_GENERATOR ZIP)
|
||||
SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}.${ARCH}.windows")
|
||||
SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}.${ARCH}.${VCVER}.windows")
|
||||
SET(CPACK_MONOLITHIC_INSTALL 1)
|
||||
IF (EMBREE_TESTING_PACKAGE)
|
||||
ADD_TEST(NAME "BuildPackage" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${PROJECT_SOURCE_DIR}/scripts/package_win.bat ${CMAKE_BUILD_TYPE} ${CPACK_PACKAGE_FILE_NAME}.zip)
|
||||
|
||||
@@ -109,6 +109,56 @@ namespace embree
|
||||
bounds1 = b1;
|
||||
}
|
||||
|
||||
/*! calculates the linear bounds of a primitive for the specified time range */
|
||||
template<typename BoundsFunc>
|
||||
__forceinline LBBox(const BoundsFunc& bounds, const BBox1f& time_range_in, const BBox1f& geom_time_range, float geom_time_segments)
|
||||
{
|
||||
/* normalize global time_range_in to local geom_time_range */
|
||||
const BBox1f time_range((time_range_in.lower-geom_time_range.lower)/geom_time_range.size(),
|
||||
(time_range_in.upper-geom_time_range.lower)/geom_time_range.size());
|
||||
|
||||
const float lower = time_range.lower*geom_time_segments;
|
||||
const float upper = time_range.upper*geom_time_segments;
|
||||
const float ilowerf = floor(lower);
|
||||
const float iupperf = ceil(upper);
|
||||
const float ilowerfc = max(0.0f,ilowerf);
|
||||
const float iupperfc = min(iupperf,geom_time_segments);
|
||||
const int ilowerc = (int)ilowerfc;
|
||||
const int iupperc = (int)iupperfc;
|
||||
assert(iupperc-ilowerc > 0);
|
||||
|
||||
/* this larger iteration range guarantees that we process borders of geom_time_range is (partially) inside time_range_in */
|
||||
const int ilower_iter = max(-1,(int)ilowerf);
|
||||
const int iupper_iter = min((int)iupperf,(int)geom_time_segments+1);
|
||||
|
||||
const BBox<T> blower0 = bounds(ilowerc);
|
||||
const BBox<T> bupper1 = bounds(iupperc);
|
||||
if (iupper_iter-ilower_iter == 1) {
|
||||
bounds0 = lerp(blower0, bupper1, max(0.0f,lower-ilowerfc));
|
||||
bounds1 = lerp(bupper1, blower0, max(0.0f,iupperfc-upper));
|
||||
return;
|
||||
}
|
||||
|
||||
const BBox<T> blower1 = bounds(ilowerc+1);
|
||||
const BBox<T> bupper0 = bounds(iupperc-1);
|
||||
BBox<T> b0 = lerp(blower0, blower1, max(0.0f,lower-ilowerfc));
|
||||
BBox<T> b1 = lerp(bupper1, bupper0, max(0.0f,iupperfc-upper));
|
||||
|
||||
for (int i = ilower_iter+1; i < iupper_iter; i++)
|
||||
{
|
||||
const float f = (float(i)/geom_time_segments - time_range.lower) / time_range.size();
|
||||
const BBox<T> bt = lerp(b0, b1, f);
|
||||
const BBox<T> bi = bounds(i);
|
||||
const T dlower = min(bi.lower-bt.lower, T(zero));
|
||||
const T dupper = max(bi.upper-bt.upper, T(zero));
|
||||
b0.lower += dlower; b1.lower += dlower;
|
||||
b0.upper += dupper; b1.upper += dupper;
|
||||
}
|
||||
|
||||
bounds0 = b0;
|
||||
bounds1 = b1;
|
||||
}
|
||||
|
||||
/*! calculates the linear bounds of a primitive for the specified time range */
|
||||
template<typename BoundsFunc>
|
||||
__forceinline LBBox(const BoundsFunc& bounds, const range<int>& time_range, int numTimeSegments)
|
||||
|
||||
@@ -230,6 +230,8 @@ namespace embree
|
||||
// __forceinline vuint4 operator *(const vuint4& a, unsigned int b) { return a * vuint4(b); }
|
||||
// __forceinline vuint4 operator *(unsigned int a, const vuint4& b) { return vuint4(a) * b; }
|
||||
|
||||
__forceinline vuint4 operator /(const vuint4& a, const vuint4& b) { return vuint4(a[0]/b[0],a[1]/b[1],a[2]/b[2],a[3]/b[3]); }
|
||||
|
||||
__forceinline vuint4 operator &(const vuint4& a, const vuint4& b) { return _mm_and_si128(a, b); }
|
||||
__forceinline vuint4 operator &(const vuint4& a, unsigned int b) { return a & vuint4(b); }
|
||||
__forceinline vuint4 operator &(unsigned int a, const vuint4& b) { return vuint4(a) & b; }
|
||||
|
||||
@@ -26,6 +26,14 @@ namespace embree
|
||||
std::string toLowerCase(const std::string& s) { std::string dst(s); std::transform(dst.begin(), dst.end(), dst.begin(), to_lower); return dst; }
|
||||
std::string toUpperCase(const std::string& s) { std::string dst(s); std::transform(dst.begin(), dst.end(), dst.begin(), to_upper); return dst; }
|
||||
|
||||
Vec2f string_to_Vec2f ( std::string str )
|
||||
{
|
||||
size_t next = 0;
|
||||
const float x = std::stof(str,&next); str = str.substr(next+1);
|
||||
const float y = std::stof(str,&next);
|
||||
return Vec2f(x,y);
|
||||
}
|
||||
|
||||
Vec3f string_to_Vec3f ( std::string str )
|
||||
{
|
||||
size_t next = 0;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "platform.h"
|
||||
#include "../math/vec2.h"
|
||||
#include "../math/vec3.h"
|
||||
|
||||
namespace embree
|
||||
@@ -42,5 +43,6 @@ namespace embree
|
||||
std::string toLowerCase(const std::string& s);
|
||||
std::string toUpperCase(const std::string& s);
|
||||
|
||||
Vec2f string_to_Vec2f ( std::string str );
|
||||
Vec3f string_to_Vec3f ( std::string str );
|
||||
}
|
||||
|
||||
+16
-6
@@ -111,14 +111,19 @@ assign a geometry ID) or using the `rtcAttachGeometryById` function
|
||||
to a single scene at a time.
|
||||
|
||||
All geometry types support multi-segment motion blur with an arbitrary
|
||||
number of equidistant time steps (in the range of 2 to 129). Each
|
||||
geometry can have a different number of time steps. The motion blur
|
||||
geometry is defined by linearly interpolating the geometries of
|
||||
neighboring time steps. To construct a motion blur geometry, first the
|
||||
number of time steps of the geometry must be specified using the
|
||||
number of equidistant time steps (in the range of 2 to 129) inside a
|
||||
user specified time range. Each geometry can have a different number
|
||||
of time steps and a different time range. The motion blur geometry is
|
||||
defined by linearly interpolating the geometries of neighboring time
|
||||
steps. To construct a motion blur geometry, first the number of time
|
||||
steps of the geometry must be specified using the
|
||||
`rtcSetGeometryTimeStepCount` function, and then a vertex buffer for
|
||||
each time step must be bound, e.g. using the
|
||||
`rtcSetSharedGeometryBuffer` function.
|
||||
`rtcSetSharedGeometryBuffer` function. Optionally, a time range
|
||||
defining the start (and end time) of the first (and last) time step
|
||||
can be set using the `rtcSetGeometryTimeRange` function. This feature
|
||||
will also allow geometries to appear and disappear during the camera
|
||||
shutter time if the time range is a sub range of [0,1].
|
||||
|
||||
The API supports per-geometry filter callback functions (see
|
||||
`rtcSetGeometryIntersectFilterFunction` and
|
||||
@@ -646,6 +651,11 @@ Embree API Reference
|
||||
```
|
||||
\pagebreak
|
||||
|
||||
## rtcSetGeometryTimeRange
|
||||
``` {include=src/api/rtcSetGeometryTimeRange.md}
|
||||
```
|
||||
\pagebreak
|
||||
|
||||
## rtcSetGeometryVertexAttributeCount
|
||||
``` {include=src/api/rtcSetGeometryVertexAttributeCount.md}
|
||||
```
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
% rtcSetGeometryTimeRange(3) | Embree Ray Tracing Kernels 3
|
||||
|
||||
#### NAME
|
||||
|
||||
rtcSetGeometryTimeRange - sets the time range for a motion blur geometry
|
||||
|
||||
#### SYNOPSIS
|
||||
|
||||
#include <embree3/rtcore.h>
|
||||
|
||||
void rtcSetGeometryTimeRange(
|
||||
RTCGeometry geometry,
|
||||
float startTime,
|
||||
float endTime
|
||||
);
|
||||
|
||||
#### DESCRIPTION
|
||||
|
||||
The `rtcSetGeometryTimeRange` function sets a time range which defines
|
||||
the start (and end time) of the first (and last) time step of a motion
|
||||
blur geometry. The time range is defined relative to the camera
|
||||
shutter interval [0,1] but it can be arbitrary. Thus the startTime can
|
||||
be smaller, equal, or larger 0, indicating a geometry whose animation
|
||||
definition start before, at, or after the camera shutter
|
||||
opens. Similar the endTime can be smaller, equal, or larger than 1,
|
||||
indicating a geometry whose animation definition ends after, at, or
|
||||
before the camera shutter closes. The startTime has to be smaller or
|
||||
equal to the endTime.
|
||||
|
||||
The default time range when this function is not called is the entire
|
||||
camera shutter [0,1]. For best performance at most one time segment of
|
||||
the piece wise linear definition of the motion should fall outside the
|
||||
shutter window to the left and to the right. Thus do not set the
|
||||
startTime or endTime too far outside the [0,1] interval for best
|
||||
performance.
|
||||
|
||||
This time range feature will also allow geometries to appear and
|
||||
disappear during the camera shutter time if the specified time range
|
||||
is a sub range of [0,1].
|
||||
|
||||
Please also have a look at the `rtcSetGeometryTimeStepCount` function
|
||||
to see how to define the time steps for the specified time range.
|
||||
|
||||
#### EXIT STATUS
|
||||
|
||||
On failure an error code is set that can be queried using
|
||||
`rtcDeviceGetError`.
|
||||
|
||||
#### SEE ALSO
|
||||
|
||||
[rtcSetGeometryTimeStepCount]
|
||||
|
||||
@@ -44,4 +44,4 @@ On failure an error code is set that can be queried using
|
||||
|
||||
#### SEE ALSO
|
||||
|
||||
[rtcNewGeometry]
|
||||
[rtcNewGeometry], [rtcSetGeometryTimeRange]
|
||||
|
||||
+18
-1
@@ -1,9 +1,26 @@
|
||||
Version History
|
||||
---------------
|
||||
|
||||
### New Features in Embree 3.3.0
|
||||
- Added support for motion blur time range per geometry. This way geometries
|
||||
can appear and disappear during the camera shutter and time steps do not have
|
||||
to start and end at camera shutter interval boundaries.
|
||||
- Fixed crash with pathtracer when using --triangle-sphere command line.
|
||||
- Fixed crash with pathtracer when using --shader ao command line.
|
||||
- Fixed tutorials showing a black window on macOS 10.14 until moved.
|
||||
|
||||
### New Features in Embree 3.2.4
|
||||
- Fixed compile issues with ICC 2019.
|
||||
- Released ZIP files for Windows are now provided in a
|
||||
version linked against Visual Studio 2013 and Visual Studio 2015.
|
||||
|
||||
### New Features in Embree 3.2.3
|
||||
- Fixed crash when using curves with RTC_SCENE_FLAG_DYNAMIC
|
||||
combined with RTC_BUILD_QUALITY_MEDIUM.
|
||||
|
||||
### New Features in Embree 3.2.2
|
||||
- Fixed intersection distance for unnormalized rays with line segments.
|
||||
- Removed libmmd.dll depdendency
|
||||
- Removed libmmd.dll dependency in release builds for Windows.
|
||||
- Fixed detection of AppleClang compiler under MacOSX.
|
||||
|
||||
### New Features in Embree 3.2.1
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
Downloading Embree
|
||||
------------------
|
||||
|
||||
For Windows we provide Embree as MSI installer and ZIP files:
|
||||
For Windows we provide Embree as MSI installer and ZIP files. For the
|
||||
ZIP files we have a version where Embree is linked against the Visual
|
||||
Studio 2013 (VC12) runtime and and Visual Studio 2015/2017 (VC14)
|
||||
runtime:
|
||||
|
||||
[embree-<EMBREE_VERSION>-x64.msi](https://github.com/embree/embree/releases/download/v<EMBREE_VERSION>/embree-<EMBREE_VERSION>.x64.msi)
|
||||
[embree-<EMBREE_VERSION>.x64.windows.zip](https://github.com/embree/embree/releases/download/v<EMBREE_VERSION>/embree-<EMBREE_VERSION>.x64.windows.zip)
|
||||
[embree-<EMBREE_VERSION>-x64.vc12.msi](https://github.com/embree/embree/releases/download/v<EMBREE_VERSION>/embree-<EMBREE_VERSION>.x64.vc12.msi)
|
||||
[embree-<EMBREE_VERSION>.x64.vc12.windows.zip](https://github.com/embree/embree/releases/download/v<EMBREE_VERSION>/embree-<EMBREE_VERSION>.x64.vc12.windows.zip)
|
||||
[embree-<EMBREE_VERSION>.x64.vc14.windows.zip](https://github.com/embree/embree/releases/download/v<EMBREE_VERSION>/embree-<EMBREE_VERSION>.x64.vc14.windows.zip)
|
||||
|
||||
For Linux we provide Embree as RPMs or as a `tar.gz` file:
|
||||
|
||||
|
||||
+10
-8
@@ -5,7 +5,7 @@ Windows MSI Installer
|
||||
---------------------
|
||||
|
||||
You can install the Embree library using the Windows MSI installer
|
||||
[embree-<EMBREE_VERSION>-x64.msi](https://github.com/embree/embree/releases/download/v<EMBREE_VERSION>/embree-<EMBREE_VERSION>.x64.msi). This
|
||||
[embree-<EMBREE_VERSION>-x64.vc12.msi](https://github.com/embree/embree/releases/download/v<EMBREE_VERSION>/embree-<EMBREE_VERSION>.x64.vc12.msi). This
|
||||
will install the 64-bit Embree version by default in `Program
|
||||
Files\Intel\Embree v<EMBREE_VERSION> x64`.
|
||||
|
||||
@@ -25,13 +25,15 @@ then clicking `Programs and Features`. Select `Embree
|
||||
Windows ZIP File
|
||||
-----------------
|
||||
|
||||
Embree is also delivered as a ZIP file
|
||||
[embree-<EMBREE_VERSION>.x64.windows.zip](https://github.com/embree/embree/releases/download/v<EMBREE_VERSION>/embree-<EMBREE_VERSION>.x64.windows.zip). After
|
||||
unpacking this ZIP file, you should set the path to the `lib` folder
|
||||
manually to your `PATH` environment variable for applications to find
|
||||
Embree. To compile applications with Embree, you also have to set the
|
||||
`Include Directories` path in Visual Studio to the `include` folder of
|
||||
the Embree installation.
|
||||
Embree linked against Visual Studio 2013
|
||||
[embree-<EMBREE_VERSION>.x64.vc12.windows.zip](https://github.com/embree/embree/releases/download/v<EMBREE_VERSION>/embree-<EMBREE_VERSION>.x64.vc12.windows.zip)
|
||||
and Visual Studio 2015
|
||||
[embree-<EMBREE_VERSION>.x64.vc14.windows.zip](https://github.com/embree/embree/releases/download/v<EMBREE_VERSION>/embree-<EMBREE_VERSION>.x64.vc14.windows.zip)
|
||||
are provided as a ZIP file. After unpacking this ZIP file, you should
|
||||
set the path to the `lib` folder manually to your `PATH` environment
|
||||
variable for applications to find Embree. To compile applications with
|
||||
Embree, you also have to set the `Include Directories` path in Visual
|
||||
Studio to the `include` folder of the Embree installation.
|
||||
|
||||
If you plan to ship Embree with your application, best use the Embree
|
||||
version from this ZIP file.
|
||||
|
||||
@@ -153,9 +153,12 @@ RTC_API void rtcEnableGeometry(RTCGeometry geometry);
|
||||
RTC_API void rtcDisableGeometry(RTCGeometry geometry);
|
||||
|
||||
|
||||
/* Sets the number of time steps of the geometry. */
|
||||
/* Sets the number of motion blur time steps of the geometry. */
|
||||
RTC_API void rtcSetGeometryTimeStepCount(RTCGeometry geometry, unsigned int timeStepCount);
|
||||
|
||||
/* Sets the motion blur time range of the geometry. */
|
||||
RTC_API void rtcSetGeometryTimeRange(RTCGeometry geometry, float startTime, float endTime);
|
||||
|
||||
/* Sets the number of vertex attributes of the geometry. */
|
||||
RTC_API void rtcSetGeometryVertexAttributeCount(RTCGeometry geometry, unsigned int vertexAttributeCount);
|
||||
|
||||
|
||||
@@ -150,9 +150,12 @@ RTC_API void rtcEnableGeometry(RTCGeometry geometry);
|
||||
RTC_API void rtcDisableGeometry(RTCGeometry geometry);
|
||||
|
||||
|
||||
/* Sets the number of time steps of the geometry. */
|
||||
/* Sets the number of motion blur time steps of the geometry. */
|
||||
RTC_API void rtcSetGeometryTimeStepCount(RTCGeometry geometry, uniform unsigned int timeStepCount);
|
||||
|
||||
/* Sets the motion blur time range of the geometry. */
|
||||
RTC_API void rtcSetGeometryTimeRange(RTCGeometry geometry, uniform float startTime, uniform float endTime);
|
||||
|
||||
/* Sets the number of vertex attributes of the geometry. */
|
||||
RTC_API void rtcSetGeometryVertexAttributeCount(RTCGeometry geometry, uniform unsigned int vertexAttributeCount);
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
// ======================================================================== //
|
||||
|
||||
#define RTC_VERSION_MAJOR 3
|
||||
#define RTC_VERSION_MINOR 2
|
||||
#define RTC_VERSION_PATCH 2
|
||||
#define RTC_VERSION 30202
|
||||
#define RTC_VERSION_STRING "3.2.2"
|
||||
#define RTC_VERSION_MINOR 3
|
||||
#define RTC_VERSION_PATCH 0
|
||||
#define RTC_VERSION 30300
|
||||
#define RTC_VERSION_STRING "3.3.0"
|
||||
|
||||
@@ -36,12 +36,12 @@ namespace embree
|
||||
{
|
||||
/*! default settings */
|
||||
Settings ()
|
||||
: branchingFactor(2), maxDepth(32), logBlockSize(0), minLeafSize(1), maxLeafSize(8), finished_range_threshold(inf) {}
|
||||
: branchingFactor(2), maxDepth(32), sahBlockSize(1), minLeafSize(1), maxLeafSize(8), finished_range_threshold(inf) {}
|
||||
|
||||
public:
|
||||
size_t branchingFactor; //!< branching factor of BVH to build
|
||||
size_t maxDepth; //!< maximum depth of BVH to build
|
||||
size_t logBlockSize; //!< log2 of blocksize for SAH heuristic
|
||||
size_t sahBlockSize; //!< blocksize for SAH heuristic
|
||||
size_t minLeafSize; //!< minimum size of a leaf
|
||||
size_t maxLeafSize; //!< maximum size of a leaf
|
||||
size_t finished_range_threshold; //!< finished range threshold
|
||||
@@ -102,6 +102,7 @@ namespace embree
|
||||
/*! checks if all primitives are from the same geometry */
|
||||
__forceinline bool sameGeometry(const PrimInfoRange& range)
|
||||
{
|
||||
if (range.size() == 0) return true;
|
||||
unsigned int firstGeomID = prims[range.begin()].geomID();
|
||||
for (size_t i=range.begin()+1; i<range.end(); i++) {
|
||||
if (prims[i].geomID() != firstGeomID){
|
||||
@@ -178,14 +179,14 @@ namespace embree
|
||||
{
|
||||
/* variable to track the SAH of the best splitting approach */
|
||||
float bestSAH = inf;
|
||||
const size_t blocks = (pinfo.size()+(1ull<<cfg.logBlockSize)-1ull) >> cfg.logBlockSize;
|
||||
const size_t blocks = (pinfo.size()+cfg.sahBlockSize-1) / cfg.sahBlockSize;
|
||||
const float leafSAH = intCost*float(blocks)*halfArea(pinfo.geomBounds);
|
||||
|
||||
/* try standard binning in aligned space */
|
||||
float alignedObjectSAH = inf;
|
||||
HeuristicBinningSAH::Split alignedObjectSplit;
|
||||
if (aligned) {
|
||||
alignedObjectSplit = alignedHeuristic.find(pinfo,cfg.logBlockSize);
|
||||
alignedObjectSplit = alignedHeuristic.find(pinfo,cfg.sahBlockSize);
|
||||
alignedObjectSAH = travCostAligned*halfArea(pinfo.geomBounds) + intCost*alignedObjectSplit.splitSAH();
|
||||
bestSAH = min(alignedObjectSAH,bestSAH);
|
||||
}
|
||||
@@ -197,7 +198,7 @@ namespace embree
|
||||
if (bestSAH > 0.7f*leafSAH) {
|
||||
uspace = unalignedHeuristic.computeAlignedSpace(pinfo);
|
||||
const PrimInfoRange sinfo = unalignedHeuristic.computePrimInfo(pinfo,uspace);
|
||||
unalignedObjectSplit = unalignedHeuristic.find(sinfo,cfg.logBlockSize,uspace);
|
||||
unalignedObjectSplit = unalignedHeuristic.find(sinfo,cfg.sahBlockSize,uspace);
|
||||
unalignedObjectSAH = travCostUnaligned*halfArea(pinfo.geomBounds) + intCost*unalignedObjectSplit.splitSAH();
|
||||
bestSAH = min(unalignedObjectSAH,bestSAH);
|
||||
}
|
||||
@@ -206,7 +207,7 @@ namespace embree
|
||||
HeuristicStrandSplitSAH::Split strandSplit;
|
||||
float strandSAH = inf;
|
||||
if (bestSAH > 0.7f*leafSAH && pinfo.size() <= 256) {
|
||||
strandSplit = strandHeuristic.find(pinfo,cfg.logBlockSize);
|
||||
strandSplit = strandHeuristic.find(pinfo,cfg.sahBlockSize);
|
||||
strandSAH = travCostUnaligned*halfArea(pinfo.geomBounds) + intCost*strandSplit.splitSAH();
|
||||
bestSAH = min(strandSAH,bestSAH);
|
||||
}
|
||||
|
||||
@@ -126,9 +126,8 @@ namespace embree
|
||||
const unsigned primID = prim.primID();
|
||||
const Mesh* mesh = scene->get<Mesh>(geomID);
|
||||
const LBBox3fa lbounds = mesh->linearBounds(primID, time_range);
|
||||
const unsigned num_time_segments = mesh->numTimeSegments();
|
||||
const range<int> tbounds = getTimeSegmentRange(time_range, (float)num_time_segments);
|
||||
return PrimRefMB (lbounds, tbounds.size(), num_time_segments, geomID, primID);
|
||||
const range<int> tbounds = mesh->timeSegmentRange(time_range);
|
||||
return PrimRefMB (lbounds, tbounds.size(), mesh->time_range, mesh->numTimeSegments(), geomID, primID);
|
||||
}
|
||||
|
||||
// __noinline is workaround for ICC16 bug under MacOSX
|
||||
@@ -138,9 +137,8 @@ namespace embree
|
||||
const unsigned primID = prim.primID();
|
||||
const Mesh* mesh = scene->get<Mesh>(geomID);
|
||||
const LBBox3fa lbounds = mesh->linearBounds(space, primID, time_range);
|
||||
const unsigned num_time_segments = mesh->numTimeSegments();
|
||||
const range<int> tbounds = getTimeSegmentRange(time_range, (float)num_time_segments);
|
||||
return PrimRefMB (lbounds, tbounds.size(), num_time_segments, geomID, primID);
|
||||
const range<int> tbounds = mesh->timeSegmentRange(time_range);
|
||||
return PrimRefMB (lbounds, tbounds.size(), mesh->time_range, mesh->numTimeSegments(), geomID, primID);
|
||||
}
|
||||
|
||||
__forceinline LBBox3fa linearBounds(const PrimRefMB& prim, const BBox1f time_range) const {
|
||||
@@ -166,9 +164,8 @@ namespace embree
|
||||
const unsigned primID = prim.primID();
|
||||
const Geometry* mesh = scene->get(geomID);
|
||||
const LBBox3fa lbounds = mesh->vlinearBounds(primID, time_range);
|
||||
const unsigned num_time_segments = mesh->numTimeSegments();
|
||||
const range<int> tbounds = getTimeSegmentRange(time_range, (float)num_time_segments);
|
||||
return PrimRefMB (lbounds, tbounds.size(), num_time_segments, geomID, primID);
|
||||
const range<int> tbounds = mesh->timeSegmentRange(time_range);
|
||||
return PrimRefMB (lbounds, tbounds.size(), mesh->time_range, mesh->numTimeSegments(), geomID, primID);
|
||||
}
|
||||
|
||||
__forceinline PrimRefMB operator() (const PrimRefMB& prim, const BBox1f time_range, const LinearSpace3fa& space) const
|
||||
@@ -177,9 +174,8 @@ namespace embree
|
||||
const unsigned primID = prim.primID();
|
||||
const Geometry* mesh = scene->get(geomID);
|
||||
const LBBox3fa lbounds = mesh->vlinearBounds(space, primID, time_range);
|
||||
const unsigned num_time_segments = mesh->numTimeSegments();
|
||||
const range<int> tbounds = getTimeSegmentRange(time_range, (float)num_time_segments);
|
||||
return PrimRefMB (lbounds, tbounds.size(), num_time_segments, geomID, primID);
|
||||
const range<int> tbounds = mesh->timeSegmentRange(time_range);
|
||||
return PrimRefMB (lbounds, tbounds.size(), mesh->time_range, mesh->numTimeSegments(), geomID, primID);
|
||||
}
|
||||
|
||||
__forceinline LBBox3fa linearBounds(const PrimRefMB& prim, const BBox1f time_range) const {
|
||||
@@ -198,14 +194,14 @@ namespace embree
|
||||
{
|
||||
/*! default settings */
|
||||
Settings ()
|
||||
: branchingFactor(2), maxDepth(32), logBlockSize(0), minLeafSize(1), maxLeafSize(8),
|
||||
: branchingFactor(2), maxDepth(32), sahBlockSize(1), minLeafSize(1), maxLeafSize(8),
|
||||
travCost(1.0f), intCost(1.0f), singleLeafTimeSegment(false),
|
||||
singleThreadThreshold(1024) {}
|
||||
|
||||
public:
|
||||
size_t branchingFactor; //!< branching factor of BVH to build
|
||||
size_t maxDepth; //!< maximum depth of BVH to build
|
||||
size_t logBlockSize; //!< log2 of blocksize for SAH heuristic
|
||||
size_t sahBlockSize; //!< blocksize for SAH heuristic
|
||||
size_t minLeafSize; //!< minimum size of a leaf
|
||||
size_t maxLeafSize; //!< maximum size of a leaf
|
||||
float travCost; //!< estimated cost of one traversal step
|
||||
@@ -298,18 +294,18 @@ namespace embree
|
||||
const Split find(const SetMB& set)
|
||||
{
|
||||
/* first try standard object split */
|
||||
const Split object_split = heuristicObjectSplit.find(set,cfg.logBlockSize);
|
||||
const Split object_split = heuristicObjectSplit.find(set,cfg.sahBlockSize);
|
||||
const float object_split_sah = object_split.splitSAH();
|
||||
|
||||
/* test temporal splits only when object split was bad */
|
||||
const float leaf_sah = set.leafSAH(cfg.logBlockSize);
|
||||
const float leaf_sah = set.leafSAH(cfg.sahBlockSize);
|
||||
if (object_split_sah < 0.50f*leaf_sah)
|
||||
return object_split;
|
||||
|
||||
/* do temporal splits only if the the time range is big enough */
|
||||
if (set.time_range.size() > 1.01f/float(set.max_num_time_segments))
|
||||
{
|
||||
const Split temporal_split = heuristicTemporalSplit.find(set,cfg.logBlockSize);
|
||||
const Split temporal_split = heuristicTemporalSplit.find(set,cfg.sahBlockSize);
|
||||
const float temporal_split_sah = temporal_split.splitSAH();
|
||||
|
||||
/* take temporal split if it improved SAH */
|
||||
@@ -336,6 +332,11 @@ namespace embree
|
||||
set.deterministic_order();
|
||||
splitFallback(set,lset,rset);
|
||||
}
|
||||
/* split by geometry */
|
||||
else if (unlikely(split.data == Split::SPLIT_GEOMID)) {
|
||||
set.deterministic_order();
|
||||
splitByGeometry(set,lset,rset);
|
||||
}
|
||||
else
|
||||
assert(false);
|
||||
|
||||
@@ -345,23 +346,27 @@ namespace embree
|
||||
/*! finds the best fallback split */
|
||||
__noinline Split findFallback(const SetMB& set)
|
||||
{
|
||||
/* split if primitives are not from same geometry */
|
||||
if (!sameGeometry(set))
|
||||
return Split(0.0f,Split::SPLIT_GEOMID);
|
||||
|
||||
/* if a leaf can only hold a single time-segment, we might have to do additional temporal splits */
|
||||
if (cfg.singleLeafTimeSegment)
|
||||
{
|
||||
/* test if one primitive has more than one time segment in time range, if so split time */
|
||||
for (size_t i=set.object_range.begin(); i<set.object_range.end(); i++)
|
||||
for (size_t i=set.begin(); i<set.end(); i++)
|
||||
{
|
||||
const PrimRefMB& prim = (*set.prims)[i];
|
||||
const range<int> itime_range = getTimeSegmentRange(set.time_range,(float)prim.totalTimeSegments());
|
||||
const range<int> itime_range = prim.timeSegmentRange(set.time_range);
|
||||
const int localTimeSegments = itime_range.size();
|
||||
assert(localTimeSegments > 0);
|
||||
if (localTimeSegments > 1) {
|
||||
const int icenter = (itime_range.begin() + itime_range.end())/2;
|
||||
const float splitTime = float(icenter)/float(prim.totalTimeSegments());
|
||||
const float splitTime = prim.timeStep(icenter);
|
||||
return Split(0.0f,(unsigned)Split::SPLIT_TEMPORAL,0,splitTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* otherwise return fallback split */
|
||||
return Split(0.0f,Split::SPLIT_FALLBACK);
|
||||
@@ -372,8 +377,8 @@ namespace embree
|
||||
{
|
||||
mvector<PrimRefMB>& prims = *set.prims;
|
||||
|
||||
const size_t begin = set.object_range.begin();
|
||||
const size_t end = set.object_range.end();
|
||||
const size_t begin = set.begin();
|
||||
const size_t end = set.end();
|
||||
const size_t center = (begin + end)/2;
|
||||
|
||||
PrimInfoMB linfo = empty;
|
||||
@@ -388,6 +393,42 @@ namespace embree
|
||||
new (&rset) SetMB(rinfo,set.prims,range<size_t>(center,end ),set.time_range);
|
||||
}
|
||||
|
||||
/*! checks if all primitives are from the same geometry */
|
||||
__forceinline bool sameGeometry(const SetMB& set)
|
||||
{
|
||||
if (set.size() == 0) return true;
|
||||
mvector<PrimRefMB>& prims = *set.prims;
|
||||
const size_t begin = set.begin();
|
||||
const size_t end = set.end();
|
||||
unsigned int firstGeomID = prims[begin].geomID();
|
||||
for (size_t i=begin+1; i<end; i++) {
|
||||
if (prims[i].geomID() != firstGeomID){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* split by geometry ID */
|
||||
void splitByGeometry(const SetMB& set, SetMB& lset, SetMB& rset)
|
||||
{
|
||||
assert(set.size() > 1);
|
||||
|
||||
mvector<PrimRefMB>& prims = *set.prims;
|
||||
const size_t begin = set.begin();
|
||||
const size_t end = set.end();
|
||||
|
||||
PrimInfoMB left(empty);
|
||||
PrimInfoMB right(empty);
|
||||
unsigned int geomID = prims[begin].geomID();
|
||||
size_t center = serial_partitioning(prims.data(),begin,end,left,right,
|
||||
[&] ( const PrimRefMB& prim ) { return prim.geomID() == geomID; },
|
||||
[ ] ( PrimInfoMB& dst, const PrimRefMB& prim ) { dst.add_primref(prim); });
|
||||
|
||||
new (&lset) SetMB(left, set.prims,range<size_t>(begin,center),set.time_range);
|
||||
new (&rset) SetMB(right,set.prims,range<size_t>(center,end ),set.time_range);
|
||||
}
|
||||
|
||||
const NodeRecordMB4D createLargeLeaf(const BuildRecord& in, Allocator alloc)
|
||||
{
|
||||
/* this should never occur but is a fatal error */
|
||||
@@ -397,8 +438,22 @@ namespace embree
|
||||
/* replace already found split by fallback split */
|
||||
const BuildRecordSplit current(BuildRecord(in.prims,in.depth),findFallback(in.prims));
|
||||
|
||||
/* special case when directly creating leaf without any splits that could shrink time_range */
|
||||
bool force_split = false;
|
||||
if (current.depth == 1 && current.size() > 0)
|
||||
{
|
||||
BBox1f c = empty;
|
||||
BBox1f p = current.prims.time_range;
|
||||
for (size_t i=current.prims.begin(); i<current.prims.end(); i++) {
|
||||
mvector<PrimRefMB>& prims = *current.prims.prims;
|
||||
c.extend(prims[i].time_range);
|
||||
}
|
||||
|
||||
force_split = c.lower > p.lower || c.upper < p.upper;
|
||||
}
|
||||
|
||||
/* create leaf for few primitives */
|
||||
if (current.size() <= cfg.maxLeafSize && current.split.data != Split::SPLIT_TEMPORAL)
|
||||
if (current.size() <= cfg.maxLeafSize && current.split.data < Split::SPLIT_ENFORCE && !force_split)
|
||||
return createLeaf(current,alloc);
|
||||
|
||||
/* fill all children by always splitting the largest one */
|
||||
@@ -413,9 +468,11 @@ namespace embree
|
||||
for (size_t i=0; i<children.size(); i++)
|
||||
{
|
||||
/* ignore leaves as they cannot get split */
|
||||
if (children[i].size() <= cfg.maxLeafSize && children[i].split.data != Split::SPLIT_TEMPORAL)
|
||||
if (children[i].size() <= cfg.maxLeafSize && children[i].split.data < Split::SPLIT_ENFORCE && !force_split)
|
||||
continue;
|
||||
|
||||
force_split = false;
|
||||
|
||||
/* remember child with largest size */
|
||||
if (children[i].size() > bestSize) {
|
||||
bestSize = children[i].size();
|
||||
@@ -438,6 +495,13 @@ namespace embree
|
||||
|
||||
} while (children.size() < cfg.branchingFactor);
|
||||
|
||||
/* detect time_ranges that have shrunken */
|
||||
for (size_t i=0; i<children.size(); i++) {
|
||||
const BBox1f c = children[i].prims.time_range;
|
||||
const BBox1f p = in.prims.time_range;
|
||||
hasTimeSplits |= c.lower > p.lower || c.upper < p.upper;
|
||||
}
|
||||
|
||||
/* create node */
|
||||
auto node = createNode(alloc, hasTimeSplits);
|
||||
|
||||
@@ -470,7 +534,7 @@ namespace embree
|
||||
const Split csplit = find(current.prims);
|
||||
|
||||
/*! compute leaf and split cost */
|
||||
const float leafSAH = cfg.intCost*current.prims.leafSAH(cfg.logBlockSize);
|
||||
const float leafSAH = cfg.intCost*current.prims.leafSAH(cfg.sahBlockSize);
|
||||
const float splitSAH = cfg.travCost*current.prims.halfArea()+cfg.intCost*csplit.splitSAH();
|
||||
assert((current.size() == 0) || ((leafSAH >= 0) && (splitSAH >= 0)));
|
||||
|
||||
@@ -517,6 +581,13 @@ namespace embree
|
||||
children.split(bestChild,lrecord,rrecord,std::move(new_vector));
|
||||
}
|
||||
|
||||
/* detect time_ranges that have shrunken */
|
||||
for (size_t i=0; i<children.size(); i++) {
|
||||
const BBox1f c = children[i].prims.time_range;
|
||||
const BBox1f p = current.prims.time_range;
|
||||
hasTimeSplits |= c.lower > p.lower || c.upper < p.upper;
|
||||
}
|
||||
|
||||
/* sort buildrecords for simpler shadow ray traversal */
|
||||
//std::sort(&children[0],&children[children.size()],std::greater<BuildRecord>()); // FIXME: reduces traversal performance of bvh8.triangle4 (need to verified) !!
|
||||
|
||||
|
||||
@@ -34,12 +34,12 @@ namespace embree
|
||||
{
|
||||
/*! default settings */
|
||||
Settings ()
|
||||
: branchingFactor(2), maxDepth(32), logBlockSize(0), minLeafSize(1), maxLeafSize(8) {}
|
||||
: branchingFactor(2), maxDepth(32), sahBlockSize(1), minLeafSize(1), maxLeafSize(8) {}
|
||||
|
||||
public:
|
||||
size_t branchingFactor; //!< branching factor of BVH to build
|
||||
size_t maxDepth; //!< maximum depth of BVH to build
|
||||
size_t logBlockSize; //!< log2 of blocksize for SAH heuristic
|
||||
size_t sahBlockSize; //!< blocksize for SAH heuristic
|
||||
size_t minLeafSize; //!< minimum size of a leaf
|
||||
size_t maxLeafSize; //!< maximum size of a leaf
|
||||
};
|
||||
@@ -56,7 +56,7 @@ namespace embree
|
||||
: depth(depth), prims(prims) {}
|
||||
|
||||
__forceinline size_t size() const {
|
||||
return prims.object_range.size();
|
||||
return prims.size();
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -122,8 +122,8 @@ namespace embree
|
||||
__forceinline bool sameGeometry(const SetMB& set)
|
||||
{
|
||||
mvector<PrimRefMB>& prims = *set.prims;
|
||||
unsigned int firstGeomID = prims[set.object_range.begin()].geomID();
|
||||
for (size_t i=set.object_range.begin()+1; i<set.object_range.end(); i++) {
|
||||
unsigned int firstGeomID = prims[set.begin()].geomID();
|
||||
for (size_t i=set.begin()+1; i<set.end(); i++) {
|
||||
if (prims[i].geomID() != firstGeomID){
|
||||
return false;
|
||||
}
|
||||
@@ -136,8 +136,8 @@ namespace embree
|
||||
{
|
||||
mvector<PrimRefMB>& prims = *set.prims;
|
||||
|
||||
const size_t begin = set.object_range.begin();
|
||||
const size_t end = set.object_range.end();
|
||||
const size_t begin = set.begin();
|
||||
const size_t end = set.end();
|
||||
const size_t center = (begin + end)/2;
|
||||
|
||||
PrimInfoMB linfo = empty;
|
||||
@@ -154,9 +154,9 @@ namespace embree
|
||||
|
||||
void splitByGeometry(const SetMB& set, SetMB& lset, SetMB& rset)
|
||||
{
|
||||
assert(set.object_range.size() > 1);
|
||||
const size_t begin = set.object_range.begin();
|
||||
const size_t end = set.object_range.end();
|
||||
assert(set.size() > 1);
|
||||
const size_t begin = set.begin();
|
||||
const size_t end = set.end();
|
||||
PrimInfoMB linfo(empty);
|
||||
PrimInfoMB rinfo(empty);
|
||||
unsigned int geomID = (*set.prims)[begin].geomID();
|
||||
@@ -175,8 +175,22 @@ namespace embree
|
||||
if (current.depth > cfg.maxDepth)
|
||||
throw_RTCError(RTC_ERROR_UNKNOWN,"depth limit reached");
|
||||
|
||||
/* special case when directly creating leaf without any splits that could shrink time_range */
|
||||
bool force_split = false;
|
||||
if (current.depth == 1 && current.size() > 0)
|
||||
{
|
||||
BBox1f c = empty;
|
||||
BBox1f p = current.prims.time_range;
|
||||
for (size_t i=current.prims.begin(); i<current.prims.end(); i++) {
|
||||
mvector<PrimRefMB>& prims = *current.prims.prims;
|
||||
c.extend(prims[i].time_range);
|
||||
}
|
||||
|
||||
force_split = c.lower > p.lower || c.upper < p.upper;
|
||||
}
|
||||
|
||||
/* create leaf for few primitives */
|
||||
if (current.size() <= cfg.maxLeafSize && sameGeometry(current.prims))
|
||||
if (current.size() <= cfg.maxLeafSize && sameGeometry(current.prims) && !force_split)
|
||||
return createLeaf(current.prims,alloc);
|
||||
|
||||
/* fill all children by always splitting the largest one */
|
||||
@@ -190,9 +204,11 @@ namespace embree
|
||||
for (unsigned i=0; i<children.size(); i++)
|
||||
{
|
||||
/* ignore leaves as they cannot get split */
|
||||
if (children[i].size() <= cfg.maxLeafSize && sameGeometry(children[i].prims))
|
||||
if (children[i].size() <= cfg.maxLeafSize && sameGeometry(children[i].prims) && !force_split)
|
||||
continue;
|
||||
|
||||
force_split = false;
|
||||
|
||||
/* remember child with largest size */
|
||||
if (children[i].size() > bestSize) {
|
||||
bestSize = children[i].size();
|
||||
@@ -213,8 +229,17 @@ namespace embree
|
||||
|
||||
} while (children.size() < cfg.branchingFactor);
|
||||
|
||||
|
||||
/* detect time_ranges that have shrunken */
|
||||
bool timesplit = false;
|
||||
for (size_t i=0; i<children.size(); i++) {
|
||||
const BBox1f c = children[i].prims.time_range;
|
||||
const BBox1f p = current.prims.time_range;
|
||||
timesplit |= c.lower > p.lower || c.upper < p.upper;
|
||||
}
|
||||
|
||||
/* create node */
|
||||
NodeRef node = createAlignedNodeMB(alloc,false);
|
||||
NodeRef node = createAlignedNodeMB(alloc,timesplit);
|
||||
|
||||
LBBox3fa bounds = empty;
|
||||
for (size_t i=0; i<children.size(); i++) {
|
||||
@@ -223,6 +248,9 @@ namespace embree
|
||||
bounds.extend(child.lbounds);
|
||||
}
|
||||
|
||||
if (timesplit)
|
||||
bounds = current.prims.linearBounds(recalculatePrimRef);
|
||||
|
||||
return NodeRecordMB4D(node,bounds,current.prims.time_range);
|
||||
}
|
||||
|
||||
@@ -231,10 +259,10 @@ namespace embree
|
||||
{
|
||||
/* variable to track the SAH of the best splitting approach */
|
||||
float bestSAH = inf;
|
||||
const float leafSAH = current.prims.leafSAH(cfg.logBlockSize);
|
||||
const float leafSAH = current.prims.leafSAH(cfg.sahBlockSize);
|
||||
|
||||
/* perform standard binning in aligned space */
|
||||
HeuristicBinning::Split alignedObjectSplit = alignedHeuristic.find(current.prims,cfg.logBlockSize);
|
||||
HeuristicBinning::Split alignedObjectSplit = alignedHeuristic.find(current.prims,cfg.sahBlockSize);
|
||||
float alignedObjectSAH = alignedObjectSplit.splitSAH();
|
||||
bestSAH = min(alignedObjectSAH,bestSAH);
|
||||
|
||||
@@ -245,7 +273,7 @@ namespace embree
|
||||
if (alignedObjectSAH > 0.7f*leafSAH) {
|
||||
uspace = unalignedHeuristic.computeAlignedSpaceMB(scene,current.prims);
|
||||
const SetMB sset = current.prims.primInfo(recalculatePrimRef,uspace);
|
||||
unalignedObjectSplit = unalignedHeuristic.find(sset,cfg.logBlockSize,uspace);
|
||||
unalignedObjectSplit = unalignedHeuristic.find(sset,cfg.sahBlockSize,uspace);
|
||||
unalignedObjectSAH = 1.3f*unalignedObjectSplit.splitSAH(); // makes unaligned splits more expensive
|
||||
bestSAH = min(unalignedObjectSAH,bestSAH);
|
||||
}
|
||||
@@ -255,7 +283,7 @@ namespace embree
|
||||
typename HeuristicTemporal::Split temporal_split;
|
||||
if (bestSAH > 0.5f*leafSAH) {
|
||||
if (current.prims.time_range.size() > 1.01f/float(current.prims.max_num_time_segments)) {
|
||||
temporal_split = temporalSplitHeuristic.find(current.prims,cfg.logBlockSize);
|
||||
temporal_split = temporalSplitHeuristic.find(current.prims,cfg.sahBlockSize);
|
||||
temporal_split_sah = temporal_split.splitSAH();
|
||||
bestSAH = min(temporal_split_sah,bestSAH);
|
||||
}
|
||||
@@ -336,6 +364,13 @@ namespace embree
|
||||
|
||||
} while (children.size() < cfg.branchingFactor);
|
||||
|
||||
/* detect time_ranges that have shrunken */
|
||||
for (size_t i=0; i<children.size(); i++) {
|
||||
const BBox1f c = children[i].prims.time_range;
|
||||
const BBox1f p = current.prims.time_range;
|
||||
timesplit |= c.lower > p.lower || c.upper < p.upper;
|
||||
}
|
||||
|
||||
/* create time split node */
|
||||
if (timesplit)
|
||||
{
|
||||
|
||||
@@ -45,17 +45,17 @@ namespace embree
|
||||
{
|
||||
/*! default settings */
|
||||
Settings ()
|
||||
: branchingFactor(2), maxDepth(32), logBlockSize(0), minLeafSize(1), maxLeafSize(8),
|
||||
: branchingFactor(2), maxDepth(32), sahBlockSize(1), minLeafSize(1), maxLeafSize(8),
|
||||
travCost(1.0f), intCost(1.0f), singleThreadThreshold(1024), primrefarrayalloc(inf) {}
|
||||
|
||||
/*! initialize settings from API settings */
|
||||
Settings (const RTCBuildArguments& settings)
|
||||
: branchingFactor(2), maxDepth(32), logBlockSize(0), minLeafSize(1), maxLeafSize(8),
|
||||
: branchingFactor(2), maxDepth(32), sahBlockSize(1), minLeafSize(1), maxLeafSize(8),
|
||||
travCost(1.0f), intCost(1.0f), singleThreadThreshold(1024), primrefarrayalloc(inf)
|
||||
{
|
||||
if (RTC_BUILD_ARGUMENTS_HAS(settings,maxBranchingFactor)) branchingFactor = settings.maxBranchingFactor;
|
||||
if (RTC_BUILD_ARGUMENTS_HAS(settings,maxDepth )) maxDepth = settings.maxDepth;
|
||||
if (RTC_BUILD_ARGUMENTS_HAS(settings,sahBlockSize )) logBlockSize = bsr(settings.sahBlockSize);
|
||||
if (RTC_BUILD_ARGUMENTS_HAS(settings,sahBlockSize )) sahBlockSize = settings.sahBlockSize;
|
||||
if (RTC_BUILD_ARGUMENTS_HAS(settings,minLeafSize )) minLeafSize = settings.minLeafSize;
|
||||
if (RTC_BUILD_ARGUMENTS_HAS(settings,maxLeafSize )) maxLeafSize = settings.maxLeafSize;
|
||||
if (RTC_BUILD_ARGUMENTS_HAS(settings,traversalCost )) travCost = settings.traversalCost;
|
||||
@@ -63,13 +63,13 @@ namespace embree
|
||||
}
|
||||
|
||||
Settings (size_t sahBlockSize, size_t minLeafSize, size_t maxLeafSize, float travCost, float intCost, size_t singleThreadThreshold, size_t primrefarrayalloc = inf)
|
||||
: branchingFactor(2), maxDepth(32), logBlockSize(bsr(sahBlockSize)), minLeafSize(minLeafSize), maxLeafSize(maxLeafSize),
|
||||
: branchingFactor(2), maxDepth(32), sahBlockSize(sahBlockSize), minLeafSize(minLeafSize), maxLeafSize(maxLeafSize),
|
||||
travCost(travCost), intCost(intCost), singleThreadThreshold(singleThreadThreshold), primrefarrayalloc(primrefarrayalloc) {}
|
||||
|
||||
public:
|
||||
size_t branchingFactor; //!< branching factor of BVH to build
|
||||
size_t maxDepth; //!< maximum depth of BVH to build
|
||||
size_t logBlockSize; //!< log2 of blocksize for SAH heuristic
|
||||
size_t sahBlockSize; //!< blocksize for SAH heuristic
|
||||
size_t minLeafSize; //!< minimum size of a leaf
|
||||
size_t maxLeafSize; //!< maximum size of a leaf
|
||||
float travCost; //!< estimated cost of one traversal step
|
||||
@@ -213,10 +213,10 @@ namespace embree
|
||||
progressMonitor(current.size());
|
||||
|
||||
/*! find best split */
|
||||
auto split = heuristic.find(current.prims,cfg.logBlockSize);
|
||||
auto split = heuristic.find(current.prims,cfg.sahBlockSize);
|
||||
|
||||
/*! compute leaf and split cost */
|
||||
const float leafSAH = cfg.intCost*current.prims.leafSAH(cfg.logBlockSize);
|
||||
const float leafSAH = cfg.intCost*current.prims.leafSAH(cfg.sahBlockSize);
|
||||
const float splitSAH = cfg.travCost*halfArea(current.prims.geomBounds)+cfg.intCost*split.splitSAH();
|
||||
assert((current.prims.size() == 0) || ((leafSAH >= 0) && (splitSAH >= 0)));
|
||||
|
||||
@@ -260,7 +260,7 @@ namespace embree
|
||||
BuildRecord& brecord = children[bestChild];
|
||||
BuildRecord lrecord(current.depth+1);
|
||||
BuildRecord rrecord(current.depth+1);
|
||||
auto split = heuristic.find(brecord.prims,cfg.logBlockSize);
|
||||
auto split = heuristic.find(brecord.prims,cfg.sahBlockSize);
|
||||
heuristic.split(split,brecord.prims,lrecord.prims,rrecord.prims);
|
||||
children[bestChild ] = lrecord;
|
||||
children[numChildren] = rrecord;
|
||||
|
||||
@@ -131,8 +131,10 @@ namespace embree
|
||||
enum
|
||||
{
|
||||
SPLIT_OBJECT = 0,
|
||||
SPLIT_TEMPORAL = 1,
|
||||
SPLIT_FALLBACK = 2,
|
||||
SPLIT_FALLBACK = 1,
|
||||
SPLIT_ENFORCE = 2, // splits with larger ID are enforced in createLargeLeaf even if we could create a leaf already
|
||||
SPLIT_TEMPORAL = 2,
|
||||
SPLIT_GEOMID = 3,
|
||||
};
|
||||
|
||||
/*! construct an invalid split by default */
|
||||
@@ -348,7 +350,7 @@ namespace embree
|
||||
}
|
||||
|
||||
/*! finds the best split by scanning binning information */
|
||||
__forceinline Split best(const BinMapping<BINS>& mapping, const size_t blocks_shift) const
|
||||
__forceinline Split best(const BinMapping<BINS>& mapping, const size_t sahBlockSize) const
|
||||
{
|
||||
/* sweep from right to left and compute parallel prefix of merged bounds */
|
||||
vfloat4 rAreas[BINS];
|
||||
@@ -364,7 +366,7 @@ namespace embree
|
||||
rAreas[i][3] = 0.0f;
|
||||
}
|
||||
/* sweep from left to right and compute SAH */
|
||||
vuint4 blocks_add = (1 << blocks_shift)-1;
|
||||
vuint4 blocks_add = sahBlockSize-1;
|
||||
vuint4 ii = 1; vfloat4 vbestSAH = pos_inf; vuint4 vbestPos = 0;
|
||||
count = 0; bx = empty; by = empty; bz = empty;
|
||||
for (size_t i=1; i<mapping.size(); i++, ii+=1)
|
||||
@@ -375,8 +377,8 @@ namespace embree
|
||||
bz.extend(bounds(i-1,2)); float Az = expectedApproxHalfArea(bz);
|
||||
const vfloat4 lArea = vfloat4(Ax,Ay,Az,Az);
|
||||
const vfloat4 rArea = rAreas[i];
|
||||
const vuint4 lCount = (count +blocks_add) >> (unsigned int)(blocks_shift); // if blocks_shift >=1 then lCount < 4B and could be represented with an vint4, which would allow for faster vfloat4 conversions.
|
||||
const vuint4 rCount = (rCounts[i]+blocks_add) >> (unsigned int)(blocks_shift);
|
||||
const vuint4 lCount = (count +blocks_add) / vuint4(sahBlockSize); // if blocks_shift >=1 then lCount < 4B and could be represented with an vint4, which would allow for faster vfloat4 conversions.
|
||||
const vuint4 rCount = (rCounts[i]+blocks_add) / vuint4(sahBlockSize);
|
||||
const vfloat4 sah = madd(lArea,vfloat4(lCount),rArea*vfloat4(rCount));
|
||||
//const vfloat4 sah = madd(lArea,vfloat4(vint4(lCount)),rArea*vfloat4(vint4(rCount)));
|
||||
|
||||
@@ -456,7 +458,7 @@ namespace embree
|
||||
vuint4 _counts[BINS]; //!< counts number of primitives that map into the bins
|
||||
};
|
||||
|
||||
#if defined(__AVX512ER__) // KNL
|
||||
#if 0 && defined(__AVX512ER__) // KNL
|
||||
|
||||
/*! mapping into bins */
|
||||
template<>
|
||||
@@ -829,8 +831,10 @@ namespace embree
|
||||
}
|
||||
|
||||
/*! finds the best split by scanning binning information */
|
||||
__forceinline Split best(const BinMapping<16>& mapping, const size_t blocks_shift) const
|
||||
__forceinline Split best(const BinMapping<16>& mapping, const size_t sahBlockSize) const
|
||||
{
|
||||
const size_t blocks_shift = bsr(sahBlockSize);
|
||||
|
||||
/* find best dimension */
|
||||
float bestSAH = inf;
|
||||
int bestDim = -1;
|
||||
|
||||
@@ -40,8 +40,8 @@ namespace embree
|
||||
return expectedApproxHalfArea(geomBounds)*float(size());
|
||||
}
|
||||
|
||||
__forceinline float leafSAH(size_t block_shift) const {
|
||||
return expectedApproxHalfArea(geomBounds)*float((size()+(size_t(1)<<block_shift)-1) >> block_shift);
|
||||
__forceinline float leafSAH(size_t sahBlockSize) const {
|
||||
return expectedApproxHalfArea(geomBounds)*float((size()+sahBlockSize-1) / sahBlockSize);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -70,21 +70,21 @@ namespace embree
|
||||
: prims(prims) {}
|
||||
|
||||
/*! finds the best split */
|
||||
__noinline const Split find(const PrimInfoRange& pinfo, const size_t logBlockSize)
|
||||
__noinline const Split find(const PrimInfoRange& pinfo, const size_t sahBlockSize)
|
||||
{
|
||||
if (likely(pinfo.size() < PARALLEL_THRESHOLD))
|
||||
return find_template<false>(pinfo,logBlockSize);
|
||||
return find_template<false>(pinfo,sahBlockSize);
|
||||
else
|
||||
return find_template<true>(pinfo,logBlockSize);
|
||||
return find_template<true>(pinfo,sahBlockSize);
|
||||
}
|
||||
|
||||
template<bool parallel>
|
||||
__forceinline const Split find_template(const PrimInfoRange& pinfo, const size_t logBlockSize)
|
||||
__forceinline const Split find_template(const PrimInfoRange& pinfo, const size_t sahBlockSize)
|
||||
{
|
||||
Binner binner(empty);
|
||||
const BinMapping<BINS> mapping(pinfo);
|
||||
bin_serial_or_parallel<parallel>(binner,prims,pinfo.begin(),pinfo.end(),PARALLEL_FIND_BLOCK_SIZE,mapping);
|
||||
return binner.best(mapping,logBlockSize);
|
||||
return binner.best(mapping,sahBlockSize);
|
||||
}
|
||||
|
||||
/*! array partitioning */
|
||||
@@ -186,12 +186,12 @@ namespace embree
|
||||
static const size_t PARALLEL_PARTITION_BLOCK_SIZE = 128;
|
||||
|
||||
/*! finds the best split */
|
||||
const Split find(const SetMB& set, const size_t logBlockSize)
|
||||
const Split find(const SetMB& set, const size_t sahBlockSize)
|
||||
{
|
||||
ObjectBinner binner(empty);
|
||||
const BinMapping<BINS> mapping(set.size(),set.centBounds);
|
||||
bin_parallel(binner,set.prims->data(),set.object_range.begin(),set.object_range.end(),PARALLEL_FIND_BLOCK_SIZE,PARALLEL_THRESHOLD,mapping);
|
||||
Split osplit = binner.best(mapping,logBlockSize);
|
||||
bin_parallel(binner,set.prims->data(),set.begin(),set.end(),PARALLEL_FIND_BLOCK_SIZE,PARALLEL_THRESHOLD,mapping);
|
||||
Split osplit = binner.best(mapping,sahBlockSize);
|
||||
osplit.sah *= set.time_range.size();
|
||||
if (!osplit.valid()) osplit.data = Split::SPLIT_FALLBACK; // use fallback split
|
||||
return osplit;
|
||||
@@ -200,8 +200,8 @@ namespace embree
|
||||
/*! array partitioning */
|
||||
__forceinline void split(const Split& split, const SetMB& set, SetMB& lset, SetMB& rset)
|
||||
{
|
||||
const size_t begin = set.object_range.begin();
|
||||
const size_t end = set.object_range.end();
|
||||
const size_t begin = set.begin();
|
||||
const size_t end = set.end();
|
||||
PrimInfoMB left = empty;
|
||||
PrimInfoMB right = empty;
|
||||
const vint4 vSplitPos(split.pos);
|
||||
|
||||
@@ -104,23 +104,23 @@ namespace embree
|
||||
};
|
||||
|
||||
/*! finds the best split */
|
||||
__forceinline const Split find(const PrimInfoRange& pinfo, const size_t logBlockSize, const LinearSpace3fa& space)
|
||||
__forceinline const Split find(const PrimInfoRange& pinfo, const size_t sahBlockSize, const LinearSpace3fa& space)
|
||||
{
|
||||
if (likely(pinfo.size() < 10000))
|
||||
return find_template<false>(pinfo,logBlockSize,space);
|
||||
return find_template<false>(pinfo,sahBlockSize,space);
|
||||
else
|
||||
return find_template<true>(pinfo,logBlockSize,space);
|
||||
return find_template<true>(pinfo,sahBlockSize,space);
|
||||
}
|
||||
|
||||
/*! finds the best split */
|
||||
template<bool parallel>
|
||||
const Split find_template(const PrimInfoRange& set, const size_t logBlockSize, const LinearSpace3fa& space)
|
||||
const Split find_template(const PrimInfoRange& set, const size_t sahBlockSize, const LinearSpace3fa& space)
|
||||
{
|
||||
Binner binner(empty);
|
||||
const BinMapping<BINS> mapping(set);
|
||||
BinBoundsAndCenter binBoundsAndCenter(scene,space);
|
||||
bin_serial_or_parallel<parallel>(binner,prims,set.begin(),set.end(),size_t(4096),mapping,binBoundsAndCenter);
|
||||
return binner.best(mapping,logBlockSize);
|
||||
return binner.best(mapping,sahBlockSize);
|
||||
}
|
||||
|
||||
/*! array partitioning */
|
||||
@@ -216,7 +216,7 @@ namespace embree
|
||||
uint64_t bestGeomPrimID = -1;
|
||||
|
||||
/*! find curve with minimum ID that defines valid direction */
|
||||
for (size_t i=set.object_range.begin(); i<set.object_range.end(); i++)
|
||||
for (size_t i=set.begin(); i<set.end(); i++)
|
||||
{
|
||||
const PrimRefMB& prim = (*set.prims)[i];
|
||||
const unsigned int geomID = prim.geomID();
|
||||
@@ -225,8 +225,7 @@ namespace embree
|
||||
if (geomprimID >= bestGeomPrimID) continue;
|
||||
|
||||
const Geometry* mesh = scene->get(geomID);
|
||||
const unsigned num_time_segments = mesh->numTimeSegments();
|
||||
const range<int> tbounds = getTimeSegmentRange(set.time_range, (float)num_time_segments);
|
||||
const range<int> tbounds = mesh->timeSegmentRange(set.time_range);
|
||||
if (tbounds.size() == 0) continue;
|
||||
|
||||
const size_t t = (tbounds.begin()+tbounds.end())/2;
|
||||
@@ -279,13 +278,13 @@ namespace embree
|
||||
};
|
||||
|
||||
/*! finds the best split */
|
||||
const Split find(const SetMB& set, const size_t logBlockSize, const LinearSpace3fa& space)
|
||||
const Split find(const SetMB& set, const size_t sahBlockSize, const LinearSpace3fa& space)
|
||||
{
|
||||
BinBoundsAndCenter binBoundsAndCenter(scene,set.time_range,space);
|
||||
ObjectBinner binner(empty);
|
||||
const BinMapping<BINS> mapping(set.size(),set.centBounds);
|
||||
bin_parallel(binner,set.prims->data(),set.object_range.begin(),set.object_range.end(),PARALLEL_FIND_BLOCK_SIZE,PARALLEL_THRESHOLD,mapping,binBoundsAndCenter);
|
||||
Split osplit = binner.best(mapping,logBlockSize);
|
||||
bin_parallel(binner,set.prims->data(),set.begin(),set.end(),PARALLEL_FIND_BLOCK_SIZE,PARALLEL_THRESHOLD,mapping,binBoundsAndCenter);
|
||||
Split osplit = binner.best(mapping,sahBlockSize);
|
||||
osplit.sah *= set.time_range.size();
|
||||
if (!osplit.valid()) osplit.data = Split::SPLIT_FALLBACK; // use fallback split
|
||||
return osplit;
|
||||
@@ -295,8 +294,8 @@ namespace embree
|
||||
__forceinline void split(const Split& split, const LinearSpace3fa& space, const SetMB& set, SetMB& lset, SetMB& rset)
|
||||
{
|
||||
BinBoundsAndCenter binBoundsAndCenter(scene,set.time_range,space);
|
||||
const size_t begin = set.object_range.begin();
|
||||
const size_t end = set.object_range.end();
|
||||
const size_t begin = set.begin();
|
||||
const size_t end = set.end();
|
||||
PrimInfoMB left = empty;
|
||||
PrimInfoMB right = empty;
|
||||
const vint4 vSplitPos(split.pos);
|
||||
|
||||
@@ -246,7 +246,7 @@ namespace embree
|
||||
}
|
||||
}
|
||||
|
||||
__noinline const Split find(PrimInfoExtRange& set, const size_t logBlockSize)
|
||||
__noinline const Split find(PrimInfoExtRange& set, const size_t sahBlockSize)
|
||||
{
|
||||
/* single element */
|
||||
if (set.size() <= 1)
|
||||
@@ -294,28 +294,28 @@ namespace embree
|
||||
}
|
||||
|
||||
/* find best split */
|
||||
return object_find(set,logBlockSize);
|
||||
return object_find(set,sahBlockSize);
|
||||
}
|
||||
|
||||
|
||||
/*! finds the best object split */
|
||||
__forceinline const Split object_find(const PrimInfoExtRange& set,const size_t logBlockSize)
|
||||
__forceinline const Split object_find(const PrimInfoExtRange& set,const size_t sahBlockSize)
|
||||
{
|
||||
if (set.size() < PARALLEL_THRESHOLD) return sequential_object_find(set,logBlockSize);
|
||||
else return parallel_object_find (set,logBlockSize);
|
||||
if (set.size() < PARALLEL_THRESHOLD) return sequential_object_find(set,sahBlockSize);
|
||||
else return parallel_object_find (set,sahBlockSize);
|
||||
}
|
||||
|
||||
/*! finds the best object split */
|
||||
__noinline const Split sequential_object_find(const PrimInfoExtRange& set, const size_t logBlockSize)
|
||||
__noinline const Split sequential_object_find(const PrimInfoExtRange& set, const size_t sahBlockSize)
|
||||
{
|
||||
Binner binner(empty);
|
||||
const BinMapping<OBJECT_BINS> mapping(set.centBounds);
|
||||
binner.bin(prims0,set.begin(),set.end(),mapping);
|
||||
return binner.best(mapping,logBlockSize);
|
||||
return binner.best(mapping,sahBlockSize);
|
||||
}
|
||||
|
||||
/*! finds the best split */
|
||||
__noinline const Split parallel_object_find(const PrimInfoExtRange& set, const size_t logBlockSize)
|
||||
__noinline const Split parallel_object_find(const PrimInfoExtRange& set, const size_t sahBlockSize)
|
||||
{
|
||||
Binner binner(empty);
|
||||
const BinMapping<OBJECT_BINS> mapping(set.centBounds);
|
||||
@@ -327,7 +327,7 @@ namespace embree
|
||||
Binner r = b0; r.merge(b1,_mapping.size()); return r;
|
||||
};
|
||||
binner = parallel_reduce(set.begin(),set.end(),PARALLEL_FIND_BLOCK_SIZE,binner,body,reduction);
|
||||
return binner.best(mapping,logBlockSize);
|
||||
return binner.best(mapping,sahBlockSize);
|
||||
}
|
||||
|
||||
/*! array partitioning */
|
||||
|
||||
@@ -344,7 +344,7 @@ namespace embree
|
||||
}
|
||||
|
||||
/*! finds the best split by scanning binning information */
|
||||
SpatialBinSplit<BINS> best(const SpatialBinMapping<BINS>& mapping, const size_t blocks_shift) const
|
||||
SpatialBinSplit<BINS> best(const SpatialBinMapping<BINS>& mapping, const size_t sahBlockSize) const
|
||||
{
|
||||
/* sweep from right to left and compute parallel prefix of merged bounds */
|
||||
vfloat4 rAreas[BINS];
|
||||
@@ -361,7 +361,7 @@ namespace embree
|
||||
}
|
||||
|
||||
/* sweep from left to right and compute SAH */
|
||||
vuint4 blocks_add = (1 << blocks_shift)-1;
|
||||
vuint4 blocks_add = sahBlockSize-1;
|
||||
vuint4 ii = 1; vfloat4 vbestSAH = pos_inf; vuint4 vbestPos = 0; vuint4 vbestlCount = 0; vuint4 vbestrCount = 0;
|
||||
count = 0; bx = empty; by = empty; bz = empty;
|
||||
for (size_t i=1; i<BINS; i++, ii+=1)
|
||||
@@ -372,8 +372,8 @@ namespace embree
|
||||
bz.extend(bounds[i-1][2]); float Az = halfArea(bz);
|
||||
const vfloat4 lArea = vfloat4(Ax,Ay,Az,Az);
|
||||
const vfloat4 rArea = rAreas[i];
|
||||
const vuint4 lCount = (count +blocks_add) >> (unsigned int)(blocks_shift);
|
||||
const vuint4 rCount = (rCounts[i]+blocks_add) >> (unsigned int)(blocks_shift);
|
||||
const vuint4 lCount = (count +blocks_add) / vuint4(sahBlockSize);
|
||||
const vuint4 rCount = (rCounts[i]+blocks_add) / vuint4(sahBlockSize);
|
||||
const vfloat4 sah = madd(lArea,vfloat4(lCount),rArea*vfloat4(rCount));
|
||||
// const vfloat4 sah = madd(lArea,vfloat4(vint4(lCount)),rArea*vfloat4(vint4(rCount)));
|
||||
const vbool4 mask = sah < vbestSAH;
|
||||
|
||||
@@ -48,8 +48,8 @@ namespace embree
|
||||
return expectedApproxHalfArea(geomBounds)*float(size());
|
||||
}
|
||||
|
||||
__forceinline float leafSAH(size_t block_shift) const {
|
||||
return expectedApproxHalfArea(geomBounds)*float((size()+(size_t(1)<<block_shift)-1) >> block_shift);
|
||||
__forceinline float leafSAH(size_t sahBlockSize) const {
|
||||
return expectedApproxHalfArea(geomBounds)*float((size()+sahBlockSize-1) / sahBlockSize);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -186,10 +186,10 @@ namespace embree
|
||||
}
|
||||
|
||||
/*! finds the best split */
|
||||
const Split find(const PrimInfoExtRange& set, const size_t logBlockSize)
|
||||
const Split find(const PrimInfoExtRange& set, const size_t sahBlockSize)
|
||||
{
|
||||
SplitInfo oinfo;
|
||||
const ObjectSplit object_split = object_find(set,logBlockSize,oinfo);
|
||||
const ObjectSplit object_split = object_find(set,sahBlockSize,oinfo);
|
||||
const float object_split_sah = object_split.splitSAH();
|
||||
|
||||
if (unlikely(set.has_ext_range()))
|
||||
@@ -200,7 +200,7 @@ namespace embree
|
||||
if (safeArea(overlap) >= SPATIAL_ASPLIT_AREA_THRESHOLD*safeArea(root_info.geomBounds) &&
|
||||
safeArea(overlap) >= SPATIAL_ASPLIT_OVERLAP_THRESHOLD*safeArea(set.geomBounds))
|
||||
{
|
||||
const SpatialSplit spatial_split = spatial_find(set, logBlockSize);
|
||||
const SpatialSplit spatial_split = spatial_find(set, sahBlockSize);
|
||||
const float spatial_split_sah = spatial_split.splitSAH();
|
||||
|
||||
/* valid spatial split, better SAH and number of splits do not exceed extended range */
|
||||
@@ -216,25 +216,25 @@ namespace embree
|
||||
}
|
||||
|
||||
/*! finds the best object split */
|
||||
__forceinline const ObjectSplit object_find(const PrimInfoExtRange& set, const size_t logBlockSize, SplitInfo &info)
|
||||
__forceinline const ObjectSplit object_find(const PrimInfoExtRange& set, const size_t sahBlockSize, SplitInfo &info)
|
||||
{
|
||||
if (set.size() < PARALLEL_THRESHOLD) return sequential_object_find(set,logBlockSize,info);
|
||||
else return parallel_object_find (set,logBlockSize,info);
|
||||
if (set.size() < PARALLEL_THRESHOLD) return sequential_object_find(set,sahBlockSize,info);
|
||||
else return parallel_object_find (set,sahBlockSize,info);
|
||||
}
|
||||
|
||||
/*! finds the best object split */
|
||||
__noinline const ObjectSplit sequential_object_find(const PrimInfoExtRange& set, const size_t logBlockSize, SplitInfo &info)
|
||||
__noinline const ObjectSplit sequential_object_find(const PrimInfoExtRange& set, const size_t sahBlockSize, SplitInfo &info)
|
||||
{
|
||||
ObjectBinner binner(empty);
|
||||
const BinMapping<OBJECT_BINS> mapping(set);
|
||||
binner.bin(prims0,set.begin(),set.end(),mapping);
|
||||
ObjectSplit s = binner.best(mapping,logBlockSize);
|
||||
ObjectSplit s = binner.best(mapping,sahBlockSize);
|
||||
binner.getSplitInfo(mapping, s, info);
|
||||
return s;
|
||||
}
|
||||
|
||||
/*! finds the best split */
|
||||
__noinline const ObjectSplit parallel_object_find(const PrimInfoExtRange& set, const size_t logBlockSize, SplitInfo &info)
|
||||
__noinline const ObjectSplit parallel_object_find(const PrimInfoExtRange& set, const size_t sahBlockSize, SplitInfo &info)
|
||||
{
|
||||
ObjectBinner binner(empty);
|
||||
const BinMapping<OBJECT_BINS> mapping(set);
|
||||
@@ -242,29 +242,29 @@ namespace embree
|
||||
binner = parallel_reduce(set.begin(),set.end(),PARALLEL_FIND_BLOCK_SIZE,binner,
|
||||
[&] (const range<size_t>& r) -> ObjectBinner { ObjectBinner binner(empty); binner.bin(prims0+r.begin(),r.size(),_mapping); return binner; },
|
||||
[&] (const ObjectBinner& b0, const ObjectBinner& b1) -> ObjectBinner { ObjectBinner r = b0; r.merge(b1,_mapping.size()); return r; });
|
||||
ObjectSplit s = binner.best(mapping,logBlockSize);
|
||||
ObjectSplit s = binner.best(mapping,sahBlockSize);
|
||||
binner.getSplitInfo(mapping, s, info);
|
||||
return s;
|
||||
}
|
||||
|
||||
/*! finds the best spatial split */
|
||||
__forceinline const SpatialSplit spatial_find(const PrimInfoExtRange& set, const size_t logBlockSize)
|
||||
__forceinline const SpatialSplit spatial_find(const PrimInfoExtRange& set, const size_t sahBlockSize)
|
||||
{
|
||||
if (set.size() < PARALLEL_THRESHOLD) return sequential_spatial_find(set, logBlockSize);
|
||||
else return parallel_spatial_find (set, logBlockSize);
|
||||
if (set.size() < PARALLEL_THRESHOLD) return sequential_spatial_find(set, sahBlockSize);
|
||||
else return parallel_spatial_find (set, sahBlockSize);
|
||||
}
|
||||
|
||||
/*! finds the best spatial split */
|
||||
__noinline const SpatialSplit sequential_spatial_find(const PrimInfoExtRange& set, const size_t logBlockSize)
|
||||
__noinline const SpatialSplit sequential_spatial_find(const PrimInfoExtRange& set, const size_t sahBlockSize)
|
||||
{
|
||||
SpatialBinner binner(empty);
|
||||
const SpatialBinMapping<SPATIAL_BINS> mapping(set);
|
||||
binner.bin2(splitterFactory,prims0,set.begin(),set.end(),mapping);
|
||||
/* todo: best spatial split not exeeding the extended range does not provide any benefit ?*/
|
||||
return binner.best(mapping,logBlockSize); //,set.ext_size());
|
||||
return binner.best(mapping,sahBlockSize); //,set.ext_size());
|
||||
}
|
||||
|
||||
__noinline const SpatialSplit parallel_spatial_find(const PrimInfoExtRange& set, const size_t logBlockSize)
|
||||
__noinline const SpatialSplit parallel_spatial_find(const PrimInfoExtRange& set, const size_t sahBlockSize)
|
||||
{
|
||||
SpatialBinner binner(empty);
|
||||
const SpatialBinMapping<SPATIAL_BINS> mapping(set);
|
||||
@@ -276,7 +276,7 @@ namespace embree
|
||||
return binner; },
|
||||
[&] (const SpatialBinner& b0, const SpatialBinner& b1) -> SpatialBinner { return SpatialBinner::reduce(b0,b1); });
|
||||
/* todo: best spatial split not exeeding the extended range does not provide any benefit ?*/
|
||||
return binner.best(mapping,logBlockSize); //,set.ext_size());
|
||||
return binner.best(mapping,sahBlockSize); //,set.ext_size());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace embree
|
||||
}
|
||||
|
||||
/*! finds the best split */
|
||||
const Split find(const range<size_t>& set, size_t logBlockSize)
|
||||
const Split find(const range<size_t>& set, size_t sahBlockSize)
|
||||
{
|
||||
Vec3fa axis0(0,0,1);
|
||||
uint64_t bestGeomPrimID = -1;
|
||||
@@ -132,8 +132,8 @@ namespace embree
|
||||
return Split(inf,axis0,axis1);
|
||||
|
||||
/*! calculate sah for the split */
|
||||
const size_t lblocks = (lnum+(1ull<<logBlockSize)-1ull) >> logBlockSize;
|
||||
const size_t rblocks = (rnum+(1ull<<logBlockSize)-1ull) >> logBlockSize;
|
||||
const size_t lblocks = (lnum+sahBlockSize-1ull) / sahBlockSize;
|
||||
const size_t rblocks = (rnum+sahBlockSize-1ull) / sahBlockSize;
|
||||
const float sah = madd(float(lblocks),halfArea(lbounds),float(rblocks)*halfArea(rbounds));
|
||||
return Split(sah,axis0,axis1);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "../common/primref_mb.h"
|
||||
#include "../../common/algorithms/parallel_filter.h"
|
||||
|
||||
#define MBLUR_TIME_SPLIT_THRESHOLD 1.25f
|
||||
|
||||
@@ -53,13 +54,13 @@ namespace embree
|
||||
}
|
||||
}
|
||||
|
||||
void bin(const PrimRefMB* prims, size_t begin, size_t end, BBox1f time_range, size_t numTimeSegments, const RecalculatePrimRef& recalculatePrimRef)
|
||||
void bin(const PrimRefMB* prims, size_t begin, size_t end, BBox1f time_range, const SetMB& set, const RecalculatePrimRef& recalculatePrimRef)
|
||||
{
|
||||
for (int b=0; b<BINS-1; b++)
|
||||
{
|
||||
const float t = float(b+1)/float(BINS);
|
||||
const float ct = lerp(time_range.lower,time_range.upper,t);
|
||||
const float center_time = roundf(ct * float(numTimeSegments)) / float(numTimeSegments);
|
||||
const float center_time = set.align_time(ct);
|
||||
if (center_time <= time_range.lower) continue;
|
||||
if (center_time >= time_range.upper) continue;
|
||||
const BBox1f dt0(time_range.lower,center_time);
|
||||
@@ -68,30 +69,40 @@ namespace embree
|
||||
/* find linear bounds for both time segments */
|
||||
for (size_t i=begin; i<end; i++)
|
||||
{
|
||||
const LBBox3fa bn0 = recalculatePrimRef.linearBounds(prims[i],dt0);
|
||||
const LBBox3fa bn1 = recalculatePrimRef.linearBounds(prims[i],dt1);
|
||||
if (prims[i].time_range_overlap(dt0))
|
||||
{
|
||||
const LBBox3fa bn0 = recalculatePrimRef.linearBounds(prims[i],dt0);
|
||||
#if MBLUR_BIN_LBBOX
|
||||
bounds0[b].extend(bn0);
|
||||
bounds1[b].extend(bn1);
|
||||
bounds0[b].extend(bn0);
|
||||
#else
|
||||
bounds0[b].extend(bn0.interpolate(0.5f));
|
||||
bounds1[b].extend(bn1.interpolate(0.5f));
|
||||
bounds0[b].extend(bn0.interpolate(0.5f));
|
||||
#endif
|
||||
count0[b] += getTimeSegmentRange(dt0,(float)prims[i].totalTimeSegments()).size();
|
||||
count1[b] += getTimeSegmentRange(dt1,(float)prims[i].totalTimeSegments()).size();
|
||||
count0[b] += prims[i].timeSegmentRange(dt0).size();
|
||||
}
|
||||
|
||||
if (prims[i].time_range_overlap(dt1))
|
||||
{
|
||||
const LBBox3fa bn1 = recalculatePrimRef.linearBounds(prims[i],dt1);
|
||||
#if MBLUR_BIN_LBBOX
|
||||
bounds1[b].extend(bn1);
|
||||
#else
|
||||
bounds1[b].extend(bn1.interpolate(0.5f));
|
||||
#endif
|
||||
count1[b] += prims[i].timeSegmentRange(dt1).size();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__forceinline void bin_parallel(const PrimRefMB* prims, size_t begin, size_t end, size_t blockSize, size_t parallelThreshold, BBox1f time_range, size_t numTimeSegments, const RecalculatePrimRef& recalculatePrimRef)
|
||||
__forceinline void bin_parallel(const PrimRefMB* prims, size_t begin, size_t end, size_t blockSize, size_t parallelThreshold, BBox1f time_range, const SetMB& set, const RecalculatePrimRef& recalculatePrimRef)
|
||||
{
|
||||
if (likely(end-begin < parallelThreshold)) {
|
||||
bin(prims,begin,end,time_range,numTimeSegments,recalculatePrimRef);
|
||||
bin(prims,begin,end,time_range,set,recalculatePrimRef);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto bin = [&](const range<size_t>& r) -> TemporalBinInfo {
|
||||
TemporalBinInfo binner(empty); binner.bin(prims, r.begin(), r.end(), time_range, numTimeSegments, recalculatePrimRef); return binner;
|
||||
TemporalBinInfo binner(empty); binner.bin(prims, r.begin(), r.end(), time_range, set, recalculatePrimRef); return binner;
|
||||
};
|
||||
*this = parallel_reduce(begin,end,blockSize,TemporalBinInfo(empty),bin,merge2);
|
||||
}
|
||||
@@ -113,7 +124,7 @@ namespace embree
|
||||
TemporalBinInfo r = a; r.merge(b); return r;
|
||||
}
|
||||
|
||||
Split best(int logBlockSize, BBox1f time_range, size_t numTimeSegments)
|
||||
Split best(int sahBlockSize, BBox1f time_range, const SetMB& set)
|
||||
{
|
||||
float bestSAH = inf;
|
||||
float bestPos = 0.0f;
|
||||
@@ -121,17 +132,19 @@ namespace embree
|
||||
{
|
||||
float t = float(b+1)/float(BINS);
|
||||
float ct = lerp(time_range.lower,time_range.upper,t);
|
||||
const float center_time = roundf(ct * float(numTimeSegments)) / float(numTimeSegments);
|
||||
const float center_time = set.align_time(ct);
|
||||
if (center_time <= time_range.lower) continue;
|
||||
if (center_time >= time_range.upper) continue;
|
||||
const BBox1f dt0(time_range.lower,center_time);
|
||||
const BBox1f dt1(center_time,time_range.upper);
|
||||
|
||||
/* calculate sah */
|
||||
const size_t lCount = (count0[b]+(size_t(1) << logBlockSize)-1) >> int(logBlockSize);
|
||||
const size_t rCount = (count1[b]+(size_t(1) << logBlockSize)-1) >> int(logBlockSize);
|
||||
const float sah0 = expectedApproxHalfArea(bounds0[b])*float(lCount)*dt0.size();
|
||||
const float sah1 = expectedApproxHalfArea(bounds1[b])*float(rCount)*dt1.size();
|
||||
const size_t lCount = (count0[b]+sahBlockSize-1) / sahBlockSize;
|
||||
const size_t rCount = (count1[b]+sahBlockSize-1) / sahBlockSize;
|
||||
float sah0 = expectedApproxHalfArea(bounds0[b])*float(lCount)*dt0.size();
|
||||
float sah1 = expectedApproxHalfArea(bounds1[b])*float(rCount)*dt1.size();
|
||||
if (unlikely(lCount == 0)) sah0 = 0.0f; // happens for initial splits when objects not alive over entire shutter time
|
||||
if (unlikely(rCount == 0)) sah1 = 0.0f;
|
||||
const float sah = sah0+sah1;
|
||||
if (sah < bestSAH) {
|
||||
bestSAH = sah;
|
||||
@@ -150,13 +163,12 @@ namespace embree
|
||||
};
|
||||
|
||||
/*! finds the best split */
|
||||
const Split find(const SetMB& set, const size_t logBlockSize)
|
||||
const Split find(const SetMB& set, const size_t sahBlockSize)
|
||||
{
|
||||
assert(set.object_range.size() > 0);
|
||||
unsigned numTimeSegments = unsigned(set.max_num_time_segments);
|
||||
assert(set.size() > 0);
|
||||
TemporalBinInfo binner(empty);
|
||||
binner.bin_parallel(set.prims->data(),set.object_range.begin(),set.object_range.end(),PARALLEL_FIND_BLOCK_SIZE,PARALLEL_THRESHOLD,set.time_range,numTimeSegments,recalculatePrimRef);
|
||||
Split tsplit = binner.best((int)logBlockSize,set.time_range,numTimeSegments);
|
||||
binner.bin_parallel(set.prims->data(),set.begin(),set.end(),PARALLEL_FIND_BLOCK_SIZE,PARALLEL_THRESHOLD,set.time_range,set,recalculatePrimRef);
|
||||
Split tsplit = binner.best((int)sahBlockSize,set.time_range,set);
|
||||
if (!tsplit.valid()) tsplit.data = Split::SPLIT_FALLBACK; // use fallback split
|
||||
return tsplit;
|
||||
}
|
||||
@@ -169,35 +181,60 @@ namespace embree
|
||||
mvector<PrimRefMB>& prims = *set.prims;
|
||||
|
||||
/* calculate primrefs for first time range */
|
||||
std::unique_ptr<mvector<PrimRefMB>> new_vector(new mvector<PrimRefMB>(device, set.object_range.size()));
|
||||
std::unique_ptr<mvector<PrimRefMB>> new_vector(new mvector<PrimRefMB>(device, set.size()));
|
||||
PrimRefVector lprims = new_vector.get();
|
||||
|
||||
auto reduction_func0 = [&] ( const range<size_t>& r) {
|
||||
|
||||
auto reduction_func0 = [&] (const range<size_t>& r) {
|
||||
PrimInfoMB pinfo = empty;
|
||||
for (size_t i=r.begin(); i<r.end(); i++)
|
||||
{
|
||||
const PrimRefMB& prim = recalculatePrimRef(prims[i],time_range0);
|
||||
(*lprims)[i-set.object_range.begin()] = prim;
|
||||
pinfo.add_primref(prim);
|
||||
if (likely(prims[i].time_range_overlap(time_range0)))
|
||||
{
|
||||
const PrimRefMB& prim = recalculatePrimRef(prims[i],time_range0);
|
||||
(*lprims)[i-set.begin()] = prim;
|
||||
pinfo.add_primref(prim);
|
||||
}
|
||||
else
|
||||
{
|
||||
(*lprims)[i-set.begin()] = prims[i];
|
||||
}
|
||||
}
|
||||
return pinfo;
|
||||
};
|
||||
const PrimInfoMB linfo = parallel_reduce(set.object_range,PARALLEL_PARTITION_BLOCK_SIZE,PARALLEL_THRESHOLD,PrimInfoMB(empty),reduction_func0,PrimInfoMB::merge2);
|
||||
PrimInfoMB linfo = parallel_reduce(set.object_range,PARALLEL_PARTITION_BLOCK_SIZE,PARALLEL_THRESHOLD,PrimInfoMB(empty),reduction_func0,PrimInfoMB::merge2);
|
||||
|
||||
/* primrefs for first time range are in lprims[0 .. set.size()) */
|
||||
/* some primitives may need to be filtered out */
|
||||
if (linfo.size() != set.size())
|
||||
linfo.object_range._end = parallel_filter(lprims->data(), size_t(0), set.size(), size_t(1024),
|
||||
[&](const PrimRefMB& prim) { return prim.time_range_overlap(time_range0); });
|
||||
|
||||
lset = SetMB(linfo,lprims,time_range0);
|
||||
|
||||
/* calculate primrefs for second time range */
|
||||
auto reduction_func1 = [&] ( const range<size_t>& r) {
|
||||
auto reduction_func1 = [&] (const range<size_t>& r) {
|
||||
PrimInfoMB pinfo = empty;
|
||||
for (size_t i=r.begin(); i<r.end(); i++)
|
||||
{
|
||||
const PrimRefMB& prim = recalculatePrimRef(prims[i],time_range1);
|
||||
prims[i] = prim;
|
||||
pinfo.add_primref(prim);
|
||||
if (likely(prims[i].time_range_overlap(time_range1)))
|
||||
{
|
||||
const PrimRefMB& prim = recalculatePrimRef(prims[i],time_range1);
|
||||
prims[i] = prim;
|
||||
pinfo.add_primref(prim);
|
||||
}
|
||||
}
|
||||
return pinfo;
|
||||
};
|
||||
const PrimInfoMB rinfo = parallel_reduce(set.object_range,PARALLEL_PARTITION_BLOCK_SIZE,PARALLEL_THRESHOLD,PrimInfoMB(empty),reduction_func1,PrimInfoMB::merge2);
|
||||
rset = SetMB(rinfo,&prims,set.object_range,time_range1);
|
||||
PrimInfoMB rinfo = parallel_reduce(set.object_range,PARALLEL_PARTITION_BLOCK_SIZE,PARALLEL_THRESHOLD,PrimInfoMB(empty),reduction_func1,PrimInfoMB::merge2);
|
||||
rinfo.object_range = range<size_t>(set.begin(), set.begin() + rinfo.size());
|
||||
|
||||
/* primrefs for second time range are in prims[set.begin() .. set.end()) */
|
||||
/* some primitives may need to be filtered out */
|
||||
if (rinfo.size() != set.size())
|
||||
rinfo.object_range._end = parallel_filter(prims.data(), set.begin(), set.end(), size_t(1024),
|
||||
[&](const PrimRefMB& prim) { return prim.time_range_overlap(time_range1); });
|
||||
|
||||
rset = SetMB(rinfo,&prims,time_range1);
|
||||
|
||||
return new_vector;
|
||||
}
|
||||
|
||||
+40
-16
@@ -145,8 +145,8 @@ namespace embree
|
||||
//return halfArea(geomBounds)*blocks(num);
|
||||
}
|
||||
|
||||
__forceinline float leafSAH(size_t block_shift) const {
|
||||
return expectedApproxHalfArea(geomBounds)*float((size()+(size_t(1)<<block_shift)-1) >> block_shift);
|
||||
__forceinline float leafSAH(size_t sahBlockSize) const {
|
||||
return expectedApproxHalfArea(geomBounds)*float((size()+sahBlockSize-1) / sahBlockSize);
|
||||
//return halfArea(geomBounds)*float((num+3) >> 2);
|
||||
//return halfArea(geomBounds)*blocks(num);
|
||||
}
|
||||
@@ -175,32 +175,48 @@ namespace embree
|
||||
}
|
||||
|
||||
__forceinline PrimInfoMBT (EmptyTy)
|
||||
: CentGeom<BBox>(empty), object_range(0,0), num_time_segments(0), max_num_time_segments(0), time_range(0.0f,1.0f) {}
|
||||
: CentGeom<BBox>(empty), object_range(0,0), num_time_segments(0), max_num_time_segments(0), max_time_range(0.0f,1.0f), time_range(1.0f,0.0f) {}
|
||||
|
||||
__forceinline PrimInfoMBT (size_t begin, size_t end)
|
||||
: CentGeom<BBox>(empty), object_range(begin,end), num_time_segments(0), max_num_time_segments(0), time_range(0.0f,1.0f) {}
|
||||
: CentGeom<BBox>(empty), object_range(begin,end), num_time_segments(0), max_num_time_segments(0), max_time_range(0.0f,1.0f), time_range(1.0f,0.0f) {}
|
||||
|
||||
template<typename PrimRef>
|
||||
__forceinline void add_primref(const PrimRef& prim)
|
||||
{
|
||||
CentGeom<BBox>::extend_primref(prim);
|
||||
time_range.extend(prim.time_range);
|
||||
object_range._end++;
|
||||
num_time_segments += prim.size();
|
||||
max_num_time_segments = max(max_num_time_segments,size_t(prim.totalTimeSegments()));
|
||||
if (max_num_time_segments < prim.totalTimeSegments()) {
|
||||
max_num_time_segments = prim.totalTimeSegments();
|
||||
max_time_range = prim.time_range;
|
||||
}
|
||||
}
|
||||
|
||||
__forceinline void merge(const PrimInfoMBT& other)
|
||||
{
|
||||
CentGeom<BBox>::merge(other);
|
||||
time_range.extend(other.time_range);
|
||||
object_range._begin += other.object_range.begin();
|
||||
object_range._end += other.object_range.end();
|
||||
object_range._end += other.object_range.end();
|
||||
num_time_segments += other.num_time_segments;
|
||||
max_num_time_segments = max(max_num_time_segments,other.max_num_time_segments);
|
||||
if (max_num_time_segments < other.max_num_time_segments) {
|
||||
max_num_time_segments = other.max_num_time_segments;
|
||||
max_time_range = other.max_time_range;
|
||||
}
|
||||
}
|
||||
|
||||
static __forceinline const PrimInfoMBT merge2(const PrimInfoMBT& a, const PrimInfoMBT& b) {
|
||||
PrimInfoMBT r = a; r.merge(b); return r;
|
||||
}
|
||||
|
||||
__forceinline size_t begin() const {
|
||||
return object_range.begin();
|
||||
}
|
||||
|
||||
__forceinline size_t end() const {
|
||||
return object_range.end();
|
||||
}
|
||||
|
||||
/*! returns the number of primitives */
|
||||
__forceinline size_t size() const {
|
||||
@@ -215,8 +231,16 @@ namespace embree
|
||||
return time_range.size()*expectedApproxHalfArea(geomBounds)*float(num_time_segments);
|
||||
}
|
||||
|
||||
__forceinline float leafSAH(size_t block_shift) const {
|
||||
return time_range.size()*expectedApproxHalfArea(geomBounds)*float((num_time_segments+(size_t(1)<<block_shift)-1) >> block_shift);
|
||||
__forceinline float leafSAH(size_t sahBlockSize) const {
|
||||
return time_range.size()*expectedApproxHalfArea(geomBounds)*float((num_time_segments+sahBlockSize-1) / sahBlockSize);
|
||||
}
|
||||
|
||||
__forceinline float align_time(float ct) const
|
||||
{
|
||||
//return roundf(ct * float(numTimeSegments)) / float(numTimeSegments);
|
||||
float t0 = (ct-max_time_range.lower)/max_time_range.size();
|
||||
float t1 = roundf(t0 * float(max_num_time_segments)) / float(max_num_time_segments);
|
||||
return t1*max_time_range.size()+max_time_range.lower;
|
||||
}
|
||||
|
||||
/*! stream output */
|
||||
@@ -235,7 +259,8 @@ namespace embree
|
||||
range<size_t> object_range; //!< primitive range
|
||||
size_t num_time_segments; //!< total number of time segments of all added primrefs
|
||||
size_t max_num_time_segments; //!< maximum number of time segments of a primitive
|
||||
BBox1f time_range;
|
||||
BBox1f max_time_range; //!< time range of primitive with max_num_time_segments
|
||||
BBox1f time_range; //!< merged time range of primitives when merging prims, or additionally clipped with build time range when used in SetMB
|
||||
};
|
||||
|
||||
typedef PrimInfoMBT<typename PrimRefMB::BBox> PrimInfoMB;
|
||||
@@ -250,21 +275,20 @@ namespace embree
|
||||
|
||||
__forceinline SetMB() {}
|
||||
|
||||
__forceinline SetMB(const PrimInfoMB& pinfo_i, PrimRefVector prims)
|
||||
: PrimInfoMB(pinfo_i), prims(prims) {}
|
||||
__forceinline SetMB(const PrimInfoMB& pinfo_i, PrimRefVector prims)
|
||||
: PrimInfoMB(pinfo_i), prims(prims) {}
|
||||
|
||||
__forceinline SetMB(const PrimInfoMB& pinfo_i, PrimRefVector prims, range<size_t> object_range_in, BBox1f time_range_in) // FIXME: remove
|
||||
__forceinline SetMB(const PrimInfoMB& pinfo_i, PrimRefVector prims, range<size_t> object_range_in, BBox1f time_range_in)
|
||||
: PrimInfoMB(pinfo_i), prims(prims)
|
||||
{
|
||||
object_range = object_range_in;
|
||||
time_range = time_range_in;
|
||||
time_range = intersect(time_range,time_range_in);
|
||||
}
|
||||
|
||||
__forceinline SetMB(const PrimInfoMB& pinfo_i, PrimRefVector prims, BBox1f time_range_in)
|
||||
: PrimInfoMB(pinfo_i), prims(prims)
|
||||
{
|
||||
object_range = range<size_t>(0,prims->size());
|
||||
time_range = time_range_in;
|
||||
time_range = intersect(time_range,time_range_in);
|
||||
}
|
||||
|
||||
void deterministic_order() const
|
||||
|
||||
@@ -110,6 +110,8 @@ namespace embree
|
||||
return mesh->createPrimRefMBArray(prims,t0t1,r,base.size());
|
||||
}, [](const PrimInfoMB& a, const PrimInfoMB& b) -> PrimInfoMB { return PrimInfoMB::merge2(a,b); });
|
||||
}
|
||||
|
||||
/* the BVH starts with that time range, even though primitives might have smaller/larger time range */
|
||||
pinfo.time_range = t0t1;
|
||||
return pinfo;
|
||||
}
|
||||
|
||||
@@ -46,12 +46,12 @@ namespace embree
|
||||
/* if we use the primrefarray for allocations we have to take it back from the BVH */
|
||||
if (settings.finished_range_threshold != size_t(inf))
|
||||
bvh->alloc.unshare(prims);
|
||||
|
||||
|
||||
/* fast path for empty BVH */
|
||||
const size_t numPrimitives = scene->getNumPrimitives<CurveGeometry,false>();
|
||||
if (numPrimitives == 0) {
|
||||
bvh->clear();
|
||||
prims.clear();
|
||||
bvh->set(BVH::emptyNode,empty,0);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ namespace embree
|
||||
/* builder settings */
|
||||
settings.branchingFactor = N;
|
||||
settings.maxDepth = BVH::maxBuildDepthLeaf;
|
||||
settings.logBlockSize = bsf(CurvePrimitive::max_size());
|
||||
settings.sahBlockSize = CurvePrimitive::max_size();
|
||||
settings.minLeafSize = CurvePrimitive::max_size();
|
||||
settings.maxLeafSize = CurvePrimitive::max_size();
|
||||
settings.finished_range_threshold = numPrimitives/1000;
|
||||
@@ -109,6 +109,7 @@ namespace embree
|
||||
scene,prims.data(),pinfo,settings);
|
||||
|
||||
bvh->set(root,LBBox3fa(pinfo.geomBounds),pinfo.size());
|
||||
|
||||
/* if we allocated using the primrefarray we have to keep it alive */
|
||||
if (settings.finished_range_threshold != size_t(inf))
|
||||
bvh->alloc.share(prims);
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace embree
|
||||
BVHBuilderHairMSMBlur::Settings settings;
|
||||
settings.branchingFactor = N;
|
||||
settings.maxDepth = BVH::maxBuildDepthLeaf;
|
||||
settings.logBlockSize = bsf(CurvePrimitive::max_size());
|
||||
settings.sahBlockSize = CurvePrimitive::max_size();
|
||||
settings.minLeafSize = CurvePrimitive::max_size();
|
||||
settings.maxLeafSize = CurvePrimitive::max_size();
|
||||
|
||||
@@ -76,7 +76,7 @@ namespace embree
|
||||
if (prims.size() == 0)
|
||||
return NodeRecordMB4D(BVH::emptyNode,empty,empty);
|
||||
|
||||
const unsigned int geomID0 = (*prims.prims)[prims.object_range.begin()].geomID();
|
||||
const unsigned int geomID0 = (*prims.prims)[prims.begin()].geomID();
|
||||
if (scene->get(geomID0)->getCurveBasis() == Geometry::GTY_BASIS_LINEAR)
|
||||
return LinePrimitive::createLeafMB(bvh,prims,alloc);
|
||||
else
|
||||
|
||||
@@ -44,6 +44,7 @@ namespace embree
|
||||
namespace isa
|
||||
{
|
||||
|
||||
#if 0
|
||||
template<int N, typename Primitive>
|
||||
struct CreateMBlurLeaf
|
||||
{
|
||||
@@ -57,6 +58,7 @@ namespace embree
|
||||
{
|
||||
size_t items = Primitive::blocks(set.size());
|
||||
size_t start = set.begin();
|
||||
for (size_t i=start; i<end; i++) assert((*current.prims.prims)[start].geomID() == (*current.prims.prims)[i].geomID()); // assert that all geomIDs are identical
|
||||
Primitive* accel = (Primitive*) alloc.malloc1(items*sizeof(Primitive),BVH::byteAlignment);
|
||||
NodeRef node = bvh->encodeLeaf((char*)accel,items);
|
||||
|
||||
@@ -71,7 +73,7 @@ namespace embree
|
||||
PrimRef* prims;
|
||||
size_t time;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
template<int N, typename Mesh, typename Primitive>
|
||||
struct CreateMSMBlurLeaf
|
||||
@@ -84,13 +86,15 @@ namespace embree
|
||||
|
||||
__forceinline const NodeRecordMB4D operator() (const BVHBuilderMSMBlur::BuildRecord& current, const FastAllocator::CachedAllocator& alloc) const
|
||||
{
|
||||
size_t items = Primitive::blocks(current.prims.object_range.size());
|
||||
size_t start = current.prims.object_range.begin();
|
||||
size_t items = Primitive::blocks(current.prims.size());
|
||||
size_t start = current.prims.begin();
|
||||
size_t end = current.prims.end();
|
||||
for (size_t i=start; i<end; i++) assert((*current.prims.prims)[start].geomID() == (*current.prims.prims)[i].geomID()); // assert that all geomIDs are identical
|
||||
Primitive* accel = (Primitive*) alloc.malloc1(items*sizeof(Primitive),BVH::byteNodeAlignment);
|
||||
NodeRef node = bvh->encodeLeaf((char*)accel,items);
|
||||
LBBox3fa allBounds = empty;
|
||||
for (size_t i=0; i<items; i++)
|
||||
allBounds.extend(accel[i].fillMB(current.prims.prims->data(), start, current.prims.object_range.end(), bvh->scene, current.prims.time_range));
|
||||
allBounds.extend(accel[i].fillMB(current.prims.prims->data(), start, current.prims.end(), bvh->scene, current.prims.time_range));
|
||||
return NodeRecordMB4D(node,allBounds,current.prims.time_range);
|
||||
}
|
||||
|
||||
@@ -128,12 +132,12 @@ namespace embree
|
||||
profile(2,PROFILE_RUNS,numPrimitives,[&] (ProfileTimer& timer) {
|
||||
#endif
|
||||
|
||||
const size_t numTimeSteps = scene->getNumTimeSteps<Mesh,true>();
|
||||
const size_t numTimeSegments = numTimeSteps-1; assert(numTimeSteps > 1);
|
||||
//const size_t numTimeSteps = scene->getNumTimeSteps<Mesh,true>();
|
||||
//const size_t numTimeSegments = numTimeSteps-1; assert(numTimeSteps > 1);
|
||||
|
||||
if (numTimeSegments == 1)
|
||||
/*if (numTimeSegments == 1)
|
||||
buildSingleSegment(numPrimitives);
|
||||
else
|
||||
else*/
|
||||
buildMultiSegment(numPrimitives);
|
||||
|
||||
#if PROFILE
|
||||
@@ -146,6 +150,7 @@ namespace embree
|
||||
bvh->postBuild(t0);
|
||||
}
|
||||
|
||||
#if 0 // No longer compatible when time_ranges are present for geometries. Would have to create temporal nodes sometimes, and put only a single geometry into leaf.
|
||||
void buildSingleSegment(size_t numPrimitives)
|
||||
{
|
||||
/* create primref array */
|
||||
@@ -162,7 +167,7 @@ namespace embree
|
||||
GeneralBVHBuilder::Settings settings;
|
||||
settings.branchingFactor = N;
|
||||
settings.maxDepth = BVH::maxBuildDepthLeaf;
|
||||
settings.logBlockSize = bsr(sahBlockSize);
|
||||
settings.sahBlockSize = sahBlockSize;
|
||||
settings.minLeafSize = minLeafSize;
|
||||
settings.maxLeafSize = maxLeafSize;
|
||||
settings.travCost = travCost;
|
||||
@@ -177,14 +182,16 @@ namespace embree
|
||||
|
||||
bvh->set(root.ref,root.lbounds,pinfo.size());
|
||||
}
|
||||
#endif
|
||||
|
||||
void buildMultiSegment(size_t numPrimitives)
|
||||
{
|
||||
/* create primref array */
|
||||
mvector<PrimRefMB> prims(scene->device,numPrimitives);
|
||||
PrimInfoMB pinfo = createPrimRefArrayMSMBlur(scene,Mesh::geom_type,prims,bvh->scene->progressInterface);
|
||||
|
||||
/* early out if no valid primitives */
|
||||
if (pinfo.object_range.size() == 0) { bvh->clear(); return; }
|
||||
if (pinfo.size() == 0) { bvh->clear(); return; }
|
||||
|
||||
/* estimate acceleration structure size */
|
||||
const size_t node_bytes = pinfo.num_time_segments*sizeof(AlignedNodeMB)/(4*N);
|
||||
@@ -195,7 +202,7 @@ namespace embree
|
||||
BVHBuilderMSMBlur::Settings settings;
|
||||
settings.branchingFactor = N;
|
||||
settings.maxDepth = BVH::maxDepth;
|
||||
settings.logBlockSize = bsr(sahBlockSize);
|
||||
settings.sahBlockSize = sahBlockSize;
|
||||
settings.minLeafSize = minLeafSize;
|
||||
settings.maxLeafSize = maxLeafSize;
|
||||
settings.travCost = travCost;
|
||||
@@ -245,8 +252,8 @@ namespace embree
|
||||
const size_t y = subgrid.y();
|
||||
const LBBox3fa lbounds = mesh->linearBounds(mesh->grid(primID),x,y,time_range);
|
||||
const unsigned num_time_segments = mesh->numTimeSegments();
|
||||
const range<int> tbounds = getTimeSegmentRange(time_range, (float)num_time_segments);
|
||||
return PrimRefMB (lbounds, tbounds.size(), num_time_segments, geomID, buildID);
|
||||
const range<int> tbounds = mesh->timeSegmentRange(time_range);
|
||||
return PrimRefMB (lbounds, tbounds.size(), mesh->time_range, num_time_segments, geomID, buildID);
|
||||
}
|
||||
|
||||
__forceinline LBBox3fa linearBounds(const PrimRefMB& prim, const BBox1f time_range) const {
|
||||
@@ -262,7 +269,6 @@ namespace embree
|
||||
|
||||
};
|
||||
|
||||
|
||||
template<int N>
|
||||
struct CreateMSMBlurLeafGrid
|
||||
{
|
||||
@@ -274,8 +280,8 @@ namespace embree
|
||||
|
||||
__forceinline const NodeRecordMB4D operator() (const BVHBuilderMSMBlur::BuildRecord& current, const FastAllocator::CachedAllocator& alloc) const
|
||||
{
|
||||
const size_t items = current.prims.object_range.size();
|
||||
const size_t start = current.prims.object_range.begin();
|
||||
const size_t items = current.prims.size();
|
||||
const size_t start = current.prims.begin();
|
||||
|
||||
const PrimRefMB* prims = current.prims.prims->data();
|
||||
/* collect all subsets with unique geomIDs */
|
||||
@@ -336,6 +342,7 @@ namespace embree
|
||||
const SubGridBuildData * const sgrids;
|
||||
};
|
||||
|
||||
#if 0
|
||||
template<int N>
|
||||
struct CreateLeafGridMB
|
||||
{
|
||||
@@ -410,7 +417,7 @@ namespace embree
|
||||
BVH* bvh;
|
||||
const SubGridBuildData * const sgrids;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* Motion blur BVH with 4D nodes and internal time splits */
|
||||
@@ -503,7 +510,7 @@ namespace embree
|
||||
PrimInfoMB pinfoMB(empty);
|
||||
for (size_t j=r.begin(); j<r.end(); j++)
|
||||
{
|
||||
if (!mesh->valid(j, getTimeSegmentRange(t0t1, mesh->fnumTimeSegments))) continue;
|
||||
if (!mesh->valid(j, mesh->timeSegmentRange(t0t1))) continue;
|
||||
LBBox3fa bounds(empty);
|
||||
PrimInfoMB gridMB(0,mesh->getNumSubGrids(j));
|
||||
pinfoMB.merge(gridMB);
|
||||
@@ -524,13 +531,13 @@ namespace embree
|
||||
PrimInfoMB pinfoMB(empty);
|
||||
for (size_t j=r.begin(); j<r.end(); j++)
|
||||
{
|
||||
if (!mesh->valid(j, getTimeSegmentRange(t0t1, mesh->fnumTimeSegments))) continue;
|
||||
if (!mesh->valid(j, mesh->timeSegmentRange(t0t1))) continue;
|
||||
const GridMesh::Grid &g = mesh->grid(j);
|
||||
|
||||
for (unsigned int y=0; y<g.resY-1u; y+=2)
|
||||
for (unsigned int x=0; x<g.resX-1u; x+=2)
|
||||
{
|
||||
const PrimRefMB prim(mesh->linearBounds(g,x,y,t0t1),mesh->numTimeSegments(),mesh->numTimeSegments(),mesh->geomID,unsigned(p_index));
|
||||
const PrimRefMB prim(mesh->linearBounds(g,x,y,t0t1),mesh->numTimeSegments(),mesh->time_range,mesh->numTimeSegments(),mesh->geomID,unsigned(p_index));
|
||||
pinfoMB.add_primref(prim);
|
||||
sgrids[p_index] = SubGridBuildData(x | g.get3x3FlagsX(x), y | g.get3x3FlagsY(y), unsigned(j));
|
||||
prims[p_index++] = prim;
|
||||
@@ -551,12 +558,12 @@ namespace embree
|
||||
|
||||
double t0 = bvh->preBuild(TOSTRING(isa) "::BVH" + toString(N) + "BuilderMBlurSAHGrid");
|
||||
|
||||
const size_t numTimeSteps = scene->getNumTimeSteps<GridMesh,true>();
|
||||
const size_t numTimeSegments = numTimeSteps-1; assert(numTimeSteps > 1);
|
||||
if (numTimeSegments == 1)
|
||||
buildSingleSegment(numPrimitives);
|
||||
else
|
||||
buildMultiSegment(numPrimitives);
|
||||
//const size_t numTimeSteps = scene->getNumTimeSteps<GridMesh,true>();
|
||||
//const size_t numTimeSegments = numTimeSteps-1; assert(numTimeSteps > 1);
|
||||
//if (numTimeSegments == 1)
|
||||
// buildSingleSegment(numPrimitives);
|
||||
//else
|
||||
buildMultiSegment(numPrimitives);
|
||||
|
||||
/* clear temporary data for static geometry */
|
||||
if (scene->isStaticAccel()) bvh->shrink();
|
||||
@@ -564,6 +571,7 @@ namespace embree
|
||||
bvh->postBuild(t0);
|
||||
}
|
||||
|
||||
#if 0
|
||||
void buildSingleSegment(size_t numPrimitives)
|
||||
{
|
||||
/* create primref array */
|
||||
@@ -582,7 +590,7 @@ namespace embree
|
||||
GeneralBVHBuilder::Settings settings;
|
||||
settings.branchingFactor = N;
|
||||
settings.maxDepth = BVH::maxBuildDepthLeaf;
|
||||
settings.logBlockSize = bsr(sahBlockSize);
|
||||
settings.sahBlockSize = sahBlockSize;
|
||||
settings.minLeafSize = minLeafSize;
|
||||
settings.maxLeafSize = maxLeafSize;
|
||||
settings.travCost = travCost;
|
||||
@@ -600,7 +608,8 @@ namespace embree
|
||||
|
||||
bvh->set(root.ref,root.lbounds,pinfo.size());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void buildMultiSegment(size_t numPrimitives)
|
||||
{
|
||||
/* create primref array */
|
||||
@@ -608,7 +617,7 @@ namespace embree
|
||||
PrimInfoMB pinfo = createPrimRefArrayMSMBlurGrid(scene,prims,bvh->scene->progressInterface);
|
||||
|
||||
/* early out if no valid primitives */
|
||||
if (pinfo.object_range.size() == 0) { bvh->clear(); return; }
|
||||
if (pinfo.size() == 0) { bvh->clear(); return; }
|
||||
|
||||
|
||||
|
||||
@@ -626,7 +635,7 @@ namespace embree
|
||||
BVHBuilderMSMBlur::Settings settings;
|
||||
settings.branchingFactor = N;
|
||||
settings.maxDepth = BVH::maxDepth;
|
||||
settings.logBlockSize = bsr(sahBlockSize);
|
||||
settings.sahBlockSize = sahBlockSize;
|
||||
settings.minLeafSize = minLeafSize;
|
||||
settings.maxLeafSize = maxLeafSize;
|
||||
settings.travCost = travCost;
|
||||
|
||||
@@ -171,7 +171,7 @@ namespace embree
|
||||
|
||||
/* settings for BVH build */
|
||||
GeneralBVHBuilder::Settings settings;
|
||||
settings.logBlockSize = bsr(N);
|
||||
settings.sahBlockSize = N;
|
||||
settings.minLeafSize = 1;
|
||||
settings.maxLeafSize = 1;
|
||||
settings.travCost = 1.0f;
|
||||
@@ -208,19 +208,19 @@ namespace embree
|
||||
__forceinline SubdivRecalculatePrimRef (mvector<BBox3fa>& bounds, SubdivPatch1* patches)
|
||||
: bounds(bounds), patches(patches) {}
|
||||
|
||||
__forceinline PrimRefMB operator() (const size_t patchIndexMB, const unsigned num_time_segments, const BBox1f time_range) const
|
||||
__forceinline PrimRefMB operator() (const size_t patchIndexMB, const BBox1f prim_time_range, const unsigned prim_num_time_segments, const BBox1f time_range) const
|
||||
{
|
||||
const LBBox3fa lbounds = LBBox3fa([&] (size_t itime) { return bounds[patchIndexMB+itime]; }, time_range, (float)num_time_segments);
|
||||
const range<int> tbounds = getTimeSegmentRange(time_range, (float)num_time_segments);
|
||||
return PrimRefMB (lbounds, tbounds.size(), num_time_segments, patchIndexMB);
|
||||
const LBBox3fa lbounds = LBBox3fa([&] (size_t itime) { return bounds[patchIndexMB+itime]; }, time_range, prim_time_range, (float)prim_num_time_segments);
|
||||
const range<int> tbounds = getTimeSegmentRange(time_range, prim_time_range, (float)prim_num_time_segments);
|
||||
return PrimRefMB (empty, lbounds, tbounds.size(), prim_time_range, prim_num_time_segments, patchIndexMB);
|
||||
}
|
||||
|
||||
__forceinline PrimRefMB operator() (const PrimRefMB& prim, const BBox1f time_range) const {
|
||||
return operator()(prim.ID(),prim.totalTimeSegments(),time_range);
|
||||
return operator()(prim.ID(),prim.time_range,prim.totalTimeSegments(),time_range);
|
||||
}
|
||||
|
||||
__forceinline LBBox3fa linearBounds(const PrimRefMB& prim, const BBox1f time_range) const {
|
||||
return LBBox3fa([&] (size_t itime) { return bounds[prim.ID()+itime]; }, time_range, (float)prim.totalTimeSegments());
|
||||
return LBBox3fa([&] (size_t itime) { return bounds[prim.ID()+itime]; }, time_range, prim.time_range, (float)prim.totalTimeSegments());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -263,10 +263,10 @@ namespace embree
|
||||
sMB += count * mesh->numTimeSteps;
|
||||
}
|
||||
return PrimInfoMB(s,sMB);
|
||||
}, [](const PrimInfoMB& a, const PrimInfoMB& b) -> PrimInfoMB { return PrimInfoMB(a.object_range.begin()+b.object_range.begin(),a.object_range.end()+b.object_range.end()); });
|
||||
}, [](const PrimInfoMB& a, const PrimInfoMB& b) -> PrimInfoMB { return PrimInfoMB(a.begin()+b.begin(),a.end()+b.end()); });
|
||||
|
||||
numSubPatches = pinfo.object_range.begin();
|
||||
numSubPatchesMB = pinfo.object_range.end();
|
||||
numSubPatches = pinfo.begin();
|
||||
numSubPatchesMB = pinfo.end();
|
||||
}
|
||||
|
||||
void rebuild(size_t numPrimitives, ParallelForForPrefixSumState<PrimInfoMB>& pstate)
|
||||
@@ -288,8 +288,8 @@ namespace embree
|
||||
BVH_Allocator alloc(bvh);
|
||||
patch_eval_subdivision(mesh->getHalfEdge(0,f),[&](const Vec2f uv[4], const int subdiv[4], const float edge_level[4], int subPatch)
|
||||
{
|
||||
const size_t patchIndex = base.object_range.begin()+s;
|
||||
const size_t patchIndexMB = base.object_range.end()+sMB;
|
||||
const size_t patchIndex = base.begin()+s;
|
||||
const size_t patchIndexMB = base.end()+sMB;
|
||||
assert(patchIndex < numPrimitives);
|
||||
|
||||
for (size_t t=0; t<mesh->numTimeSteps; t++)
|
||||
@@ -299,7 +299,7 @@ namespace embree
|
||||
}
|
||||
SubdivPatch1Base& patch0 = subdiv_patches[patchIndexMB];
|
||||
patch0.root_ref.set((int64_t) GridSOA::create(&patch0,(unsigned)mesh->numTimeSteps,scene,alloc,&bounds[patchIndexMB]));
|
||||
primsMB[patchIndex] = recalculatePrimRef(patchIndexMB,mesh->numTimeSegments(),BBox1f(0.0f,1.0f));
|
||||
primsMB[patchIndex] = recalculatePrimRef(patchIndexMB,mesh->time_range,mesh->numTimeSegments(),BBox1f(0.0f,1.0f));
|
||||
s++;
|
||||
sMB += mesh->numTimeSteps;
|
||||
pinfo.add_primref(primsMB[patchIndex]);
|
||||
@@ -309,14 +309,14 @@ namespace embree
|
||||
pinfo.object_range._end = sMB;
|
||||
return pinfo;
|
||||
}, [](const PrimInfoMB& a, const PrimInfoMB& b) -> PrimInfoMB { return PrimInfoMB::merge2(a,b); });
|
||||
pinfo.object_range._end = pinfo.object_range.begin();
|
||||
pinfo.object_range._end = pinfo.begin();
|
||||
pinfo.object_range._begin = 0;
|
||||
|
||||
auto createLeafFunc = [&] (const BVHBuilderMSMBlur::BuildRecord& current, const Allocator& alloc) -> NodeRecordMB4D {
|
||||
mvector<PrimRefMB>& prims = *current.prims.prims;
|
||||
size_t items MAYBE_UNUSED = current.prims.size();
|
||||
assert(items == 1);
|
||||
const size_t patchIndexMB = prims[current.prims.object_range.begin()].ID();
|
||||
const size_t patchIndexMB = prims[current.prims.begin()].ID();
|
||||
SubdivPatch1Base& patch = subdiv_patches[patchIndexMB+0];
|
||||
NodeRef node = bvh->encodeLeaf((char*)&patch,1);
|
||||
size_t patchNumTimeSteps = scene->get<SubdivMesh>(patch.geomID())->numTimeSteps;
|
||||
@@ -328,7 +328,7 @@ namespace embree
|
||||
BVHBuilderMSMBlur::Settings settings;
|
||||
settings.branchingFactor = N;
|
||||
settings.maxDepth = BVH::maxDepth;
|
||||
settings.logBlockSize = bsr(N);
|
||||
settings.sahBlockSize = N;
|
||||
settings.minLeafSize = 1;
|
||||
settings.maxLeafSize = 1;
|
||||
settings.travCost = 1.0f;
|
||||
|
||||
@@ -212,7 +212,7 @@ namespace embree
|
||||
GeneralBVHBuilder::Settings settings;
|
||||
settings.branchingFactor = N;
|
||||
settings.maxDepth = BVH::maxBuildDepthLeaf;
|
||||
settings.logBlockSize = bsr(N);
|
||||
settings.sahBlockSize = N;
|
||||
settings.minLeafSize = 1;
|
||||
settings.maxLeafSize = 1;
|
||||
settings.travCost = 1.0f;
|
||||
@@ -308,7 +308,7 @@ namespace embree
|
||||
#endif
|
||||
|
||||
std::make_heap(refs.begin(),refs.end());
|
||||
while (refs.size()+3 <= extSize)
|
||||
while (refs.size()+N-1 <= extSize)
|
||||
{
|
||||
std::pop_heap (refs.begin(),refs.end());
|
||||
NodeRef ref = refs.back().node;
|
||||
|
||||
@@ -134,13 +134,13 @@ namespace embree
|
||||
}
|
||||
|
||||
/*! calculates the linear bounds of the i'th primitive for the specified time range */
|
||||
__forceinline LBBox3fa linearBounds(size_t primID, const BBox1f& time_range) const {
|
||||
return LBBox3fa([&] (size_t itime) { return bounds(primID, itime); }, time_range, fnumTimeSegments);
|
||||
__forceinline LBBox3fa linearBounds(size_t primID, const BBox1f& dt) const {
|
||||
return LBBox3fa([&] (size_t itime) { return bounds(primID, itime); }, dt, time_range, fnumTimeSegments);
|
||||
}
|
||||
|
||||
/*! calculates the linear bounds of the i'th primitive for the specified time range */
|
||||
__forceinline bool linearBounds(size_t i, const BBox1f& time_range, LBBox3fa& bbox) const {
|
||||
if (!valid(i, getTimeSegmentRange(time_range, fnumTimeSegments))) return false;
|
||||
if (!valid(i, timeSegmentRange(time_range))) return false;
|
||||
bbox = linearBounds(i, time_range);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -206,7 +206,9 @@ namespace embree
|
||||
primrefarray = std::move(primrefarray_i);
|
||||
}
|
||||
|
||||
void unshare(mvector<PrimRef>& primrefarray_o) {
|
||||
void unshare(mvector<PrimRef>& primrefarray_o)
|
||||
{
|
||||
reset(); // this removes blocks that are allocated inside the shared primref array
|
||||
primrefarray_o = std::move(primrefarray);
|
||||
}
|
||||
|
||||
|
||||
@@ -233,4 +233,56 @@ namespace embree
|
||||
typedef BBox<Vec3vf4> BBox3vf4;
|
||||
typedef BBox<Vec3vf8> BBox3vf8;
|
||||
typedef BBox<Vec3vf16> BBox3vf16;
|
||||
|
||||
|
||||
/* calculate time segment itime and fractional time ftime */
|
||||
__forceinline int getTimeSegment(float time, float numTimeSegments, float& ftime)
|
||||
{
|
||||
const float timeScaled = time * numTimeSegments;
|
||||
const float itimef = clamp(floorf(timeScaled), 0.0f, numTimeSegments-1.0f);
|
||||
ftime = timeScaled - itimef;
|
||||
return int(itimef);
|
||||
}
|
||||
|
||||
__forceinline int getTimeSegment(float time, float start_time, float end_time, float numTimeSegments, float& ftime)
|
||||
{
|
||||
const float timeScaled = (time-start_time)/(end_time-start_time) * numTimeSegments;
|
||||
const float itimef = clamp(floorf(timeScaled), 0.0f, numTimeSegments-1.0f);
|
||||
ftime = timeScaled - itimef;
|
||||
return int(itimef);
|
||||
}
|
||||
|
||||
template<int N>
|
||||
__forceinline vint<N> getTimeSegment(const vfloat<N>& time, const vfloat<N>& numTimeSegments, vfloat<N>& ftime)
|
||||
{
|
||||
const vfloat<N> timeScaled = time * numTimeSegments;
|
||||
const vfloat<N> itimef = clamp(floor(timeScaled), vfloat<N>(zero), numTimeSegments-1.0f);
|
||||
ftime = timeScaled - itimef;
|
||||
return vint<N>(itimef);
|
||||
}
|
||||
|
||||
template<int N>
|
||||
__forceinline vint<N> getTimeSegment(const vfloat<N>& time, const vfloat<N>& start_time, const vfloat<N>& end_time, const vfloat<N>& numTimeSegments, vfloat<N>& ftime)
|
||||
{
|
||||
const vfloat<N> timeScaled = (time-start_time)/(end_time-start_time) * numTimeSegments;
|
||||
const vfloat<N> itimef = clamp(floor(timeScaled), vfloat<N>(zero), numTimeSegments-1.0f);
|
||||
ftime = timeScaled - itimef;
|
||||
return vint<N>(itimef);
|
||||
}
|
||||
|
||||
/* calculate overlapping time segment range */
|
||||
__forceinline range<int> getTimeSegmentRange(const BBox1f& time_range, float numTimeSegments)
|
||||
{
|
||||
const int itime_lower = (int)max(floor(time_range.lower*numTimeSegments), 0.0f);
|
||||
const int itime_upper = (int)min(ceil (time_range.upper*numTimeSegments), numTimeSegments);
|
||||
return make_range(itime_lower, itime_upper);
|
||||
}
|
||||
|
||||
/* calculate overlapping time segment range */
|
||||
__forceinline range<int> getTimeSegmentRange(const BBox1f& range, BBox1f time_range, float numTimeSegments)
|
||||
{
|
||||
const float lower = (range.lower-time_range.lower)/time_range.size();
|
||||
const float upper = (range.upper-time_range.lower)/time_range.size();
|
||||
return getTimeSegmentRange(BBox1f(lower,upper),numTimeSegments);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace embree
|
||||
|
||||
Geometry::Geometry (Device* device, GType gtype, unsigned int numPrimitives, unsigned int numTimeSteps)
|
||||
: device(device), scene(nullptr), userPtr(nullptr),
|
||||
geomID(0), numPrimitives(numPrimitives), numTimeSteps(unsigned(numTimeSteps)), fnumTimeSegments(float(numTimeSteps-1)),
|
||||
geomID(0), numPrimitives(numPrimitives), numTimeSteps(unsigned(numTimeSteps)), fnumTimeSegments(float(numTimeSteps-1)), time_range(0.0f,1.0f),
|
||||
mask(-1),
|
||||
gtype(gtype),
|
||||
quality(RTC_BUILD_QUALITY_MEDIUM),
|
||||
@@ -88,6 +88,12 @@ namespace embree
|
||||
|
||||
Geometry::update();
|
||||
}
|
||||
|
||||
void Geometry::setTimeRange (const BBox1f range)
|
||||
{
|
||||
time_range = range;
|
||||
Geometry::update();
|
||||
}
|
||||
|
||||
void Geometry::update()
|
||||
{
|
||||
|
||||
+31
-32
@@ -25,32 +25,6 @@ namespace embree
|
||||
{
|
||||
class Scene;
|
||||
|
||||
/* calculate time segment itime and fractional time ftime */
|
||||
__forceinline int getTimeSegment(float time, float numTimeSegments, float& ftime)
|
||||
{
|
||||
const float timeScaled = time * numTimeSegments;
|
||||
const float itimef = clamp(floorf(timeScaled), 0.0f, numTimeSegments-1.0f);
|
||||
ftime = timeScaled - itimef;
|
||||
return int(itimef);
|
||||
}
|
||||
|
||||
template<int N>
|
||||
__forceinline vint<N> getTimeSegment(const vfloat<N>& time, const vfloat<N>& numTimeSegments, vfloat<N>& ftime)
|
||||
{
|
||||
const vfloat<N> timeScaled = time * numTimeSegments;
|
||||
const vfloat<N> itimef = clamp(floor(timeScaled), vfloat<N>(zero), numTimeSegments-1.0f);
|
||||
ftime = timeScaled - itimef;
|
||||
return vint<N>(itimef);
|
||||
}
|
||||
|
||||
/* calculate overlapping time segment range */
|
||||
__forceinline range<int> getTimeSegmentRange(const BBox1f& time_range, float numTimeSegments)
|
||||
{
|
||||
const int itime_lower = (int)floor(time_range.lower*numTimeSegments);
|
||||
const int itime_upper = (int)ceil (time_range.upper*numTimeSegments);
|
||||
return make_range(itime_lower, itime_upper);
|
||||
}
|
||||
|
||||
/*! Base class all geometries are derived from */
|
||||
class Geometry : public RefCount
|
||||
{
|
||||
@@ -187,6 +161,9 @@ namespace embree
|
||||
/*! sets number of time steps */
|
||||
virtual void setNumTimeSteps (unsigned int numTimeSteps_in);
|
||||
|
||||
/*! sets motion blur time range */
|
||||
void setTimeRange (const BBox1f range);
|
||||
|
||||
/*! sets number of vertex attributes */
|
||||
virtual void setVertexAttributeCount (unsigned int N) {
|
||||
throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
|
||||
@@ -203,6 +180,27 @@ namespace embree
|
||||
this->quality = quality_in;
|
||||
Geometry::update();
|
||||
}
|
||||
|
||||
/* calculate time segment itime and fractional time ftime */
|
||||
__forceinline int timeSegment(float time, float& ftime) const {
|
||||
return getTimeSegment(time,time_range.lower,time_range.upper,fnumTimeSegments,ftime);
|
||||
}
|
||||
|
||||
template<int N>
|
||||
__forceinline vint<N> timeSegment(const vfloat<N>& time, vfloat<N>& ftime) const {
|
||||
return getTimeSegment(time,vfloat<N>(time_range.lower),vfloat<N>(time_range.upper),vfloat<N>(fnumTimeSegments),ftime);
|
||||
}
|
||||
|
||||
/* calculate overlapping time segment range */
|
||||
__forceinline range<int> timeSegmentRange(const BBox1f& range) const {
|
||||
return getTimeSegmentRange(range,time_range,fnumTimeSegments);
|
||||
}
|
||||
|
||||
/* returns time that corresponds to time step */
|
||||
__forceinline float timeStep(const int i) const {
|
||||
assert(i>=0 && i<numTimeSteps);
|
||||
return time_range.lower + time_range.size()*float(i)/fnumTimeSegments;
|
||||
}
|
||||
|
||||
/*! for all geometries */
|
||||
public:
|
||||
@@ -426,22 +424,23 @@ namespace embree
|
||||
Device* device; //!< device this geometry belongs to
|
||||
Scene* scene; //!< pointer to scene this mesh belongs to
|
||||
|
||||
void* userPtr; //!< user pointer
|
||||
void* userPtr; //!< user pointer
|
||||
unsigned int geomID; //!< internal geometry ID
|
||||
unsigned int numPrimitives; //!< number of primitives of this geometry
|
||||
|
||||
unsigned int numTimeSteps; //!< number of time steps
|
||||
float fnumTimeSegments; //!< number of time segments (precalculation)
|
||||
unsigned int numTimeSteps; //!< number of time steps
|
||||
float fnumTimeSegments; //!< number of time segments (precalculation)
|
||||
BBox1f time_range; //!< motion blur time range
|
||||
|
||||
unsigned int mask; //!< for masking out geometry
|
||||
struct {
|
||||
GType gtype : 6; //!< geometry type
|
||||
GType gtype : 6; //!< geometry type
|
||||
RTCBuildQuality quality : 3; //!< build quality for geometry
|
||||
State state : 2;
|
||||
bool numPrimitivesChanged : 1; //!< true if number of primitives changed
|
||||
bool enabled : 1; //!< true if geometry is enabled
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
RTCFilterFunctionN intersectionFilterN;
|
||||
RTCFilterFunctionN occlusionFilterN;
|
||||
};
|
||||
|
||||
+34
-17
@@ -129,18 +129,16 @@ namespace embree
|
||||
|
||||
__forceinline PrimRefMB () {}
|
||||
|
||||
__forceinline PrimRefMB (const LBBox3fa& bounds, unsigned int activeTimeSegments, unsigned int totalTimeSegments, unsigned int geomID, unsigned int primID)
|
||||
: bbox(bounds.interpolate(0.5f))
|
||||
__forceinline PrimRefMB (const LBBox3fa& bounds, unsigned int activeTimeSegments, BBox1f time_range, unsigned int totalTimeSegments, unsigned int geomID, unsigned int primID)
|
||||
: bbox(bounds.interpolate(0.5f)), _activeTimeSegments(activeTimeSegments), _totalTimeSegments(totalTimeSegments), time_range(time_range)
|
||||
{
|
||||
assert(activeTimeSegments > 0);
|
||||
bbox.lower.a = geomID;
|
||||
bbox.upper.a = primID;
|
||||
num.x = activeTimeSegments;
|
||||
num.y = totalTimeSegments;
|
||||
}
|
||||
|
||||
__forceinline PrimRefMB (const LBBox3fa& bounds, unsigned int activeTimeSegments, unsigned int totalTimeSegments, size_t id)
|
||||
: bbox(bounds.interpolate(0.5f))
|
||||
|
||||
__forceinline PrimRefMB (EmptyTy empty, const LBBox3fa& bounds, unsigned int activeTimeSegments, BBox1f time_range, unsigned int totalTimeSegments, size_t id)
|
||||
: bbox(bounds.interpolate(0.5f)), _activeTimeSegments(activeTimeSegments), _totalTimeSegments(totalTimeSegments), time_range(time_range)
|
||||
{
|
||||
assert(activeTimeSegments > 0);
|
||||
#if defined(__X86_64__)
|
||||
@@ -150,22 +148,39 @@ namespace embree
|
||||
bbox.lower.u = id;
|
||||
bbox.upper.u = 0;
|
||||
#endif
|
||||
num.x = activeTimeSegments;
|
||||
num.y = totalTimeSegments;
|
||||
}
|
||||
|
||||
|
||||
/*! returns bounds for binning */
|
||||
__forceinline BBox3fa bounds() const {
|
||||
return bbox;
|
||||
}
|
||||
|
||||
/*! returns the number of time segments of this primref */
|
||||
__forceinline unsigned size() const {
|
||||
return num.x;
|
||||
__forceinline unsigned int size() const {
|
||||
return _activeTimeSegments;
|
||||
}
|
||||
|
||||
__forceinline unsigned totalTimeSegments() const {
|
||||
return num.y;
|
||||
__forceinline unsigned int totalTimeSegments() const {
|
||||
return _totalTimeSegments;
|
||||
}
|
||||
|
||||
/* calculate overlapping time segment range */
|
||||
__forceinline range<int> timeSegmentRange(const BBox1f& range) const {
|
||||
return getTimeSegmentRange(range,time_range,float(_totalTimeSegments));
|
||||
}
|
||||
|
||||
/* returns time that corresponds to time step */
|
||||
__forceinline float timeStep(const int i) const {
|
||||
assert(i>=0 && i<=_totalTimeSegments);
|
||||
return time_range.lower + time_range.size()*float(i)/float(_totalTimeSegments);
|
||||
}
|
||||
|
||||
/*! checks if time range overlaps */
|
||||
__forceinline bool time_range_overlap(const BBox1f& range) const
|
||||
{
|
||||
if (0.9999f*time_range.upper <= range.lower) return false;
|
||||
if (1.0001f*time_range.lower >= range.upper) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*! returns center for binning */
|
||||
@@ -181,12 +196,12 @@ namespace embree
|
||||
}
|
||||
|
||||
/*! returns the geometry ID */
|
||||
__forceinline unsigned geomID() const {
|
||||
__forceinline unsigned int geomID() const {
|
||||
return bbox.lower.a;
|
||||
}
|
||||
|
||||
/*! returns the primitive ID */
|
||||
__forceinline unsigned primID() const {
|
||||
__forceinline unsigned int primID() const {
|
||||
return bbox.upper.a;
|
||||
}
|
||||
|
||||
@@ -216,7 +231,9 @@ namespace embree
|
||||
|
||||
public:
|
||||
BBox3fa bbox; // bounds, geomID, primID
|
||||
Vec3ia num; // activeTimeSegments, totalTimeSegments
|
||||
unsigned int _activeTimeSegments;
|
||||
unsigned int _totalTimeSegments;
|
||||
BBox1f time_range; // entire geometry time range
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1086,6 +1086,20 @@ namespace embree
|
||||
RTC_CATCH_END2(geometry);
|
||||
}
|
||||
|
||||
RTC_API void rtcSetGeometryTimeRange(RTCGeometry hgeometry, float startTime, float endTime)
|
||||
{
|
||||
Ref<Geometry> geometry = (Geometry*) hgeometry;
|
||||
RTC_CATCH_BEGIN;
|
||||
RTC_TRACE(rtcSetGeometryTimeRange);
|
||||
RTC_VERIFY_HANDLE(hgeometry);
|
||||
|
||||
if (startTime > endTime)
|
||||
throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"startTime has to be smaller or equal to the endTime");
|
||||
|
||||
geometry->setTimeRange(BBox1f(startTime,endTime));
|
||||
RTC_CATCH_END2(geometry);
|
||||
}
|
||||
|
||||
RTC_API void rtcSetGeometryVertexAttributeCount(RTCGeometry hgeometry, unsigned int N)
|
||||
{
|
||||
Geometry* geometry = (Geometry*) hgeometry;
|
||||
|
||||
@@ -692,8 +692,7 @@ namespace embree
|
||||
Vec3fa axisz(0,0,1);
|
||||
Vec3fa axisy(0,1,0);
|
||||
|
||||
const unsigned num_time_segments = this->numTimeSegments();
|
||||
const range<int> tbounds = getTimeSegmentRange(time_range, (float)num_time_segments);
|
||||
const range<int> tbounds = this->timeSegmentRange(time_range);
|
||||
if (tbounds.size() == 0) return frame(axisz);
|
||||
|
||||
const size_t t = (tbounds.begin()+tbounds.end())/2;
|
||||
@@ -769,18 +768,18 @@ namespace embree
|
||||
}
|
||||
|
||||
/*! calculates the linear bounds of the i'th primitive for the specified time range */
|
||||
__forceinline LBBox3fa linearBounds(size_t primID, const BBox1f& time_range) const {
|
||||
return LBBox3fa([&] (size_t itime) { return bounds(primID, itime); }, time_range, fnumTimeSegments);
|
||||
__forceinline LBBox3fa linearBounds(size_t primID, const BBox1f& dt) const {
|
||||
return LBBox3fa([&] (size_t itime) { return bounds(primID, itime); }, dt, this->time_range, fnumTimeSegments);
|
||||
}
|
||||
|
||||
/*! calculates the linear bounds of the i'th primitive for the specified time range */
|
||||
__forceinline LBBox3fa linearBounds(const LinearSpace3fa& space, size_t primID, const BBox1f& time_range) const {
|
||||
return LBBox3fa([&] (size_t itime) { return bounds(space, primID, itime); }, time_range, fnumTimeSegments);
|
||||
__forceinline LBBox3fa linearBounds(const LinearSpace3fa& space, size_t primID, const BBox1f& dt) const {
|
||||
return LBBox3fa([&] (size_t itime) { return bounds(space, primID, itime); }, dt, this->time_range, fnumTimeSegments);
|
||||
}
|
||||
|
||||
/*! calculates the linear bounds of the i'th primitive for the specified time range */
|
||||
__forceinline LBBox3fa linearBounds(const Vec3fa& ofs, const float scale, const float r_scale0, const LinearSpace3fa& space, size_t primID, const BBox1f& time_range) const {
|
||||
return LBBox3fa([&] (size_t itime) { return bounds(ofs, scale, r_scale0, space, primID, itime); }, time_range, fnumTimeSegments);
|
||||
__forceinline LBBox3fa linearBounds(const Vec3fa& ofs, const float scale, const float r_scale0, const LinearSpace3fa& space, size_t primID, const BBox1f& dt) const {
|
||||
return LBBox3fa([&] (size_t itime) { return bounds(ofs, scale, r_scale0, space, primID, itime); }, dt, this->time_range, fnumTimeSegments);
|
||||
}
|
||||
|
||||
PrimInfo createPrimRefArray(mvector<PrimRef>& prims, const range<size_t>& r, size_t k) const
|
||||
@@ -803,10 +802,10 @@ namespace embree
|
||||
PrimInfoMB pinfo(empty);
|
||||
for (size_t j=r.begin(); j<r.end(); j++)
|
||||
{
|
||||
if (!valid(ctype, j, getTimeSegmentRange(t0t1, fnumTimeSegments))) continue;
|
||||
if (!valid(ctype, j, this->timeSegmentRange(t0t1))) continue;
|
||||
const LBBox3fa lbox = linearBounds(j,t0t1);
|
||||
if (lbox.bounds0.empty() || lbox.bounds1.empty()) continue; // checks oriented curves with invalid normals which cause NaNs here
|
||||
const PrimRefMB prim(lbox,this->numTimeSegments(),this->numTimeSegments(),this->geomID,unsigned(j));
|
||||
const PrimRefMB prim(lbox,this->numTimeSegments(),this->time_range,this->numTimeSegments(),this->geomID,unsigned(j));
|
||||
pinfo.add_primref(prim);
|
||||
prims[k++] = prim;
|
||||
}
|
||||
|
||||
@@ -165,7 +165,7 @@ namespace embree
|
||||
__forceinline void gather(Vec3fa& p0, Vec3fa& p1, Vec3fa& p2, Vec3fa& p3, size_t i, float time) const
|
||||
{
|
||||
float ftime;
|
||||
const size_t itime = getTimeSegment(time, fnumTimeSegments, ftime);
|
||||
const size_t itime = timeSegment(time, ftime);
|
||||
|
||||
const float t0 = 1.0f - ftime;
|
||||
const float t1 = ftime;
|
||||
@@ -183,7 +183,7 @@ namespace embree
|
||||
__forceinline void gather(Vec3fa& p0, Vec3fa& p1, Vec3fa& p2, Vec3fa& p3, Vec3fa& n0, Vec3fa& n1, size_t i, float time) const
|
||||
{
|
||||
float ftime;
|
||||
const size_t itime = getTimeSegment(time, fnumTimeSegments, ftime);
|
||||
const size_t itime = timeSegment(time, ftime);
|
||||
|
||||
const float t0 = 1.0f - ftime;
|
||||
const float t1 = ftime;
|
||||
@@ -221,7 +221,7 @@ namespace embree
|
||||
__forceinline void gather_hermite(Vec3fa& p0, Vec3fa& t0, Vec3fa& p1, Vec3fa& t1, size_t i, float time) const
|
||||
{
|
||||
float ftime;
|
||||
const size_t itime = getTimeSegment(time, fnumTimeSegments, ftime);
|
||||
const size_t itime = timeSegment(time, ftime);
|
||||
const float f0 = 1.0f - ftime, f1 = ftime;
|
||||
Vec3fa ap0,at0,ap1,at1;
|
||||
gather_hermite(ap0,at0,ap1,at1,i,itime);
|
||||
@@ -259,7 +259,7 @@ namespace embree
|
||||
__forceinline void gather_hermite(Vec3fa& p0, Vec3fa& t0, Vec3fa& n0, Vec3fa& p1, Vec3fa& t1, Vec3fa& n1, size_t i, float time) const
|
||||
{
|
||||
float ftime;
|
||||
const size_t itime = getTimeSegment(time, fnumTimeSegments, ftime);
|
||||
const size_t itime = timeSegment(time, ftime);
|
||||
const float f0 = 1.0f - ftime, f1 = ftime;
|
||||
Vec3fa ap0,at0,an0,ap1,at1,an1;
|
||||
gather_hermite(ap0,at0,an0,ap1,at1,an1,i,itime);
|
||||
|
||||
@@ -201,9 +201,8 @@ namespace embree
|
||||
}
|
||||
|
||||
/*! calculates the linear bounds of the i'th primitive for the specified time range */
|
||||
__forceinline LBBox3fa linearBounds(const Grid& g, size_t sx, size_t sy, const BBox1f& time_range) const {
|
||||
|
||||
return LBBox3fa([&] (size_t itime) { return bounds(g,sx,sy,itime); }, time_range, fnumTimeSegments);
|
||||
__forceinline LBBox3fa linearBounds(const Grid& g, size_t sx, size_t sy, const BBox1f& dt) const {
|
||||
return LBBox3fa([&] (size_t itime) { return bounds(g,sx,sy,itime); }, dt, time_range, fnumTimeSegments);
|
||||
}
|
||||
|
||||
/* returns true if topology changed */
|
||||
|
||||
@@ -66,9 +66,9 @@ namespace embree
|
||||
}
|
||||
|
||||
/*! calculates the linear bounds of the i'th primitive for the specified time range */
|
||||
__forceinline LBBox3fa linearBounds(size_t i, const BBox1f& time_range) const {
|
||||
__forceinline LBBox3fa linearBounds(size_t i, const BBox1f& dt) const {
|
||||
assert(i == 0);
|
||||
return LBBox3fa([&] (size_t itime) { return bounds(i, itime); }, time_range, fnumTimeSegments);
|
||||
return LBBox3fa([&] (size_t itime) { return bounds(i, itime); }, dt, time_range, fnumTimeSegments);
|
||||
}
|
||||
|
||||
/*! check if the i'th primitive is valid between the specified time range */
|
||||
@@ -85,10 +85,9 @@ namespace embree
|
||||
return local2world[0];
|
||||
}
|
||||
|
||||
__forceinline AffineSpace3fa getLocal2World(float t) const
|
||||
__forceinline AffineSpace3fa getLocal2World(float t) const
|
||||
{
|
||||
float ftime;
|
||||
const unsigned int itime = getTimeSegment(t, fnumTimeSegments, ftime);
|
||||
float ftime; const unsigned int itime = timeSegment(t, ftime);
|
||||
return lerp(local2world[itime+0],local2world[itime+1],ftime);
|
||||
}
|
||||
|
||||
@@ -104,7 +103,7 @@ namespace embree
|
||||
__forceinline AffineSpace3vf<K> getWorld2Local(const vbool<K>& valid, const vfloat<K>& t) const
|
||||
{
|
||||
vfloat<K> ftime;
|
||||
const vint<K> itime_k = getTimeSegment(t, vfloat<K>(fnumTimeSegments), ftime);
|
||||
const vint<K> itime_k = timeSegment(t, ftime);
|
||||
assert(any(valid));
|
||||
const size_t index = bsf(movemask(valid));
|
||||
const int itime = itime_k[index];
|
||||
@@ -171,8 +170,8 @@ namespace embree
|
||||
assert(r.end() == 1);
|
||||
|
||||
PrimInfoMB pinfo(empty);
|
||||
if (!valid(0, getTimeSegmentRange(t0t1, fnumTimeSegments))) return pinfo;
|
||||
const PrimRefMB prim(linearBounds(0,t0t1),this->numTimeSegments(),this->numTimeSegments(),this->geomID,unsigned(0));
|
||||
if (!valid(0, timeSegmentRange(t0t1))) return pinfo;
|
||||
const PrimRefMB prim(linearBounds(0,t0t1),this->numTimeSegments(),this->time_range,this->numTimeSegments(),this->geomID,unsigned(0));
|
||||
pinfo.add_primref(prim);
|
||||
prims[k++] = prim;
|
||||
return pinfo;
|
||||
|
||||
@@ -197,19 +197,19 @@ namespace embree
|
||||
}
|
||||
|
||||
/*! calculates the linear bounds of the i'th primitive for the specified time range */
|
||||
__forceinline LBBox3fa linearBounds(size_t primID, const BBox1f& time_range) const {
|
||||
return LBBox3fa([&] (size_t itime) { return bounds(primID, itime); }, time_range, fnumTimeSegments);
|
||||
__forceinline LBBox3fa linearBounds(size_t primID, const BBox1f& dt) const {
|
||||
return LBBox3fa([&] (size_t itime) { return bounds(primID, itime); }, dt, time_range, fnumTimeSegments);
|
||||
}
|
||||
|
||||
/*! calculates the linear bounds of the i'th primitive for the specified time range */
|
||||
__forceinline LBBox3fa linearBounds(const LinearSpace3fa& space, size_t primID, const BBox1f& time_range) const {
|
||||
return LBBox3fa([&] (size_t itime) { return bounds(space, primID, itime); }, time_range, fnumTimeSegments);
|
||||
__forceinline LBBox3fa linearBounds(const LinearSpace3fa& space, size_t primID, const BBox1f& dt) const {
|
||||
return LBBox3fa([&] (size_t itime) { return bounds(space, primID, itime); }, dt, time_range, fnumTimeSegments);
|
||||
}
|
||||
|
||||
/*! calculates the linear bounds of the i'th primitive for the specified time range */
|
||||
__forceinline bool linearBounds(size_t i, const BBox1f& time_range, LBBox3fa& bbox) const
|
||||
{
|
||||
if (!valid(i, getTimeSegmentRange(time_range, fnumTimeSegments))) return false;
|
||||
if (!valid(i, timeSegmentRange(time_range))) return false;
|
||||
bbox = linearBounds(i, time_range);
|
||||
return true;
|
||||
}
|
||||
@@ -286,8 +286,8 @@ namespace embree
|
||||
PrimInfoMB pinfo(empty);
|
||||
for (size_t j=r.begin(); j<r.end(); j++)
|
||||
{
|
||||
if (!valid(j, getTimeSegmentRange(t0t1, fnumTimeSegments))) continue;
|
||||
const PrimRefMB prim(linearBounds(j,t0t1),this->numTimeSegments(),this->numTimeSegments(),this->geomID,unsigned(j));
|
||||
if (!valid(j, timeSegmentRange(t0t1))) continue;
|
||||
const PrimRefMB prim(linearBounds(j,t0t1),this->numTimeSegments(),this->time_range,this->numTimeSegments(),this->geomID,unsigned(j));
|
||||
pinfo.add_primref(prim);
|
||||
prims[k++] = prim;
|
||||
}
|
||||
|
||||
@@ -193,15 +193,15 @@ namespace embree
|
||||
}
|
||||
|
||||
/*! calculates the linear bounds of the i'th primitive for the specified time range */
|
||||
__forceinline LBBox3fa linearBounds(size_t primID, const BBox1f& time_range) const {
|
||||
return LBBox3fa([&] (size_t itime) { return bounds(primID, itime); }, time_range, fnumTimeSegments);
|
||||
__forceinline LBBox3fa linearBounds(size_t primID, const BBox1f& dt) const {
|
||||
return LBBox3fa([&] (size_t itime) { return bounds(primID, itime); }, dt, time_range, fnumTimeSegments);
|
||||
}
|
||||
|
||||
/*! calculates the linear bounds of the i'th primitive for the specified time range */
|
||||
__forceinline bool linearBounds(size_t i, const BBox1f& time_range, LBBox3fa& bbox) const
|
||||
__forceinline bool linearBounds(size_t i, const BBox1f& dt, LBBox3fa& bbox) const
|
||||
{
|
||||
if (!valid(i, getTimeSegmentRange(time_range, fnumTimeSegments))) return false;
|
||||
bbox = linearBounds(i, time_range);
|
||||
if (!valid(i, timeSegmentRange(dt))) return false;
|
||||
bbox = linearBounds(i, dt);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -257,8 +257,8 @@ namespace embree
|
||||
PrimInfoMB pinfo(empty);
|
||||
for (size_t j=r.begin(); j<r.end(); j++)
|
||||
{
|
||||
if (!valid(j, getTimeSegmentRange(t0t1, fnumTimeSegments))) continue;
|
||||
const PrimRefMB prim(linearBounds(j,t0t1),this->numTimeSegments(),this->numTimeSegments(),this->geomID,unsigned(j));
|
||||
if (!valid(j, timeSegmentRange(t0t1))) continue;
|
||||
const PrimRefMB prim(linearBounds(j,t0t1),this->numTimeSegments(),this->time_range,this->numTimeSegments(),this->geomID,unsigned(j));
|
||||
pinfo.add_primref(prim);
|
||||
prims[k++] = prim;
|
||||
}
|
||||
|
||||
@@ -192,14 +192,14 @@ namespace embree
|
||||
}
|
||||
|
||||
/*! calculates the linear bounds of the i'th primitive for the specified time range */
|
||||
__forceinline LBBox3fa linearBounds(size_t primID, const BBox1f& time_range) const {
|
||||
return LBBox3fa([&] (size_t itime) { return bounds(primID, itime); }, time_range, fnumTimeSegments);
|
||||
__forceinline LBBox3fa linearBounds(size_t primID, const BBox1f& dt) const {
|
||||
return LBBox3fa([&] (size_t itime) { return bounds(primID, itime); }, dt, time_range, fnumTimeSegments);
|
||||
}
|
||||
|
||||
/*! calculates the linear bounds of the i'th primitive for the specified time range */
|
||||
__forceinline bool linearBounds(size_t i, const BBox1f& time_range, LBBox3fa& bbox) const {
|
||||
if (!valid(i, getTimeSegmentRange(time_range, fnumTimeSegments))) return false;
|
||||
bbox = linearBounds(i, time_range);
|
||||
__forceinline bool linearBounds(size_t i, const BBox1f& dt, LBBox3fa& bbox) const {
|
||||
if (!valid(i, timeSegmentRange(dt))) return false;
|
||||
bbox = linearBounds(i, dt);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -255,8 +255,8 @@ namespace embree
|
||||
PrimInfoMB pinfo(empty);
|
||||
for (size_t j=r.begin(); j<r.end(); j++)
|
||||
{
|
||||
if (!valid(j, getTimeSegmentRange(t0t1, fnumTimeSegments))) continue;
|
||||
const PrimRefMB prim(linearBounds(j,t0t1),this->numTimeSegments(),this->numTimeSegments(),this->geomID,unsigned(j));
|
||||
if (!valid(j, timeSegmentRange(t0t1))) continue;
|
||||
const PrimRefMB prim(linearBounds(j,t0t1),this->numTimeSegments(),this->time_range,this->numTimeSegments(),this->geomID,unsigned(j));
|
||||
pinfo.add_primref(prim);
|
||||
prims[k++] = prim;
|
||||
}
|
||||
|
||||
@@ -77,8 +77,8 @@ namespace embree
|
||||
PrimInfoMB pinfo(empty);
|
||||
for (size_t j=r.begin(); j<r.end(); j++)
|
||||
{
|
||||
if (!valid(j, getTimeSegmentRange(t0t1, fnumTimeSegments))) continue;
|
||||
const PrimRefMB prim(linearBounds(j,t0t1),this->numTimeSegments(),this->numTimeSegments(),this->geomID,unsigned(j));
|
||||
if (!valid(j, timeSegmentRange(t0t1))) continue;
|
||||
const PrimRefMB prim(linearBounds(j,t0t1),this->numTimeSegments(),this->time_range,this->numTimeSegments(),this->geomID,unsigned(j));
|
||||
pinfo.add_primref(prim);
|
||||
prims[k++] = prim;
|
||||
}
|
||||
|
||||
@@ -138,10 +138,10 @@ namespace embree
|
||||
template<typename BVH, typename SetMB, typename Allocator>
|
||||
__forceinline static typename BVH::NodeRecordMB4D createLeafMB(BVH* bvh, const SetMB& prims, const Allocator& alloc)
|
||||
{
|
||||
size_t start = prims.object_range.begin();
|
||||
size_t end = prims.object_range.end();
|
||||
size_t items = CurveNiMB::blocks(prims.object_range.size());
|
||||
size_t numbytes = CurveNiMB::bytes(prims.object_range.size());
|
||||
size_t start = prims.begin();
|
||||
size_t end = prims.end();
|
||||
size_t items = CurveNiMB::blocks(prims.size());
|
||||
size_t numbytes = CurveNiMB::bytes(prims.size());
|
||||
CurveNiMB* accel = (CurveNiMB*) alloc.malloc1(numbytes,BVH::byteAlignment);
|
||||
const typename BVH::NodeRef node = bvh->encodeLeaf((char*)accel,items);
|
||||
|
||||
|
||||
+41
-41
@@ -94,7 +94,7 @@ namespace embree
|
||||
__forceinline void gather(Vec4vf<M>& p0,
|
||||
Vec4vf<M>& p1,
|
||||
const LineSegments* geom,
|
||||
const vint<M>& itime) const;
|
||||
const int itime) const;
|
||||
|
||||
__forceinline void gather(Vec4vf<M>& p0,
|
||||
Vec4vf<M>& p1,
|
||||
@@ -203,10 +203,10 @@ namespace embree
|
||||
template<typename BVH, typename SetMB, typename Allocator>
|
||||
__forceinline static typename BVH::NodeRecordMB4D createLeafMB(BVH* bvh, const SetMB& prims, const Allocator& alloc)
|
||||
{
|
||||
size_t start = prims.object_range.begin();
|
||||
size_t end = prims.object_range.end();
|
||||
size_t items = LineMi::blocks(prims.object_range.size());
|
||||
size_t numbytes = LineMi::bytes(prims.object_range.size());
|
||||
size_t start = prims.begin();
|
||||
size_t end = prims.end();
|
||||
size_t items = LineMi::blocks(prims.size());
|
||||
size_t numbytes = LineMi::bytes(prims.size());
|
||||
LineMi* accel = (LineMi*) alloc.malloc1(numbytes,M*sizeof(float));
|
||||
const typename BVH::NodeRef node = bvh->encodeLeaf((char*)accel,items);
|
||||
|
||||
@@ -269,18 +269,18 @@ namespace embree
|
||||
__forceinline void LineMi<4>::gather(Vec4vf4& p0,
|
||||
Vec4vf4& p1,
|
||||
const LineSegments* geom,
|
||||
const vint4& itime) const
|
||||
const int itime) const
|
||||
{
|
||||
const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(v0[0],itime[0]));
|
||||
const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(v0[1],itime[1]));
|
||||
const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(v0[2],itime[2]));
|
||||
const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(v0[3],itime[3]));
|
||||
const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(v0[0],itime));
|
||||
const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(v0[1],itime));
|
||||
const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(v0[2],itime));
|
||||
const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(v0[3],itime));
|
||||
transpose(a0,a1,a2,a3,p0.x,p0.y,p0.z,p0.w);
|
||||
|
||||
const vfloat4 b0 = vfloat4::loadu(geom->vertexPtr(v0[0]+1,itime[0]));
|
||||
const vfloat4 b1 = vfloat4::loadu(geom->vertexPtr(v0[1]+1,itime[1]));
|
||||
const vfloat4 b2 = vfloat4::loadu(geom->vertexPtr(v0[2]+1,itime[2]));
|
||||
const vfloat4 b3 = vfloat4::loadu(geom->vertexPtr(v0[3]+1,itime[3]));
|
||||
const vfloat4 b0 = vfloat4::loadu(geom->vertexPtr(v0[0]+1,itime));
|
||||
const vfloat4 b1 = vfloat4::loadu(geom->vertexPtr(v0[1]+1,itime));
|
||||
const vfloat4 b2 = vfloat4::loadu(geom->vertexPtr(v0[2]+1,itime));
|
||||
const vfloat4 b3 = vfloat4::loadu(geom->vertexPtr(v0[3]+1,itime));
|
||||
transpose(b0,b1,b2,b3,p1.x,p1.y,p1.z,p1.w);
|
||||
}
|
||||
|
||||
@@ -291,16 +291,16 @@ namespace embree
|
||||
float time) const
|
||||
{
|
||||
const LineSegments* geom = scene->get<LineSegments>(geomID());
|
||||
const vfloat4 numTimeSegments(geom->fnumTimeSegments);
|
||||
vfloat4 ftime;
|
||||
const vint4 itime = getTimeSegment(vfloat4(time), numTimeSegments, ftime);
|
||||
|
||||
float ftime;
|
||||
const int itime = geom->timeSegment(time, ftime);
|
||||
|
||||
Vec4vf4 a0,a1;
|
||||
gather(a0,a1,geom,itime);
|
||||
Vec4vf4 b0,b1;
|
||||
gather(b0,b1,geom,itime+1);
|
||||
p0 = lerp(a0,b0,ftime);
|
||||
p1 = lerp(a1,b1,ftime);
|
||||
p0 = lerp(a0,b0,vfloat4(ftime));
|
||||
p1 = lerp(a1,b1,vfloat4(ftime));
|
||||
}
|
||||
|
||||
#if defined(__AVX__)
|
||||
@@ -337,26 +337,26 @@ namespace embree
|
||||
__forceinline void LineMi<8>::gather(Vec4vf8& p0,
|
||||
Vec4vf8& p1,
|
||||
const LineSegments* geom,
|
||||
const vint8& itime) const
|
||||
const int itime) const
|
||||
{
|
||||
const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(v0[0],itime[0]));
|
||||
const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(v0[1],itime[1]));
|
||||
const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(v0[2],itime[2]));
|
||||
const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(v0[3],itime[3]));
|
||||
const vfloat4 a4 = vfloat4::loadu(geom->vertexPtr(v0[4],itime[4]));
|
||||
const vfloat4 a5 = vfloat4::loadu(geom->vertexPtr(v0[5],itime[5]));
|
||||
const vfloat4 a6 = vfloat4::loadu(geom->vertexPtr(v0[6],itime[6]));
|
||||
const vfloat4 a7 = vfloat4::loadu(geom->vertexPtr(v0[7],itime[7]));
|
||||
const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(v0[0],itime));
|
||||
const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(v0[1],itime));
|
||||
const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(v0[2],itime));
|
||||
const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(v0[3],itime));
|
||||
const vfloat4 a4 = vfloat4::loadu(geom->vertexPtr(v0[4],itime));
|
||||
const vfloat4 a5 = vfloat4::loadu(geom->vertexPtr(v0[5],itime));
|
||||
const vfloat4 a6 = vfloat4::loadu(geom->vertexPtr(v0[6],itime));
|
||||
const vfloat4 a7 = vfloat4::loadu(geom->vertexPtr(v0[7],itime));
|
||||
transpose(a0,a1,a2,a3,a4,a5,a6,a7,p0.x,p0.y,p0.z,p0.w);
|
||||
|
||||
const vfloat4 b0 = vfloat4::loadu(geom->vertexPtr(v0[0]+1,itime[0]));
|
||||
const vfloat4 b1 = vfloat4::loadu(geom->vertexPtr(v0[1]+1,itime[1]));
|
||||
const vfloat4 b2 = vfloat4::loadu(geom->vertexPtr(v0[2]+1,itime[2]));
|
||||
const vfloat4 b3 = vfloat4::loadu(geom->vertexPtr(v0[3]+1,itime[3]));
|
||||
const vfloat4 b4 = vfloat4::loadu(geom->vertexPtr(v0[4]+1,itime[4]));
|
||||
const vfloat4 b5 = vfloat4::loadu(geom->vertexPtr(v0[5]+1,itime[5]));
|
||||
const vfloat4 b6 = vfloat4::loadu(geom->vertexPtr(v0[6]+1,itime[6]));
|
||||
const vfloat4 b7 = vfloat4::loadu(geom->vertexPtr(v0[7]+1,itime[7]));
|
||||
const vfloat4 b0 = vfloat4::loadu(geom->vertexPtr(v0[0]+1,itime));
|
||||
const vfloat4 b1 = vfloat4::loadu(geom->vertexPtr(v0[1]+1,itime));
|
||||
const vfloat4 b2 = vfloat4::loadu(geom->vertexPtr(v0[2]+1,itime));
|
||||
const vfloat4 b3 = vfloat4::loadu(geom->vertexPtr(v0[3]+1,itime));
|
||||
const vfloat4 b4 = vfloat4::loadu(geom->vertexPtr(v0[4]+1,itime));
|
||||
const vfloat4 b5 = vfloat4::loadu(geom->vertexPtr(v0[5]+1,itime));
|
||||
const vfloat4 b6 = vfloat4::loadu(geom->vertexPtr(v0[6]+1,itime));
|
||||
const vfloat4 b7 = vfloat4::loadu(geom->vertexPtr(v0[7]+1,itime));
|
||||
transpose(b0,b1,b2,b3,b4,b5,b6,b7,p1.x,p1.y,p1.z,p1.w);
|
||||
}
|
||||
|
||||
@@ -367,16 +367,16 @@ namespace embree
|
||||
float time) const
|
||||
{
|
||||
const LineSegments* geom = scene->get<LineSegments>(geomID());
|
||||
const vfloat8 numTimeSegments(geom->fnumTimeSegments);
|
||||
vfloat8 ftime;
|
||||
const vint8 itime = getTimeSegment(vfloat8(time), numTimeSegments, ftime);
|
||||
|
||||
float ftime;
|
||||
const int itime = geom->timeSegment(time, ftime);
|
||||
|
||||
Vec4vf8 a0,a1;
|
||||
gather(a0,a1,geom,itime);
|
||||
Vec4vf8 b0,b1;
|
||||
gather(b0,b1,geom,itime+1);
|
||||
p0 = lerp(a0,b0,ftime);
|
||||
p1 = lerp(a1,b1,ftime);
|
||||
p0 = lerp(a0,b0,vfloat8(ftime));
|
||||
p1 = lerp(a1,b1,vfloat8(ftime));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+18
-28
@@ -144,7 +144,7 @@ namespace embree
|
||||
const QuadMesh* mesh = scene->get<QuadMesh>(geomID(index));
|
||||
|
||||
vfloat<K> ftime;
|
||||
const vint<K> itime = getTimeSegment(time, vfloat<K>(mesh->fnumTimeSegments), ftime);
|
||||
const vint<K> itime = mesh->timeSegment(time, ftime);
|
||||
|
||||
const size_t first = bsf(movemask(valid));
|
||||
if (likely(all(valid,itime[first] == itime)))
|
||||
@@ -167,11 +167,8 @@ namespace embree
|
||||
Vec3vf<M>& p1,
|
||||
Vec3vf<M>& p2,
|
||||
Vec3vf<M>& p3,
|
||||
const QuadMesh* mesh0,
|
||||
const QuadMesh* mesh1,
|
||||
const QuadMesh* mesh2,
|
||||
const QuadMesh* mesh3,
|
||||
const vint<M>& itime) const;
|
||||
const QuadMesh* mesh,
|
||||
const int itime) const;
|
||||
|
||||
__forceinline void gather(Vec3vf<M>& p0,
|
||||
Vec3vf<M>& p1,
|
||||
@@ -402,16 +399,13 @@ namespace embree
|
||||
Vec3vf4& p1,
|
||||
Vec3vf4& p2,
|
||||
Vec3vf4& p3,
|
||||
const QuadMesh* mesh0,
|
||||
const QuadMesh* mesh1,
|
||||
const QuadMesh* mesh2,
|
||||
const QuadMesh* mesh3,
|
||||
const vint4& itime) const
|
||||
const QuadMesh* mesh,
|
||||
const int itime) const
|
||||
{
|
||||
const float* vertices0 = (const float*) mesh0->vertexPtr(0,itime[0]);
|
||||
const float* vertices1 = (const float*) mesh1->vertexPtr(0,itime[1]);
|
||||
const float* vertices2 = (const float*) mesh2->vertexPtr(0,itime[2]);
|
||||
const float* vertices3 = (const float*) mesh3->vertexPtr(0,itime[3]);
|
||||
const float* vertices0 = (const float*) mesh->vertexPtr(0,itime);
|
||||
const float* vertices1 = (const float*) mesh->vertexPtr(0,itime);
|
||||
const float* vertices2 = (const float*) mesh->vertexPtr(0,itime);
|
||||
const float* vertices3 = (const float*) mesh->vertexPtr(0,itime);
|
||||
const vfloat4 a0 = vfloat4::loadu(vertices0 + v0[0]);
|
||||
const vfloat4 a1 = vfloat4::loadu(vertices1 + v0[1]);
|
||||
const vfloat4 a2 = vfloat4::loadu(vertices2 + v0[2]);
|
||||
@@ -442,21 +436,17 @@ namespace embree
|
||||
const Scene *const scene,
|
||||
const float time) const
|
||||
{
|
||||
const QuadMesh* mesh0 = scene->get<QuadMesh>(geomID(0));
|
||||
const QuadMesh* mesh1 = scene->get<QuadMesh>(geomID(1));
|
||||
const QuadMesh* mesh2 = scene->get<QuadMesh>(geomID(2));
|
||||
const QuadMesh* mesh3 = scene->get<QuadMesh>(geomID(3));
|
||||
const QuadMesh* mesh = scene->get<QuadMesh>(geomID(0)); // in mblur mode all geometries are identical
|
||||
|
||||
const vfloat4 numTimeSegments(mesh0->fnumTimeSegments, mesh1->fnumTimeSegments, mesh2->fnumTimeSegments, mesh3->fnumTimeSegments);
|
||||
vfloat4 ftime;
|
||||
const vint4 itime = getTimeSegment(vfloat4(time), numTimeSegments, ftime);
|
||||
float ftime;
|
||||
const int itime = mesh->timeSegment(time, ftime);
|
||||
|
||||
Vec3vf4 a0,a1,a2,a3; gather(a0,a1,a2,a3,mesh0,mesh1,mesh2,mesh3,itime);
|
||||
Vec3vf4 b0,b1,b2,b3; gather(b0,b1,b2,b3,mesh0,mesh1,mesh2,mesh3,itime+1);
|
||||
p0 = lerp(a0,b0,ftime);
|
||||
p1 = lerp(a1,b1,ftime);
|
||||
p2 = lerp(a2,b2,ftime);
|
||||
p3 = lerp(a3,b3,ftime);
|
||||
Vec3vf4 a0,a1,a2,a3; gather(a0,a1,a2,a3,mesh,itime);
|
||||
Vec3vf4 b0,b1,b2,b3; gather(b0,b1,b2,b3,mesh,itime+1);
|
||||
p0 = lerp(a0,b0,vfloat4(ftime));
|
||||
p1 = lerp(a1,b1,vfloat4(ftime));
|
||||
p2 = lerp(a2,b2,vfloat4(ftime));
|
||||
p3 = lerp(a3,b3,vfloat4(ftime));
|
||||
}
|
||||
|
||||
template<int M>
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace embree
|
||||
const GridMesh::Grid &g = mesh->grid(subgrid.primID());
|
||||
|
||||
float ftime;
|
||||
const int itime = getTimeSegment(ray.time(), float(mesh->fnumTimeSegments), ftime);
|
||||
const int itime = mesh->timeSegment(ray.time(), ftime);
|
||||
Vec3vf4 v0,v1,v2,v3; subgrid.gatherMB(v0,v1,v2,v3,context->scene,itime,ftime);
|
||||
pre.intersect(ray,context,v0,v1,v2,v3,g,subgrid);
|
||||
}
|
||||
@@ -47,7 +47,7 @@ namespace embree
|
||||
const GridMesh::Grid &g = mesh->grid(subgrid.primID());
|
||||
|
||||
float ftime;
|
||||
const int itime = getTimeSegment(ray.time(), float(mesh->fnumTimeSegments), ftime);
|
||||
const int itime = mesh->timeSegment(ray.time(), ftime);
|
||||
|
||||
Vec3vf4 v0,v1,v2,v3; subgrid.gatherMB(v0,v1,v2,v3,context->scene,itime,ftime);
|
||||
return pre.occluded(ray,context,v0,v1,v2,v3,g,subgrid);
|
||||
@@ -134,7 +134,7 @@ namespace embree
|
||||
const GridMesh::Grid &g = mesh->grid(subgrid.primID());
|
||||
|
||||
vfloat<K> ftime;
|
||||
const vint<K> itime = getTimeSegment(ray.time(), vfloat<K>(mesh->fnumTimeSegments), ftime);
|
||||
const vint<K> itime = mesh->timeSegment(ray.time(), ftime);
|
||||
Vec3vf4 v0,v1,v2,v3; subgrid.gatherMB(v0,v1,v2,v3,context->scene,itime[k],ftime[k]);
|
||||
pre.intersect1(ray,k,context,v0,v1,v2,v3,g,subgrid);
|
||||
}
|
||||
@@ -146,7 +146,7 @@ namespace embree
|
||||
const GridMesh::Grid &g = mesh->grid(subgrid.primID());
|
||||
|
||||
vfloat<K> ftime;
|
||||
const vint<K> itime = getTimeSegment(ray.time(), vfloat<K>(mesh->fnumTimeSegments), ftime);
|
||||
const vint<K> itime = mesh->timeSegment(ray.time(), ftime);
|
||||
Vec3vf4 v0,v1,v2,v3; subgrid.gatherMB(v0,v1,v2,v3,context->scene,itime[k],ftime[k]);
|
||||
return pre.occluded1(ray,k,context,v0,v1,v2,v3,g,subgrid);
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ namespace embree
|
||||
const TriangleMesh* mesh = scene->get<TriangleMesh>(geomID(index));
|
||||
|
||||
vfloat<K> ftime;
|
||||
const vint<K> itime = getTimeSegment(time, vfloat<K>(mesh->fnumTimeSegments), ftime);
|
||||
const vint<K> itime = mesh->timeSegment(time, ftime);
|
||||
|
||||
const size_t first = bsf(movemask(valid));
|
||||
if (likely(all(valid,itime[first] == itime)))
|
||||
@@ -147,11 +147,8 @@ namespace embree
|
||||
__forceinline void gather(Vec3vf<M>& p0,
|
||||
Vec3vf<M>& p1,
|
||||
Vec3vf<M>& p2,
|
||||
const TriangleMesh* mesh0,
|
||||
const TriangleMesh* mesh1,
|
||||
const TriangleMesh* mesh2,
|
||||
const TriangleMesh* mesh3,
|
||||
const vint<M>& itime) const;
|
||||
const TriangleMesh* mesh,
|
||||
const int itime) const;
|
||||
|
||||
__forceinline void gather(Vec3vf<M>& p0,
|
||||
Vec3vf<M>& p1,
|
||||
@@ -315,28 +312,22 @@ namespace embree
|
||||
__forceinline void TriangleMi<4>::gather(Vec3vf4& p0,
|
||||
Vec3vf4& p1,
|
||||
Vec3vf4& p2,
|
||||
const TriangleMesh* mesh0,
|
||||
const TriangleMesh* mesh1,
|
||||
const TriangleMesh* mesh2,
|
||||
const TriangleMesh* mesh3,
|
||||
const vint4& itime) const
|
||||
const TriangleMesh* mesh,
|
||||
const int itime) const
|
||||
{
|
||||
const float* vertices0 = (const float*) mesh0->vertexPtr(0,itime[0]);
|
||||
const float* vertices1 = (const float*) mesh1->vertexPtr(0,itime[1]);
|
||||
const float* vertices2 = (const float*) mesh2->vertexPtr(0,itime[2]);
|
||||
const float* vertices3 = (const float*) mesh3->vertexPtr(0,itime[3]);
|
||||
const vfloat4 a0 = vfloat4::loadu(vertices0 + v0[0]);
|
||||
const vfloat4 a1 = vfloat4::loadu(vertices1 + v0[1]);
|
||||
const vfloat4 a2 = vfloat4::loadu(vertices2 + v0[2]);
|
||||
const vfloat4 a3 = vfloat4::loadu(vertices3 + v0[3]);
|
||||
const vfloat4 b0 = vfloat4::loadu(vertices0 + v1[0]);
|
||||
const vfloat4 b1 = vfloat4::loadu(vertices1 + v1[1]);
|
||||
const vfloat4 b2 = vfloat4::loadu(vertices2 + v1[2]);
|
||||
const vfloat4 b3 = vfloat4::loadu(vertices3 + v1[3]);
|
||||
const vfloat4 c0 = vfloat4::loadu(vertices0 + v2[0]);
|
||||
const vfloat4 c1 = vfloat4::loadu(vertices1 + v2[1]);
|
||||
const vfloat4 c2 = vfloat4::loadu(vertices2 + v2[2]);
|
||||
const vfloat4 c3 = vfloat4::loadu(vertices3 + v2[3]);
|
||||
const float* vertices = (const float*) mesh->vertexPtr(0,itime);
|
||||
const vfloat4 a0 = vfloat4::loadu(vertices + v0[0]);
|
||||
const vfloat4 a1 = vfloat4::loadu(vertices + v0[1]);
|
||||
const vfloat4 a2 = vfloat4::loadu(vertices + v0[2]);
|
||||
const vfloat4 a3 = vfloat4::loadu(vertices + v0[3]);
|
||||
const vfloat4 b0 = vfloat4::loadu(vertices + v1[0]);
|
||||
const vfloat4 b1 = vfloat4::loadu(vertices + v1[1]);
|
||||
const vfloat4 b2 = vfloat4::loadu(vertices + v1[2]);
|
||||
const vfloat4 b3 = vfloat4::loadu(vertices + v1[3]);
|
||||
const vfloat4 c0 = vfloat4::loadu(vertices + v2[0]);
|
||||
const vfloat4 c1 = vfloat4::loadu(vertices + v2[1]);
|
||||
const vfloat4 c2 = vfloat4::loadu(vertices + v2[2]);
|
||||
const vfloat4 c3 = vfloat4::loadu(vertices + v2[3]);
|
||||
transpose(a0,a1,a2,a3,p0.x,p0.y,p0.z);
|
||||
transpose(b0,b1,b2,b3,p1.x,p1.y,p1.z);
|
||||
transpose(c0,c1,c2,c3,p2.x,p2.y,p2.z);
|
||||
@@ -349,20 +340,16 @@ namespace embree
|
||||
const Scene *const scene,
|
||||
const float time) const
|
||||
{
|
||||
const TriangleMesh* mesh0 = scene->get<TriangleMesh>(geomID(0));
|
||||
const TriangleMesh* mesh1 = scene->get<TriangleMesh>(geomID(1));
|
||||
const TriangleMesh* mesh2 = scene->get<TriangleMesh>(geomID(2));
|
||||
const TriangleMesh* mesh3 = scene->get<TriangleMesh>(geomID(3));
|
||||
const TriangleMesh* mesh = scene->get<TriangleMesh>(geomID(0)); // in mblur mode all geometries are identical
|
||||
|
||||
const vfloat4 numTimeSegments(mesh0->fnumTimeSegments, mesh1->fnumTimeSegments, mesh2->fnumTimeSegments, mesh3->fnumTimeSegments);
|
||||
vfloat4 ftime;
|
||||
const vint4 itime = getTimeSegment(vfloat4(time), numTimeSegments, ftime);
|
||||
float ftime;
|
||||
const int itime = mesh->timeSegment(time, ftime);
|
||||
|
||||
Vec3vf4 a0,a1,a2; gather(a0,a1,a2,mesh0,mesh1,mesh2,mesh3,itime);
|
||||
Vec3vf4 b0,b1,b2; gather(b0,b1,b2,mesh0,mesh1,mesh2,mesh3,itime+1);
|
||||
p0 = lerp(a0,b0,ftime);
|
||||
p1 = lerp(a1,b1,ftime);
|
||||
p2 = lerp(a2,b2,ftime);
|
||||
Vec3vf4 a0,a1,a2; gather(a0,a1,a2,mesh,itime);
|
||||
Vec3vf4 b0,b1,b2; gather(b0,b1,b2,mesh,itime+1);
|
||||
p0 = lerp(a0,b0,vfloat4(ftime));
|
||||
p1 = lerp(a1,b1,vfloat4(ftime));
|
||||
p2 = lerp(a2,b2,vfloat4(ftime));
|
||||
}
|
||||
|
||||
template<int M>
|
||||
|
||||
@@ -167,8 +167,7 @@ namespace embree
|
||||
const unsigned geomID = prim.geomID();
|
||||
const unsigned primID = prim.primID();
|
||||
const TriangleMesh* const mesh = scene->get<TriangleMesh>(geomID);
|
||||
const unsigned numTimeSegments = mesh->numTimeSegments();
|
||||
const range<int> itime_range = getTimeSegmentRange(time_range, (float)numTimeSegments);
|
||||
const range<int> itime_range = mesh->timeSegmentRange(time_range);
|
||||
assert(itime_range.size() == 1);
|
||||
const int ilower = itime_range.begin();
|
||||
const TriangleMesh::Triangle& tri = mesh->triangle(primID);
|
||||
@@ -179,7 +178,7 @@ namespace embree
|
||||
const Vec3fa& b1 = mesh->vertex(tri.v[1],ilower+1);
|
||||
const Vec3fa& c0 = mesh->vertex(tri.v[2],ilower+0);
|
||||
const Vec3fa& c1 = mesh->vertex(tri.v[2],ilower+1);
|
||||
const BBox1f time_range_v(float(ilower+0)/float(numTimeSegments),float(ilower+1)/float(numTimeSegments));
|
||||
const BBox1f time_range_v(mesh->timeStep(ilower+0),mesh->timeStep(ilower+1));
|
||||
auto a01 = globalLinear(std::make_pair(a0,a1),time_range_v);
|
||||
auto b01 = globalLinear(std::make_pair(b0,b1),time_range_v);
|
||||
auto c01 = globalLinear(std::make_pair(c0,c1),time_range_v);
|
||||
|
||||
@@ -24,10 +24,10 @@ float&\ RTCRayN_dir_y(RTCRayN*\ ray,\ unsigned\ int\ N,\ unsigned\ int\ i);
|
||||
float&\ RTCRayN_dir_z(RTCRayN*\ ray,\ unsigned\ int\ N,\ unsigned\ int\ i);
|
||||
float&\ RTCRayN_time\ (RTCRayN*\ ray,\ unsigned\ int\ N,\ unsigned\ int\ i);
|
||||
|
||||
float&\ \ \ \ RTCRayN_tfar\ (RTCRayN*\ ray,\ unsigned\ int\ N,\ unsigned\ int\ i);
|
||||
unsigned&\ RTCRayN_mask\ (RTCRayN*\ ray,\ unsigned\ int\ N,\ unsigned\ int\ i);
|
||||
unsigned&\ RTCRayN_id\ \ \ (RTCRayN*\ ray,\ unsigned\ int\ N,\ unsigned\ int\ i);
|
||||
unsigned&\ RTCRayN_flags(RTCRayN*\ ray,\ unsigned\ int\ N,\ unsigned\ int\ i);
|
||||
float&\ \ \ \ \ \ \ \ RTCRayN_tfar\ (RTCRayN*\ ray,\ unsigned\ int\ N,\ unsigned\ int\ i);
|
||||
unsigned\ int&\ RTCRayN_mask\ (RTCRayN*\ ray,\ unsigned\ int\ N,\ unsigned\ int\ i);
|
||||
unsigned\ int&\ RTCRayN_id\ \ \ (RTCRayN*\ ray,\ unsigned\ int\ N,\ unsigned\ int\ i);
|
||||
unsigned\ int&\ RTCRayN_flags(RTCRayN*\ ray,\ unsigned\ int\ N,\ unsigned\ int\ i);
|
||||
\f[]
|
||||
.fi
|
||||
.SS DESCRIPTION
|
||||
|
||||
@@ -3,20 +3,35 @@
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE\ \-
|
||||
\ \ Bezier\ curve\ geometry\ type\ using\ a\ sweep\ surface
|
||||
|
||||
RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE\ \-
|
||||
\ \ B\-spline\ curve\ geometry\ type\ using\ a\ sweep\ surface
|
||||
|
||||
RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE\ \-
|
||||
\ \ linear\ curve\ geometry\ type
|
||||
\ \ flat\ curve\ geometry\ with\ linear\ basis
|
||||
|
||||
RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE\ \-
|
||||
\ \ Bezier\ curve\ geometry\ type\ using\ a\ ribbon\ approximation
|
||||
\ \ flat\ curve\ geometry\ with\ cubic\ Bézier\ basis
|
||||
|
||||
RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE\ \-\
|
||||
\ \ B\-spline\ curve\ geometry\ type\ using\ a\ ribbon\ approximation
|
||||
\ \ flat\ curve\ geometry\ with\ cubic\ B\-spline\ basis
|
||||
|
||||
RTC_GEOMETRY_TYPE_FLAT_HERMITE_CURVE\ \-\
|
||||
\ \ flat\ curve\ geometry\ with\ cubic\ Hermite\ basis
|
||||
|
||||
RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BEZIER_CURVE\ \-
|
||||
\ \ flat\ normal\ oriented\ curve\ geometry\ with\ cubic\ Bézier\ basis
|
||||
|
||||
RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BSPLINE_CURVE\ \-\
|
||||
\ \ flat\ normal\ oriented\ curve\ geometry\ with\ cubic\ B\-spline\ basis
|
||||
|
||||
RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_HERMITE_CURVE\ \-\
|
||||
\ \ flat\ normal\ oriented\ curve\ geometry\ with\ cubic\ Hermite\ basis
|
||||
|
||||
RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE\ \-
|
||||
\ \ sweep\ surface\ curve\ geometry\ with\ cubic\ Bézier\ basis
|
||||
|
||||
RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE\ \-
|
||||
\ \ sweep\ surface\ curve\ geometry\ with\ cubic\ B\-spline\ basis
|
||||
|
||||
RTC_GEOMETRY_TYPE_ROUND_HERMITE_CURVE\ \-
|
||||
\ \ sweep\ surface\ curve\ geometry\ with\ cubic\ Hermite\ basis
|
||||
\f[]
|
||||
.fi
|
||||
.SS SYNOPSIS
|
||||
@@ -25,41 +40,103 @@ RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE\ \-\
|
||||
\f[C]
|
||||
#include\ <embree3/rtcore.h>
|
||||
|
||||
rtcNewGeometry(device,\ RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE);
|
||||
rtcNewGeometry(device,\ RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE);
|
||||
rtcNewGeometry(device,\ RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE);
|
||||
rtcNewGeometry(device,\ RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE);
|
||||
rtcNewGeometry(device,\ RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE);
|
||||
rtcNewGeometry(device,\ RTC_GEOMETRY_TYPE_FLAT_HERMITE_CURVE);
|
||||
rtcNewGeometry(device,\ RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BEZIER_CURVE);
|
||||
rtcNewGeometry(device,\ RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BSPLINE_CURVE);
|
||||
rtcNewGeometry(device,\ RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_HERMITE_CURVE);
|
||||
rtcNewGeometry(device,\ RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE);
|
||||
rtcNewGeometry(device,\ RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE);
|
||||
rtcNewGeometry(device,\ RTC_GEOMETRY_TYPE_ROUND_HERMITE_CURVE);
|
||||
\f[]
|
||||
.fi
|
||||
.SS DESCRIPTION
|
||||
.PP
|
||||
Curves with per vertex radii are supported with linear, cubic Bezier,
|
||||
and cubic B\-spline bases.
|
||||
Curves with per vertex radii are supported with linear, cubic Bézier,
|
||||
cubic B\-spline, and cubic Hermite bases.
|
||||
Such curve geometries are created by passing
|
||||
\f[C]RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE\f[],
|
||||
\f[C]RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE\f[],
|
||||
\f[C]RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE\f[],
|
||||
\f[C]RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE\f[], or
|
||||
\f[C]RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE\f[], to the
|
||||
\f[C]RTC_GEOMETRY_TYPE_FLAT_HERMITE_CURVE\f[],
|
||||
\f[C]RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_FLAT_BEZIER_CURVE\f[],
|
||||
\f[C]RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_FLAT_BSPLINE_CURVE\f[],
|
||||
\f[C]RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_FLAT_HERMITE_CURVE\f[],
|
||||
\f[C]RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE\f[],
|
||||
\f[C]RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE\f[], or
|
||||
\f[C]RTC_GEOMETRY_TYPE_ROUND_HERMITE_CURVE\f[] to the
|
||||
\f[C]rtcNewGeometry\f[] function.
|
||||
The curve indices can be specified through an index buffer
|
||||
(\f[C]RTC_BUFFER_TYPE_INDEX\f[]) and the curve vertices through a vertex
|
||||
buffer (\f[C]RTC_BUFFER_TYPE_VERTEX\f[]).
|
||||
For the Hermite basis a tangent buffer
|
||||
(\f[C]RTC_BUFFER_TYPE_TANGENT\f[]) and for normal oriented curves a
|
||||
normal buffer (\f[C]RTC_BUFFER_TYPE_NORMAL\f[]) has to get specified
|
||||
additionally.
|
||||
See \f[C]rtcSetGeometryBuffer\f[] and
|
||||
\f[C]rtcSetSharedGeometryBuffer\f[] for more details on how to set
|
||||
buffers.
|
||||
.PP
|
||||
The index buffer contains an array of 32\-bit indices
|
||||
(\f[C]RTC_FORMAT_UINT\f[] format), each pointing to the ID of the first
|
||||
control vertex.
|
||||
(\f[C]RTC_FORMAT_UINT\f[] format), each pointing to the first control
|
||||
vertex in the vertex buffer, but also to the first tangent in the
|
||||
tangent buffer, and first normal in the normal buffer if these buffers
|
||||
are present.
|
||||
.PP
|
||||
The vertex buffer stores each control vertex in the form of a single
|
||||
precision position and radius stored in \f[C]x\f[], \f[C]y\f[],
|
||||
\f[C]z\f[], \f[C]r\f[] order in memory (\f[C]RTC_FORMAT_FLOAT4\f[]
|
||||
precision position and radius stored in (\f[C]x\f[], \f[C]y\f[],
|
||||
\f[C]z\f[], \f[C]r\f[]) order in memory (\f[C]RTC_FORMAT_FLOAT4\f[]
|
||||
format).
|
||||
The number of vertices is inferred from the size of this buffer.
|
||||
The radii may be smaller than zero for the B\-Spline basis, but the
|
||||
interpolated radii should always be greater or equal to zero.
|
||||
The radii may be smaller than zero but the interpolated radii should
|
||||
always be greater or equal to zero.
|
||||
Similarly, the tangent buffer stores the derivative of each control
|
||||
vertex (\f[C]x\f[], \f[C]y\f[], \f[C]z\f[], \f[C]r\f[] order and
|
||||
\f[C]RTC_FORMAT_FLOAT4\f[] format) and the normal buffer stores a single
|
||||
precision normal per control vertex (\f[C]x\f[], \f[C]y\f[], \f[C]z\f[]
|
||||
order and \f[C]RTC_FORMAT_FLOAT3\f[] format).
|
||||
.PP
|
||||
For the linear basis the indices point to the first of 2 consecutive
|
||||
control points in the vertex buffer.
|
||||
The first control point is the start and the second control point the
|
||||
end of the line segment.
|
||||
When constructing hair strands in this basis, the end\-point can be
|
||||
shared with the start of the next line segment.
|
||||
.PP
|
||||
For the cubic Bézier basis the indices point to the first of 4
|
||||
consecutive control points in the vertex buffer.
|
||||
These control points use the cubic Bézier basis, where the first control
|
||||
point represents the start point of the curve, and the 4th control point
|
||||
the end point of the curve.
|
||||
The Bézier basis is interpolating, thus the curve does go exactly
|
||||
through the first and fourth control vertex.
|
||||
.PP
|
||||
For the cubic B\-spline basis the indices point to the first of 4
|
||||
consecutive control points in the vertex buffer.
|
||||
These control points make up a cardinal cubic B\-spline (implicit
|
||||
equidistant knot vector).
|
||||
This basis is not interpolating, thus the curve does in general not go
|
||||
through any of the control points directly.
|
||||
A big advantage of this basis is that 3 control points can be shared for
|
||||
two continuous neighboring curve segments, e.g.
|
||||
the curves (p0,p1,p2,p3) and (p1,p2,p3,p4) are C1 continuous.
|
||||
This feature make this basis a good choise to construct continuous
|
||||
multi\-segment curves, as memory consumption can be kept minimal.
|
||||
.PP
|
||||
For the cubic Hermite basis the indices point to the first of 2
|
||||
consecutive points in the vertex buffer, and the first of 2 consecutive
|
||||
tangents in the tangent buffer.
|
||||
These two points and two tangents make up a cubic Hermite curve.
|
||||
This basis is interpolating, thus does exactly go through the first and
|
||||
second control point, and the first order derivative at the begin and
|
||||
end matches exactly the value specified in the tangent buffer.
|
||||
When connecting two segments continuously, the end point and tangent of
|
||||
the previous segment can be shared.
|
||||
Different versions of Catmull\-Rom splines can be easily constructed
|
||||
usig the Hermite basis, by calculating a proper tangent buffer from the
|
||||
control points.
|
||||
.PP
|
||||
The \f[C]RTC_GEOMETRY_TYPE_FLAT_*\f[] flat mode is a fast mode designed
|
||||
to render distant hair.
|
||||
@@ -71,11 +148,64 @@ The number of quads to subdivide into can be specified through the
|
||||
\f[C]rtcSetGeometryTessellationRate\f[] function.
|
||||
By default the tessellation rate is 4.
|
||||
.PP
|
||||
The \f[C]RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_*\f[] mode is a mode designed
|
||||
to render blades of grass.
|
||||
In this mode the curve is rendered as a flat band whose center exactly
|
||||
follows the provided vertex spline, whose half width approximately
|
||||
follows the provided radius spline, and whose orientation follows the
|
||||
provided normals.
|
||||
For normal oriented curves, the indices point to the first of 2
|
||||
consecutive normals in the normal buffer.
|
||||
The normal of the constructed curve will match the direction of the
|
||||
first normal at the beginning, and the direction of the second normal at
|
||||
the end of the curve.
|
||||
Please note that this layout of the normal buffer is independent of the
|
||||
used basis for the curve itself.
|
||||
For the cubic B\-spline and cubic Hermite basis the stride from the
|
||||
first control vertex of the first and the next segment is typically 1,
|
||||
thus the normal buffer is compact and the curves share the normal at the
|
||||
begin and end.
|
||||
However, for the cubic Bézier basis, the stride is typically 3, thus
|
||||
begin and end normal cannot get shared.
|
||||
We recommend using the Hermite basis instead of the Bézier basis, as it
|
||||
allows a more compact layout.
|
||||
.PP
|
||||
To intersect the normal oriented curve, we perform a newton\-raphson
|
||||
style intersection of a ray with a tensor product surface of a linear
|
||||
basis (perpendicular to the curve) and cubic Bézier basis (along the
|
||||
curve).
|
||||
We construct the 8 control points of this surface in Bézier basis by
|
||||
calculating a normalized direction \f[C]d01=normalize(v1\-v0,n0)\f[] and
|
||||
\f[C]d23=normalize(v3\-v2,n1)\f[].
|
||||
These directions are perpendicular to the tangent direction of the
|
||||
center curve and first and second specified normal.
|
||||
The 8 control vertices of the surface are constructed as:
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
\ p00\ =\ v0\-r0*d01,\ p10\ =\ v0+r0*d01
|
||||
\ p01\ =\ v1\-r1*d01,\ p11\ =\ v1+r1*d01
|
||||
\ p02\ =\ v2\-r2*d23,\ p12\ =\ v2+r2*d23
|
||||
\ p03\ =\ v3\-r3*d23,\ p13\ =\ v3+r3*d23
|
||||
\f[]
|
||||
.fi
|
||||
.PP
|
||||
The center of this curve exactly follows the specified center spline,
|
||||
the normal at the start (and end) exactly match the fisrst (and second)
|
||||
specified normal, and the half width exactly matches the evaluated
|
||||
radius spline at the start (and end).
|
||||
In\-between the radius and orientation of the curve changes smoothly.
|
||||
Note that the construction does not work when the provided normals are
|
||||
parallel to the curve direction, as then no well defined perpendicular
|
||||
direction \f[C]d01\f[] or \f[C]d23\f[] are defined.
|
||||
For this reason thus the provided normals should best be kept as
|
||||
perpendicular to the curve direction as possible.
|
||||
.PP
|
||||
In the \f[C]RTC_GEOMETRY_TYPE_ROUND_*\f[] round mode, a real geometric
|
||||
surface is rendered for the curve, which is more expensive but allows
|
||||
closeup views.
|
||||
For the Bezier and B\-spline bases this mode renders a sweep surface by
|
||||
sweeping a varying radius circle tangential along the curve.
|
||||
This mode renders a sweep surface by sweeping a varying radius circle
|
||||
tangential along the curve.
|
||||
As a limitation, the radius of the curve has to be smaller than the
|
||||
curvature radius of the curve at each location on the curve.
|
||||
The round mode is currently not supported for the linear basis.
|
||||
@@ -83,19 +213,23 @@ The round mode is currently not supported for the linear basis.
|
||||
The intersection with the curve segment stores the parametric hit
|
||||
location along the curve segment as u\-coordinate (range 0 to +1).
|
||||
.PP
|
||||
For Bezier and B\-spline curves the v\-coordinate is set to the
|
||||
normalized distance in the range \-1 to +1.
|
||||
For Bézier, B\-spline, and Hermite curves, the v\-coordinate is set to
|
||||
the normalized distance in the range \-1 to +1.
|
||||
For the linear basis and in round mode the v\-coordinate is set to zero.
|
||||
.PP
|
||||
In flat mode, the geometry normal \f[C]Ng\f[] is set to the tangent of
|
||||
the curve at the hit location.
|
||||
In round mode, the geometry normal \f[C]Ng\f[] is set to the
|
||||
non\-normalized geometric normal of the surface.
|
||||
In round mode and for normal oriented curves, the geometry normal
|
||||
\f[C]Ng\f[] is set to the non\-normalized geometric normal of the
|
||||
surface.
|
||||
.PP
|
||||
For multi\-segment motion blur, the number of time steps must be first
|
||||
specified using the \f[C]rtcSetGeometryTimeStepCount\f[] call.
|
||||
Then a vertex buffer for each time step can be set using different
|
||||
buffer slots, and all these buffers must have the same stride and size.
|
||||
For the Hermite basis also a tangent buffer has to be set for each time
|
||||
step and for normal oriented curves a normal buffer has to get specified
|
||||
for each time step.
|
||||
.PP
|
||||
Also see tutorials [Hair] and [Curves] for examples of how to create and
|
||||
use curve geometries.
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
.TH "RTC_GEOMETRY_TYPE_GRID" "3" "" "" "Embree Ray Tracing Kernels 3"
|
||||
.SS NAME
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
RTC_GEOMETRY_TYPE_GRID\ \-\ grid\ geometry\ type
|
||||
\f[]
|
||||
.fi
|
||||
.SS SYNOPSIS
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
#include\ <embree3/rtcore.h>
|
||||
|
||||
RTCGeometry\ geometry\ =
|
||||
\ \ rtcNewGeometry(device,\ RTC_GEOMETRY_TYPE_GRID);
|
||||
\f[]
|
||||
.fi
|
||||
.SS DESCRIPTION
|
||||
.PP
|
||||
Grid meshes are created by passing \f[C]RTC_GEOMETRY_TYPE_GRID\f[] to
|
||||
the \f[C]rtcNewGeometry\f[] function call, and contain an array of grid
|
||||
primitives.
|
||||
This array of grids can be specified by setting up a grid buffer (with
|
||||
\f[C]RTC_BUFFER_TYPE_GRID\f[] type and \f[C]RTC_FORMAT_GRID\f[] format)
|
||||
and the grid mesh vertices by setting a vertex buffer
|
||||
(\f[C]RTC_BUFFER_TYPE_VERTEX\f[] type).
|
||||
See \f[C]rtcSetGeometryBuffer\f[] and
|
||||
\f[C]rtcSetSharedGeometryBuffer\f[] for more details on how to set
|
||||
buffers.
|
||||
The number of grid primitives in the grid mesh is inferred from the size
|
||||
of the grid buffer.
|
||||
.PP
|
||||
The vertex buffer contains an array of single precision \f[C]x\f[],
|
||||
\f[C]y\f[], \f[C]z\f[] floating point coordinates
|
||||
(\f[C]RTC_FORMAT_FLOAT3\f[] format), and the number of vertices is
|
||||
inferred from the size of that buffer.
|
||||
.PP
|
||||
Each grid in the grid buffer is of the type \f[C]RTCGrid\f[]:
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
struct\ RTCGrid
|
||||
{
|
||||
\ \ unsigned\ int\ startVertexID;
|
||||
\ \ unsigned\ int\ stride;
|
||||
\ \ unsigned\ short\ width,height;\
|
||||
};
|
||||
\f[]
|
||||
.fi
|
||||
.PP
|
||||
The \f[C]RTCGrid\f[] structure describes a 2D grid of vertices (with
|
||||
respect to the vertex buffer of the grid mesh).
|
||||
The \f[C]width\f[] and \f[C]height\f[] members specify the number of
|
||||
vertices in u and v direction, e.g.
|
||||
setting both \f[C]width\f[] and \f[C]height\f[] to 3 sets up a 3x3
|
||||
vertex grid.
|
||||
The maximum allowed \f[C]width\f[] and \f[C]height\f[] is 32767.
|
||||
The \f[C]startVertexID\f[] specifies the ID of the top\-left vertex in
|
||||
the vertex grid, while the \f[C]stride\f[] parameter specifies a stride
|
||||
(in number of vertices) used to step to the next row.
|
||||
.PP
|
||||
A vertex grid of dimensions \f[C]width\f[] and \f[C]height\f[] is
|
||||
treated as a \f[C](width\-1)\f[] x \f[C](height\-1)\f[] grid of
|
||||
\f[C]quads\f[] (triangle\-pairs), with the same shared edge handling as
|
||||
for regular quad meshes.
|
||||
However, the \f[C]u\f[]/\f[C]v\f[] coordinates have the uniform range
|
||||
\f[C][0..1]\f[] for an entire vertex grid.
|
||||
The \f[C]u\f[] direction follows the \f[C]width\f[] of the grid while
|
||||
the \f[C]v\f[] direction the \f[C]height\f[].
|
||||
.PP
|
||||
For multi\-segment motion blur, the number of time steps must be first
|
||||
specified using the \f[C]rtcSetGeometryTimeStepCount\f[] call.
|
||||
Then a vertex buffer for each time step can be set using different
|
||||
buffer slots, and all these buffers must have the same stride and size.
|
||||
.SS EXIT STATUS
|
||||
.PP
|
||||
On failure \f[C]NULL\f[] is returned and an error code is set that can
|
||||
be queried using \f[C]rtcDeviceGetError\f[].
|
||||
.SS SEE ALSO
|
||||
.PP
|
||||
[rtcNewGeometry]
|
||||
@@ -27,7 +27,7 @@ See \f[C]rtcSetGeometryBuffer\f[] and
|
||||
\f[C]rtcSetSharedGeometryBuffer\f[] for more details on how to set
|
||||
buffers.
|
||||
The index buffer contains an array of four 32\-bit indices per quad
|
||||
(\f[C]RTC_FORMAT_UINT\f[] format), and the number of primitives is
|
||||
(\f[C]RTC_FORMAT_UINT4\f[] format), and the number of primitives is
|
||||
inferred from the size of that buffer.
|
||||
The vertex buffer contains an array of single precision \f[C]x\f[],
|
||||
\f[C]y\f[], \f[C]z\f[] floating point coordinates
|
||||
|
||||
@@ -38,4 +38,4 @@ On failure an error code is set that can be queried using
|
||||
\f[C]rtcDeviceGetError\f[].
|
||||
.SS SEE ALSO
|
||||
.PP
|
||||
[rtcCommitJoinScene]
|
||||
[rtcJoinCommitScene]
|
||||
|
||||
@@ -14,7 +14,7 @@ rtcGetDeviceProperty\ \-\ queries\ properties\ of\ the\ device
|
||||
|
||||
ssize_t\ rtcGetDeviceProperty(
|
||||
\ \ RTCDevice\ device,
|
||||
\ \ RTCDeviceProperty\ prop
|
||||
\ \ enum\ RTCDeviceProperty\ prop
|
||||
);
|
||||
\f[]
|
||||
.fi
|
||||
@@ -27,6 +27,20 @@ The returned property is an integer of type \f[C]ssize_t\f[].
|
||||
.PP
|
||||
Possible properties to query are:
|
||||
.IP \[bu] 2
|
||||
\f[C]RTC_DEVICE_PROPERTY_VERSION\f[]: Queries the combined version
|
||||
number (MAJOR.MINOR.PATCH) with two decimal digits per component.
|
||||
E.g.
|
||||
for Embree 2.8.3 the integer 208003 is returned.
|
||||
.IP \[bu] 2
|
||||
\f[C]RTC_DEVICE_PROPERTY_VERSION_MAJOR\f[]: Queries the major version
|
||||
number of Embree.
|
||||
.IP \[bu] 2
|
||||
\f[C]RTC_DEVICE_PROPERTY_VERSION_MINOR\f[]: Queries the minor version
|
||||
number of Embree.
|
||||
.IP \[bu] 2
|
||||
\f[C]RTC_DEVICE_PROPERTY_VERSION_PATCH\f[]: Queries the patch version
|
||||
number of Embree.
|
||||
.IP \[bu] 2
|
||||
\f[C]RTC_DEVICE_PROPERTY_NATIVE_RAY4_SUPPORTED\f[]: Queries whether the
|
||||
\f[C]rtcIntersect4\f[] and \f[C]rtcOccluded4\f[] functions preserve
|
||||
packet size and ray order when invoking callback functions.
|
||||
@@ -77,6 +91,26 @@ with \f[C]EMBREE_FILTER_FUNCTION\f[] enabled.
|
||||
whether invalid rays are ignored, which is the case if Embree is
|
||||
compiled with \f[C]EMBREE_IGNORE_INVALID_RAYS\f[] enabled.
|
||||
.IP \[bu] 2
|
||||
\f[C]RTC_DEVICE_PROPERTY_TRIANGLE_GEOMETRY_SUPPORTED\f[]: Queries
|
||||
whether triangles are supported, which is the case if Embree is compiled
|
||||
with \f[C]EMBREE_GEOMETRY_TRIANGLE\f[] enabled.
|
||||
.IP \[bu] 2
|
||||
\f[C]RTC_DEVICE_PROPERTY_QUAD_GEOMETRY_SUPPORTED\f[]: Queries whether
|
||||
quads are supported, which is the case if Embree is compiled with
|
||||
\f[C]EMBREE_GEOMETRY_QUAD\f[] enabled.
|
||||
.IP \[bu] 2
|
||||
\f[C]RTC_DEVICE_PROPERTY_SUBDIVISION_GEOMETRY_SUPPORTED\f[]: Queries
|
||||
whether subdivision meshes are supported, which is the case if Embree is
|
||||
compiled with \f[C]EMBREE_GEOMETRY_SUBDIVISION\f[] enabled.
|
||||
.IP \[bu] 2
|
||||
\f[C]RTC_DEVICE_PROPERTY_CURVE_GEOMETRY_SUPPORTED\f[]: Queries whether
|
||||
curves are supported, which is the case if Embree is compiled with
|
||||
\f[C]EMBREE_GEOMETRY_CURVE\f[] enabled.
|
||||
.IP \[bu] 2
|
||||
\f[C]RTC_DEVICE_PROPERTY_USER_GEOMETRY_SUPPORTED\f[]: Queries whether
|
||||
user geometries are supported, which is the case if Embree is compiled
|
||||
with \f[C]EMBREE_GEOMETRY_USER\f[] enabled.
|
||||
.IP \[bu] 2
|
||||
\f[C]RTC_DEVICE_PROPERTY_TASKING_SYSTEM\f[]: Queries the tasking system
|
||||
Embree is compiled with.
|
||||
Possible return values are:
|
||||
@@ -89,40 +123,6 @@ Intel Threading Building Blocks (TBB)
|
||||
Parallel Patterns Library (PPL)
|
||||
.RE
|
||||
.IP \[bu] 2
|
||||
\f[C]RTC_DEVICE_PROPERTY_VERSION_MAJOR\f[]: Queries the major version
|
||||
number of Embree.
|
||||
.IP \[bu] 2
|
||||
\f[C]RTC_DEVICE_PROPERTY_VERSION_MINOR\f[]: Queries the minor version
|
||||
number of Embree.
|
||||
.IP \[bu] 2
|
||||
\f[C]RTC_DEVICE_PROPERTY_VERSION_PATCH\f[]: Queries the patch version
|
||||
number of Embree.
|
||||
.IP \[bu] 2
|
||||
\f[C]RTC_DEVICE_PROPERTY_VERSION\f[]: Queries the combined version
|
||||
number (MAJOR.MINOR.PATCH) with two decimal digits per component.
|
||||
E.g.
|
||||
for Embree 2.8.3 the integer 208003 is returned.
|
||||
.IP \[bu] 2
|
||||
\f[C]RTC_DEVICE_PROPERTY_TRIANGLE_GEOMETRY_SUPPORTED\f[]: Queries
|
||||
whether triangles are supported, which is the case if Embree is compiled
|
||||
with \f[C]EMBREE_GEOMETRY_TRIANGLE\f[] enabled.
|
||||
.IP \[bu] 2
|
||||
\f[C]RTC_DEVICE_PROPERTY_QUAD_GEOMETRY_SUPPORTED\f[]: Queries whether
|
||||
quads are supported, which is the case if Embree is compiled with
|
||||
\f[C]EMBREE_GEOMETRY_QUAD\f[] enabled.
|
||||
.IP \[bu] 2
|
||||
\f[C]RTC_DEVICE_PROPERTY_CURVE_GEOMETRY_SUPPORTED\f[]: Queries whether
|
||||
curves are supported, which is the case if Embree is compiled with
|
||||
\f[C]EMBREE_GEOMETRY_CURVE\f[] enabled.
|
||||
.IP \[bu] 2
|
||||
\f[C]RTC_DEVICE_PROPERTY_SUBDIVISION_GEOMETRY_SUPPORTED\f[]: Queries
|
||||
whether subdivision meshes are supported, which is the case if Embree is
|
||||
compiled with \f[C]EMBREE_GEOMETRY_SUBDIVISION\f[] enabled.
|
||||
.IP \[bu] 2
|
||||
\f[C]RTC_DEVICE_PROPERTY_USER_GEOMETRY_SUPPORTED\f[]: Queries whether
|
||||
user geometries are supported, which is the case if Embree is compiled
|
||||
with \f[C]EMBREE_GEOMETRY_USER\f[] enabled.
|
||||
.IP \[bu] 2
|
||||
\f[C]RTC_DEVICE_PROPERTY_COMMIT_JOIN_SUPPORTED\f[]: Queries whether
|
||||
\f[C]rtcJoinCommitScene\f[] is supported.
|
||||
This is not the case when Embree is compiled with PPL or older versions
|
||||
@@ -135,6 +135,3 @@ For properties returning a boolean value, the return value 0 denotes
|
||||
.PP
|
||||
On failure zero is returned and an error code is set that can be queried
|
||||
using \f[C]rtcDeviceGetError\f[].
|
||||
.SS SEE ALSO
|
||||
.PP
|
||||
[rtcSetDeviceProperty]
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
.TH "rtcGetGeometryFace" "3" "" "" "Embree Ray Tracing Kernels 3"
|
||||
.SS NAME
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
rtcGetGeometryFace\ \-\ returns\ the\ face\ of\ some\ half\ edge
|
||||
\f[]
|
||||
.fi
|
||||
.SS SYNOPSIS
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
#include\ <embree3/rtcore.h>
|
||||
|
||||
unsigned\ int\ rtcGetGeometryFace(
|
||||
\ \ RTCGeometry\ geometry,
|
||||
\ \ unsigned\ int\ edgeID
|
||||
);
|
||||
\f[]
|
||||
.fi
|
||||
.SS DESCRIPTION
|
||||
.PP
|
||||
The \f[C]rtcGetGeometryFace\f[] function returns the ID of the face the
|
||||
specified half edge (\f[C]edgeID\f[] argument) belongs to.
|
||||
For instance in the following example the face \f[C]f1\f[] is returned
|
||||
for edges \f[C]e4\f[], \f[C]e5\f[], \f[C]e6\f[], and \f[C]e7\f[].
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
\f[]
|
||||
.fi
|
||||
.PP
|
||||
This function can only be used for subdivision geometries.
|
||||
As all topologies of a subdivision geometry share the same face buffer
|
||||
the function does not depend on the topology ID.
|
||||
.SS EXIT STATUS
|
||||
.PP
|
||||
On failure an error code is set that can be queried using
|
||||
\f[C]rtcDeviceGetError\f[].
|
||||
.SS SEE ALSO
|
||||
.PP
|
||||
[rtcGetGeometryFirstHalfEdge], [rtcGetGeometryFace],
|
||||
[rtcGetGeometryOppositeHalfEdge], [rtcGetGeometryNextHalfEdge],
|
||||
[rtcGetGeometryPreviousHalfEdge]
|
||||
@@ -0,0 +1,53 @@
|
||||
.TH "rtcGetGeometryFirstHalfEdge" "3" "" "" "Embree Ray Tracing Kernels 3"
|
||||
.SS NAME
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
rtcGetGeometryFirstHalfEdge\ \-\ returns\ the\ first\ half\ edge\ of\ a\ face
|
||||
\f[]
|
||||
.fi
|
||||
.SS SYNOPSIS
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
#include\ <embree3/rtcore.h>
|
||||
|
||||
unsigned\ int\ rtcGetGeometryFirstHalfEdge(
|
||||
\ \ RTCGeometry\ geometry,
|
||||
\ \ unsigned\ int\ faceID
|
||||
);
|
||||
\f[]
|
||||
.fi
|
||||
.SS DESCRIPTION
|
||||
.PP
|
||||
The \f[C]rtcGetGeometryFirstHalfEdge\f[] function returns the ID of the
|
||||
first half edge belonging to the specified face (\f[C]faceID\f[]
|
||||
argument).
|
||||
For instance in the following example the first half edge of face
|
||||
\f[C]f1\f[] is \f[C]e4\f[].
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
\f[]
|
||||
.fi
|
||||
.PP
|
||||
This function can only be used for subdivision geometries.
|
||||
As all topologies of a subdivision geometry share the same face buffer
|
||||
the function does not depend on the topology ID.
|
||||
.PP
|
||||
Here f0 to f7 are 8 quadrilateral faces with 4 vertices each.
|
||||
The edges e0 to e23 of these faces are shown with their orientation.
|
||||
For each face the ID of the edges corresponds to the slots the face
|
||||
occupies in the index array of the geometry.
|
||||
E.g.
|
||||
as the indices of face f1 start at location 4 of the index array, the
|
||||
first edge is edge e4, the next edge e5, etc.
|
||||
.SS EXIT STATUS
|
||||
.PP
|
||||
On failure an error code is set that can be queried using
|
||||
\f[C]rtcDeviceGetError\f[].
|
||||
.SS SEE ALSO
|
||||
.PP
|
||||
[rtcGetGeometryFirstHalfEdge], [rtcGetGeometryFace],
|
||||
[rtcGetGeometryOppositeHalfEdge], [rtcGetGeometryNextHalfEdge],
|
||||
[rtcGetGeometryPreviousHalfEdge]
|
||||
@@ -0,0 +1,44 @@
|
||||
.TH "rtcGetGeometryNextHalfEdge" "3" "" "" "Embree Ray Tracing Kernels 3"
|
||||
.SS NAME
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
rtcGetGeometryNextHalfEdge\ \-\ returns\ the\ next\ half\ edge
|
||||
\f[]
|
||||
.fi
|
||||
.SS SYNOPSIS
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
#include\ <embree3/rtcore.h>
|
||||
|
||||
unsigned\ int\ rtcGetGeometryNextHalfEdge(
|
||||
\ \ RTCGeometry\ geometry,
|
||||
\ \ unsigned\ int\ edgeID
|
||||
);
|
||||
\f[]
|
||||
.fi
|
||||
.SS DESCRIPTION
|
||||
.PP
|
||||
The \f[C]rtcGetGeometryNextHalfEdge\f[] function returns the ID of the
|
||||
next half edge of the specified half edge (\f[C]edgeID\f[] argument).
|
||||
For instance in the following example the next half edge of \f[C]e10\f[]
|
||||
is \f[C]e11\f[].
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
\f[]
|
||||
.fi
|
||||
.PP
|
||||
This function can only be used for subdivision geometries.
|
||||
As all topologies of a subdivision geometry share the same face buffer
|
||||
the function does not depend on the topology ID.
|
||||
.SS EXIT STATUS
|
||||
.PP
|
||||
On failure an error code is set that can be queried using
|
||||
\f[C]rtcDeviceGetError\f[].
|
||||
.SS SEE ALSO
|
||||
.PP
|
||||
[rtcGetGeometryFirstHalfEdge], [rtcGetGeometryFace],
|
||||
[rtcGetGeometryOppositeHalfEdge], [rtcGetGeometryNextHalfEdge],
|
||||
[rtcGetGeometryPreviousHalfEdge]
|
||||
@@ -0,0 +1,51 @@
|
||||
.TH "rtcGetGeometryOppositeHalfEdge" "3" "" "" "Embree Ray Tracing Kernels 3"
|
||||
.SS NAME
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
rtcGetGeometryOppositeHalfEdge\ \-\ returns\ the\ opposite\ half\ edge
|
||||
\f[]
|
||||
.fi
|
||||
.SS SYNOPSIS
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
#include\ <embree3/rtcore.h>
|
||||
|
||||
unsigned\ int\ rtcGetGeometryOppositeHalfEdge(
|
||||
\ \ RTCGeometry\ geometry,
|
||||
\ \ unsigned\ int\ topologyID,
|
||||
\ \ unsigned\ int\ edgeID
|
||||
);
|
||||
\f[]
|
||||
.fi
|
||||
.SS DESCRIPTION
|
||||
.PP
|
||||
The \f[C]rtcGetGeometryOppositeHalfEdge\f[] function returns the ID of
|
||||
the opposite half edge of the specified half edge (\f[C]edgeID\f[]
|
||||
argument) in the specified topology (\f[C]topologyID\f[] argument).
|
||||
For instance in the following example the opposite half edge of
|
||||
\f[C]e6\f[] is \f[C]e16\f[].
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
\f[]
|
||||
.fi
|
||||
.PP
|
||||
An opposite half edge does not exist if the specified half edge has
|
||||
either no neighboring face, or more than 2 neighboring faces.
|
||||
In these cases the function just returns the same edge \f[C]edgeID\f[]
|
||||
again.
|
||||
.PP
|
||||
This function can only be used for subdivision geometries.
|
||||
The function depends on the topology as the topologies of a subdivision
|
||||
geometry have different index buffers assigned.
|
||||
.SS EXIT STATUS
|
||||
.PP
|
||||
On failure an error code is set that can be queried using
|
||||
\f[C]rtcDeviceGetError\f[].
|
||||
.SS SEE ALSO
|
||||
.PP
|
||||
[rtcGetGeometryFirstHalfEdge], [rtcGetGeometryFace],
|
||||
[rtcGetGeometryOppositeHalfEdge], [rtcGetGeometryNextHalfEdge],
|
||||
[rtcGetGeometryPreviousHalfEdge]
|
||||
@@ -0,0 +1,45 @@
|
||||
.TH "rtcGetGeometryPreviousHalfEdge" "3" "" "" "Embree Ray Tracing Kernels 3"
|
||||
.SS NAME
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
rtcGetGeometryPreviousHalfEdge\ \-\ returns\ the\ previous\ half\ edge
|
||||
\f[]
|
||||
.fi
|
||||
.SS SYNOPSIS
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
#include\ <embree3/rtcore.h>
|
||||
|
||||
unsigned\ int\ rtcGetGeometryPreviousHalfEdge(
|
||||
\ \ RTCGeometry\ geometry,
|
||||
\ \ unsigned\ int\ edgeID
|
||||
);
|
||||
\f[]
|
||||
.fi
|
||||
.SS DESCRIPTION
|
||||
.PP
|
||||
The \f[C]rtcGetGeometryPreviousHalfEdge\f[] function returns the ID of
|
||||
the previous half edge of the specified half edge (\f[C]edgeID\f[]
|
||||
argument).
|
||||
For instance in the following example the previous half edge of
|
||||
\f[C]e6\f[] is \f[C]e5\f[].
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
\f[]
|
||||
.fi
|
||||
.PP
|
||||
This function can only be used for subdivision geometries.
|
||||
As all topologies of a subdivision geometry share the same face buffer
|
||||
the function does not depend on the topology ID.
|
||||
.SS EXIT STATUS
|
||||
.PP
|
||||
On failure an error code is set that can be queried using
|
||||
\f[C]rtcDeviceGetError\f[].
|
||||
.SS SEE ALSO
|
||||
.PP
|
||||
[rtcGetGeometryFirstHalfEdge], [rtcGetGeometryFace],
|
||||
[rtcGetGeometryOppositeHalfEdge], [rtcGetGeometryNextHalfEdge],
|
||||
[rtcGetGeometryPreviousHalfEdge]
|
||||
@@ -74,12 +74,12 @@ or accumulating transparencies.
|
||||
The support for the context filter function must be enabled for a scene
|
||||
by using the \f[C]RTC_SCENE_FLAG_CONTEXT_FILTER_FUNCTION\f[] scene flag.
|
||||
.PP
|
||||
Is is guaranteed that the pointer to the intersection context passed to
|
||||
It is guaranteed that the pointer to the intersection context passed to
|
||||
a ray query is directly passed to the registered callback functions.
|
||||
This way it is possible to attach arbitrary data to the end of the
|
||||
intersection context, such as a per\-ray payload.
|
||||
.PP
|
||||
Please not that the ray pointer is not guaranteed to be passed to the
|
||||
Please note that the ray pointer is not guaranteed to be passed to the
|
||||
callback functions, thus reading additional data from the ray pointer
|
||||
passed to callbacks is not possible.
|
||||
.SS EXIT STATUS
|
||||
|
||||
@@ -16,7 +16,8 @@ struct\ RTCInterpolateArguments
|
||||
{
|
||||
\ \ RTCGeometry\ geometry;
|
||||
\ \ unsigned\ int\ primID;
|
||||
\ \ float\ u,\ v;
|
||||
\ \ float\ u;
|
||||
\ \ float\ v;
|
||||
\ \ enum\ RTCBufferType\ bufferType;
|
||||
\ \ unsigned\ int\ bufferSlot;
|
||||
\ \ float*\ P;
|
||||
|
||||
@@ -67,17 +67,17 @@ For \f[C]rtcIntersect4\f[] the ray packet must be aligned to 16 bytes,
|
||||
for \f[C]rtcIntersect8\f[] the alignment must be 32 bytes, and for
|
||||
\f[C]rtcIntersect16\f[] the alignment must be 64 bytes.
|
||||
.PP
|
||||
Further, \f[C]rtcIntersect4\f[] is only available when Embree was
|
||||
compiled with \f[C]EMBREE_RAY_PACKETS\f[] turned on in CMake (which is
|
||||
the default).
|
||||
Further, the \f[C]rtcIntersect8\f[] function works only if Embree was
|
||||
compiled with \f[C]AVX\f[] or \f[C]AVX2\f[], and if the CPU it is
|
||||
running on supports the enabled ISA.
|
||||
Similar, the \f[C]rtcIntersect16\f[] function works only if Embree was
|
||||
compiled with \f[C]AVX512SKX\f[] or \f[C]AVX512KNL\f[] and the CPU it is
|
||||
running on supports the enabled ISA.
|
||||
For this reason, use these functions only after checking whether they
|
||||
are available by using an \f[C]rtcGetDeviceParameter\f[] query.
|
||||
The \f[C]rtcIntersect4\f[], \f[C]rtcIntersect8\f[] and
|
||||
\f[C]rtcIntersect16\f[] functions may change the ray packet size and ray
|
||||
order when calling back into intersect filter functions or user geometry
|
||||
callbacks.
|
||||
Under some conditions the application can assume packets to stay intakt,
|
||||
which can determined by querying the
|
||||
\f[C]RTC_DEVICE_PROPERTY_NATIVE_RAY4_SUPPORTED\f[],
|
||||
\f[C]RTC_DEVICE_PROPERTY_NATIVE_RAY8_SUPPORTED\f[],
|
||||
\f[C]RTC_DEVICE_PROPERTY_NATIVE_RAY16_SUPPORTED\f[] properties through
|
||||
the \f[C]rtcGetDeviceProperty\f[] function.
|
||||
See [rtcGetDeviceProperty] for more information.
|
||||
.SS EXIT STATUS
|
||||
.PP
|
||||
For performance reasons this function does not do any error checks, thus
|
||||
|
||||
@@ -22,6 +22,9 @@ enum\ RTCGeometryType
|
||||
\ RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE,
|
||||
\ RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE,
|
||||
\ RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE,
|
||||
\ RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BEZIER_CURVE,
|
||||
\ RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BSPLINE_CURVE,
|
||||
\ RTC_GEOMETRY_TYPE_GRID,
|
||||
\ RTC_GEOMETRY_TYPE_USER,
|
||||
\ RTC_GEOMETRY_TYPE_INSTANCE
|
||||
};
|
||||
@@ -52,8 +55,11 @@ with different bases (\f[C]RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE\f[],
|
||||
\f[C]RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE\f[],
|
||||
\f[C]RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE\f[],
|
||||
\f[C]RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE\f[],
|
||||
\f[C]RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE\f[] types), user\-defined
|
||||
geometries (\f[C]RTC_GEOMETRY_TYPE_USER\f[]), and instances
|
||||
\f[C]RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE\f[],
|
||||
\f[C]RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BEZIER_CURVE\f[],
|
||||
\f[C]RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BSPLINE_CURVE\f[] types), grid
|
||||
meshes (\f[C]RTC_GEOMETRY_TYPE_GRID\f[]), user\-defined geometries
|
||||
(\f[C]RTC_GEOMETRY_TYPE_USER\f[]), and instances
|
||||
(\f[C]RTC_GEOMETRY_TYPE_INSTANCE\f[]).
|
||||
.PP
|
||||
The types \f[C]RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE\f[] and
|
||||
@@ -112,5 +118,5 @@ be queried using \f[C]rtcDeviceGetError\f[].
|
||||
[rtcInterpolate], [rtcInterpolateN], [rtcSetGeometryBuildQuality],
|
||||
[rtcSetSceneBuildQuality], [RTC_GEOMETRY_TYPE_TRIANGLE],
|
||||
[RTC_GEOMETRY_TYPE_QUAD], [RTC_GEOMETRY_TYPE_SUBDIVISION],
|
||||
[RTC_GEOMETRY_TYPE_CURVE], [RTC_GEOMETRY_TYPE_USER],
|
||||
[RTC_GEOMETRY_TYPE_INSTANCE]
|
||||
[RTC_GEOMETRY_TYPE_CURVE], [RTC_GEOMETRY_TYPE_GRID],
|
||||
[RTC_GEOMETRY_TYPE_USER], [RTC_GEOMETRY_TYPE_INSTANCE]
|
||||
|
||||
@@ -15,7 +15,7 @@ rtcOccluded1M\ \-\ finds\ any\ hits\ for\ a\ stream\ of\ M\ single\ rays
|
||||
void\ rtcOccluded1M(
|
||||
\ \ RTCScene\ scene,
|
||||
\ \ struct\ RTCIntersectContext*\ context,
|
||||
\ \ struct\ RTCRay*\ rays,
|
||||
\ \ struct\ RTCRay*\ ray,
|
||||
\ \ unsigned\ int\ M,
|
||||
\ \ size_t\ byteStride
|
||||
);
|
||||
@@ -24,10 +24,10 @@ void\ rtcOccluded1M(
|
||||
.SS DESCRIPTION
|
||||
.PP
|
||||
The \f[C]rtcOccluded1M\f[] function checks whether there are any hits
|
||||
for a stream of \f[C]M\f[] single rays (\f[C]rays\f[] argument) with the
|
||||
for a stream of \f[C]M\f[] single rays (\f[C]ray\f[] argument) with the
|
||||
scene (\f[C]scene\f[] argument).
|
||||
The \f[C]rays\f[] argument points to an array of rays with specified
|
||||
byte stride (\f[C]byteStride\f[] argument) between the rays.
|
||||
The \f[C]ray\f[] argument points to an array of rays with specified byte
|
||||
stride (\f[C]byteStride\f[] argument) between the rays.
|
||||
See Section [rtcOccluded1] for a description of how to set up and trace
|
||||
occlusion rays.
|
||||
.IP
|
||||
|
||||
@@ -16,7 +16,7 @@ rtcOccluded1Mp\ \-\ find\ any\ hits\ for\ a\ stream\ of\ M\ pointers\ to
|
||||
void\ rtcOccluded1M(
|
||||
\ \ RTCScene\ scene,
|
||||
\ \ struct\ RTCIntersectContext*\ context,
|
||||
\ \ struct\ RTCRay**\ rays,
|
||||
\ \ struct\ RTCRay**\ ray,
|
||||
\ \ unsigned\ int\ M
|
||||
);
|
||||
\f[]
|
||||
@@ -24,9 +24,9 @@ void\ rtcOccluded1M(
|
||||
.SS DESCRIPTION
|
||||
.PP
|
||||
The \f[C]rtcOccluded1Mp\f[] function checks whether there are any hits
|
||||
for a stream of \f[C]M\f[] single rays (\f[C]rays\f[] argument) with the
|
||||
for a stream of \f[C]M\f[] single rays (\f[C]ray\f[] argument) with the
|
||||
scene (\f[C]scene\f[] argument).
|
||||
The \f[C]rays\f[] argument points to an array of pointers to rays.
|
||||
The \f[C]ray\f[] argument points to an array of pointers to rays.
|
||||
Section [rtcOccluded1] for a description of how to set up and trace a
|
||||
occlusion rays.
|
||||
.IP
|
||||
|
||||
@@ -66,17 +66,17 @@ For \f[C]rtcOccluded4\f[] the ray packet must be aligned to 16 bytes,
|
||||
for \f[C]rtcOccluded8\f[] the alignment must be 32 bytes, and for
|
||||
\f[C]rtcOccluded16\f[] the alignment must be 64 bytes.
|
||||
.PP
|
||||
Further, \f[C]rtcOccluded4\f[] is only available when Embree was
|
||||
compiled with \f[C]EMBREE_RAY_PACKETS\f[] turned on in CMake (which is
|
||||
the default).
|
||||
Further, the \f[C]rtcOccluded8\f[] function is works only if Embree was
|
||||
compiled with \f[C]AVX\f[] or \f[C]AVX2\f[] and the CPU it is running on
|
||||
supports the enabled ISA.
|
||||
Similar, the \f[C]rtcOccluded16\f[] function works only if Embree was
|
||||
compiled with \f[C]AVX512SKX\f[] or \f[C]AVX512KNL\f[] and the CPU it is
|
||||
running on supports the enabled ISA.
|
||||
For this reason, use these functions only after checking whether they
|
||||
are available by using an \f[C]rtcGetDeviceParameter\f[] query.
|
||||
The \f[C]rtcOccluded4\f[], \f[C]rtcOccluded8\f[] and
|
||||
\f[C]rtcOccluded16\f[] functions may change the ray packet size and ray
|
||||
order when calling back into intersect filter functions or user geometry
|
||||
callbacks.
|
||||
Under some conditions the application can assume packets to stay intakt,
|
||||
which can determined by querying the
|
||||
\f[C]RTC_DEVICE_PROPERTY_NATIVE_RAY4_SUPPORTED\f[],
|
||||
\f[C]RTC_DEVICE_PROPERTY_NATIVE_RAY8_SUPPORTED\f[],
|
||||
\f[C]RTC_DEVICE_PROPERTY_NATIVE_RAY16_SUPPORTED\f[] properties through
|
||||
the \f[C]rtcGetDeviceProperty\f[] function.
|
||||
See [rtcGetDeviceProperty] for more information.
|
||||
.SS EXIT STATUS
|
||||
.PP
|
||||
For performance reasons this function does not do any error checks, thus
|
||||
|
||||
@@ -16,7 +16,7 @@ rtcOccludedNM\ \-\ finds\ any\ hits\ for\ a\ stream\ of\ M\ ray\ packets\ of
|
||||
void\ rtcOccludedNM(
|
||||
\ \ RTCScene\ scene,
|
||||
\ \ struct\ RTCIntersectContext*\ context,
|
||||
\ \ struct\ RTCRayN*\ rays,
|
||||
\ \ struct\ RTCRayN*\ ray,
|
||||
\ \ unsigned\ int\ N,
|
||||
\ \ unsigned\ int\ M,
|
||||
\ \ size_t\ byteStride
|
||||
@@ -26,9 +26,9 @@ void\ rtcOccludedNM(
|
||||
.SS DESCRIPTION
|
||||
.PP
|
||||
The \f[C]rtcOccludedNM\f[] function checks whether there are any hits
|
||||
for a stream of \f[C]M\f[] ray packets (\f[C]rays\f[] argument) of size
|
||||
for a stream of \f[C]M\f[] ray packets (\f[C]ray\f[] argument) of size
|
||||
\f[C]N\f[] with the scene (\f[C]scene\f[] argument).
|
||||
The \f[C]rays\f[] argument points to an array of ray packets with
|
||||
The \f[C]ray\f[] argument points to an array of ray packets with
|
||||
specified byte stride (\f[C]byteStride\f[] argument) between the ray
|
||||
packets.
|
||||
See Section [rtcOccluded1] for a description of how to set up and trace
|
||||
|
||||
@@ -15,7 +15,7 @@ rtcOccludedNp\ \-\ finds\ any\ hits\ for\ a\ SOA\ ray\ stream\ of\ size\ N
|
||||
void\ rtcOccludedNp(
|
||||
\ \ RTCScene\ scene,
|
||||
\ \ struct\ RTCIntersectContext*\ context,
|
||||
\ \ struct\ RTCRayNp*\ rays,
|
||||
\ \ struct\ RTCRayNp*\ ray,
|
||||
\ \ unsigned\ int\ N
|
||||
);
|
||||
\f[]
|
||||
@@ -23,9 +23,9 @@ void\ rtcOccludedNp(
|
||||
.SS DESCRIPTION
|
||||
.PP
|
||||
The \f[C]rtcOccludedNp\f[] function checks whether there are any hits
|
||||
for a SOA ray stream (\f[C]rays\f[] argument) of size \f[C]N\f[]
|
||||
for a SOA ray stream (\f[C]ray\f[] argument) of size \f[C]N\f[]
|
||||
(basically a large ray packet) with the scene (\f[C]scene\f[] argument).
|
||||
The \f[C]rays\f[] argument points to a structure of pointers with one
|
||||
The \f[C]ray\f[] argument points to a structure of pointers with one
|
||||
pointer for each ray component.
|
||||
Each of these pointers points to an array with the ray component data
|
||||
for each ray.
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
.TH "rtcSetGeometryTimeRange" "3" "" "" "Embree Ray Tracing Kernels 3"
|
||||
.SS NAME
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
rtcSetGeometryTimeRange\ \-\ sets\ the\ time\ range\ for\ a\ motion\ blur\ geometry
|
||||
\f[]
|
||||
.fi
|
||||
.SS SYNOPSIS
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
#include\ <embree3/rtcore.h>
|
||||
|
||||
void\ rtcSetGeometryTimeRange(
|
||||
\ \ RTCGeometry\ geometry,
|
||||
\ \ float\ startTime,
|
||||
\ \ float\ endTime
|
||||
);
|
||||
\f[]
|
||||
.fi
|
||||
.SS DESCRIPTION
|
||||
.PP
|
||||
The \f[C]rtcSetGeometryTimeRange\f[] function sets a time range which
|
||||
defines the start (and end time) of the first (and last) time step of a
|
||||
motion blur geometry.
|
||||
The time range is defined relative to the camera shutter interval [0,1]
|
||||
but it can be arbitrary.
|
||||
Thus the startTime can be smaller, equal, or larger 0, indicating a
|
||||
geometry whose animation definition start before, at, or after the
|
||||
camera shutter opens.
|
||||
Similar the endTime can be smaller, equal, or larger than 1, indicating
|
||||
a geometry whose animation definition ends after, at, or before the
|
||||
camera shutter closes.
|
||||
The startTime has to be smaller or equal to the endTime.
|
||||
.PP
|
||||
The default time range when this function is not called is the entire
|
||||
camera shutter [0,1].
|
||||
For best performance at most one time segment of the piece wise linear
|
||||
definition of the motion should fall outside the shutter window to the
|
||||
left and to the right.
|
||||
Thus do not set the startTime or endTime too far outside the [0,1]
|
||||
interval for best performance.
|
||||
.PP
|
||||
This time range feature will also allow geometries to appear and
|
||||
disappear during the camera shutter time if the specified time range is
|
||||
a sub range of [0,1].
|
||||
.PP
|
||||
Please also have a look at the \f[C]rtcSetGeometryTimeStepCount\f[]
|
||||
function to see how to define the time steps for the specified time
|
||||
range.
|
||||
.SS EXIT STATUS
|
||||
.PP
|
||||
On failure an error code is set that can be queried using
|
||||
\f[C]rtcDeviceGetError\f[].
|
||||
.SS SEE ALSO
|
||||
.PP
|
||||
[rtcSetGeometryTimeStepCount]
|
||||
@@ -34,7 +34,7 @@ directly corresponds to the number of vertex buffer slots available
|
||||
For these geometries, one vertex buffer per time step must be specified
|
||||
when creating multi\-segment motion blur geometries.
|
||||
.PP
|
||||
For instance geometries (\f[C]RTC_GEOMETRY_TYPE_TRIANGLE\f[]), a
|
||||
For instance geometries (\f[C]RTC_GEOMETRY_TYPE_INSTANCE\f[]), a
|
||||
transformation must be specified for each time step (see
|
||||
\f[C]rtcSetGeometryTransform\f[]).
|
||||
.PP
|
||||
@@ -48,4 +48,4 @@ On failure an error code is set that can be queried using
|
||||
\f[C]rtcDeviceGetError\f[].
|
||||
.SS SEE ALSO
|
||||
.PP
|
||||
[rtcNewGeometry]
|
||||
[rtcNewGeometry], [rtcSetGeometryTimeRange]
|
||||
|
||||
@@ -15,9 +15,9 @@ rtcSetGeometryTransform\ \-\ sets\ the\ transformation\ for\ a\ particular
|
||||
|
||||
void\ rtcSetGeometryTransform(
|
||||
\ \ RTCGeometry\ geometry,
|
||||
\ \ enum\ RTCMatrixType\ layout,
|
||||
\ \ const\ float*\ xfm,
|
||||
\ \ unsigned\ int\ timeStep
|
||||
\ \ unsigned\ int\ timeStep,
|
||||
\ \ enum\ RTCFormat\ format,
|
||||
\ \ const\ float*\ xfm
|
||||
);
|
||||
\f[]
|
||||
.fi
|
||||
@@ -28,8 +28,8 @@ affine transformation (\f[C]xfm\f[] parameter) of an instance geometry
|
||||
(\f[C]geometry\f[] parameter) for a particular time step
|
||||
(\f[C]timeStep\f[] parameter).
|
||||
The transformation is specified as a 3×4 matrix (3×3 linear
|
||||
transformation plus translation), for which the following layouts
|
||||
(\f[C]layout\f[] parameter) are supported:
|
||||
transformation plus translation), for which the following formats
|
||||
(\f[C]format\f[] parameter) are supported:
|
||||
.IP \[bu] 2
|
||||
\f[C]RTC_FORMAT_FLOAT3X4_ROW_MAJOR\f[]: The 3×4 float matrix is laid out
|
||||
in row\-major form.
|
||||
|
||||
@@ -52,4 +52,4 @@ On failure an error code is set that can be queried using
|
||||
\f[C]rtcDeviceGetError\f[].
|
||||
.SS SEE ALSO
|
||||
.PP
|
||||
[rtcGetSceneBuildQuality], [rtcSetGeometryBuildQuality]
|
||||
[rtcSetGeometryBuildQuality]
|
||||
|
||||
@@ -15,7 +15,7 @@ rtcSetSceneProgressMonitorFunction\ \-\ registers\ a\ callback
|
||||
|
||||
typedef\ bool\ (*RTCProgressMonitorFunction)(
|
||||
\ \ void*\ ptr,
|
||||
\ \ double\ progress
|
||||
\ \ double\ n
|
||||
);
|
||||
|
||||
void\ rtcSetSceneProgressMonitorFunction(
|
||||
@@ -45,7 +45,7 @@ Once registered, Embree will invoke the callback function multiple times
|
||||
during hierarchy build operations of the scene, by passing the payload
|
||||
as set at registration time (\f[C]userPtr\f[] argument), and a double in
|
||||
the range [0, 1] which estimates the progress of the operation
|
||||
(\f[C]progress\f[] argument).
|
||||
(\f[C]n\f[] argument).
|
||||
The callback function might be called from multiple threads
|
||||
concurrently.
|
||||
.PP
|
||||
|
||||
BIN
Binary file not shown.
+11
-3
@@ -105,6 +105,12 @@ def runConfig(config):
|
||||
elif (compiler == "ICC18"):
|
||||
conf.append("-G \"Visual Studio 12 2013"+ext+"\"")
|
||||
conf.append("-T \"Intel C++ Compiler 18.0\"")
|
||||
elif (compiler == "ICC17-VC14"):
|
||||
conf.append("-G \"Visual Studio 14 2015"+ext+"\"")
|
||||
conf.append("-T \"Intel C++ Compiler 17.0\"")
|
||||
elif (compiler == "ICC17-VC12"):
|
||||
conf.append("-G \"Visual Studio 12 2013"+ext+"\"")
|
||||
conf.append("-T \"Intel C++ Compiler 17.0\"")
|
||||
elif (compiler == "ICC17"):
|
||||
conf.append("-G \"Visual Studio 12 2013"+ext+"\"")
|
||||
conf.append("-T \"Intel C++ Compiler 17.0\"")
|
||||
@@ -121,7 +127,9 @@ def runConfig(config):
|
||||
raise ValueError('unknown compiler: ' + compiler + '')
|
||||
|
||||
elif OS == "linux":
|
||||
if (compiler == "ICC18"):
|
||||
if (compiler == "ICC19"):
|
||||
conf.append("-D CMAKE_CXX_COMPILER="+nas+"/intel/2019.0/bin/icpc -D CMAKE_C_COMPILER="+nas+"/intel/2019.0/bin/icc")
|
||||
elif (compiler == "ICC18"):
|
||||
conf.append("-D CMAKE_CXX_COMPILER="+nas+"/intel/2018.0/bin/icpc -D CMAKE_C_COMPILER="+nas+"/intel/2018.0/bin/icc")
|
||||
elif (compiler == "ICC17"):
|
||||
conf.append("-D CMAKE_CXX_COMPILER="+nas+"/intel/2017.1/bin/icpc -D CMAKE_C_COMPILER="+nas+"/intel/2017.1/bin/icc")
|
||||
@@ -227,9 +235,9 @@ def runConfig(config):
|
||||
raise ValueError('unknown tasking system: ' + tasking + '')
|
||||
|
||||
if platform == "x64":
|
||||
env.append("set PATH="+tbb_path+"\\bin\\intel64\\vc12;%PATH%")
|
||||
env.append("set PATH="+tbb_path+"\\bin\\intel64\\vc12;"+tbb_path+"\\bin\\intel64\\vc14;%PATH%")
|
||||
else:
|
||||
env.append("set PATH="+tbb_path+"\\bin\\ia32\\vc12;%PATH%")
|
||||
env.append("set PATH="+tbb_path+"\\bin\\ia32\\vc12;"+tbb_path+"\\bin\\ia32\\vc14;%PATH%")
|
||||
|
||||
else:
|
||||
sys.stderr.write("unknown operating system "+OS)
|
||||
|
||||
@@ -23,9 +23,26 @@
|
||||
// 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)
|
||||
{
|
||||
@@ -63,6 +80,15 @@ inline float cosineSampleHemispherePDF(float cosTheta)
|
||||
return cosTheta / float(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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -23,7 +23,23 @@
|
||||
// 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)
|
||||
{
|
||||
@@ -61,6 +77,15 @@ 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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -20,7 +20,7 @@ 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,1);
|
||||
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);
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace embree
|
||||
|
||||
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,1);
|
||||
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);
|
||||
|
||||
@@ -80,7 +80,7 @@ namespace embree
|
||||
|
||||
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,1);
|
||||
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,width+1,width+1,height+1));
|
||||
|
||||
@@ -98,7 +98,7 @@ namespace embree
|
||||
|
||||
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,1);
|
||||
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);
|
||||
@@ -136,7 +136,7 @@ namespace embree
|
||||
unsigned numPhi = unsigned(N);
|
||||
unsigned numTheta = 2*numPhi;
|
||||
unsigned numVertices = numTheta*(numPhi+1);
|
||||
Ref<SceneGraph::TriangleMeshNode> mesh = new SceneGraph::TriangleMeshNode(material,1);
|
||||
Ref<SceneGraph::TriangleMeshNode> mesh = new SceneGraph::TriangleMeshNode(material,BBox1f(0,1),1);
|
||||
mesh->positions[0].resize(numVertices);
|
||||
|
||||
/* create sphere geometry */
|
||||
@@ -195,7 +195,7 @@ namespace embree
|
||||
unsigned numPhi = unsigned(N);
|
||||
unsigned numTheta = 2*numPhi;
|
||||
unsigned numVertices = numTheta*(numPhi+1);
|
||||
Ref<SceneGraph::QuadMeshNode> mesh = new SceneGraph::QuadMeshNode(material,1);
|
||||
Ref<SceneGraph::QuadMeshNode> mesh = new SceneGraph::QuadMeshNode(material,BBox1f(0,1),1);
|
||||
mesh->positions[0].resize(numVertices);
|
||||
|
||||
/* create sphere geometry */
|
||||
@@ -251,7 +251,7 @@ namespace embree
|
||||
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,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++)
|
||||
@@ -284,7 +284,7 @@ namespace embree
|
||||
unsigned numPhi = unsigned(N);
|
||||
unsigned numTheta = 2*numPhi;
|
||||
unsigned numVertices = numTheta*(numPhi+1);
|
||||
Ref<SceneGraph::SubdivMeshNode> mesh = new SceneGraph::SubdivMeshNode(material,1);
|
||||
Ref<SceneGraph::SubdivMeshNode> mesh = new SceneGraph::SubdivMeshNode(material,BBox1f(0,1),1);
|
||||
mesh->tessellationRate = tessellationRate;
|
||||
mesh->positions[0].resize(numVertices);
|
||||
|
||||
@@ -350,7 +350,7 @@ namespace embree
|
||||
|
||||
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,1);
|
||||
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(Vec3fa(center+Vec3fa(-radius,0,0),radius));
|
||||
mesh->positions[0].push_back(Vec3fa(center+Vec3fa(0,0,0),radius));
|
||||
@@ -365,7 +365,7 @@ namespace embree
|
||||
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,1);
|
||||
Ref<SceneGraph::HairSetNode> mesh = new SceneGraph::HairSetNode(type,material,BBox1f(0,1),1);
|
||||
|
||||
if (numHairs == 1) {
|
||||
const Vec3fa p0 = pos;
|
||||
@@ -400,7 +400,7 @@ namespace embree
|
||||
{
|
||||
RandomSampler sampler;
|
||||
RandomSampler_init(sampler,hash);
|
||||
Ref<SceneGraph::TriangleMeshNode> mesh = new SceneGraph::TriangleMeshNode(material,mblur?2:1);
|
||||
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++) {
|
||||
@@ -438,7 +438,7 @@ namespace embree
|
||||
{
|
||||
RandomSampler sampler;
|
||||
RandomSampler_init(sampler,hash);
|
||||
Ref<SceneGraph::QuadMeshNode> mesh = new SceneGraph::QuadMeshNode(material,mblur?2:1);
|
||||
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++) {
|
||||
@@ -477,7 +477,7 @@ namespace embree
|
||||
{
|
||||
RandomSampler sampler;
|
||||
RandomSampler_init(sampler,hash);
|
||||
Ref<SceneGraph::GridMeshNode> mesh = new SceneGraph::GridMeshNode(material,mblur?2:1);
|
||||
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++) {
|
||||
@@ -513,7 +513,7 @@ namespace embree
|
||||
{
|
||||
RandomSampler sampler;
|
||||
RandomSampler_init(sampler,hash);
|
||||
Ref<SceneGraph::HairSetNode> mesh = new SceneGraph::HairSetNode(RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE,material,mblur?2:1);
|
||||
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++) {
|
||||
@@ -549,7 +549,7 @@ namespace embree
|
||||
{
|
||||
RandomSampler sampler;
|
||||
RandomSampler_init(sampler,hash);
|
||||
Ref<SceneGraph::HairSetNode> mesh = new SceneGraph::HairSetNode(RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE,material,mblur?2:1);
|
||||
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++) {
|
||||
@@ -585,7 +585,7 @@ namespace embree
|
||||
{
|
||||
RandomSampler sampler;
|
||||
RandomSampler_init(sampler,hash);
|
||||
Ref<SceneGraph::SubdivMeshNode> mesh = new SceneGraph::SubdivMeshNode(material,mblur?2:1);
|
||||
Ref<SceneGraph::SubdivMeshNode> mesh = new SceneGraph::SubdivMeshNode(material,BBox1f(0,1),mblur?2:1);
|
||||
|
||||
for (size_t i=0; i<numFaces; i++)
|
||||
{
|
||||
|
||||
@@ -538,7 +538,8 @@ namespace embree
|
||||
|
||||
if (subdivMode)
|
||||
{
|
||||
Ref<SceneGraph::SubdivMeshNode> mesh = new SceneGraph::SubdivMeshNode(curMaterial,1);
|
||||
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]);
|
||||
@@ -564,7 +565,8 @@ namespace embree
|
||||
}
|
||||
else
|
||||
{
|
||||
Ref<SceneGraph::TriangleMeshNode> mesh = new SceneGraph::TriangleMeshNode(curMaterial,1);
|
||||
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;
|
||||
|
||||
@@ -302,7 +302,7 @@ namespace embree
|
||||
Ref<SceneGraph::Node> import()
|
||||
{
|
||||
Ref<SceneGraph::MaterialNode> material = new OBJMaterial;
|
||||
Ref<SceneGraph::TriangleMeshNode> mesh_o = new SceneGraph::TriangleMeshNode(material,1);
|
||||
Ref<SceneGraph::TriangleMeshNode> mesh_o = new SceneGraph::TriangleMeshNode(material,BBox1f(0,1),1);
|
||||
|
||||
/* convert all vertices */
|
||||
const Element& vertices = mesh.elements.at("vertex");
|
||||
|
||||
@@ -933,6 +933,33 @@ namespace embree
|
||||
}
|
||||
}
|
||||
|
||||
void SceneGraph::set_time_range(Ref<SceneGraph::Node> node, const BBox1f& time_range)
|
||||
{
|
||||
if (Ref<SceneGraph::TransformNode> xfmNode = node.dynamicCast<SceneGraph::TransformNode>()) {
|
||||
xfmNode->spaces.time_range = time_range;
|
||||
}
|
||||
else if (Ref<SceneGraph::GroupNode> groupNode = node.dynamicCast<SceneGraph::GroupNode>())
|
||||
{
|
||||
for (size_t i=0; i<groupNode->children.size(); i++)
|
||||
set_time_range(groupNode->children[i],time_range);
|
||||
}
|
||||
else if (Ref<SceneGraph::TriangleMeshNode> mesh = node.dynamicCast<SceneGraph::TriangleMeshNode>()) {
|
||||
mesh->time_range = time_range;
|
||||
}
|
||||
else if (Ref<SceneGraph::QuadMeshNode> mesh = node.dynamicCast<SceneGraph::QuadMeshNode>()) {
|
||||
mesh->time_range = time_range;
|
||||
}
|
||||
else if (Ref<SceneGraph::GridMeshNode> mesh = node.dynamicCast<SceneGraph::GridMeshNode>()) {
|
||||
mesh->time_range = time_range;
|
||||
}
|
||||
else if (Ref<SceneGraph::HairSetNode> mesh = node.dynamicCast<SceneGraph::HairSetNode>()) {
|
||||
mesh->time_range = time_range;
|
||||
}
|
||||
else if (Ref<SceneGraph::SubdivMeshNode> mesh = node.dynamicCast<SceneGraph::SubdivMeshNode>()) {
|
||||
mesh->time_range = time_range;
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<int,int> quad_index2(int p, int a0, int a1, int b0, int b1)
|
||||
{
|
||||
if (b0 == a0) return std::make_pair(p-1,b1);
|
||||
@@ -958,7 +985,7 @@ namespace embree
|
||||
|
||||
Ref<SceneGraph::Node> SceneGraph::convert_triangles_to_quads ( Ref<SceneGraph::TriangleMeshNode> tmesh )
|
||||
{
|
||||
Ref<SceneGraph::QuadMeshNode> qmesh = new SceneGraph::QuadMeshNode(tmesh->material);
|
||||
Ref<SceneGraph::QuadMeshNode> qmesh = new SceneGraph::QuadMeshNode(tmesh->material,tmesh->time_range,0);
|
||||
|
||||
for (auto& p : tmesh->positions)
|
||||
qmesh->positions.push_back(p);
|
||||
@@ -1015,7 +1042,7 @@ namespace embree
|
||||
Ref<SceneGraph::Node> SceneGraph::convert_quads_to_grids ( Ref<SceneGraph::QuadMeshNode> qmesh , const unsigned int resX, const unsigned int resY )
|
||||
{
|
||||
const size_t timeSteps = qmesh->positions.size();
|
||||
Ref<SceneGraph::GridMeshNode> gmesh = new SceneGraph::GridMeshNode(qmesh->material,timeSteps);
|
||||
Ref<SceneGraph::GridMeshNode> gmesh = new SceneGraph::GridMeshNode(qmesh->material,qmesh->time_range,timeSteps);
|
||||
std::vector<SceneGraph::QuadMeshNode::Quad>& quads = qmesh->quads;
|
||||
|
||||
for (size_t i=0;i<quads.size();i++)
|
||||
@@ -1063,7 +1090,7 @@ namespace embree
|
||||
|
||||
Ref<SceneGraph::Node> SceneGraph::convert_grids_to_quads ( Ref<SceneGraph::GridMeshNode> gmesh )
|
||||
{
|
||||
Ref<SceneGraph::QuadMeshNode> qmesh = new SceneGraph::QuadMeshNode(gmesh->material);
|
||||
Ref<SceneGraph::QuadMeshNode> qmesh = new SceneGraph::QuadMeshNode(gmesh->material,gmesh->time_range,0);
|
||||
|
||||
for (size_t i=0; i<gmesh->numPrimitives(); i++)
|
||||
{
|
||||
@@ -1226,7 +1253,7 @@ namespace embree
|
||||
}
|
||||
else if (Ref<SceneGraph::QuadMeshNode> qmesh = node.dynamicCast<SceneGraph::QuadMeshNode>())
|
||||
{
|
||||
Ref<SceneGraph::GridMeshNode> gmesh = new SceneGraph::GridMeshNode(qmesh->material,qmesh->numTimeSteps());
|
||||
Ref<SceneGraph::GridMeshNode> gmesh = new SceneGraph::GridMeshNode(qmesh->material,qmesh->time_range,qmesh->numTimeSteps());
|
||||
|
||||
std::vector<bool> visited;
|
||||
visited.resize(qmesh->numPrimitives());
|
||||
@@ -1307,7 +1334,7 @@ namespace embree
|
||||
}
|
||||
else if (Ref<SceneGraph::QuadMeshNode> tmesh = node.dynamicCast<SceneGraph::QuadMeshNode>())
|
||||
{
|
||||
Ref<SceneGraph::SubdivMeshNode> smesh = new SceneGraph::SubdivMeshNode(tmesh->material);
|
||||
Ref<SceneGraph::SubdivMeshNode> smesh = new SceneGraph::SubdivMeshNode(tmesh->material,tmesh->time_range,0);
|
||||
|
||||
for (auto& p : tmesh->positions)
|
||||
smesh->positions.push_back(p);
|
||||
@@ -1348,7 +1375,7 @@ namespace embree
|
||||
}
|
||||
else if (Ref<SceneGraph::HairSetNode> hmesh = node.dynamicCast<SceneGraph::HairSetNode>())
|
||||
{
|
||||
Ref<SceneGraph::HairSetNode> lmesh = new SceneGraph::HairSetNode(RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE, hmesh->material);
|
||||
Ref<SceneGraph::HairSetNode> lmesh = new SceneGraph::HairSetNode(RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE, hmesh->material, hmesh->time_range, 0);
|
||||
|
||||
for (auto& p : hmesh->positions)
|
||||
lmesh->positions.push_back(p);
|
||||
|
||||
@@ -39,6 +39,7 @@ namespace embree
|
||||
void optimize_animation(Ref<Node> node0);
|
||||
void set_motion_vector(Ref<Node> node, const Vec3fa& dP);
|
||||
void set_motion_vector(Ref<Node> node, const avector<Vec3fa>& motion_vector);
|
||||
void set_time_range(Ref<SceneGraph::Node> node, const BBox1f& time_range);
|
||||
void resize_randomly(RandomSampler& sampler, Ref<Node> node, const size_t N);
|
||||
Ref<Node> convert_triangles_to_quads(Ref<Node> node, float prop);
|
||||
Ref<Node> convert_triangles_to_quads( Ref<TriangleMeshNode> tmesh);
|
||||
@@ -165,24 +166,30 @@ namespace embree
|
||||
{
|
||||
__forceinline Transformations() {}
|
||||
|
||||
__forceinline Transformations(OneTy) {
|
||||
__forceinline Transformations(OneTy)
|
||||
: time_range(0.0f,1.0f)
|
||||
{
|
||||
spaces.push_back(one);
|
||||
}
|
||||
|
||||
__forceinline Transformations( size_t N )
|
||||
: spaces(N) {}
|
||||
__forceinline Transformations( const BBox1f& time_range, size_t N )
|
||||
: time_range(time_range), spaces(N) {}
|
||||
|
||||
__forceinline Transformations(const AffineSpace3fa& space) {
|
||||
__forceinline Transformations(const AffineSpace3fa& space)
|
||||
: time_range(0.0f,1.0f)
|
||||
{
|
||||
spaces.push_back(space);
|
||||
}
|
||||
|
||||
__forceinline Transformations(const AffineSpace3fa& space0, const AffineSpace3fa& space1) {
|
||||
__forceinline Transformations(const AffineSpace3fa& space0, const AffineSpace3fa& space1)
|
||||
: time_range(0.0f,1.0f)
|
||||
{
|
||||
spaces.push_back(space0);
|
||||
spaces.push_back(space1);
|
||||
}
|
||||
|
||||
__forceinline Transformations(const avector<AffineSpace3fa>& spaces)
|
||||
: spaces(spaces) { assert(spaces.size()); }
|
||||
: time_range(0.0f,1.0f), spaces(spaces) { assert(spaces.size()); }
|
||||
|
||||
__forceinline size_t size() const {
|
||||
return spaces.size();
|
||||
@@ -226,19 +233,19 @@ namespace embree
|
||||
{
|
||||
if (a.size() == 1)
|
||||
{
|
||||
Transformations c(b.size());
|
||||
Transformations c(intersect(a.time_range,b.time_range),b.size());
|
||||
for (size_t i=0; i<b.size(); i++) c[i] = a[0] * b[i];
|
||||
return c;
|
||||
}
|
||||
else if (b.size() == 1)
|
||||
{
|
||||
Transformations c(a.size());
|
||||
Transformations c(intersect(a.time_range,b.time_range),a.size());
|
||||
for (size_t i=0; i<a.size(); i++) c[i] = a[i] * b[0];
|
||||
return c;
|
||||
}
|
||||
else if (a.size() == b.size())
|
||||
{
|
||||
Transformations c(a.size());
|
||||
Transformations c(intersect(a.time_range,b.time_range),a.size());
|
||||
for (size_t i=0; i<a.size(); i++) c[i] = a[i] * b[i];
|
||||
return c;
|
||||
}
|
||||
@@ -248,6 +255,7 @@ namespace embree
|
||||
|
||||
AffineSpace3fa interpolate (const float gtime) const
|
||||
{
|
||||
assert(time_range.lower == 0.0f && time_range.upper == 1.0f);
|
||||
if (spaces.size() == 1) return spaces[0];
|
||||
|
||||
/* calculate time segment itime and fractional time ftime */
|
||||
@@ -259,6 +267,7 @@ namespace embree
|
||||
}
|
||||
|
||||
public:
|
||||
BBox1f time_range;
|
||||
avector<AffineSpace3fa> spaces;
|
||||
};
|
||||
|
||||
@@ -617,23 +626,22 @@ namespace embree
|
||||
const std::vector<Vec2f>& texcoords,
|
||||
const std::vector<Triangle>& triangles,
|
||||
Ref<MaterialNode> material)
|
||||
: Node(true), texcoords(texcoords), triangles(triangles), material(material)
|
||||
: Node(true), time_range(0.0f,1.0f), texcoords(texcoords), triangles(triangles), material(material)
|
||||
{
|
||||
positions.push_back(positions_in);
|
||||
normals.push_back(normals_in);
|
||||
}
|
||||
|
||||
TriangleMeshNode (Ref<MaterialNode> material, size_t numTimeSteps = 0)
|
||||
: Node(true), material(material)
|
||||
TriangleMeshNode (Ref<MaterialNode> material, const BBox1f time_range = BBox1f(0,1), size_t numTimeSteps = 0)
|
||||
: Node(true), time_range(time_range), material(material)
|
||||
{
|
||||
for (size_t i=0; i<numTimeSteps; i++)
|
||||
positions.push_back(avector<Vertex>());
|
||||
for (size_t i=0; i<numTimeSteps; i++)
|
||||
normals.push_back(avector<Vertex>());
|
||||
}
|
||||
|
||||
TriangleMeshNode (Ref<SceneGraph::TriangleMeshNode> imesh, const Transformations& spaces)
|
||||
: Node(true),
|
||||
time_range(imesh->time_range),
|
||||
positions(transformMSMBlurBuffer(imesh->positions,spaces)),
|
||||
normals(transformMSMBlurNormalBuffer(imesh->normals,spaces)),
|
||||
texcoords(imesh->texcoords), triangles(imesh->triangles), material(imesh->material) {}
|
||||
@@ -686,6 +694,7 @@ namespace embree
|
||||
virtual void resetInDegree();
|
||||
|
||||
public:
|
||||
BBox1f time_range;
|
||||
std::vector<avector<Vertex>> positions;
|
||||
std::vector<avector<Vertex>> normals;
|
||||
std::vector<Vec2f> texcoords;
|
||||
@@ -709,17 +718,16 @@ namespace embree
|
||||
};
|
||||
|
||||
public:
|
||||
QuadMeshNode (Ref<MaterialNode> material, size_t numTimeSteps = 0)
|
||||
: Node(true), material(material)
|
||||
QuadMeshNode (Ref<MaterialNode> material, const BBox1f time_range = BBox1f(0,1), size_t numTimeSteps = 0 )
|
||||
: Node(true), time_range(time_range), material(material)
|
||||
{
|
||||
for (size_t i=0; i<numTimeSteps; i++)
|
||||
positions.push_back(avector<Vertex>());
|
||||
for (size_t i=0; i<numTimeSteps; i++)
|
||||
normals.push_back(avector<Vertex>());
|
||||
}
|
||||
|
||||
QuadMeshNode (Ref<SceneGraph::QuadMeshNode> imesh, const Transformations& spaces)
|
||||
: Node(true),
|
||||
time_range(imesh->time_range),
|
||||
positions(transformMSMBlurBuffer(imesh->positions,spaces)),
|
||||
normals(transformMSMBlurNormalBuffer(imesh->normals,spaces)),
|
||||
texcoords(imesh->texcoords), quads(imesh->quads), material(imesh->material) {}
|
||||
@@ -772,6 +780,7 @@ namespace embree
|
||||
virtual void resetInDegree();
|
||||
|
||||
public:
|
||||
BBox1f time_range;
|
||||
std::vector<avector<Vertex>> positions;
|
||||
std::vector<avector<Vertex>> normals;
|
||||
std::vector<Vec2f> texcoords;
|
||||
@@ -784,8 +793,9 @@ namespace embree
|
||||
{
|
||||
typedef Vec3fa Vertex;
|
||||
|
||||
SubdivMeshNode (Ref<MaterialNode> material, size_t numTimeSteps = 0)
|
||||
: Node(true),
|
||||
SubdivMeshNode (Ref<MaterialNode> material, const BBox1f time_range = BBox1f(0,1), size_t numTimeSteps = 0)
|
||||
: Node(true),
|
||||
time_range(time_range),
|
||||
position_subdiv_mode(RTC_SUBDIVISION_MODE_SMOOTH_BOUNDARY),
|
||||
normal_subdiv_mode(RTC_SUBDIVISION_MODE_SMOOTH_BOUNDARY),
|
||||
texcoord_subdiv_mode(RTC_SUBDIVISION_MODE_SMOOTH_BOUNDARY),
|
||||
@@ -793,13 +803,12 @@ namespace embree
|
||||
{
|
||||
for (size_t i=0; i<numTimeSteps; i++)
|
||||
positions.push_back(avector<Vertex>());
|
||||
for (size_t i=0; i<numTimeSteps; i++)
|
||||
normals.push_back(avector<Vertex>());
|
||||
zero_pad_arrays();
|
||||
}
|
||||
|
||||
SubdivMeshNode (Ref<SceneGraph::SubdivMeshNode> imesh, const Transformations& spaces)
|
||||
: Node(true),
|
||||
: Node(true),
|
||||
time_range(imesh->time_range),
|
||||
positions(transformMSMBlurBuffer(imesh->positions,spaces)),
|
||||
normals(transformMSMBlurNormalBuffer(imesh->normals,spaces)),
|
||||
texcoords(imesh->texcoords),
|
||||
@@ -886,6 +895,7 @@ namespace embree
|
||||
virtual void resetInDegree();
|
||||
|
||||
public:
|
||||
BBox1f time_range; //!< geometry time range for motion blur
|
||||
std::vector<avector<Vertex>> positions; //!< vertex positions for multiple timesteps
|
||||
std::vector<avector<Vertex>> normals; //!< vertex normals
|
||||
std::vector<Vec2f> texcoords; //!< face texture coordinates
|
||||
@@ -921,21 +931,26 @@ namespace embree
|
||||
};
|
||||
|
||||
public:
|
||||
HairSetNode (RTCGeometryType type, Ref<MaterialNode> material, size_t numTimeSteps = 0)
|
||||
: Node(true), type(type), material(material), tessellation_rate(4)
|
||||
HairSetNode (RTCGeometryType type, Ref<MaterialNode> material, const BBox1f time_range = BBox1f(0,1), size_t numTimeSteps = 0)
|
||||
: Node(true), time_range(time_range), type(type), material(material), tessellation_rate(4)
|
||||
{
|
||||
for (size_t i=0; i<numTimeSteps; i++)
|
||||
positions.push_back(avector<Vertex>());
|
||||
}
|
||||
|
||||
HairSetNode (const avector<Vertex>& positions_in, const std::vector<Hair>& hairs, Ref<MaterialNode> material, RTCGeometryType type)
|
||||
: Node(true), type(type), hairs(hairs), material(material), tessellation_rate(4)
|
||||
: Node(true), time_range(0.0f,1.0f), type(type), hairs(hairs), material(material), tessellation_rate(4)
|
||||
{
|
||||
positions.push_back(positions_in);
|
||||
}
|
||||
|
||||
HairSetNode (Ref<SceneGraph::HairSetNode> imesh, const Transformations& spaces)
|
||||
: Node(true), type(imesh->type), positions(transformMSMBlurBuffer(imesh->positions,spaces)), normals(transformMSMBlurNormalBuffer(imesh->normals,spaces)), tangents(transformMSMBlurVectorBuffer(imesh->tangents,spaces)),
|
||||
: Node(true),
|
||||
time_range(imesh->time_range),
|
||||
type(imesh->type),
|
||||
positions(transformMSMBlurBuffer(imesh->positions,spaces)),
|
||||
normals(transformMSMBlurNormalBuffer(imesh->normals,spaces)),
|
||||
tangents(transformMSMBlurVectorBuffer(imesh->tangents,spaces)),
|
||||
hairs(imesh->hairs), flags(imesh->flags), material(imesh->material), tessellation_rate(imesh->tessellation_rate) {}
|
||||
|
||||
virtual void setMaterial(Ref<MaterialNode> material) {
|
||||
@@ -991,6 +1006,7 @@ namespace embree
|
||||
virtual void resetInDegree();
|
||||
|
||||
public:
|
||||
BBox1f time_range; //!< geometry time range for motion blur
|
||||
RTCGeometryType type; //!< type of curve
|
||||
std::vector<avector<Vertex>> positions; //!< hair control points (x,y,z,r) for multiple timesteps
|
||||
std::vector<avector<Vertex>> normals; //!< hair control normals (nx,ny,nz) for multiple timesteps
|
||||
@@ -1025,8 +1041,8 @@ namespace embree
|
||||
};
|
||||
|
||||
public:
|
||||
GridMeshNode (Ref<MaterialNode> material, size_t numTimeSteps = 0)
|
||||
: Node(true), material(material)
|
||||
GridMeshNode (Ref<MaterialNode> material, const BBox1f time_range = BBox1f(0,1), size_t numTimeSteps = 0)
|
||||
: Node(true), time_range(time_range), material(material)
|
||||
{
|
||||
for (size_t i=0; i<numTimeSteps; i++)
|
||||
positions.push_back(avector<Vertex>());
|
||||
@@ -1034,6 +1050,7 @@ namespace embree
|
||||
|
||||
GridMeshNode (Ref<SceneGraph::GridMeshNode> imesh, const Transformations& spaces)
|
||||
: Node(true),
|
||||
time_range(imesh->time_range),
|
||||
positions(transformMSMBlurBuffer(imesh->positions,spaces)),
|
||||
grids(imesh->grids), material(imesh->material) {}
|
||||
|
||||
@@ -1085,6 +1102,7 @@ namespace embree
|
||||
virtual void resetInDegree();
|
||||
|
||||
public:
|
||||
BBox1f time_range;
|
||||
std::vector<avector<Vertex>> positions;
|
||||
std::vector<Grid> grids;
|
||||
Ref<MaterialNode> material;
|
||||
|
||||
@@ -245,6 +245,7 @@ namespace embree
|
||||
|
||||
Ref<SceneGraph::Node> loadTriangleMesh(const Ref<XML>& xml);
|
||||
Ref<SceneGraph::Node> loadQuadMesh(const Ref<XML>& xml);
|
||||
Ref<SceneGraph::Node> loadGridMesh(const Ref<XML>& xml);
|
||||
Ref<SceneGraph::Node> loadSubdivMesh(const Ref<XML>& xml);
|
||||
Ref<SceneGraph::Node> loadBezierCurves(const Ref<XML>& xml, SceneGraph::CurveSubtype subtype); // only for compatibility
|
||||
Ref<SceneGraph::Node> loadCurves(const Ref<XML>& xml, RTCGeometryType type);
|
||||
@@ -898,7 +899,7 @@ namespace embree
|
||||
Ref<SceneGraph::Node> XMLLoader::loadTriangleMesh(const Ref<XML>& xml)
|
||||
{
|
||||
Ref<SceneGraph::MaterialNode> material = loadMaterial(xml->child("material"));
|
||||
Ref<SceneGraph::TriangleMeshNode> mesh = new SceneGraph::TriangleMeshNode(material);
|
||||
Ref<SceneGraph::TriangleMeshNode> mesh = new SceneGraph::TriangleMeshNode(material,BBox1f(0,1),0);
|
||||
|
||||
if (Ref<XML> animation = xml->childOpt("animated_positions")) {
|
||||
for (size_t i=0; i<animation->size(); i++)
|
||||
@@ -933,15 +934,13 @@ namespace embree
|
||||
Ref<SceneGraph::Node> XMLLoader::loadQuadMesh(const Ref<XML>& xml)
|
||||
{
|
||||
Ref<SceneGraph::MaterialNode> material = loadMaterial(xml->child("material"));
|
||||
Ref<SceneGraph::QuadMeshNode> mesh = new SceneGraph::QuadMeshNode(material);
|
||||
Ref<SceneGraph::QuadMeshNode> mesh = new SceneGraph::QuadMeshNode(material,BBox1f(0,1),0);
|
||||
|
||||
if (Ref<XML> animation = xml->childOpt("animated_positions")) {
|
||||
for (size_t i=0; i<animation->size(); i++)
|
||||
mesh->positions.push_back(loadVec3faArray(animation->child(i)));
|
||||
} else {
|
||||
auto vec = loadVec3faArray(xml->childOpt("normals"));
|
||||
for (size_t i=0; i<mesh->numTimeSteps(); i++)
|
||||
mesh->normals.push_back(vec);
|
||||
mesh->positions.push_back(loadVec3faArray(xml->childOpt("positions")));
|
||||
}
|
||||
|
||||
if (Ref<XML> animation = xml->childOpt("animated_normals")) {
|
||||
@@ -964,6 +963,25 @@ namespace embree
|
||||
return mesh.dynamicCast<SceneGraph::Node>();
|
||||
}
|
||||
|
||||
Ref<SceneGraph::Node> XMLLoader::loadGridMesh(const Ref<XML>& xml)
|
||||
{
|
||||
Ref<SceneGraph::MaterialNode> material = loadMaterial(xml->child("material"));
|
||||
Ref<SceneGraph::GridMeshNode> mesh = new SceneGraph::GridMeshNode(material,BBox1f(0,1),0);
|
||||
|
||||
if (Ref<XML> animation = xml->childOpt("animated_positions")) {
|
||||
for (size_t i=0; i<animation->size(); i++)
|
||||
mesh->positions.push_back(loadVec3faArray(animation->child(i)));
|
||||
} else {
|
||||
mesh->positions.push_back(loadVec3faArray(xml->childOpt("positions")));
|
||||
}
|
||||
|
||||
std::vector<Vec4i> grids = loadVec4iArray(xml->childOpt("grids"));
|
||||
for (size_t i=0; i<grids.size(); i++)
|
||||
mesh->grids.push_back(SceneGraph::GridMeshNode::Grid(grids[i].x,grids[i].y,grids[i].z,grids[i].w));
|
||||
mesh->verify();
|
||||
return mesh.dynamicCast<SceneGraph::Node>();
|
||||
}
|
||||
|
||||
RTCSubdivisionMode parseSubdivMode(const Ref<XML>& xml)
|
||||
{
|
||||
std::string subdiv_mode = xml->parm("subdiv_mode");
|
||||
@@ -979,7 +997,7 @@ namespace embree
|
||||
Ref<SceneGraph::Node> XMLLoader::loadSubdivMesh(const Ref<XML>& xml)
|
||||
{
|
||||
Ref<SceneGraph::MaterialNode> material = loadMaterial(xml->child("material"));
|
||||
Ref<SceneGraph::SubdivMeshNode> mesh = new SceneGraph::SubdivMeshNode(material);
|
||||
Ref<SceneGraph::SubdivMeshNode> mesh = new SceneGraph::SubdivMeshNode(material,BBox1f(0,1),0);
|
||||
|
||||
if (Ref<XML> animation = xml->childOpt("animated_positions")) {
|
||||
for (size_t i=0; i<animation->size(); i++)
|
||||
@@ -1046,7 +1064,7 @@ namespace embree
|
||||
{
|
||||
Ref<SceneGraph::MaterialNode> material = loadMaterial(xml->child("material"));
|
||||
RTCGeometryType type = (subtype == SceneGraph::ROUND_CURVE) ? RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE : RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE;
|
||||
Ref<SceneGraph::HairSetNode> mesh = new SceneGraph::HairSetNode(type,material);
|
||||
Ref<SceneGraph::HairSetNode> mesh = new SceneGraph::HairSetNode(type,material,BBox1f(0,1),0);
|
||||
|
||||
if (Ref<XML> animation = xml->childOpt("animated_positions")) {
|
||||
for (size_t i=0; i<animation->size(); i++)
|
||||
@@ -1075,7 +1093,7 @@ namespace embree
|
||||
Ref<SceneGraph::Node> XMLLoader::loadCurves(const Ref<XML>& xml, RTCGeometryType type)
|
||||
{
|
||||
Ref<SceneGraph::MaterialNode> material = loadMaterial(xml->child("material"));
|
||||
Ref<SceneGraph::HairSetNode> mesh = new SceneGraph::HairSetNode(type,material);
|
||||
Ref<SceneGraph::HairSetNode> mesh = new SceneGraph::HairSetNode(type,material,BBox1f(0,1),0);
|
||||
|
||||
if (Ref<XML> animation = xml->childOpt("animated_positions")) {
|
||||
for (size_t i=0; i<animation->size(); i++) {
|
||||
@@ -1269,6 +1287,7 @@ namespace embree
|
||||
else if (xml->name == "QuadLight" ) node = state.sceneMap[id] = loadQuadLight (xml);
|
||||
else if (xml->name == "TriangleMesh" ) node = state.sceneMap[id] = loadTriangleMesh (xml);
|
||||
else if (xml->name == "QuadMesh" ) node = state.sceneMap[id] = loadQuadMesh (xml);
|
||||
else if (xml->name == "GridMesh" ) node = state.sceneMap[id] = loadGridMesh (xml);
|
||||
else if (xml->name == "SubdivisionMesh" ) node = state.sceneMap[id] = loadSubdivMesh (xml);
|
||||
else if (xml->name == "Hair" ) node = state.sceneMap[id] = loadBezierCurves (xml,SceneGraph::FLAT_CURVE);
|
||||
else if (xml->name == "LineSegments" ) node = state.sceneMap[id] = loadCurves (xml,RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE);
|
||||
@@ -1338,7 +1357,12 @@ namespace embree
|
||||
else if (xml->name == "ConvertQuadsToSubdivs" ) node = state.sceneMap[id] = convert_quads_to_subdivs (loadNode(xml->child(0)));
|
||||
else if (xml->name == "ConvertBezierToLines" ) node = state.sceneMap[id] = convert_bezier_to_lines (loadNode(xml->child(0)));
|
||||
else if (xml->name == "ConvertHairToCurves" ) node = state.sceneMap[id] = convert_flat_to_round_curves(loadNode(xml->child(0)));
|
||||
else if (xml->name == "Flatten" ) node = state.sceneMap[id] = flatten (loadNode(xml->child(0)), SceneGraph::INSTANCING_NONE);
|
||||
else if (xml->name == "Flatten" ) node = state.sceneMap[id] = flatten(loadNode(xml->child(0)), SceneGraph::INSTANCING_NONE);
|
||||
else if (xml->name == "TimeRange" ) {
|
||||
const Vec2f time_range = xml->parm_Vec2f("time");
|
||||
node = state.sceneMap[id] = loadNode(xml->child(0));
|
||||
set_time_range(node,BBox1f(time_range.x,time_range.y));
|
||||
}
|
||||
|
||||
else THROW_RUNTIME_ERROR(xml->loc.str()+": unknown tag: "+xml->name);
|
||||
|
||||
@@ -1363,7 +1387,7 @@ namespace embree
|
||||
{
|
||||
size_t matid = xml->child("materiallist")->body[0].Int();
|
||||
Ref<SceneGraph::MaterialNode> material = id2material.at(matid);
|
||||
Ref<SceneGraph::TriangleMeshNode> mesh = new SceneGraph::TriangleMeshNode(material);
|
||||
Ref<SceneGraph::TriangleMeshNode> mesh = new SceneGraph::TriangleMeshNode(material,BBox1f(0,1),0);
|
||||
|
||||
mesh->positions.push_back(loadVec3faArray(xml->childOpt("vertex")));
|
||||
mesh->normals.push_back(loadVec3faArray(xml->childOpt("normal")));
|
||||
|
||||
@@ -29,7 +29,11 @@ namespace embree
|
||||
{
|
||||
while (cin->peek() == Token::Sym("<!--")) {
|
||||
cin->drop();
|
||||
while (cin->peek() != Token::Sym("-->")) cin->drop();
|
||||
while (cin->peek() != Token::Sym("-->")) {
|
||||
if (cin->peek() == Token::Eof())
|
||||
THROW_RUNTIME_ERROR(cin->get().Location().str()+": --> expected");
|
||||
cin->drop();
|
||||
}
|
||||
cin->drop();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,11 +43,16 @@ namespace embree
|
||||
if (i == parms.end()) return ""; else return i->second;
|
||||
}
|
||||
|
||||
Vec2f parm_Vec2f(const std::string& parmID) const {
|
||||
std::map<std::string,std::string>::const_iterator i = parms.find(parmID);
|
||||
if (i == parms.end()) THROW_RUNTIME_ERROR (loc.str()+": XML node has no parameter \"" + parmID + "\"");
|
||||
return string_to_Vec2f(i->second);
|
||||
}
|
||||
|
||||
Vec3fa parm_Vec3fa(const std::string& parmID) const {
|
||||
std::map<std::string,std::string>::const_iterator i = parms.find(parmID);
|
||||
if (i == parms.end()) THROW_RUNTIME_ERROR (loc.str()+": XML node has no parameter \"" + parmID + "\"");
|
||||
const Vec3f p = string_to_Vec3f(i->second);
|
||||
return Vec3fa(p);
|
||||
return Vec3fa(string_to_Vec3f(i->second));
|
||||
}
|
||||
|
||||
float parm_float(const std::string& parmID) const {
|
||||
|
||||
@@ -140,6 +140,8 @@ namespace embree
|
||||
|
||||
texcoords = in->texcoords.data();
|
||||
triangles = (ISPCTriangle*) in->triangles.data();
|
||||
startTime = in->time_range.lower;
|
||||
endTime = in->time_range.upper;
|
||||
numTimeSteps = (unsigned) in->numTimeSteps();
|
||||
numVertices = (unsigned) in->numVertices();
|
||||
numTriangles = (unsigned) in->numPrimitives();
|
||||
@@ -166,6 +168,8 @@ namespace embree
|
||||
|
||||
texcoords = in->texcoords.data();
|
||||
quads = (ISPCQuad*) in->quads.data();
|
||||
startTime = in->time_range.lower;
|
||||
endTime = in->time_range.upper;
|
||||
numTimeSteps = (unsigned) in->numTimeSteps();
|
||||
numVertices = (unsigned) in->numVertices();
|
||||
numQuads = (unsigned) in->numPrimitives();
|
||||
@@ -186,6 +190,8 @@ namespace embree
|
||||
positions[i] = in->positions[i].data();
|
||||
|
||||
grids = (ISPCGrid*) in->grids.data();
|
||||
startTime = in->time_range.lower;
|
||||
endTime = in->time_range.upper;
|
||||
numTimeSteps = (unsigned) in->numTimeSteps();
|
||||
numVertices = (unsigned) in->numVertices();
|
||||
numGrids = (unsigned) in->numPrimitives();
|
||||
@@ -223,6 +229,8 @@ namespace embree
|
||||
edge_crease_weights = in->edge_crease_weights.data();
|
||||
vertex_creases = in->vertex_creases.data();
|
||||
vertex_crease_weights = in->vertex_crease_weights.data();
|
||||
startTime = in->time_range.lower;
|
||||
endTime = in->time_range.upper;
|
||||
numTimeSteps = unsigned(in->numTimeSteps());
|
||||
numVertices = unsigned(in->numPositions());
|
||||
numFaces = unsigned(in->numPrimitives());
|
||||
@@ -275,6 +283,8 @@ namespace embree
|
||||
|
||||
hairs = (ISPCHair*) in->hairs.data();
|
||||
flags = (unsigned char*)in->flags.data();
|
||||
startTime = in->time_range.lower;
|
||||
endTime = in->time_range.upper;
|
||||
numTimeSteps = (unsigned) in->numTimeSteps();
|
||||
numVertices = (unsigned) in->numVertices();
|
||||
numHairs = (unsigned)in->numPrimitives();
|
||||
@@ -294,6 +304,8 @@ namespace embree
|
||||
spaces = (AffineSpace3fa*) alignedMalloc(in->spaces.size()*sizeof(AffineSpace3fa),16);
|
||||
geom.geomID = scene->geometryID(in->child);
|
||||
child = ISPCScene::convertGeometry(scene,in->child);
|
||||
startTime = in->spaces.time_range.lower;
|
||||
endTime = in->spaces.time_range.upper;
|
||||
for (size_t i=0; i<numTimeSteps; i++)
|
||||
spaces[i] = in->spaces[i];
|
||||
}
|
||||
@@ -350,6 +362,7 @@ namespace embree
|
||||
{
|
||||
RTCGeometry geom = rtcNewGeometry (device, RTC_GEOMETRY_TYPE_TRIANGLE);
|
||||
rtcSetGeometryTimeStepCount(geom,mesh->numTimeSteps);
|
||||
rtcSetGeometryTimeRange(geom,mesh->startTime,mesh->endTime);
|
||||
rtcSetGeometryBuildQuality(geom, quality);
|
||||
for (unsigned int t=0; t<mesh->numTimeSteps; t++) {
|
||||
rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_VERTEX, t, RTC_FORMAT_FLOAT3, mesh->positions[t], 0, sizeof(Vec3fa), mesh->numVertices);
|
||||
@@ -367,6 +380,7 @@ namespace embree
|
||||
{
|
||||
RTCGeometry geom = rtcNewGeometry (device, RTC_GEOMETRY_TYPE_QUAD);
|
||||
rtcSetGeometryTimeStepCount(geom,mesh->numTimeSteps);
|
||||
rtcSetGeometryTimeRange(geom,mesh->startTime,mesh->endTime);
|
||||
rtcSetGeometryBuildQuality(geom, quality);
|
||||
for (unsigned int t=0; t<mesh->numTimeSteps; t++) {
|
||||
rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_VERTEX, t, RTC_FORMAT_FLOAT3, mesh->positions[t], 0, sizeof(Vec3fa), mesh->numVertices);
|
||||
@@ -384,6 +398,7 @@ namespace embree
|
||||
{
|
||||
RTCGeometry geom = rtcNewGeometry (device, RTC_GEOMETRY_TYPE_GRID);
|
||||
rtcSetGeometryTimeStepCount(geom,mesh->numTimeSteps);
|
||||
rtcSetGeometryTimeRange(geom,mesh->startTime,mesh->endTime);
|
||||
rtcSetGeometryBuildQuality(geom, quality);
|
||||
for (unsigned int t=0; t<mesh->numTimeSteps; t++) {
|
||||
rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_VERTEX, t, RTC_FORMAT_FLOAT3, mesh->positions[t], 0, sizeof(Vec3fa), mesh->numVertices);
|
||||
@@ -401,6 +416,7 @@ namespace embree
|
||||
{
|
||||
RTCGeometry geom = rtcNewGeometry(device, RTC_GEOMETRY_TYPE_SUBDIVISION);
|
||||
rtcSetGeometryTimeStepCount(geom,mesh->numTimeSteps);
|
||||
rtcSetGeometryTimeRange(geom,mesh->startTime,mesh->endTime);
|
||||
rtcSetGeometryBuildQuality(geom, quality);
|
||||
for (unsigned int i=0; i<mesh->numEdges; i++) mesh->subdivlevel[i] = FIXED_EDGE_TESSELLATION_VALUE;
|
||||
for (unsigned int t=0; t<mesh->numTimeSteps; t++) {
|
||||
@@ -455,6 +471,7 @@ namespace embree
|
||||
{
|
||||
RTCGeometry geom = rtcNewGeometry(device, mesh->type);
|
||||
rtcSetGeometryTimeStepCount(geom,mesh->numTimeSteps);
|
||||
rtcSetGeometryTimeRange(geom,mesh->startTime,mesh->endTime);
|
||||
rtcSetGeometryBuildQuality(geom, quality);
|
||||
|
||||
for (unsigned int t=0; t<mesh->numTimeSteps; t++) {
|
||||
@@ -522,10 +539,12 @@ namespace embree
|
||||
instance->geom.geomID = geomID;
|
||||
return geomID;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
RTCGeometry geom = rtcNewGeometry (device, RTC_GEOMETRY_TYPE_INSTANCE);
|
||||
rtcSetGeometryInstancedScene(geom,scene_inst);
|
||||
rtcSetGeometryTimeStepCount(geom,instance->numTimeSteps);
|
||||
rtcSetGeometryTimeRange(geom,instance->startTime,instance->endTime);
|
||||
for (size_t t=0; t<instance->numTimeSteps; t++)
|
||||
rtcSetGeometryTransform(geom,(unsigned int)t,RTC_FORMAT_FLOAT4X4_COLUMN_MAJOR,&instance->spaces[t].l.vx.x);
|
||||
rtcCommitGeometry(geom);
|
||||
|
||||
@@ -115,7 +115,9 @@ namespace embree
|
||||
Vec3fa** normals; //!< vertex normal array
|
||||
Vec2f* texcoords; //!< vertex texcoord array
|
||||
ISPCTriangle* triangles; //!< list of triangles
|
||||
|
||||
|
||||
float startTime;
|
||||
float endTime;
|
||||
unsigned int numTimeSteps;
|
||||
unsigned int numVertices;
|
||||
unsigned int numTriangles;
|
||||
@@ -139,7 +141,9 @@ namespace embree
|
||||
Vec3fa** normals; //!< vertex normal array
|
||||
Vec2f* texcoords; //!< vertex texcoord array
|
||||
ISPCQuad* quads; //!< list of quads
|
||||
|
||||
|
||||
float startTime;
|
||||
float endTime;
|
||||
unsigned int numTimeSteps;
|
||||
unsigned int numVertices;
|
||||
unsigned int numQuads;
|
||||
@@ -176,7 +180,9 @@ namespace embree
|
||||
unsigned int* vertex_creases; //!< indices of vertex creases
|
||||
float* vertex_crease_weights; //!< weight for each vertex crease
|
||||
unsigned int* face_offsets;
|
||||
|
||||
|
||||
float startTime;
|
||||
float endTime;
|
||||
unsigned int numTimeSteps;
|
||||
unsigned int numVertices;
|
||||
unsigned int numFaces;
|
||||
@@ -212,6 +218,8 @@ namespace embree
|
||||
uint8* flags; //!< end cap flags per segment
|
||||
#endif
|
||||
RTCGeometryType type;
|
||||
float startTime;
|
||||
float endTime;
|
||||
unsigned int numTimeSteps;
|
||||
unsigned int numVertices;
|
||||
unsigned int numHairs;
|
||||
@@ -235,7 +243,9 @@ namespace embree
|
||||
ISPCGeometry geom;
|
||||
Vec3fa** positions; //!< vertex position array
|
||||
ISPCGrid* grids; //!< list of quads
|
||||
|
||||
|
||||
float startTime;
|
||||
float endTime;
|
||||
unsigned int numTimeSteps;
|
||||
unsigned int numVertices;
|
||||
unsigned int numGrids;
|
||||
@@ -257,6 +267,8 @@ namespace embree
|
||||
|
||||
ISPCGeometry geom;
|
||||
ISPCGeometry* child;
|
||||
float startTime;
|
||||
float endTime;
|
||||
unsigned int numTimeSteps;
|
||||
AffineSpace3fa* spaces;
|
||||
};
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user