Isis 3 Programmer Reference
EmbreeTargetShape.cpp
Go to the documentation of this file.
1 
25 #include "EmbreeTargetShape.h"
26 
27 #include <iostream>
28 #include <iomanip>
29 #include <numeric>
30 #include <sstream>
31 
32 #include "NaifDskApi.h"
33 
34 #include "FileName.h"
35 #include "IException.h"
36 #include "IString.h"
37 #include "NaifStatus.h"
38 #include "Pvl.h"
39 
40 namespace Isis {
41 
46  tnear = 0.0;
47  tfar = std::numeric_limits<float>::infinity(); // Should be INF
48  mask = 0xFFFFFFFF;
49  lastHit = -1;
50  u = 0.0;
51  v = 0.0;
52  geomID = RTC_INVALID_GEOMETRY_ID;
53  primID = RTC_INVALID_GEOMETRY_ID;
54  instID = RTC_INVALID_GEOMETRY_ID;
55  org[0] = 0.0;
56  org[1] = 0.0;
57  org[2] = 0.0;
58  dir[0] = 0.0;
59  dir[1] = 0.0;
60  dir[2] = 0.0;
61  Ng[0] = 0.0;
62  Ng[1] = 0.0;
63  Ng[2] = 0.0;
64  }
65 
66 
73  RTCMultiHitRay::RTCMultiHitRay(const std::vector<double> &origin,
74  const std::vector<double> &direction) {
75  tnear = 0.0;
76  tfar = std::numeric_limits<float>::infinity(); // Should be INF
77  mask = 0xFFFFFFFF;
78  lastHit = -1;
79  u = 0.0;
80  v = 0.0;
81  geomID = RTC_INVALID_GEOMETRY_ID;
82  primID = RTC_INVALID_GEOMETRY_ID;
83  instID = RTC_INVALID_GEOMETRY_ID;
84  org[0] = origin[0];
85  org[1] = origin[1];
86  org[2] = origin[2];
87  dir[0] = direction[0];
88  dir[1] = direction[1];
89  dir[2] = direction[2];
90  Ng[0] = 0.0;
91  Ng[1] = 0.0;
92  Ng[2] = 0.0;
93  }
94 
95 
104  LinearAlgebra::Vector direction) {
105  tnear = 0.0;
106  tfar = std::numeric_limits<float>::infinity(); // Should be INF
107  mask = 0xFFFFFFFF;
108  lastHit = -1;
109  u = 0.0;
110  v = 0.0;
111  geomID = RTC_INVALID_GEOMETRY_ID;
112  primID = RTC_INVALID_GEOMETRY_ID;
113  instID = RTC_INVALID_GEOMETRY_ID;
114  org[0] = origin[0];
115  org[1] = origin[1];
116  org[2] = origin[2];
117  dir[0] = direction[0];
118  dir[1] = direction[1];
119  dir[2] = direction[2];
120  Ng[0] = 0.0;
121  Ng[1] = 0.0;
122  Ng[2] = 0.0;
123  }
124 
125 
130  tnear = 0.0;
131  tfar = std::numeric_limits<float>::infinity(); // Should be INF
132  mask = 0xFFFFFFFF;
133  lastHit = -1;
134  u = 0.0;
135  v = 0.0;
136  ignorePrimID = -1;
137  geomID = RTC_INVALID_GEOMETRY_ID;
138  primID = RTC_INVALID_GEOMETRY_ID;
139  instID = RTC_INVALID_GEOMETRY_ID;
140  org[0] = 0.0;
141  org[1] = 0.0;
142  org[2] = 0.0;
143  dir[0] = 0.0;
144  dir[1] = 0.0;
145  dir[2] = 0.0;
146  Ng[0] = 0.0;
147  Ng[1] = 0.0;
148  Ng[2] = 0.0;
149  }
150 
151 
158  RTCOcclusionRay::RTCOcclusionRay(const std::vector<double> &origin,
159  const std::vector<double> &direction) {
160  tnear = 0.0;
161  tfar = std::numeric_limits<float>::infinity(); // Should be INF
162  mask = 0xFFFFFFFF;
163  lastHit = -1;
164  u = 0.0;
165  v = 0.0;
166  geomID = RTC_INVALID_GEOMETRY_ID;
167  ignorePrimID = -1;
168  instID = RTC_INVALID_GEOMETRY_ID;
169  org[0] = origin[0];
170  org[1] = origin[1];
171  org[2] = origin[2];
172  dir[0] = direction[0];
173  dir[1] = direction[1];
174  dir[2] = direction[2];
175  Ng[0] = 0.0;
176  Ng[1] = 0.0;
177  Ng[2] = 0.0;
178  }
179 
188  LinearAlgebra::Vector direction) {
189  tnear = 0.0;
190  tfar = std::numeric_limits<float>::infinity(); // Should be INF
191  mask = 0xFFFFFFFF;
192  lastHit = -1;
193  u = 0.0;
194  v = 0.0;
195  geomID = RTC_INVALID_GEOMETRY_ID;
196  ignorePrimID = -1;
197  instID = RTC_INVALID_GEOMETRY_ID;
198  org[0] = origin[0];
199  org[1] = origin[1];
200  org[2] = origin[2];
201  dir[0] = direction[0];
202  dir[1] = direction[1];
203  dir[2] = direction[2];
204  Ng[0] = 0.0;
205  Ng[1] = 0.0;
206  Ng[2] = 0.0;
207  }
208 
209 
216  primID = 0;
217  }
218 
219 
229  LinearAlgebra::Vector &normal,
230  int prim)
231  : intersection(location),
232  surfaceNormal(normal) ,
233  primID(prim) { }
234 
235 
243  : m_name(),
244  m_mesh(),
245  m_cloud(),
246  m_device(rtcNewDevice(NULL)),
247  m_scene(rtcDeviceNewScene(m_device,
248  RTC_SCENE_STATIC | RTC_SCENE_HIGH_QUALITY | RTC_SCENE_ROBUST,
249  RTC_INTERSECT1)) { }
250 
251 
258  EmbreeTargetShape::EmbreeTargetShape(pcl::PolygonMesh::Ptr mesh, const QString &name)
259  : m_name(name),
260  m_mesh(),
261  m_cloud(),
262  m_device(rtcNewDevice(NULL)),
263  m_scene(rtcDeviceNewScene(m_device,
264  RTC_SCENE_STATIC | RTC_SCENE_HIGH_QUALITY | RTC_SCENE_ROBUST,
265  RTC_INTERSECT1)) {
266  initMesh(mesh);
267  }
268 
269 
280  EmbreeTargetShape::EmbreeTargetShape(const QString &dem, const Pvl *conf)
281  : m_name(),
282  m_mesh(),
283  m_cloud(),
284  m_device(rtcNewDevice(NULL)),
285  m_scene(rtcDeviceNewScene(m_device,
286  RTC_SCENE_STATIC | RTC_SCENE_HIGH_QUALITY | RTC_SCENE_ROBUST,
287  RTC_INTERSECT1)) {
288  FileName file(dem);
289  pcl::PolygonMesh::Ptr mesh;
290  m_name = file.baseName();
291 
292  try {
293  // DEMs (ISIS cubes) TODO implement this
294  if (file.extension() == "cub") {
295  QString msg = "DEMs cannot be used to create an EmbreeTargetShape.";
296  throw IException(IException::Io, msg, _FILEINFO_);
297  }
298  // DSKs
299  else if (file.extension() == "bds") {
300  mesh = readDSK(file);
301  }
302  // Let PCL try to handle other formats (obj, ply, etc.)
303  else {
304  mesh = readPC(file);
305  }
306  }
307  catch (IException &e) {
308  QString msg = "Failed creating an EmbreeTargetShape from ["
309  + file.expanded() + "].";
310  throw IException(e, IException::Io, msg, _FILEINFO_);
311  }
312  initMesh(mesh);
313  }
314 
315 
327  pcl::PolygonMesh::Ptr EmbreeTargetShape::readDSK(FileName file) {
328 
330  SpiceInt dskHandle;
331  SpiceDLADescr dlaDescriptor;
333  SpiceDSKDescr dskDescriptor;
334  SpiceInt numPlates;
335  SpiceInt numVertices;
336 
337  // Sanity check
338  if ( !file.fileExists() ) {
339  QString mess = "NAIF DSK file [" + file.expanded() + "] does not exist.";
340  throw IException(IException::User, mess, _FILEINFO_);
341  }
342 
343  // Open the NAIF Digital Shape Kernel (DSK)
344  dasopr_c( file.expanded().toLatin1().data(), &dskHandle );
346 
347  // Search to the first DLA segment
348  SpiceBoolean found;
349  dlabfs_c( dskHandle, &dlaDescriptor, &found );
351  if ( !found ) {
352  QString mess = "No segments found in DSK file [" + file.expanded() + "]";
353  throw IException(IException::User, mess, _FILEINFO_);
354  }
355 
356  dskgd_c( dskHandle, &dlaDescriptor, &dskDescriptor );
358 
359  // Get The number of polygons and vertices
360  dskz02_c( dskHandle, &dlaDescriptor, &numVertices, &numPlates );
362 
363  // Allocate polygon and vertices arrays
364  // These arrays are actually numVertices x 3 and numPlates x 3,
365  // this allocation is easier and produces needed memory layout for dskv02_c
366  // These arrays are very large, so they need to be heap allocated.
367  double *verticesArray = new double[numVertices * 3];
368  int *polygonsArray = new int[numPlates * 3];
369 
370  // Read the vertices from the dsk file
371  SpiceInt numRead = 0;
372  dskv02_c(dskHandle, &dlaDescriptor, 1, numVertices,
373  &numRead, ( SpiceDouble(*)[3] )(verticesArray) );
375  if ( numRead != numVertices ) {
376  QString msg = "Failed reading all vertices from the DSK file, ["
377  + toString(numRead) + "] out of ["
378  + toString(numVertices) + "] vertices read.";
379  throw IException(IException::Io, msg, _FILEINFO_);
380  }
381 
382  // Read the polygons from the DSK
383  numRead = 0;
384  dskp02_c(dskHandle, &dlaDescriptor, 1, numPlates,
385  &numRead, ( SpiceInt(*)[3] )(polygonsArray) );
387  if ( numRead != numPlates ) {
388  QString msg = "Failed reading all polygons from the DSK file, ["
389  + toString(numRead) + "] out of ["
390  + toString(numPlates) + "] polygons read.";
391  throw IException(IException::Io, msg, _FILEINFO_);
392  }
393 
394  // Store the vertices in a point cloud
395  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
396  for (int vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex) {
397  cloud->push_back(pcl::PointXYZ(verticesArray[vertexIndex * 3],
398  verticesArray[vertexIndex * 3 + 1],
399  verticesArray[vertexIndex * 3 + 2]));
400  }
401 
402  // Store the polygons as a vector of vertices
403  std::vector<pcl::Vertices> polygons;
404  for (int plateIndex = 0; plateIndex < numPlates; ++plateIndex) {
405  pcl::Vertices vertexIndices;
406  // NAIF uses 1 based indexing for the vertices, so subtract 1
407  vertexIndices.vertices.push_back(polygonsArray[plateIndex * 3] - 1);
408  vertexIndices.vertices.push_back(polygonsArray[plateIndex * 3 + 1] - 1);
409  vertexIndices.vertices.push_back(polygonsArray[plateIndex * 3 + 2] - 1);
410  polygons.push_back(vertexIndices);
411  }
412 
413  // Create the mesh
414  pcl::PolygonMesh::Ptr mesh(new pcl::PolygonMesh);
415  mesh->polygons = polygons;
416  pcl::PCLPointCloud2::Ptr cloudBlob(new pcl::PCLPointCloud2);
417  pcl::toPCLPointCloud2(*cloud, *cloudBlob);
418  mesh->cloud = *cloudBlob;
419 
420  // Free the vectors used to read the vertices and polygons
421  delete [] verticesArray;
422  delete [] polygonsArray;
423 
424  return mesh;
425  }
426 
427 
437  pcl::PolygonMesh::Ptr EmbreeTargetShape::readPC(FileName file) {
438  pcl::PolygonMesh::Ptr mesh( new pcl::PolygonMesh );
439 
440  int loadStatus = pcl::io::load(file.expanded().toStdString(), *mesh);
441  if (loadStatus == -1) {
442  QString msg = "Failed loading target shape file [" + file.expanded() + "]";
443  throw IException(IException::Io, msg, _FILEINFO_);
444  }
445  return mesh;
446  }
447 
448 
466  void EmbreeTargetShape::initMesh(pcl::PolygonMesh::Ptr mesh) {
467  m_mesh = mesh;
468 
469  // The points are stored in a pcl::PCLPointCloud2 object that we cannot used.
470  // So, convert them into a pcl::PointCloud<pcl::PointXYZ> object that we can use.
471  pcl::fromPCLPointCloud2(mesh->cloud, m_cloud);
472 
473  // Create a static geometry (the body) in our scene
474  unsigned geomID = rtcNewTriangleMesh(m_scene,
475  RTC_GEOMETRY_STATIC,
478  1);
479  // Add vertices and faces (indices)
480  addVertices(geomID); // add cloud of points
481  addIndices(geomID); // connect dots of cloud into triangles
482 
483  // Add the multi-hit filter
484  rtcSetIntersectionFilterFunction(m_scene, geomID,
485  (RTCFilterFunc)&EmbreeTargetShape::multiHitFilter);
486 
487  // Add the occlusion filter
488  rtcSetOcclusionFilterFunction(m_scene, geomID,
489  (RTCFilterFunc)&EmbreeTargetShape::occlusionFilter);
490 
491  // Done, now we can perform some ray tracing
492  rtcCommit(m_scene);
493  }
494 
495 
506  if (!isValid()) {
507  return;
508  }
509  // Add the body's vertices to the Embree ray tracing device's vertex buffer
510  Vertex *vertices = (Vertex *) rtcMapBuffer(m_scene, geomID, RTC_VERTEX_BUFFER);
511  for (int v = 0; v < numberOfVertices(); ++v) {
512  vertices[v].x = m_cloud.points[v].x;
513  vertices[v].y = m_cloud.points[v].y;
514  vertices[v].z = m_cloud.points[v].z;
515  }
516  // Flush buffer
517  rtcUnmapBuffer(m_scene, geomID, RTC_VERTEX_BUFFER);
518  }
519 
520 
530  void EmbreeTargetShape::addIndices(int geomID) {
531  if (!isValid()) {
532  return;
533  }
534  // Add the body's face (vertex indices) to the Embree device's index buffer
535  Triangle *triangles = (Triangle *) rtcMapBuffer(m_scene, geomID, RTC_INDEX_BUFFER);
536  for (int t = 0; t < numberOfPolygons(); ++t) {
537  triangles[t].v0 = m_mesh->polygons[t].vertices[0];
538  triangles[t].v1 = m_mesh->polygons[t].vertices[1];
539  triangles[t].v2 = m_mesh->polygons[t].vertices[2];
540  }
541  // Flush buffer
542  rtcUnmapBuffer(m_scene, geomID, RTC_INDEX_BUFFER);
543  }
544 
545 
551  rtcDeleteScene(m_scene);
552  rtcDeleteDevice(m_device);
553  }
554 
555 
563  if (isValid()) {
564  return m_mesh->polygons.size();
565  }
566  return 0;
567  }
568 
569 
577  if (isValid()) {
578  return m_mesh->cloud.height * m_mesh->cloud.width;
579  }
580  return 0;
581  }
582 
583 
594  RTCBounds EmbreeTargetShape::sceneBounds() const {
595  RTCBounds sceneBounds;
596  if (isValid()) {
597  rtcGetBounds(m_scene, sceneBounds);
598  }
599  else {
600  sceneBounds.lower_x = 0.0;
601  sceneBounds.lower_y = 0.0;
602  sceneBounds.lower_z = 0.0;
603  sceneBounds.upper_x = 0.0;
604  sceneBounds.upper_y = 0.0;
605  sceneBounds.upper_z = 0.0;
606  }
607  return sceneBounds;
608  }
609 
610 
618  RTCBounds sceneBoundary = sceneBounds();
619  LinearAlgebra::Vector diagonal(3);
620  diagonal[0] = sceneBoundary.upper_x - sceneBoundary.lower_x;
621  diagonal[1] = sceneBoundary.upper_y - sceneBoundary.lower_y;
622  diagonal[2] = sceneBoundary.upper_z - sceneBoundary.lower_z;
623  return LinearAlgebra::magnitude(diagonal);
624  }
625 
626 
657  if (isValid()) {
658  rtcIntersect(m_scene, *((RTCRay*)&ray));
659  }
660  }
661 
662 
671  rtcOccluded(m_scene, ray);
672 
673  // rtcOccluded sets the geomID to 0 if the ray hits anything
674  if (ray.geomID == 0) {
675  return true;
676  }
677  return false;
678  }
679 
680 
701  if (hitIndex > ray.lastHit || hitIndex < 0) {
702  QString msg = "Hit index [" + toString(hitIndex) + "] is out of bounds.";
704  }
705 
706  // Get the vertices of the triangle hit
707  pcl::PointXYZ v0 = m_cloud.points[m_mesh->polygons[ray.hitPrimIDs[hitIndex]].vertices[0]];
708  pcl::PointXYZ v1 = m_cloud.points[m_mesh->polygons[ray.hitPrimIDs[hitIndex]].vertices[1]];
709  pcl::PointXYZ v2 = m_cloud.points[m_mesh->polygons[ray.hitPrimIDs[hitIndex]].vertices[2]];
710 
711  // The intersection location comes out in barycentric coordinates, (u, v, w).
712  // Only u and v are returned because u + v + w = 1. If the coordinates of the
713  // triangle vertices are v0, v1, and v2, then the cartesian coordinates are:
714  // w*v0 + u*v1 + v*v2
715  float u = ray.hitUs[hitIndex];
716  float v = ray.hitVs[hitIndex];
717  float w = 1.0 - u - v;
718 
719  LinearAlgebra::Vector intersection(3);
720  intersection[0] = w*v0.x + v*v1.x + u*v2.x;
721  intersection[1] = w*v0.y + v*v1.y + u*v2.y;
722  intersection[2] = w*v0.z + v*v1.z + u*v2.z;
723 
724  // Calculate the normal vector as (v1 - v0) x (v2 - v0) and normalize it
725  // TODO This calculation assumes that the shape conforms to the NAIF dsk standard
726  // of the plate vertices being ordered counterclockwise about the normal.
727  // Check if this is true for other file types and/or make a more generic process
728  LinearAlgebra::Vector surfaceNormal(3);
729  surfaceNormal[0] = (v1.y - v0.y) * (v2.z - v0.z)
730  - (v1.z - v0.z) * (v2.y - v0.y);
731  surfaceNormal[1] = (v1.z - v0.z) * (v2.x - v0.x)
732  - (v1.x - v0.x) * (v2.z - v0.z);
733  surfaceNormal[2] = (v1.x - v0.x) * (v2.y - v0.y)
734  - (v1.y - v0.y) * (v2.x - v0.x);
735 
736  // The surface normal is not normalized so normalize it.
737  surfaceNormal = LinearAlgebra::normalize(surfaceNormal);
738  return RayHitInformation(intersection, surfaceNormal, ray.hitPrimIDs[hitIndex]);
739  }
740 
741 
747  QString EmbreeTargetShape::name() const {
748  return ( m_name );
749  }
750 
751 
758  return m_mesh.get();
759  }
760 
761 
771  void EmbreeTargetShape::multiHitFilter(void* userDataPtr, RTCMultiHitRay& ray) {
772  // Calculate the index to store the hit in
773  ray.lastHit ++;
774 
775  // Store the hits
776  ray.hitGeomIDs[ray.lastHit] = ray.geomID;
777  ray.hitPrimIDs[ray.lastHit] = ray.primID;
778  ray.hitUs[ray.lastHit] = ray.u;
779  ray.hitVs[ray.lastHit] = ray.v;
780 
781  // If there are less than 16 hits, continue ray tracing.
782  if (ray.lastHit < 15) {
783  ray.geomID = RTC_INVALID_GEOMETRY_ID;
784  }
785  }
786 
796  void EmbreeTargetShape::occlusionFilter(void* userDataPtr, RTCOcclusionRay& ray) {
797 
798  // This is the case where we've re-intersected the occluded plate. If this happens, ignore
799  // and keep tracing
800  if ( ray.primID == ray.ignorePrimID) {
801  ray.geomID = RTC_INVALID_GEOMETRY_ID;
802  }
803  }
804 
805 } // namespace Isis
Container that holds the body fixed intersection point and unit surface normal for a hit...
static Vector vector(double v0, double v1, double v2)
Constructs a 3 dimensional vector with the given component values.
unsigned hitGeomIDs[16]
IDs of the geometries (bodies) hit.
int numberOfVertices() const
Return the number of vertices in the target shape.
File name manipulation and expansion.
Definition: FileName.h:116
RTCMultiHitRay()
Default constructor for RTCMultiHitRay.
RTCOcclusionRay()
Default constructor for RTCOcclussionRay.
int numberOfPolygons() const
Return the number of polygons in the target shape.
int lastHit
Index of the last hit in the hit containers.
static double magnitude(const Vector &vector)
Computes the magnitude (i.e., the length) of the given vector using the Euclidean norm (L2 norm)...
double maximumSceneDistance() const
Return the maximum distance within the scene.
Struct for capturing multiple intersections when using embree::rtcintersectscene. ...
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition: IString.cpp:226
static Vector normalize(const Vector &vector)
Returns a unit vector that is codirectional with the given vector by dividing each component of the v...
pcl::PolygonMesh::Ptr readPC(FileName file)
Read a PointCloudLibrary file into a PointCloudLibrary polygon mesh.
This error is for when a programmer made an API call that was illegal.
Definition: IException.h:162
A type of error that occurred when performing an actual I/O operation.
Definition: IException.h:171
unsigned hitPrimIDs[16]
IDs of the primitives (trinagles) hit.
virtual ~EmbreeTargetShape()
Desctructor.
float hitUs[16]
Barycentric u coordinate of the hits.
void addIndices(int geomID)
Adds the polygon vertex indices from the internalized polygon mesh to the Embree scene.
Container for a tin, or triangular polygon.
LinearAlgebra::Vector surfaceNormal
The unit surface normal vector at the intersection.
int v1
The index of the second vertex in the tin.
boost::numeric::ublas::vector< double > Vector
Definition for an Isis::LinearAlgebra::Vector of doubles.
void initMesh(pcl::PolygonMesh::Ptr mesh)
Internalize a PointCloudLibrary polygon mesh in the target shape.
float y
Vertex y position.
RTCScene m_scene
!< The Embree device for rendering the scene.
RayHitInformation()
Default constructor for RayHitInformation.
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:40
unsigned ignorePrimID
IDs of the primitives (trinagles) which should be ignored.
A type of error that could only have occurred due to a mistake on the user&#39;s part (e...
Definition: IException.h:142
QString expanded() const
Returns a QString of the full file name including the file path, excluding the attributes.
Definition: FileName.cpp:212
int v0
The index of the first vertex in the tin.
float x
Vertex x position.
void addVertices(int geomID)
Adds the vertices from the internalized vertex point cloud to the Embree scene.
void intersectRay(RTCMultiHitRay &ray)
Intersect a ray with the target shape.
pcl::PolygonMesh::Ptr m_mesh
!< The name of the target.
RTCBounds sceneBounds() const
Returns the bounds of the Embree scene.
Container for cube-like labels.
Definition: Pvl.h:135
float hitVs[16]
Barycentric v coordinate of the hits.
LinearAlgebra::Vector intersection
The (x, y, z) intersection location.
QString baseName() const
Returns the name of the file without the path and without extensions.
Definition: FileName.cpp:161
RayHitInformation getHitInformation(RTCMultiHitRay &ray, int hitIndex)
Extract the intersection point and unit surface normal from an RTCMultiHitRay that has been intersect...
QString name() const
Return the name of the target shape.
Struct for capturing occluded plates when using embree::rtcintersectscene.
bool isValid() const
Return if a valid mesh is internalized and ready for use.
static void CheckErrors(bool resetNaif=true)
This method looks for any naif errors that might have occurred.
Definition: NaifStatus.cpp:43
Isis exception class.
Definition: IException.h:107
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
QString extension() const
Returns the last extension of the file name.
Definition: FileName.cpp:194
int primID
The primitive ID of the hit.
EmbreeTargetShape()
Default empty constructor.
int lastHit
Index of the last hit in the hit containers.
bool isOccluded(RTCOcclusionRay &ray)
Check if a ray intersects the target body.
Container for a vertex.
RTCDevice m_device
!< The point cloud representation of the target.
pcl::PointCloud< pcl::PointXYZ > m_cloud
!< A boost shared pointer to the polygon mesh representation of the target.
static void occlusionFilter(void *userDataPtr, RTCOcclusionRay &ray)
Filter function for collecting multiple primitiveIDs This function is called by the Embree library du...
bool fileExists() const
Returns true if the file exists; false otherwise.
Definition: FileName.cpp:465
int v2
The index of the third vertex in the tin.
float z
Vertex z position.
static void multiHitFilter(void *userDataPtr, RTCMultiHitRay &ray)
Filter function for collecting multiple hits during ray intersection.
pcl::PolygonMesh::Ptr readDSK(FileName file)
Read a NAIF type 2 DSK file into a PointCloudLibrary polygon mesh.