1.3.64
 
Loading...
Searching...
No Matches
VoxelIntersection.cu
Go to the documentation of this file.
1
16#include "VoxelIntersection.h"
17
18#define CUDA_CHECK_ERROR(ans) \
19 { \
20 gpuAssert((ans), __FILE__, __LINE__); \
21 }
22inline void gpuAssert(cudaError_t code, const char *file, int line, bool abort = true) {
23 if (code != cudaSuccess) {
24 fprintf(stderr, "GPUassert: %s %s %d\n", cudaGetErrorString(code), file, line);
25 if (abort)
26 exit(code);
27 }
28}
29
30float3 inline vec3tofloat3(helios::vec3 v3) {
31 float3 f3;
32 f3.x = v3.x;
33 f3.y = v3.y;
34 f3.z = v3.z;
35 return f3;
36}
37
38helios::vec3 inline float3tovec3(float3 f3) {
39 helios::vec3 v3;
40 v3.x = f3.x;
41 v3.y = f3.y;
42 v3.z = f3.z;
43 return v3;
44}
45
46__device__ float3 d_rotatePoint_vi(const float3 &position, const float &theta, const float &phi) {
47
48 float Ry[3][3], Rz[3][3];
49
50 float st = sinf(theta);
51 float ct = cosf(theta);
52
53 float sp = sinf(phi);
54 float cp = cosf(phi);
55
56 // Setup the rotation matrix, this matrix is based off of the rotation matrix used in glRotatef.
57 Ry[0][0] = ct;
58 Ry[0][1] = 0.f;
59 Ry[0][2] = st;
60 Ry[1][0] = 0.f;
61 Ry[1][1] = 1.f;
62 Ry[1][2] = 0.f;
63 Ry[2][0] = -st;
64 Ry[2][1] = 0.f;
65 Ry[2][2] = ct;
66
67 Rz[0][0] = cp;
68 Rz[0][1] = -sp;
69 Rz[0][2] = 0.f;
70 Rz[1][0] = sp;
71 Rz[1][1] = cp;
72 Rz[1][2] = 0.f;
73 Rz[2][0] = 0.f;
74 Rz[2][1] = 0.f;
75 Rz[2][2] = 1.f;
76
77 // Multiply Ry*Rz
78
79 float rotMat[3][3] = {0.f};
80
81 for (int i = 0; i < 3; i++) {
82 for (int j = 0; j < 3; j++) {
83 for (int k = 0; k < 3; k++) {
84 rotMat[i][j] = rotMat[i][j] + Rz[i][k] * Ry[k][j];
85 }
86 }
87 }
88
89 // Multiply the rotation matrix with the position vector.
90 float3 tmp;
91 tmp.x = rotMat[0][0] * position.x + rotMat[0][1] * position.y + rotMat[0][2] * position.z;
92 tmp.y = rotMat[1][0] * position.x + rotMat[1][1] * position.y + rotMat[1][2] * position.z;
93 tmp.z = rotMat[2][0] * position.x + rotMat[2][1] * position.y + rotMat[2][2] * position.z;
94
95 return tmp;
96}
97
98__global__ void insideVolume_vi(const uint Nhits, const float3 *d_hit_xyz, const uint Ngridcells, const float3 *d_grid_size, const float3 *d_grid_center, const float *d_grid_rotation, int *d_hit_vol) {
99
100 uint t = blockIdx.x * blockDim.x + threadIdx.x;
101
102 if (t >= Nhits) {
103 return;
104 }
105
106 d_hit_vol[t] = -1;
107
108 float3 hit_xyz = d_hit_xyz[t];
109
110 for (int i = 0; i < Ngridcells; i++) {
111
112 float3 center = d_grid_center[i];
113 float3 size = d_grid_size[i];
114 float rotation = d_grid_rotation[i];
115
116 float3 origin = make_float3(0, 0, 0);
117
118 float3 xyz = hit_xyz;
119 xyz.x -= center.x;
120 xyz.y -= center.y;
121 xyz.z -= center.z;
122 float3 hit_xyz_rot = d_rotatePoint_vi(xyz, 0, -rotation);
123 hit_xyz_rot.x += center.x;
124 hit_xyz_rot.y += center.y;
125 hit_xyz_rot.z += center.z;
126
127 float3 direction = hit_xyz_rot;
128 direction.x -= origin.x;
129 direction.y -= origin.y;
130 direction.z -= origin.z;
131
132 float mag = sqrt(direction.x * direction.x + direction.y * direction.y + direction.z * direction.z);
133 direction.x = direction.x / mag;
134 direction.y = direction.y / mag;
135 direction.z = direction.z / mag;
136
137 float ox = origin.x;
138 float oy = origin.y;
139 float oz = origin.z;
140 float dx = direction.x;
141 float dy = direction.y;
142 float dz = direction.z;
143
144 float x0 = center.x - 0.5f * size.x;
145 float x1 = center.x + 0.5f * size.x;
146 float y0 = center.y - 0.5f * size.y;
147 float y1 = center.y + 0.5f * size.y;
148 float z0 = center.z - 0.5f * size.z;
149 float z1 = center.z + 0.5f * size.z;
150
151 float tx_min, ty_min, tz_min;
152 float tx_max, ty_max, tz_max;
153
154 float a = 1.0 / dx;
155 if (a >= 0) {
156 tx_min = (x0 - ox) * a;
157 tx_max = (x1 - ox) * a;
158 } else {
159 tx_min = (x1 - ox) * a;
160 tx_max = (x0 - ox) * a;
161 }
162
163 float b = 1.0 / dy;
164 if (b >= 0) {
165 ty_min = (y0 - oy) * b;
166 ty_max = (y1 - oy) * b;
167 } else {
168 ty_min = (y1 - oy) * b;
169 ty_max = (y0 - oy) * b;
170 }
171
172 float c = 1.0 / dz;
173 if (c >= 0) {
174 tz_min = (z0 - oz) * c;
175 tz_max = (z1 - oz) * c;
176 } else {
177 tz_min = (z1 - oz) * c;
178 tz_max = (z0 - oz) * c;
179 }
180
181 float t0, t1;
182
183 // find largest entering t value
184
185 if (tx_min > ty_min)
186 t0 = tx_min;
187 else
188 t0 = ty_min;
189
190 if (tz_min > t0)
191 t0 = tz_min;
192
193 // find smallest exiting t value
194
195 if (tx_max < ty_max)
196 t1 = tx_max;
197 else
198 t1 = ty_max;
199
200 if (tz_max < t1)
201 t1 = tz_max;
202
203 if (t0 < t1 && t1 > 1e-6) { // Ray passed through box
204 float T = mag;
205 if (T >= t0 && T <= t1) { // Ray endpoint is inside box
206 d_hit_vol[t] = i;
207 return;
208 }
209 }
210 }
211}
212
214 printmessages = false;
215}
216
218 printmessages = true;
219}
220
224
226
227 if (printmessages) {
228 std::cout << "Calculating primitive-voxel intersections..." << std::flush;
229 }
230
231 std::vector<uint> UUIDs_voxels;
232 std::vector<uint> UUIDs_prims;
233
234 UUIDs_voxels.resize(UUIDs.size());
235 UUIDs_prims.resize(UUIDs.size());
236
237 size_t Nvoxels = 0;
238 size_t Nprims = 0;
239
240 // separate out UUIDs of voxels from planar primitives
241 for (size_t u = 0; u < UUIDs.size(); u++) {
242 size_t p = UUIDs[u];
243
244 helios::PrimitiveType type = context->getPrimitiveType(p);
245
246 if (type == helios::PRIMITIVE_TYPE_VOXEL) {
247 UUIDs_voxels.at(Nvoxels) = p;
248 Nvoxels++;
249 } else {
250 UUIDs_prims.at(Nprims) = p;
251 Nprims++;
252 }
253 }
254
255 if (Nvoxels == 0) {
256 if (printmessages) {
257 std::cout << "done. ";
258 std::cout << "WARNING: no voxels found in Context, nothing to intersect." << std::endl;
259 }
260 } else if (Nprims == 0) {
261 if (printmessages) {
262 std::cout << "done. ";
263 std::cout << "WARNING: no planar primitives found in Context, nothing to intersect." << std::endl;
264 }
265 }
266
267 UUIDs_voxels.resize(Nvoxels);
268 UUIDs_prims.resize(Nprims);
269
270 std::map<uint, std::vector<uint>> vint;
271
272 // ---- Determine Primitive positions and copy to GPU ---- //
273
274 const uint N = Nprims;
275
276 float3 *d_hit_xyz;
277 float3 *hit_xyz = (float3 *) malloc(N * sizeof(float3)); // allocate host memory
278 CUDA_CHECK_ERROR(cudaMalloc((void **) &d_hit_xyz, N * sizeof(float3))); // allocate device memory
279
280 // copy scan data into the host buffer
281 for (std::size_t r = 0; r < N; r++) {
282 hit_xyz[r] = vec3tofloat3(context->getPrimitiveVertices(UUIDs_prims.at(r)).front());
283 }
284
285 // copy from host to device memory
286 CUDA_CHECK_ERROR(cudaMemcpy(d_hit_xyz, hit_xyz, N * sizeof(float3), cudaMemcpyHostToDevice));
287
288 // ---- Voxels ---- //
289
290 float3 *d_grid_center;
291 float3 *d_grid_size;
292 float *d_grid_rotation;
293
294 const uint Ncells = Nvoxels;
295
296 float3 *center = (float3 *) malloc(Ncells * sizeof(float3)); // allocate host memory
297 CUDA_CHECK_ERROR(cudaMalloc((void **) &d_grid_center, Ncells * sizeof(float3))); // allocate device memory
298
299 float3 *size = (float3 *) malloc(Ncells * sizeof(float3)); // allocate host memory
300 CUDA_CHECK_ERROR(cudaMalloc((void **) &d_grid_size, Ncells * sizeof(float3))); // allocate device memory
301
302 float *rotation = (float *) malloc(Ncells * sizeof(float)); // allocate host memory
303 CUDA_CHECK_ERROR(cudaMalloc((void **) &d_grid_rotation, Ncells * sizeof(float))); // allocate device memory
304
305 // copy grid data into the host buffer
306 for (int c = 0; c < Ncells; c++) {
307 center[c] = vec3tofloat3(context->getVoxelCenter(UUIDs_voxels.at(c)));
308 size[c] = vec3tofloat3(context->getVoxelSize(UUIDs_voxels.at(c)));
309 // rotation[c] = voxel->getRotation();
310 rotation[c] = 0.f;
311 std::vector<uint> empty_uint_vector;
312 context->setPrimitiveData(UUIDs_voxels.at(c), "inside_UUIDs", empty_uint_vector);
313 }
314
315 // copy from host to device memory
316 CUDA_CHECK_ERROR(cudaMemcpy(d_grid_center, center, Ncells * sizeof(float3), cudaMemcpyHostToDevice));
317 CUDA_CHECK_ERROR(cudaMemcpy(d_grid_size, size, Ncells * sizeof(float3), cudaMemcpyHostToDevice));
318 CUDA_CHECK_ERROR(cudaMemcpy(d_grid_rotation, rotation, Ncells * sizeof(float), cudaMemcpyHostToDevice));
319
320 free(hit_xyz);
321 free(center);
322 free(size);
323 free(rotation);
324
325 // Result buffer
326 int *hit_vol = (int *) malloc(N * sizeof(int));
327 int *d_hit_vol;
328 CUDA_CHECK_ERROR(cudaMalloc(&d_hit_vol, N * sizeof(int)));
329
330 dim3 dimBlock(64, 1);
331 dim3 dimGrid(ceil(N / 64.f));
332 insideVolume_vi<<<dimGrid, dimBlock>>>(N, d_hit_xyz, Ncells, d_grid_size, d_grid_center, d_grid_rotation, d_hit_vol);
333
334 CUDA_CHECK_ERROR(cudaPeekAtLastError());
335 CUDA_CHECK_ERROR(cudaDeviceSynchronize());
336
337 CUDA_CHECK_ERROR(cudaMemcpy(hit_vol, d_hit_vol, N * sizeof(int), cudaMemcpyDeviceToHost));
338
339 for (std::size_t r = 0; r < N; r++) {
340 if (hit_vol[r] >= 0) {
341 vint[UUIDs_voxels.at(hit_vol[r])].push_back(UUIDs_prims.at(r));
342 }
343 }
344
345 for (std::map<uint, std::vector<uint>>::iterator it = vint.begin(); it != vint.end(); ++it) {
346 uint UUID = it->first;
347 size_t s = vint.at(UUID).size();
348 context->setPrimitiveData(UUID, "inside_UUIDs", vint.at(UUID));
349 }
350
351 free(hit_vol);
352
353 CUDA_CHECK_ERROR(cudaFree(d_hit_vol));
354 CUDA_CHECK_ERROR(cudaFree(d_hit_xyz));
355 CUDA_CHECK_ERROR(cudaFree(d_grid_center));
356 CUDA_CHECK_ERROR(cudaFree(d_grid_size));
357
358
359 if (printmessages) {
360 std::cout << "done." << std::endl;
361 }
362}