DHART
Loading...
Searching...
No Matches
embree_raytracer.cpp
Go to the documentation of this file.
1
7
8#include <embree_raytracer.h>
9#include <corecrt_math_defines.h>
10#include <functional>
11#include <iostream>
12#include <thread>
13#include <robin_hood.h>
14
15#include <meshinfo.h>
16#include <RayRequest.h>
17#include <HFExceptions.h>
18
19using std::vector;
20
21namespace HF::RayTracer {
22
23 template <typename numeric1, typename numeric2, typename dist_type = float>
24 inline RTCRayHit ConstructHit(
25 numeric1 x, numeric1 y, numeric1 z,
26 numeric2 dx, numeric2 dy, numeric2 dz,
27 dist_type distance = -1.0f, int mesh_id = -1)
28 {
29 // Define an Embree hit data type to store results
30 RTCRayHit hit;
31
32 // Use the referenced values of the x,y,z position as the ray origin
33 hit.ray.org_x = x; hit.ray.org_y = y; hit.ray.org_z = z;
34 // Define the directions
35 hit.ray.dir_x = dx; hit.ray.dir_y = dy; hit.ray.dir_z = dz;
36
37 hit.ray.tnear = 0.00000001f; // The start of the ray segment
38 hit.ray.tfar = distance > 0 ? distance : INFINITY; // The end of the ray segment
39 hit.ray.time = 0.0f; // Time of ray for motion blur, unrelated to our package
40
41 hit.hit.geomID = RTC_INVALID_GEOMETRY_ID;
42 hit.hit.primID = -1;
43
44 return hit;
45 }
46
47 template <typename numeric1, typename numeric2, typename dist_type = float>
48 inline RTCRay ConstructRay(
49 numeric1 x, numeric1 y, numeric1 z,
50 numeric2 dx, numeric2 dy, numeric2 dz,
51 dist_type distance = -1.0f, int mesh_id = -1)
52 {
53 RTCRay ray;
54 ray.org_x = x; ray.org_y = y; ray.org_z = z;
55 ray.dir_x = dx; ray.dir_y = dy; ray.dir_z = dz;
56
57 ray.tnear = 0.0000001f;
58 ray.tfar = (distance > 0) ? distance : INFINITY;
59 ray.time = 0.0f;
60 ray.flags = 0;
61
62 return ray;
63 }
69 RTCError CheckState(RTCDevice& device) {
70 return rtcGetDeviceError(device);
71 }
72
73 using std::vector;
77 struct Vertex { float x, y, z; };
78
82 struct Triangle { int v0, v1, v2; };
83
92 inline void vectorsToBuffers(
93 const std::vector<std::array<float, 3>>& vertices,
94 std::vector<Triangle>& Tribuffer,
95 std::vector<Vertex>& Vbuffer
96 ) {
97 robin_hood::unordered_map <std::array<float, 3>, int> index_map;
98
99 int next_id = 0;
100 int vertsize = vertices.size();
101
102 for (int i = 0; i < vertsize; i += 3) {
103 std::array<int, 3> ids;
104
105 // Get the ids for the next 3 vertices
106 for (int k = 0; k < 3; k++)
107 {
108 auto vert = vertices[i + k];
109 int current_id;
110
111 // Get ID from index map, or create a new ID if one doesn't exist
112 if (index_map.count(vert) > 0)
113 current_id = index_map[vert];
114 else {
115 index_map[vert] = next_id;
116 current_id = next_id;
117
118 // Store new vertex in the vertex buffer
119 Vbuffer.emplace_back(Vertex{ vert[0], vert[1], vert[2] });
120 next_id++;
121 }
122 ids[k] = current_id;
123 }
124 // Store new triangle in the triangle buffer.
125 Tribuffer.emplace_back(Triangle{ ids[0], ids[1], ids[2] });
126 }
127 }
128
141 inline void buffersToStructs(
142 std::vector<float>& in_vertices,
143 std::vector<int>& in_indices,
144 std::vector<Vertex>& out_vertices,
145 std::vector<Triangle>& out_triangles
146 ) {
147 out_vertices.resize(in_vertices.size() / 3);
148 for (int i = 0; i < in_vertices.size(); i += 3) {
149 out_vertices[i / 3] = Vertex{
150 in_vertices[i],
151 in_vertices[i + 1],
152 in_vertices[i + 2]
153 };
154 }
155
156 out_triangles.resize(in_indices.size() / 3);
157 for (int i = 0; i < in_indices.size(); i += 3) {
158 out_triangles[i / 3] = Triangle{
159 in_indices[i],
160 in_indices[i + 1],
161 in_indices[i + 2]
162 };
163 }
164 }
165
167 {
168 this->use_precise = false;
169 SetupScene();
170 }
171
173 // Throw if MI's size is less than 0
174 this->use_precise = true;
175
176 if (MI.empty())
177 throw std::logic_error("Embree Ray Tracer was passed an empty vector of mesh info!");
178
179 SetupScene();
180
181 AddMesh(MI, true);
182 }
183
185 SetupScene();
186 this->use_precise = use_precise;
187 AddMesh(MI, true);
188 }
189
191 device = rtcNewDevice("");
192 scene = rtcNewScene(device);
193 rtcSetSceneBuildQuality(scene, RTC_BUILD_QUALITY_HIGH);
194 rtcSetSceneFlags(scene, RTC_SCENE_FLAG_ROBUST);
195 // Initialize the intersect context, which should later allow RTC_INTERSECT_CONTEXT_FLAG_COHERENT
196 rtcInitIntersectContext(&context);
197 }
198
200 {
201 // Copy over pointers to relevant embree objects
202 device = ERT2.device;
203 context = ERT2.context;
204 scene = ERT2.scene;
205 geometry = ERT2.geometry;
206
207 // Increment embree's internal refrence counter.
208 rtcRetainScene(scene);
209 rtcRetainDevice(device);
210 }
211
212 int EmbreeRayTracer::InsertGeom(RTCGeometry& geom, int id)
213 {
214 if (id >= 0) {
215 rtcAttachGeometryByID(scene, geom, id);
216
217 // If we're attaching by ID, then we must check to see if the ID already exists.
218 // If it does already exist, then we'll have to just add it without specifying any ID
219 RTCError error = CheckState(device);
220
221 // Don't know the specific error that will be raised here (Documentation just states some error code)
222 if (error != RTCError::RTC_ERROR_NONE)
223 return InsertGeom(geom);
224 }
225
226 return static_cast<int>(rtcAttachGeometry(scene, geom));
227 }
228
229 inline Vector3D cross(const Vector3D& x, const Vector3D& y) {
230 return Vector3D{
231 x.y * y.z - y.y * x.z,
232 x.z * y.x - y.z * x.x,
233 x.x * y.y - y.x * x.y
234 };
235 }
236
237 inline double dot(const Vector3D& v1, const Vector3D& v2) {
238 return (v1.x * v2.x + v1.y * v2.y + v1.z * v2.z);
239 }
240
241 inline Vector3D InvertVector(const Vector3D& V) {
242 return Vector3D{ -V.x, -V.y, -V.z };
243 }
244
245
247 const Vector3D& origin,
248 const Vector3D& direction,
249 const Vector3D& v1,
250 const Vector3D& v2,
251 const Vector3D& v3)
252 {
253
254 const double EPSILON = 0.0000001;
255 const Vector3D inverted_direction = direction;//InvertVector(direction);
256
257 const Vector3D edge1 = v2 - v1;
258 const Vector3D edge2 = v3 - v1;
259 const Vector3D h = cross(inverted_direction, edge2);
260 const double a = dot(edge1, h);
261
262 // This ray is parallel to this triangle.
263 if (a > -EPSILON && a < EPSILON)
264 return -1;
265
266 const double f = 1.0 / a;
267 const Vector3D s = origin - v1;
268 const double u = f * dot(s, h);
269 if (u < 0.0 || u > 1.0)
270 return -1;
271
272 const Vector3D q = cross(s, edge1);
273 const double v = f * dot(direction, q);
274 if (v < 0.0 || u + v > 1.0)
275 return -1;
276
277 // At this stage we can compute t to find out where the intersection point is on the line.
278 double t_hit = f * dot(edge2, q);
279 return t_hit;
280 }
281
283 unsigned int geom_id,
284 unsigned int prim_id,
285 const Vector3D & origin,
286 const Vector3D & direction) const
287 {
288 // Get the triangle intersected by this hit
289 auto triangle = this->GetTriangle(geom_id, prim_id);
290
291 // Perform the raytriangle intersection
293 origin,
294 direction,
295 triangle[0],
296 triangle[1],
297 triangle[2]
298 );
299 }
300
301 EmbreeRayTracer::EmbreeRayTracer(const std::vector<std::array<float, 3>>& geometry) {
302 SetupScene();
303
304 // Set Setup buffers
305 std::vector<Triangle> tris;
306 std::vector<Vertex> verts;
307 vectorsToBuffers(geometry, tris, verts);
308
309 RTCGeometry inserted_geom = ConstructGeometryFromBuffers(tris, verts);
310 // Cast to triangle/vertex structs so we can operate on them. This trick is from the embree tutorial
311 InsertGeom(inserted_geom);
312
313 rtcCommitScene(scene);
314 }
315
316 bool EmbreeRayTracer::AddMesh(std::vector<std::array<float, 3>>& Mesh, int ID, bool Commit)
317 {
318 // Set Setup buffers
319 std::vector<Triangle> tris; std::vector<Vertex> verts;
320 vectorsToBuffers(Mesh, tris, verts);
321
322 // Add the geometry to embree as a geometry object
323 auto geom = ConstructGeometryFromBuffers(tris, verts);
324
325 // Add the geometry by ID
326 int added_id = InsertGeom(geom);
327
328 // Commit the scene if specified
329 if (Commit)
330 rtcCommitScene(scene);
331
332 // Return False if it's id didn't need to be changed, true otherwise.
333 return (added_id == ID);
334 }
335
336 RTCGeometry EmbreeRayTracer::ConstructGeometryFromBuffers(vector<Triangle>& tris, vector<Vertex>& verts) {
337 // Create new geometry object
338 RTCGeometry geom = rtcNewGeometry(device, RTC_GEOMETRY_TYPE_TRIANGLE);
339
340 // Allocate it's triangle and index buffers in embree
341 triangles = static_cast<Triangle*>(
342 rtcSetNewGeometryBuffer(
343 geom,
344 RTC_BUFFER_TYPE_INDEX,
345 0,
346 RTC_FORMAT_UINT3,
347 sizeof(Triangle),
348 tris.size() + 1
349 )
350 );
351 Vertices = static_cast<Vertex*>(
352 rtcSetNewGeometryBuffer(
353 geom,
354 RTC_BUFFER_TYPE_VERTEX,
355 0,
356 RTC_FORMAT_FLOAT3,
357 sizeof(Vertex),
358 verts.size() + 1
359 )
360 );
361
362 // Move data from input tris/verts into buffers
363 std::move(tris.begin(), tris.end(), triangles);
364 std::move(verts.begin(), verts.end(), Vertices);
365
366 // Add a reference to this geometry to internal array of geometry.
367 geometry.push_back(geom);
368
369 // Commit this geometry to finalize the process then return
370 rtcCommitGeometry(geom);
371
372 return geom;
373 }
374
376
377 if (Mesh.NumTris() < 1 || Mesh.NumVerts() < 1)
379 // Get vertex and triangle data from the mesh
380
381 std::vector<Triangle> tris; std::vector<Vertex> verts;
382 auto indices = Mesh.getRawIndices(); auto vertices = Mesh.GetIndexedVertices();
383 buffersToStructs(vertices, indices, verts, tris);
384
385 // Construct geometry using embree
386 auto geom = ConstructGeometryFromBuffers(tris, verts);
387
388 // Add the Mesh to the scene and update it's ID
389 Mesh.meshid = InsertGeom(geom, Mesh.meshid);
390
391 // commit if specified
392 if (Commit)
393 rtcCommitScene(scene);
394
395 return true;
396 }
397
398 bool EmbreeRayTracer::AddMesh(std::vector<HF::Geometry::MeshInfo<float>>& Meshes, bool Commit)
399 {
400 // Add every mesh in a loop
401 for (auto& mesh : Meshes)
402 AddMesh(mesh, false);
403
404 // Commit at the end to save performance
405 if (Commit)
406 rtcCommitScene(scene);
407
408 return true;
409 }
410
412 std::array<float, 3>& origin,
413 const std::array<float, 3>& dir,
414 float distance,
415 int mesh_id
416 ) {
417 return PointIntersection(origin[0], origin[1], origin[2], dir[0], dir[1], dir[2], distance, mesh_id);
418 }
419
421 float& x,
422 float& y,
423 float& z,
424 float dx,
425 float dy,
426 float dz,
427 float distance,
428 int mesh_id)
429 {
430 HitStruct<float> res = Intersect<float>(x, y, z, dx, dy, dz, distance, mesh_id);
431
432 // If the ray did hit, update the node position by translating the distance along the directions
433 // This REQUIRES a normalized vector
434 // Translate the point along the direction vector
435 if (res.DidHit()) {
436 x = x + (dx * res.distance);
437 y = y + (dy * res.distance);
438 z = z + (dz * res.distance);
439
440 return true;
441 }
442 else
443 return false;
444 }
445
446 inline Vector3D GetPointFromBuffer(int index, Vertex* buffer) {
447 return Vector3D{buffer[index].x, buffer[index].y,buffer[index].z};
448 }
449
450 std::array<Vector3D, 3> EmbreeRayTracer::GetTriangle(unsigned int geomID, unsigned int primID) const
451 {
452 // Get the index buffer for the geometry at geomID
453 Triangle* index_buffer = reinterpret_cast<Triangle*>(rtcGetGeometryBufferData(
454 rtcGetGeometry(this->scene, geomID),
455 RTCBufferType::RTC_BUFFER_TYPE_INDEX,
456 0
457 ));
458
459 // Get the indices of the 3 vertices that form this triangle from thig
460 // geometry's index buffer
461 int v1_index = index_buffer[primID].v0;
462 int v2_index = index_buffer[primID].v1;
463 int v3_index = index_buffer[primID].v2;
464
465 // Get a pointer to this geometry's vertex buffer
466 Vertex * vertex_buffer = reinterpret_cast<Vertex *>(rtcGetGeometryBufferData(
467 rtcGetGeometry(this->scene, geomID),
468 RTCBufferType::RTC_BUFFER_TYPE_VERTEX,
469 0
470 ));
471
472 // Get the vertices at these indices from the vertex buffer.
473 return std::array<Vector3D, 3>{
474 GetPointFromBuffer(v1_index, vertex_buffer),
475 GetPointFromBuffer(v2_index, vertex_buffer),
476 GetPointFromBuffer(v3_index, vertex_buffer)
477 };
478 }
479
481 std::vector<std::array<float, 3>>& origins,
482 std::vector<std::array<float, 3>>& directions,
483 bool use_parallel,
484 float max_distance,
485 int mesh_id
486 ) {
487 std::vector<char> out_results(origins.size());
488
489 // Allow users to shoot multiple rays with a single direction or origin
490 if (origins.size() > 1 && directions.size() > 1) {
491#pragma omp parallel for if(use_parallel) schedule(dynamic, 128)
492 for (int i = 0; i < origins.size(); i++) {
493 auto& org = origins[i];
494 auto& dir = directions[i];
495 out_results[i] = PointIntersection(
496 org[0], org[1], org[2],
497 dir[0], dir[1], dir[2],
498 max_distance, mesh_id
499 );
500 }
501 }
502
503 else if (origins.size() > 1 && directions.size() == 1) {
504 const auto& dir = directions[0];
505#pragma omp parallel for if(use_parallel) schedule(dynamic, 128)
506 for (int i = 0; i < origins.size(); i++) {
507 auto& org = origins[i];
508 out_results[i] = PointIntersection(
509 org[0], org[1], org[2],
510 dir[0], dir[1], dir[2],
511 max_distance, mesh_id
512 );
513 }
514 }
515
516 else if (origins.size() == 1 && directions.size() > 1) {
517 out_results.resize(directions.size());
518#pragma omp parallel for if(use_parallel) schedule(dynamic, 128)
519 for (int i = 0; i < directions.size(); i++) {
520 auto org = origins[0];
521 auto& dir = directions[i];
522 bool did_hit = PointIntersection(
523 org[0], org[1], org[2],
524 dir[0], dir[1], dir[2],
525 max_distance, mesh_id
526 );
527 if (did_hit) // Directions is the output array in this case
528 {
529 directions[i][0] = org[0];
530 directions[i][1] = org[1];
531 directions[i][2] = org[2];
532 }
533 out_results[i] = did_hit;
534 }
535 }
536 else {
537 throw std::exception("Incorrect usage of castrays");
538 }
539
540 return out_results;
541 }
542
544 float x, float y, float z,
545 float dx, float dy, float dz,
546 float max_distance, int mesh_id)
547 {
548 RTCRayHit hit = ConstructHit(x, y, z, dx, dy, dz);
549
550 rtcIntersect1(scene, &context, &hit);
551
552 return hit;
553 }
554
556 const std::array<float, 3>& origin,
557 const std::array<float, 3>& direction,
558 float max_dist
559 ) {
560 return Occluded_IMPL(origin[0], origin[1], origin[2], direction[0], direction[1], direction[2]);
561 }
562
564 const std::vector<std::array<float, 3>>& origins,
565 const std::vector<std::array<float, 3>>& directions,
566 float max_distance, bool use_parallel)
567 {
568 std::vector<char> out_array;
569 int cores = static_cast<int> (std::thread::hardware_concurrency());
570 if (origins.size() < cores || directions.size() < cores)
571 // Don't use more cores than there are rays. This caused a hard to find bug earlier.
572 // Doesn't seem to happen with the other ray types. (race condition?)
573 omp_set_num_threads(min(max(origins.size(), directions.size()), cores));
574
575 if (directions.size() > 1 && origins.size() > 1) {
576 out_array.resize(origins.size());
577#pragma omp parallel for if(use_parallel) schedule(dynamic, 128)
578 for (int i = 0; i < origins.size(); i++) {
579 out_array[i] = Occluded_IMPL(
580 origins[i][0], origins[i][1], origins[i][2],
581 directions[i][0], directions[i][1], directions[i][2],
582 max_distance, -1
583 );
584 }
585 }
586 else if (directions.size() > 1 && origins.size() == 1) {
587 out_array.resize(directions.size());
588 const auto& origin = origins[0];
589 printf("Using multidirection, single origin\n");
590#pragma omp parallel for if(use_parallel) schedule(dynamic, 128)
591 for (int i = 0; i < directions.size(); i++) {
592 const auto& direction = directions[i];
593 out_array[i] = Occluded_IMPL(
594 origin[0], origin[1], origin[2],
595 direction[0], direction[1], direction[2],
596 max_distance, -1
597 );
598 }
599 }
600
601 // This is might seem to be an application of coherent rays with streaming,
602 // but coherent rays also require the origins to be very similar, so it doesn't help
603 else if (directions.size() == 1 && origins.size() > 1)
604 {
605 out_array.resize(origins.size());
606 const auto& direction = directions[0];
607
608 // Use chunk size of 256 for reducing parallel overhead
609 #pragma omp parallel for if(use_parallel) schedule(dynamic, 256)
610 for (int i = 0; i < origins.size(); i++) {
611 const auto& origin = origins[i];
612 out_array[i] = Occluded_IMPL(origin[0], origin[1], origin[2],
613 direction[0], direction[1], direction[2],
614 max_distance, -1);
615 }
616 }
617
618 else if (directions.size() == 1 && origins.size() == 1) {
619 out_array = { Occluded_IMPL(origins[0], directions[0], max_distance) };
620 }
621 return out_array;
622 }
623
624 bool EmbreeRayTracer::Occluded_IMPL(float x, float y, float z, float dx, float dy, float dz, float distance, int mesh_id)
625 {
626 auto ray = ConstructRay(x, y, z, dx, dy, dz, distance);
627 rtcOccluded1(scene, &context, &ray);
628 return ray.tfar == -INFINITY;
629 }
630
631 // Increment reference counters to prevent destruction when this thing goes out of scope
633
634 this->use_precise = ERT2.use_precise;
635 device = ERT2.device;
636 context = ERT2.context;
637 scene = ERT2.scene;
638 geometry = ERT2.geometry;
639
640 rtcRetainScene(scene);
641 rtcRetainDevice(device);
642 }
643
645 rtcReleaseScene(scene);
646 rtcReleaseDevice(device);
647 }
648
649}
Contains definitions for the Exceptions namespace.
Contains definitions for the MeshInfo class.
Contains definitions for the EmbreeRayTracer
Contains definitions for the RayTracer namespace.
Cast rays to determine if and where they intersect geometry.
A vertex. Used internally in Embree.
A triangle. Used internally in Embree.
Vector3D cross(const Vector3D &x, const Vector3D &y)
RTCError CheckState(RTCDevice &device)
Check an embree device for errors.
Vector3D GetPointFromBuffer(int index, Vertex *buffer)
void vectorsToBuffers(const std::vector< std::array< float, 3 > > &vertices, std::vector< Triangle > &Tribuffer, std::vector< Vertex > &Vbuffer)
Index a list of verticies and place them into a triangle and vertex buffer.
RTCRay ConstructRay(numeric1 x, numeric1 y, numeric1 z, numeric2 dx, numeric2 dy, numeric2 dz, dist_type distance=-1.0f, int mesh_id=-1)
RTCRayHit ConstructHit(numeric1 x, numeric1 y, numeric1 z, numeric2 dx, numeric2 dy, numeric2 dz, dist_type distance=-1.0f, int mesh_id=-1)
double RayTriangleIntersection(const Vector3D &origin, const Vector3D &direction, const Vector3D &v1, const Vector3D &v2, const Vector3D &v3)
Determine the distance between a ray's origin and it's point of intersection with a triangle.
void buffersToStructs(std::vector< float > &in_vertices, std::vector< int > &in_indices, std::vector< Vertex > &out_vertices, std::vector< Triangle > &out_triangles)
Package raw arrays of floats and indices in buffers to the required Embree types.
Vector3D InvertVector(const Vector3D &V)
double dot(const Vector3D &v1, const Vector3D &v2)
The OBJ file was not valid.
Definition: HFExceptions.h:65
A collection of vertices and indices representing geometry.
Definition: meshinfo.h:124
int meshid
Identifier for this mesh.
Definition: meshinfo.h:126
int NumTris() const
Calculate the total number of triangles in this mesh.
Definition: meshinfo.cpp:181
int NumVerts() const
Determine how many vertices are in this mesh.
Definition: meshinfo.cpp:178
std::vector< numeric_type > GetIndexedVertices() const
A copy of every vertex in this array.
Definition: meshinfo.cpp:244
std::vector< int > getRawIndices() const
Retrieve a copy of this mesh's index buffer as a 1D array.
Definition: meshinfo.cpp:256
A wrapper for Intel's Embree Library.
RTCIntersectContext context
Context to cast rays within.
std::vector< char > PointIntersections(std::vector< std::array< float, 3 > > &origins, std::vector< std::array< float, 3 > > &directions, bool use_parallel=true, float max_distance=-1, int mesh_id=-1)
Cast multiple rays and recieve hitpoints in return.
bool use_precise
If true, use custom triangle intersection intersection instead of embree's.
void SetupScene()
Performs all the necessary operations to set up the scene.
double CalculatePreciseDistance(unsigned int geom_id, unsigned int prim_id, const Vector3D &origin, const Vector3D &direction) const
Calculate the distance from origin to the point of intersection using an algorithm with higher precis...
~EmbreeRayTracer()
Custom destructor to ensure cleanup of embree resources.
std::vector< RTCGeometry > geometry
RTCDevice device
All objects in Embree are created from this. https://www.embree.org/api.html#device-object.
std::array< Vector3D, 3 > GetTriangle(unsigned int geomID, unsigned int primID) const
Get the vertices for a specific triangle in a mesh.
Vertex * Vertices
Vertex buffer. Is used in multiple places but contents are dumped.
bool AddMesh(std::vector< std::array< float, 3 > > &Mesh, int ID, bool Commit=false)
Add a new mesh to this raytracer's BVH with the specified ID.
Triangle * triangles
Triangle buffer. Is used in multiple places, but contents are dumped.
int InsertGeom(RTCGeometry &geom, int id=-1)
Attach geometry to the current scene.
void operator=(const EmbreeRayTracer &ERT2)
Increment reference counters to prevent destruction when a copy is made.
RTCScene scene
Container for a set of geometries, and the BVH. https://www.embree.org/api.html#scene-object.
RTCGeometry ConstructGeometryFromBuffers(std::vector< Triangle > &tris, std::vector< Vertex > &verts)
Create a new instance of RTCGeometry from a triangle and vertex buffer.
bool PointIntersection(std::array< float, 3 > &origin, const std::array< float, 3 > &dir, float distance=-1, int mesh_id=-1)
Cast a ray and overwrite the origin with the hitpoint if it intersects any geometry.
bool Occluded_IMPL(float x, float y, float z, float dx, float dy, float dz, float distance=-1, int mesh_id=-1)
Implementation for fundamental occlusion ray intersection.
RTCRayHit Intersect_IMPL(float x, float y, float z, float dx, float dy, float dz, float max_distance=-1, int mesh_id=-1)
Implementation for fundamental ray intersection.
EmbreeRayTracer(bool use_precise=false)
Construct an empty EmbreeRayTracer;.
std::vector< char > Occlusions(const std::vector< std::array< float, 3 > > &origins, const std::vector< std::array< float, 3 > > &directions, float max_distance=-1, bool use_parallel=true)
Cast multiple occlusion rays in parallel.
A simple hit struct to carry all relevant information about hits.
Definition: HitStruct.h:7
bool DidHit() const
Determine whether or not this hitstruct contains a hit.
Definition: HitStruct.h:17
numeric_type distance
Distance from the origin point to the hit point. Set to -1 if no hit was recorded.
Definition: HitStruct.h:8