NVIDIA OptiX 8.1 nvidia_logo_transpbg.gif Up
optix_micromap_impl.h
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: Copyright (c) 2022 - 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3 * SPDX-License-Identifier: BSD-3-Clause
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31
38#ifndef OPTIX_OPTIX_MICROMAP_IMPL_H
39#define OPTIX_OPTIX_MICROMAP_IMPL_H
40
41#ifndef OPTIX_MICROMAP_FUNC
42#ifdef __CUDACC__
43#define OPTIX_MICROMAP_FUNC __device__
44#else
45#define OPTIX_MICROMAP_FUNC
46#endif
47#endif
48
49namespace optix_impl {
50
55#define OPTIX_MICROMAP_INLINE_FUNC OPTIX_MICROMAP_FUNC inline
56
57#ifdef __CUDACC__
58// the device implementation of __uint_as_float is declared in cuda_runtime.h
59#else
60// the host implementation of __uint_as_float
62{
63 union { float f; unsigned int i; } var;
64 var.i = x;
65 return var.f;
66}
67#endif
68
69// Extract even bits
70OPTIX_MICROMAP_INLINE_FUNC unsigned int extractEvenBits( unsigned int x )
71{
72 x &= 0x55555555;
73 x = ( x | ( x >> 1 ) ) & 0x33333333;
74 x = ( x | ( x >> 2 ) ) & 0x0f0f0f0f;
75 x = ( x | ( x >> 4 ) ) & 0x00ff00ff;
76 x = ( x | ( x >> 8 ) ) & 0x0000ffff;
77 return x;
78}
79
80
81// Calculate exclusive prefix or (log(n) XOR's and SHF's)
82OPTIX_MICROMAP_INLINE_FUNC unsigned int prefixEor( unsigned int x )
83{
84 x ^= x >> 1;
85 x ^= x >> 2;
86 x ^= x >> 4;
87 x ^= x >> 8;
88 return x;
89}
90
91// Convert distance along the curve to discrete barycentrics
92OPTIX_MICROMAP_INLINE_FUNC void index2dbary( unsigned int index, unsigned int& u, unsigned int& v, unsigned int& w )
93{
94 unsigned int b0 = extractEvenBits( index );
95 unsigned int b1 = extractEvenBits( index >> 1 );
96
97 unsigned int fx = prefixEor( b0 );
98 unsigned int fy = prefixEor( b0 & ~b1 );
99
100 unsigned int t = fy ^ b1;
101
102 u = ( fx & ~t ) | ( b0 & ~t ) | ( ~b0 & ~fx & t );
103 v = fy ^ b0;
104 w = ( ~fx & ~t ) | ( b0 & ~t ) | ( ~b0 & fx & t );
105}
106
107// Compute barycentrics of a sub or micro triangle wrt a base triangle. The order of the returned
108// bary0, bary1, bary2 matters and allows for using this function for sub triangles and the
109// conversion from sub triangle to base triangle barycentric space
110OPTIX_MICROMAP_INLINE_FUNC void micro2bary( unsigned int index, unsigned int subdivisionLevel, float2& bary0, float2& bary1, float2& bary2 )
111{
112 if( subdivisionLevel == 0 )
113 {
114 bary0 = { 0, 0 };
115 bary1 = { 1, 0 };
116 bary2 = { 0, 1 };
117 return;
118 }
119
120 unsigned int iu, iv, iw;
121 index2dbary( index, iu, iv, iw );
122
123 // we need to only look at "level" bits
124 iu = iu & ( ( 1 << subdivisionLevel ) - 1 );
125 iv = iv & ( ( 1 << subdivisionLevel ) - 1 );
126 iw = iw & ( ( 1 << subdivisionLevel ) - 1 );
127
128 int yFlipped = ( iu & 1 ) ^ ( iv & 1 ) ^ ( iw & 1 ) ^ 1;
129
130 int xFlipped = ( ( 0x8888888888888888ull ^ 0xf000f000f000f000ull ^ 0xffff000000000000ull ) >> index ) & 1;
131 xFlipped ^= ( ( 0x8888888888888888ull ^ 0xf000f000f000f000ull ^ 0xffff000000000000ull ) >> ( index >> 6 ) ) & 1;
132
133 const float levelScale = __uint_as_float( ( 127u - subdivisionLevel ) << 23 );
134
135 // scale the barycentic coordinate to the global space/scale
136 float du = 1.f * levelScale;
137 float dv = 1.f * levelScale;
138
139 // scale the barycentic coordinate to the global space/scale
140 float u = (float)iu * levelScale;
141 float v = (float)iv * levelScale;
142
143 // c d
144 // x-----x
145 // / \ /
146 // / \ /
147 // x-----x
148 // a b
149 //
150 // !xFlipped && !yFlipped: abc
151 // !xFlipped && yFlipped: cdb
152 // xFlipped && !yFlipped: bac
153 // xFlipped && yFlipped: dcb
154
155 bary0 = { u + xFlipped * du , v + yFlipped * dv };
156 bary1 = { u + (1-xFlipped) * du, v + yFlipped * dv };
157 bary2 = { u + yFlipped * du , v + (1-yFlipped) * dv };
158}
159
160// avoid any conflicts due to multiple definitions
161#define OPTIX_MICROMAP_FLOAT2_SUB(a,b) { a.x - b.x, a.y - b.y }
162
163// Compute barycentrics for micro triangle from base barycentrics
164OPTIX_MICROMAP_INLINE_FUNC float2 base2micro( const float2& baseBarycentrics, const float2 microVertexBaseBarycentrics[3] )
165{
166 float2 baryV0P = OPTIX_MICROMAP_FLOAT2_SUB( baseBarycentrics, microVertexBaseBarycentrics[0] );
167 float2 baryV0V1 = OPTIX_MICROMAP_FLOAT2_SUB( microVertexBaseBarycentrics[1], microVertexBaseBarycentrics[0] );
168 float2 baryV0V2 = OPTIX_MICROMAP_FLOAT2_SUB( microVertexBaseBarycentrics[2], microVertexBaseBarycentrics[0] );
169
170 float rdetA = 1.f / ( baryV0V1.x * baryV0V2.y - baryV0V1.y * baryV0V2.x );
171 float4 A = { baryV0V2.y, -baryV0V2.x, -baryV0V1.y, baryV0V1.x };
172
173 float2 localUV;
174 localUV.x = rdetA * ( baryV0P.x * A.x + baryV0P.y * A.y );
175 localUV.y = rdetA * ( baryV0P.x * A.z + baryV0P.y * A.w );
176
177 return localUV;
178}
179#undef OPTIX_MICROMAP_FLOAT2_SUB
180 // end group optix_utilities
182
183} // namespace optix_impl
184
185#endif // OPTIX_OPTIX_MICROMAP_IMPL_H
OPTIX_MICROMAP_INLINE_FUNC float2 base2micro(const float2 &baseBarycentrics, const float2 microVertexBaseBarycentrics[3])
Definition: optix_micromap_impl.h:164
#define OPTIX_MICROMAP_INLINE_FUNC
Definition: optix_micromap_impl.h:55
OPTIX_MICROMAP_INLINE_FUNC void micro2bary(unsigned int index, unsigned int subdivisionLevel, float2 &bary0, float2 &bary1, float2 &bary2)
Definition: optix_micromap_impl.h:110
OPTIX_MICROMAP_INLINE_FUNC unsigned int prefixEor(unsigned int x)
Definition: optix_micromap_impl.h:82
#define OPTIX_MICROMAP_FLOAT2_SUB(a, b)
Definition: optix_micromap_impl.h:161
OPTIX_MICROMAP_INLINE_FUNC float __uint_as_float(unsigned int x)
Definition: optix_micromap_impl.h:61
OPTIX_MICROMAP_INLINE_FUNC void index2dbary(unsigned int index, unsigned int &u, unsigned int &v, unsigned int &w)
Definition: optix_micromap_impl.h:92
OPTIX_MICROMAP_INLINE_FUNC unsigned int extractEvenBits(unsigned int x)
Definition: optix_micromap_impl.h:70
Definition: optix_device_impl_transformations.h:27