1 // =============================================================================
2 // PROJECT CHRONO - http://projectchrono.org
3 //
4 // Copyright (c) 2019 projectchrono.org
5 // All rights reserved.
6 //
7 // Use of this source code is governed by a BSD-style license that can be found
8 // in the LICENSE file at the top level of the distribution and at
9 // http://projectchrono.org/license-chrono.txt.
10 //
11 // =============================================================================
12 // Authors: Asher Elmquist
13 // =============================================================================
14 //
15 // =============================================================================
16
17 #ifndef CHSENSORDEVICEUTILS_H
18 #define CHSENSORDEVICEUTILS_H
19
20 #include "chrono_sensor/optix/ChOptixDefinitions.h"
21
22 #include <math_constants.h>
23 #include <optix.h>
24
25 extern "C" {
26 __constant__ ContextParameters params;
27 }
28
make_half4(const float4 & a)29 __device__ __inline__ half4 make_half4(const float4& a) {
30 return {__float2half(a.x), __float2half(a.y), __float2half(a.z), __float2half(a.w)};
31 }
32
make_half4(const float & a,const float & b,const float & c,const float & d)33 __device__ __inline__ half4 make_half4(const float& a, const float& b, const float& c, const float& d) {
34 return {__float2half(a), __float2half(b), __float2half(c), __float2half(d)};
35 }
36
make_color(const float3 & c)37 static __device__ __inline__ uchar4 make_color(const float3& c) {
38 return make_uchar4(static_cast<unsigned char>(__saturatef(c.x) * 255.9999f),
39 static_cast<unsigned char>(__saturatef(c.y) * 255.9999f),
40 static_cast<unsigned char>(__saturatef(c.z) * 255.9999f), 255);
41 }
42
ints_as_pointer(unsigned int & a,unsigned int & b)43 static __device__ __inline__ void* ints_as_pointer(unsigned int& a, unsigned int& b) {
44 const unsigned long long ptr = static_cast<unsigned long long>(a) << 32 | b;
45 return reinterpret_cast<void*>(ptr);
46 }
47
pointer_as_ints(void * ptr,unsigned int & a,unsigned int & b)48 static __device__ __inline__ void pointer_as_ints(void* ptr, unsigned int& a, unsigned int& b) {
49 const unsigned long long uptr = reinterpret_cast<unsigned long long>(ptr);
50 a = uptr >> 32;
51 b = uptr & 0x00000000ffffffff;
52 }
53
sensor_rand(unsigned int seed)54 static __device__ __inline__ float sensor_rand(unsigned int seed) {
55 unsigned int next = (1103515245u * seed + 12345u) % 2147483648u;
56 return (float)(next) / (float)(2147483648u);
57 }
58
sensor_next_rand(float & rand)59 static __device__ __inline__ float sensor_next_rand(float& rand) {
60 unsigned int next_seed = (unsigned int)(rand * 2147483648u);
61 float next_rand = sensor_rand(next_seed);
62 rand = next_rand;
63 return rand;
64 }
65
getCameraPRD()66 __device__ __inline__ PerRayData_camera* getCameraPRD() {
67 unsigned int opt0 = optixGetPayload_0();
68 unsigned int opt1 = optixGetPayload_1();
69 return reinterpret_cast<PerRayData_camera*>(ints_as_pointer(opt0, opt1));
70 }
71
getSemanticPRD()72 __device__ __inline__ PerRayData_semantic* getSemanticPRD() {
73 unsigned int opt0 = optixGetPayload_0();
74 unsigned int opt1 = optixGetPayload_1();
75 return reinterpret_cast<PerRayData_semantic*>(ints_as_pointer(opt0, opt1));
76 }
77
getLidarPRD()78 __device__ __inline__ PerRayData_lidar* getLidarPRD() {
79 unsigned int opt0 = optixGetPayload_0();
80 unsigned int opt1 = optixGetPayload_1();
81 return reinterpret_cast<PerRayData_lidar*>(ints_as_pointer(opt0, opt1));
82 }
83
getRadarPRD()84 __device__ __inline__ PerRayData_radar* getRadarPRD() {
85 unsigned int opt0 = optixGetPayload_0();
86 unsigned int opt1 = optixGetPayload_1();
87 return reinterpret_cast<PerRayData_radar*>(ints_as_pointer(opt0, opt1));
88 }
89
getShadowPRD()90 __device__ __inline__ PerRayData_shadow* getShadowPRD() {
91 unsigned int opt0 = optixGetPayload_0();
92 unsigned int opt1 = optixGetPayload_1();
93 return reinterpret_cast<PerRayData_shadow*>(ints_as_pointer(opt0, opt1));
94 }
95
default_camera_prd()96 __device__ __inline__ PerRayData_camera default_camera_prd() {
97 PerRayData_camera prd = {};
98 prd.color = make_float3(0.f, 0.f, 0.f);
99 prd.contrib_to_pixel = make_float3(1.f, 1.f, 1.f);
100 prd.rng = curandState_t();
101 prd.depth = 2;
102 prd.use_gi = false;
103 prd.albedo = make_float3(0.f, 0.f, 0.f);
104 prd.normal = make_float3(0.f, 0.f, 0.f);
105 return prd;
106 };
107
default_semantic_prd()108 __device__ __inline__ PerRayData_semantic default_semantic_prd() {
109 PerRayData_semantic prd = {};
110 prd.class_id = 0;
111 prd.instance_id = 0;
112 return prd;
113 };
114
default_shadow_prd()115 __device__ __inline__ PerRayData_shadow default_shadow_prd() {
116 PerRayData_shadow prd = {make_float3(1.f, 1.f, 1.f), // default opacity amount
117 3, // default depth
118 0.f}; // default distance remaining to light
119 return prd;
120 };
121
default_lidar_prd()122 __device__ __inline__ PerRayData_lidar default_lidar_prd() {
123 PerRayData_lidar prd = {
124 0.f, // default range
125 0.f // default intensity
126 };
127 return prd;
128 };
default_radar_prd()129 __device__ __inline__ PerRayData_radar default_radar_prd() {
130 PerRayData_radar prd = {
131 0.f, // default range
132 0.f // default rcs
133 };
134 return prd;
135 };
136
137 /// =======================
138 /// float3-float3 operators
139 /// =======================
140 __device__ __inline__ float3 operator+(const float3& a, const float3& b) {
141 return make_float3(a.x + b.x, a.y + b.y, a.z + b.z);
142 }
143
144 __device__ __inline__ void operator+=(float3& a, const float3& b) {
145 a = a + b;
146 }
147
148 __device__ __inline__ float3 operator-(const float3& a, const float3& b) {
149 return make_float3(a.x - b.x, a.y - b.y, a.z - b.z);
150 }
151
152 __device__ __inline__ float3 operator-(const float3& a) {
153 return make_float3(-a.x, -a.y, -a.z);
154 }
155
156 __device__ __inline__ float3 operator/(const float3& a, const float3& b) {
157 return make_float3(a.x / b.x, a.y / b.y, a.z / b.z);
158 }
159
160 __device__ __inline__ float3 operator*(const float3& a, const float3& b) {
161 return make_float3(a.x * b.x, a.y * b.y, a.z * b.z);
162 }
163
164 /// =======================
165 /// float4-float4 operators
166 /// =======================
167 __device__ __inline__ float4 operator+(const float4& a, const float4& b) {
168 return make_float4(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w);
169 }
170
171 __device__ __inline__ void operator+=(float4& a, const float4& b) {
172 a = a + b;
173 }
174
175 __device__ __inline__ float4 operator-(const float4& a, const float4& b) {
176 return make_float4(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w);
177 }
178
179 __device__ __inline__ float4 operator-(const float4& a) {
180 return make_float4(-a.x, -a.y, -a.z, -a.w);
181 }
182
183 __device__ __inline__ float4 operator/(const float4& a, const float4& b) {
184 return make_float4(a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w);
185 }
186
187 __device__ __inline__ float4 operator*(const float4& a, const float4& b) {
188 return make_float4(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w);
189 }
190
191 /// ================
192 /// vector functions
193 /// ================
Dot(const float4 & v1,const float4 & v2)194 __device__ __inline__ float Dot(const float4& v1, const float4& v2) {
195 return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z + v1.w * v2.w;
196 }
197
Dot(const float3 & v1,const float3 & v2)198 __device__ __inline__ float Dot(const float3& v1, const float3& v2) {
199 return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
200 }
201
Dot(const float2 & v1,const float2 & v2)202 __device__ __inline__ float Dot(const float2& v1, const float2& v2) {
203 return v1.x * v2.x + v1.y * v2.y;
204 }
205
Cross(const float3 & v1,const float3 & v2)206 __device__ __inline__ float3 Cross(const float3& v1, const float3& v2) {
207 return make_float3(v1.y * v2.z - v1.z * v2.y, v1.z * v2.x - v1.x * v2.z, v1.x * v2.y - v1.y * v2.x);
208 }
209
Length(const float4 & v)210 __device__ __inline__ float Length(const float4& v) {
211 return sqrt(Dot(v, v));
212 }
213
Length(const float3 & v)214 __device__ __inline__ float Length(const float3& v) {
215 return sqrt(Dot(v, v));
216 }
217
Length(const float2 & v)218 __device__ __inline__ float Length(const float2& v) {
219 return sqrt(Dot(v, v));
220 }
221
fmaxf(const float3 & a)222 __device__ __inline__ float fmaxf(const float3& a) {
223 return fmaxf(a.x, fmaxf(a.y, a.z));
224 }
225
fminf(const float3 & a)226 __device__ __inline__ float fminf(const float3& a) {
227 return fminf(a.x, fminf(a.y, a.z));
228 }
229
make_float3(const float & a)230 __device__ __inline__ float3 make_float3(const float& a) {
231 return make_float3(a, a, a);
232 }
233
make_float3(const float4 & a)234 __device__ __inline__ float3 make_float3(const float4& a) {
235 return make_float3(a.x, a.y, a.z);
236 }
237
Pow(const float3 & v,const float & a)238 __device__ __inline__ float3 Pow(const float3& v, const float& a) {
239 return make_float3(pow(v.x, a), pow(v.y, a), pow(v.z, a));
240 }
241 /// =======================
242 /// float3-float operators
243 /// =======================
244 __device__ __inline__ float3 operator*(const float& a, const float3& v) {
245 return make_float3(a * v.x, a * v.y, a * v.z);
246 }
247
248 __device__ __inline__ float3 operator*(const float3& v, const float& a) {
249 return make_float3(a * v.x, a * v.y, a * v.z);
250 }
251
252 __device__ __inline__ float3 operator/(const float3& v, const float& a) {
253 const float inv = 1 / a;
254 return make_float3(inv * v.x, inv * v.y, inv * v.z);
255 }
256
normalize(const float3 & a)257 __device__ __inline__ float3 normalize(const float3& a) {
258 return a / Length(a);
259 }
260
261 /// =======================
262 /// float4-float operators
263 /// =======================
264 __device__ __inline__ float4 operator*(const float& a, const float4& v) {
265 return make_float4(a * v.x, a * v.y, a * v.z, a * v.w);
266 }
267
268 __device__ __inline__ float4 operator*(const float4& v, const float& a) {
269 return make_float4(a * v.x, a * v.y, a * v.z, a * v.w);
270 }
271
272 __device__ __inline__ float4 operator/(const float4& v, const float& a) {
273 const float inv = 1 / a;
274 return make_float4(inv * v.x, inv * v.y, inv * v.z, inv * v.w);
275 }
276
normalize(const float4 & a)277 __device__ __inline__ float4 normalize(const float4& a) {
278 return a / Length(a);
279 }
280
281 /// ======================
282 /// float3-float functions
283 /// ======================
fmaxf(const float3 & a,const float3 & b)284 __device__ __inline__ float3 fmaxf(const float3& a, const float3& b) {
285 return make_float3(fmaxf(a.x, b.x), fmaxf(a.y, b.y), fmaxf(a.z, b.z));
286 }
287
fminf(const float3 & a,const float3 & b)288 __device__ __inline__ float3 fminf(const float3& a, const float3& b) {
289 return make_float3(fminf(a.x, b.x), fminf(a.y, b.y), fminf(a.z, b.z));
290 }
291
292 /// =======================
293 /// float2-float2 operators
294 /// =======================
295 __device__ __inline__ float2 operator+(const float2& a, const float2& b) {
296 return make_float2(a.x + b.x, a.y + b.y);
297 }
298
299 __device__ __inline__ float2 operator-(const float2& a, const float2& b) {
300 return make_float2(a.x - b.x, a.y - b.y);
301 }
302
303 __device__ __inline__ float2 operator-(const float2& a) {
304 return make_float2(-a.x, -a.y);
305 }
306
307 __device__ __inline__ float2 operator/(const float2& a, const float2& b) {
308 return make_float2(a.x / b.x, a.y / b.y);
309 }
310
311 /// =======================
312 /// float2-float operators
313 /// =======================
314 __device__ __inline__ float2 operator*(const float& a, const float2& v) {
315 return make_float2(a * v.x, a * v.y);
316 }
317
318 __device__ __inline__ float2 operator*(const float2& v, const float& a) {
319 return make_float2(a * v.x, a * v.y);
320 }
321
322 __device__ __inline__ float2 operator/(const float2& v, const float& a) {
323 const float inv = 1 / a;
324 return make_float2(inv * v.x, inv * v.y);
325 }
326
327 /// ================
328 /// float2 functions
329 /// ================
make_float2(const float & a)330 __device__ __inline__ float2 make_float2(const float& a) {
331 return make_float2(a, a);
332 }
333
make_float2(const int2 & a)334 __device__ __inline__ float2 make_float2(const int2& a) {
335 return make_float2((float)a.x, (float)a.y);
336 }
337
normalize(const float2 & a)338 __device__ __inline__ float2 normalize(const float2& a) {
339 return a / Length(a);
340 }
341
342 /// ================
343 /// clamp functions
344 /// ================
clamp(const float & a,const float & low,const float & high)345 __device__ __inline__ float clamp(const float& a, const float& low, const float& high) {
346 return max(low, min(a, high));
347 }
348
clamp(const float2 & a,const float2 & low,const float2 & high)349 __device__ __inline__ float2 clamp(const float2& a, const float2& low, const float2& high) {
350 return make_float2(clamp(a.x, low.x, high.x), clamp(a.y, low.y, high.y));
351 }
352
clamp(const float3 & a,const float3 & low,const float3 & high)353 __device__ __inline__ float3 clamp(const float3& a, const float3& low, const float3& high) {
354 return make_float3(clamp(a.x, low.x, high.x), clamp(a.y, low.y, high.y), clamp(a.z, low.z, high.z));
355 }
356
357 /// ==================
358 /// graphics functions
359 /// ==================
360 __device__ __inline__ float fresnel_schlick(const float& cos,
361 const float& exp = 5.f,
362 const float& min = 0.f,
363 const float& max = 1.f) {
364 return clamp(min + (max - min) * powf(fmaxf(0.f, 1.f - cos), exp), min, max);
365 }
366
fresnel_schlick(const float & cos,const float & exp,const float3 & min,const float3 & max)367 __device__ __inline__ float3 fresnel_schlick(const float& cos, const float& exp, const float3& min, const float3& max) {
368 return make_float3(fresnel_schlick(cos, exp, min.x, max.x), fresnel_schlick(cos, exp, min.y, max.y),
369 fresnel_schlick(cos, exp, min.z, max.z));
370 }
371
luminance(const float3 & color)372 __device__ __inline__ float luminance(const float3& color) {
373 const float3 l = {0.30f, 0.59f, 0.11f};
374 return Dot(color, l);
375 }
376
377 // assumes v in coming into the surface
reflect(const float3 & v,const float3 & n)378 __device__ __inline__ float3 reflect(const float3& v, const float3& n) {
379 return 2 * Dot(n, -v) * n + v;
380 }
381
refract(const float3 & v,const float3 & n,const float & n1,const float & n2)382 __device__ __inline__ float3 refract(const float3& v, const float3& n, const float& n1, const float& n2) {
383 float n_ratio = n1 / n2;
384 float cosi = -Dot(n, v);
385 return n_ratio * v + (n_ratio * cosi - sqrtf(max(0.f, 1 - n_ratio * n_ratio * cosi * cosi))) * n;
386 }
387
basis_from_quaternion(const float4 & q,float3 & f,float3 & g,float3 & h)388 __device__ __inline__ void basis_from_quaternion(const float4& q, float3& f, float3& g, float3& h) {
389 const float e0e0 = q.x * q.x;
390 const float e1e1 = q.y * q.y;
391 const float e2e2 = q.z * q.z;
392 const float e3e3 = q.w * q.w;
393 const float e0e1 = q.x * q.y;
394 const float e0e2 = q.x * q.z;
395 const float e0e3 = q.x * q.w;
396 const float e1e2 = q.y * q.z;
397 const float e1e3 = q.y * q.w;
398 const float e2e3 = q.z * q.w;
399 f = make_float3((e0e0 + e1e1) * 2 - 1, (e1e2 + e0e3) * 2, (e1e3 - e0e2) * 2);
400 g = make_float3((e1e2 - e0e3) * 2, (e0e0 + e2e2) * 2 - 1, (e2e3 + e0e1) * 2);
401 h = make_float3((e1e3 + e0e2) * 2, (e2e3 - e0e1) * 2, (e0e0 + e3e3) * 2 - 1);
402 }
403
lerp(const float & a,const float & b,const float & t)404 __device__ __inline__ float lerp(const float& a, const float& b, const float& t) {
405 return a + t * (b - a);
406 }
407
lerp(const float2 & a,const float2 & b,const float & t)408 __device__ __inline__ float2 lerp(const float2& a, const float2& b, const float& t) {
409 return a + t * (b - a);
410 }
411
lerp(const float3 & a,const float3 & b,const float & t)412 __device__ __inline__ float3 lerp(const float3& a, const float3& b, const float& t) {
413 return a + t * (b - a);
414 }
415
lerp(const float4 & a,const float4 & b,const float & t)416 __device__ __inline__ float4 lerp(const float4& a, const float4& b, const float& t) {
417 return a + t * (b - a);
418 }
419
nlerp(const float2 & a,const float2 & b,const float & t)420 __device__ __inline__ float2 nlerp(const float2& a, const float2& b, const float& t) {
421 return normalize(lerp(a, b, t));
422 }
423
nlerp(const float3 & a,const float3 & b,const float & t)424 __device__ __inline__ float3 nlerp(const float3& a, const float3& b, const float& t) {
425 return normalize(lerp(a, b, t));
426 }
427
nlerp(const float4 & a,const float4 & b,const float & t)428 __device__ __inline__ float4 nlerp(const float4& a, const float4& b, const float& t) {
429 return normalize(lerp(a, b, t));
430 }
431
sample_hemisphere_dir(const float & z1,const float & z2,const float3 & normal)432 __device__ __inline__ float3 sample_hemisphere_dir(const float& z1, const float& z2, const float3& normal) {
433 const float radius = sqrtf(z1);
434 const float theta = 2.f * CUDART_PI_F * z2;
435 float x = radius * cosf(theta);
436 float y = radius * sinf(theta);
437 float z = sqrtf(fmaxf(0.f, 1.f - x * x - y * y));
438 float3 binormal = make_float3(0);
439
440 // Prevent normal = (0, 0, 1)
441 if (fabs(normal.x) > fabs(normal.z)) {
442 binormal.x = -normal.y;
443 binormal.y = normal.x;
444 binormal.z = 0;
445 } else {
446 binormal.x = 0;
447 binormal.y = -normal.z;
448 binormal.z = normal.y;
449 }
450
451 // float3 binormal = make_float3(-normal.y, normal.x, 0);
452 float3 tangent = Cross(normal, binormal);
453 return x * tangent + y * binormal + z * normal;
454 }
455
456 #endif
457