Compare commits

...
75 Commits
Author SHA1 Message Date
Sven Woop 86dbc8a437 fixed comments 2018-12-13 08:41:14 +01:00
Sven Woop 4c93274a31 added support for arbitrary SAH block size 2018-12-13 08:39:06 +01:00
Sven Woop bd7ea15f50 replaced logBlockSize by sahBlockSize 2018-12-13 08:22:12 +01:00
Sven Woop 1df9591a8c replaced logBlockSize by sahBlockSize 2018-12-13 07:53:13 +01:00
Sven Woop 23753277fa regenerated documentation 2018-11-22 07:18:21 +01:00
Sven Woop 95053e8c6e setting version to v3.3.0 2018-11-22 07:16:52 +01:00
Sven Woop 0ff0a6909b Merge branch 'devel' of gitlab.com:sdvis/embree into devel 2018-11-21 07:15:17 +01:00
Sven Woop 40e445ade8 setting CMP0042 policy to NEW by default 2018-11-21 07:15:06 +01:00
Sven Woop 8c08b5c5b5 bugfix in open_sequential function, this codepath is currently disabled 2018-11-20 05:39:10 +01:00
Sven Woop a07e9b0c5c Revert "Applied bugfix for missed perfectly axis aligned motion blurred"
This issue is already worked around in the setBounds function of
BVH.

This reverts commit 17a17f7e18.
2018-11-19 17:45:39 +01:00
Sven Woop 0f4f821f76 added documentation for motion blur time range 2018-11-19 08:31:50 +01:00
Sven Woop cf4d9e9f62 Merge branch 'devel' into swoop 2018-11-19 07:54:14 +01:00
Sven Woop d25f7b0ac2 moved previous changelog update to doc/src/changelog.md 2018-11-09 11:03:18 +01:00
Tim Rowley 15caf3fd1b Fix black tutorial windows on macOS 10.14 until moved. 2018-11-07 10:25:32 -06:00
Sven Woop 0eb47c2c6b bugfixes in ambient occlusion shader (--shader ao) 2018-11-06 08:16:03 +01:00
Sven Woop 9de546d581 Fixed crash with pathtracer when using --shader ao command line 2018-11-06 08:00:40 +01:00
Sven Woop 33bd19d2a3 setting version to v3.2.5-alpha.0 2018-11-06 07:45:17 +01:00
Sven Woop 4e1a7741fb Fixed segfault of pathtracer when invoking with --triangle-sphere command line option. 2018-11-06 07:44:19 +01:00
Johannes Günther e2f4851405 Fix typo&links (vs1[24]->vc1[24]), package correct tbb.dll for vc14 2018-10-29 14:29:15 +01:00
Sven Woop 7662e7b260 regenerated documentation 2018-10-25 17:14:31 +02:00
Sven Woop 4a12bfed63 setting version to v3.2.4 2018-10-25 12:34:10 +02:00
Sven Woop 1bf492e704 releasing ZIP files for vs12 and vs14 2018-10-25 12:33:50 +02:00
Sven Woop 8e3fc16de5 bugfix in CI 2018-10-25 12:16:53 +02:00
Sven Woop d110857224 fixed compile issues with ICC 2019 2018-10-25 11:50:28 +02:00
Sven Woop 09a6013b79 regenerated documentation 2018-10-11 06:59:50 +02:00
Sven Woop 60254acc8a setting version to v3.2.3 2018-10-11 06:57:50 +02:00
Sven Woop 6c6aa92560 setting version to v3.2.3-alpha.0 2018-10-10 10:01:17 +02:00
Sven Woop 79c9f4a1b8 Fixed crash when using curves with RTC_SCENE_FLAG_DYNAMIC and RTC_BUILD_QUALITY_MEDIUM 2018-10-10 09:51:30 +02:00
Sven Woop ae20787a43 added hair to regression_dynamic test 2018-10-10 09:51:23 +02:00
Sven Woop a8fda51877 fixed typo in changelog 2018-10-10 07:12:40 +02:00
Sven Woop 17a17f7e18 Applied bugfix for missed perfectly axis aligned motion blurred
geometry also to time range implementation for motion blur.
2018-09-11 07:00:39 +02:00
Sven Woop b27a31f572 Merge branch 'devel' into swoop 2018-09-11 06:57:54 +02:00
Sven Woop a7772b05aa changed model hash to include time segment mblur test for instances 2018-09-06 10:31:49 +02:00
Sven Woop 03f24bbba5 fixes to scenegraph to support time range for instances 2018-09-06 10:29:45 +02:00
Sven Woop d2db02fa10 bugfix in time range for motion blur geometry of instances 2018-09-06 09:30:25 +02:00
Attila Afra 80c0fae902 cleanup 2018-07-13 17:38:12 +03:00
Attila Afra fd6eca502f fixed bug in temporal splitting 2018-07-13 17:21:00 +03:00
cbenthin a1c750b5a2 merged devel into swoop 2018-07-11 16:46:56 +02:00
Attila Afra 226f9e1fb5 fixed bug in getTimeSegmentRange 2018-07-11 14:15:30 +03:00
cbenthin ef9dd1951d version v3.3.0-alpha.0 2018-06-28 11:10:14 +02:00
Sven Woop a6527de9c9 updates to changelog, added geometry mblur time range 2018-05-28 10:10:58 +02:00
Sven Woop 9805370657 cleanups 2018-05-28 10:08:34 +02:00
Sven Woop ff669ab8f4 bugfix in createLargeLeaf for object time range mblur builder 2018-05-28 09:24:14 +02:00
Sven Woop 4efa364c7b bugfix in BuildRecord construction for object time range mblur builder 2018-05-28 09:07:18 +02:00
Sven Woop ca932f7669 bugfix in time_range handling, have to clip time range when constructing SetMB 2018-05-28 08:25:30 +02:00
Sven Woop 7297e6ffff cleanups 2018-05-28 07:46:00 +02:00
Sven Woop b04f338936 fixed bug with singleTimeSegment feature, however, this is not used anymore 2018-05-28 07:29:02 +02:00
Sven Woop bb4cd86ea4 using mblur time range tests 2018-05-25 14:48:06 +02:00
Sven Woop ba404619cc added grid mesh support to viewer_stream 2018-05-25 14:43:05 +02:00
Sven Woop a88881677e fixed various bugs where time_range was not properly copied 2018-05-25 14:39:38 +02:00
Sven Woop 7b7c88337d bugfix in --convert-triangles-to-quads, time range was not copied 2018-05-25 14:21:51 +02:00
Sven Woop a9b96ac13f added mblur_time_range_grid.xml 2018-05-25 14:09:39 +02:00
Sven Woop 0e27f93cb2 bugfix for mblur time range of grids 2018-05-25 14:09:02 +02:00
Sven Woop 4e725e928b added GridMesh support to XML loader 2018-05-25 13:46:32 +02:00
Sven Woop d9fd88e841 fixing mblur time range for quads 2018-05-25 13:41:17 +02:00
Sven Woop abf293aa0a adde mblur_time_range_line.xml 2018-05-25 13:28:08 +02:00
Sven Woop b71f37e1f6 added geometry time range support for curves 2018-05-25 13:26:11 +02:00
Sven Woop 0eabcdddd3 added geometry time range support to all other primitives, except curves everything should be working now 2018-05-25 07:47:40 +02:00
Sven Woop 7b8fa2e8a2 further disabling of buildSingleSegment 2018-05-25 07:13:32 +02:00
Sven Woop a72873c854 bugfix in filtering of non overlapping time ranges 2018-05-23 12:29:38 +02:00
Sven Woop d5e09d228d cleanups 2018-05-23 12:25:59 +02:00
Sven Woop 60b0c0154f bugfix in linear bounds calculation when time ranges were present 2018-05-23 12:17:13 +02:00
Sven Woop 5a7230da1f added triangle_msmblur_time_range.xml 2018-05-23 09:57:12 +02:00
Sven Woop a8dc2540de fixed bug in comment parsing 2018-05-23 09:31:52 +02:00
Sven Woop 03f654c62e optimized trianglei for mblur to only support single geomID 2018-05-23 09:11:52 +02:00
Sven Woop 7aeb056b32 added assertion in msmblur leaf creation to check that all geomIDs are identical 2018-05-23 09:02:48 +02:00
Sven Woop 4262431328 disabling buildSingleSegment in bvh_builder_sah_mb.cpp 2018-05-23 08:58:24 +02:00
Sven Woop 11d5e26d82 properly creating time bounding node when time bounds have shrunken 2018-05-23 08:47:02 +02:00
Sven Woop 3ae221bf73 properly extending time_range during split 2018-05-23 08:07:12 +02:00
Sven Woop f3b787a0ea msmblur builder creates leaves with single geometry only 2018-05-23 07:34:24 +02:00
Sven Woop 0ec8f6a299 filtering out primitives which are not valid in current time interval 2018-05-15 14:24:47 +02:00
Sven Woop 4be6966f63 added TimeRange node to XML format 2018-05-15 12:43:42 +02:00
Sven Woop 49fab5e8e0 assigning mblur time debugging to HOME/END keys 2018-05-15 11:22:47 +02:00
Sven Woop a8ee444842 first attempt to get extended motion blur working for triangles 2018-05-15 11:19:19 +02:00
Sven Woop d710ab6245 added rtcSetGeometryTimeRange API function 2018-05-15 08:22:25 +02:00
117 changed files with 2791 additions and 883 deletions
+17 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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")
+51 -39
View File
@@ -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}
```
+3 -6
View File
@@ -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()
+1
View File
@@ -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
+10 -4
View File
@@ -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)
+50
View File
@@ -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)
+2
View File
@@ -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; }
+8
View File
@@ -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;
+2
View File
@@ -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
View File
@@ -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}
```
+52
View File
@@ -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]
+1 -1
View File
@@ -44,4 +44,4 @@ On failure an error code is set that can be queried using
#### SEE ALSO
[rtcNewGeometry]
[rtcNewGeometry], [rtcSetGeometryTimeRange]
+18 -1
View File
@@ -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
+7 -3
View File
@@ -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
View File
@@ -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.
+4 -1
View 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);
+4 -1
View File
@@ -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);
+4 -4
View File
@@ -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"
+7 -6
View File
@@ -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);
}
+97 -26
View File
@@ -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) !!
+52 -17
View File
@@ -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)
{
+8 -8
View File
@@ -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;
+12 -8
View File
@@ -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);
+9 -9
View File
@@ -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 */
+4 -4
View File
@@ -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;
+19 -19
View File
@@ -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());
}
+3 -3
View File
@@ -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);
}
+74 -37
View File
@@ -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
View File
@@ -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
+2
View File
@@ -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;
}
+4 -3
View File
@@ -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);
+2 -2
View File
@@ -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
+39 -30
View File
@@ -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;
+16 -16
View File
@@ -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;
+2 -2
View File
@@ -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;
+3 -3
View File
@@ -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;
}
+3 -1
View File
@@ -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);
}
+52
View File
@@ -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);
}
}
+7 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
+14
View File
@@ -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;
+9 -10
View File
@@ -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;
}
+4 -4
View File
@@ -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);
+2 -3
View File
@@ -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 */
+7 -8
View File
@@ -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;
+7 -7
View File
@@ -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;
}
+7 -7
View File
@@ -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;
}
+7 -7
View File
@@ -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;
}
+2 -2
View File
@@ -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;
}
+4 -4
View File
@@ -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
View File
@@ -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
View File
@@ -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>
+4 -4
View File
@@ -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);
}
+26 -39
View File
@@ -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>
+2 -3
View File
@@ -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);
+4 -4
View File
@@ -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
+161 -27
View File
@@ -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.
+82
View File
@@ -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]
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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]
+35 -38
View File
@@ -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]
+44
View File
@@ -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]
+2 -2
View File
@@ -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
+2 -1
View File
@@ -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;
+11 -11
View File
@@ -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
+10 -4
View File
@@ -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]
+4 -4
View File
@@ -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
+3 -3
View File
@@ -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
+11 -11
View File
@@ -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
+3 -3
View File
@@ -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
+3 -3
View File
@@ -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.
+58
View File
@@ -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]
+5 -5
View File
@@ -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.
+1 -1
View File
@@ -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
View File
Binary file not shown.
+11 -3
View File
@@ -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)
+26
View File
@@ -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
////////////////////////////////////////////////////////////////////////////////
+25
View File
@@ -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++)
{
+4 -2
View File
@@ -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;
+1 -1
View File
@@ -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");
+33 -6
View File
@@ -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);
+47 -29
View File
@@ -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;
+34 -10
View File
@@ -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")));
+5 -1
View File
@@ -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();
}
}
+7 -2
View File
@@ -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 {
+20 -1
View File
@@ -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);
+16 -4
View File
@@ -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