8#include "EmbreeTargetShape.h"
15#include "NaifDskApi.h"
18#include "IException.h"
20#include "NaifStatus.h"
30 ray.tfar = std::numeric_limits<float>::infinity();
31 ray.mask = 0xFFFFFFFF;
35 hit.geomID = RTC_INVALID_GEOMETRY_ID;
36 hit.primID = RTC_INVALID_GEOMETRY_ID;
37 hit.instID[0] = RTC_INVALID_GEOMETRY_ID;
57 const std::vector<double> &direction) {
59 ray.tfar = std::numeric_limits<float>::infinity();
60 ray.mask = 0xFFFFFFFF;
64 hit.geomID = RTC_INVALID_GEOMETRY_ID;
65 hit.primID = RTC_INVALID_GEOMETRY_ID;
66 hit.instID[0] = RTC_INVALID_GEOMETRY_ID;
67 ray.org_x = origin[0];
68 ray.org_y = origin[1];
69 ray.org_z = origin[2];
70 ray.dir_x = direction[0];
71 ray.dir_y = direction[1];
72 ray.dir_z = direction[2];
89 ray.tfar = std::numeric_limits<float>::infinity();
90 ray.mask = 0xFFFFFFFF;
94 hit.geomID = RTC_INVALID_GEOMETRY_ID;
95 hit.primID = RTC_INVALID_GEOMETRY_ID;
96 hit.instID[0] = RTC_INVALID_GEOMETRY_ID;
97 ray.org_x = origin[0];
98 ray.org_y = origin[1];
99 ray.org_z = origin[2];
100 ray.dir_x = direction[0];
101 ray.dir_y = direction[1];
102 ray.dir_z = direction[2];
114 ray.tfar = std::numeric_limits<float>::infinity();
115 ray.mask = 0xFFFFFFFF;
120 hit.geomID = RTC_INVALID_GEOMETRY_ID;
121 hit.primID = RTC_INVALID_GEOMETRY_ID;
122 hit.instID[0] = RTC_INVALID_GEOMETRY_ID;
142 const std::vector<double> &direction) {
144 ray.tfar = std::numeric_limits<float>::infinity();
145 ray.mask = 0xFFFFFFFF;
149 hit.geomID = RTC_INVALID_GEOMETRY_ID;
151 hit.instID[0] = RTC_INVALID_GEOMETRY_ID;
152 ray.org_x = origin[0];
153 ray.org_y = origin[1];
154 ray.org_z = origin[2];
155 ray.dir_x = direction[0];
156 ray.dir_y = direction[1];
157 ray.dir_z = direction[2];
173 ray.tfar = std::numeric_limits<float>::infinity();
174 ray.mask = 0xFFFFFFFF;
178 hit.geomID = RTC_INVALID_GEOMETRY_ID;
180 hit.instID[0] = RTC_INVALID_GEOMETRY_ID;
181 ray.org_x = origin[0];
182 ray.org_y = origin[1];
183 ray.org_z = origin[2];
184 ray.dir_x = direction[0];
185 ray.dir_y = direction[1];
186 ray.dir_z = direction[2];
214 : intersection(location),
215 surfaceNormal(normal) ,
229 m_device(rtcNewDevice(NULL)),
230 m_scene(rtcNewScene(m_device))
232 rtcSetSceneFlags(
m_scene, RTC_SCENE_FLAG_ROBUST | RTC_SCENE_FLAG_CONTEXT_FILTER_FUNCTION);
233 rtcSetSceneBuildQuality(
m_scene, RTC_BUILD_QUALITY_HIGH);
246 m_device(rtcNewDevice(NULL)),
247 m_scene(rtcNewScene(m_device))
249 rtcSetSceneFlags(
m_scene, RTC_SCENE_FLAG_ROBUST | RTC_SCENE_FLAG_CONTEXT_FILTER_FUNCTION);
250 rtcSetSceneBuildQuality(
m_scene, RTC_BUILD_QUALITY_HIGH);
268 m_device(rtcNewDevice(NULL)),
269 m_scene(rtcNewScene(m_device)) {
270 rtcSetSceneFlags(
m_scene, RTC_SCENE_FLAG_ROBUST | RTC_SCENE_FLAG_CONTEXT_FILTER_FUNCTION);
271 rtcSetSceneBuildQuality(
m_scene, RTC_BUILD_QUALITY_HIGH);
273 pcl::PolygonMesh::Ptr mesh;
274 m_name = file.baseName();
278 if (file.extension() ==
"cub") {
279 QString msg =
"DEMs cannot be used to create an EmbreeTargetShape.";
283 else if (file.extension().toLower() ==
"bds") {
292 QString msg =
"Failed creating an EmbreeTargetShape from ["
293 + file.expanded() +
"].";
315 SpiceDLADescr dlaDescriptor;
317 SpiceDSKDescr dskDescriptor;
319 SpiceInt numVertices;
322 if ( !file.fileExists() ) {
323 QString mess =
"NAIF DSK file [" + file.expanded() +
"] does not exist.";
328 dasopr_c( file.expanded().toLatin1().data(), &dskHandle );
333 dlabfs_c( dskHandle, &dlaDescriptor, &found );
336 QString mess =
"No segments found in DSK file [" + file.expanded() +
"]";
340 dskgd_c( dskHandle, &dlaDescriptor, &dskDescriptor );
344 dskz02_c( dskHandle, &dlaDescriptor, &numVertices, &numPlates );
351 double *verticesArray =
new double[numVertices * 3];
352 int *polygonsArray =
new int[numPlates * 3];
355 SpiceInt numRead = 0;
356 dskv02_c(dskHandle, &dlaDescriptor, 1, numVertices,
357 &numRead, ( SpiceDouble(*)[3] )(verticesArray) );
359 if ( numRead != numVertices ) {
360 QString msg =
"Failed reading all vertices from the DSK file, ["
362 +
toString(numVertices) +
"] vertices read.";
368 dskp02_c(dskHandle, &dlaDescriptor, 1, numPlates,
369 &numRead, ( SpiceInt(*)[3] )(polygonsArray) );
371 if ( numRead != numPlates ) {
372 QString msg =
"Failed reading all polygons from the DSK file, ["
374 +
toString(numPlates) +
"] polygons read.";
379 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(
new pcl::PointCloud<pcl::PointXYZ>);
380 for (
int vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex) {
381 cloud->push_back(pcl::PointXYZ(verticesArray[vertexIndex * 3],
382 verticesArray[vertexIndex * 3 + 1],
383 verticesArray[vertexIndex * 3 + 2]));
387 std::vector<pcl::Vertices> polygons;
388 for (
int plateIndex = 0; plateIndex < numPlates; ++plateIndex) {
389 pcl::Vertices vertexIndices;
391 vertexIndices.vertices.push_back(polygonsArray[plateIndex * 3] - 1);
392 vertexIndices.vertices.push_back(polygonsArray[plateIndex * 3 + 1] - 1);
393 vertexIndices.vertices.push_back(polygonsArray[plateIndex * 3 + 2] - 1);
394 polygons.push_back(vertexIndices);
398 pcl::PolygonMesh::Ptr mesh(
new pcl::PolygonMesh);
399 mesh->polygons = polygons;
400 pcl::PCLPointCloud2::Ptr cloudBlob(
new pcl::PCLPointCloud2);
401 pcl::toPCLPointCloud2(*cloud, *cloudBlob);
402 mesh->cloud = *cloudBlob;
405 delete [] verticesArray;
406 delete [] polygonsArray;
422 pcl::PolygonMesh::Ptr mesh(
new pcl::PolygonMesh );
424 int loadStatus = pcl::io::load(file.expanded().toStdString(), *mesh);
425 if (loadStatus == -1) {
426 QString msg =
"Failed loading target shape file [" + file.expanded() +
"]";
455 pcl::fromPCLPointCloud2(mesh->cloud,
m_cloud);
458 RTCGeometry rtcMesh = rtcNewGeometry(
m_device, RTC_GEOMETRY_TYPE_TRIANGLE);
466 vertices[v].
x =
m_cloud.points[v].x;
467 vertices[v].
y =
m_cloud.points[v].y;
468 vertices[v].
z =
m_cloud.points[v].z;
477 triangles[t].
v0 =
m_mesh->polygons[t].vertices[0];
478 triangles[t].v1 =
m_mesh->polygons[t].vertices[1];
479 triangles[t].v2 =
m_mesh->polygons[t].vertices[2];
488 rtcCommitGeometry(rtcMesh);
489 unsigned int geomID = rtcAttachGeometry(
m_scene, rtcMesh);
490 rtcReleaseGeometry(rtcMesh);
565 return m_mesh->polygons.size();
621 diagonal[0] = sceneBoundary.upper_x - sceneBoundary.lower_x;
622 diagonal[1] = sceneBoundary.upper_y - sceneBoundary.lower_y;
623 diagonal[2] = sceneBoundary.upper_z - sceneBoundary.lower_z;
659 RTCIntersectContext context;
660 rtcInitIntersectContext(&context);
675 RTCIntersectContext context;
676 rtcInitIntersectContext(&context);
678 rtcOccluded1(
m_scene, &context, (RTCRay*)&ray);
681 if (isinf(ray.ray.tfar) && ray.ray.tfar < 0) {
708 if (hitIndex > ray.lastHit || hitIndex < 0) {
709 QString msg =
"Hit index [" +
toString(hitIndex) +
"] is out of bounds.";
714 pcl::PointXYZ v0 =
m_cloud.points[
m_mesh->polygons[ray.hitPrimIDs[hitIndex]].vertices[0]];
715 pcl::PointXYZ v1 =
m_cloud.points[
m_mesh->polygons[ray.hitPrimIDs[hitIndex]].vertices[1]];
716 pcl::PointXYZ v2 =
m_cloud.points[
m_mesh->polygons[ray.hitPrimIDs[hitIndex]].vertices[2]];
722 float u = ray.hitUs[hitIndex];
723 float v = ray.hitVs[hitIndex];
724 float w = 1.0 - u - v;
727 intersection[0] = w*v0.x + v*v1.x + u*v2.x;
728 intersection[1] = w*v0.y + v*v1.y + u*v2.y;
729 intersection[2] = w*v0.z + v*v1.z + u*v2.z;
736 surfaceNormal[0] = (v1.y - v0.y) * (v2.z - v0.z)
737 - (v1.z - v0.z) * (v2.y - v0.y);
738 surfaceNormal[1] = (v1.z - v0.z) * (v2.x - v0.x)
739 - (v1.x - v0.x) * (v2.z - v0.z);
740 surfaceNormal[2] = (v1.x - v0.x) * (v2.y - v0.y)
741 - (v1.y - v0.y) * (v2.x - v0.x);
780 if (args->context ==
nullptr)
783 assert(args->N == 1);
784 int *valid = args->valid;
785 if (valid[0] != -1) {
789 RTCHit *hit = (RTCHit *)args->hit;
795 ray->hitGeomIDs[ray->lastHit] = hit->geomID;
796 ray->hitPrimIDs[ray->lastHit] = hit->primID;
797 ray->hitUs[ray->lastHit] = hit->u;
798 ray->hitVs[ray->lastHit] = hit->v;
801 if (ray->lastHit < 15) {
803 ray->hit.geomID = RTC_INVALID_GEOMETRY_ID;
804 hit->geomID = RTC_INVALID_GEOMETRY_ID;
819 if (args->context ==
nullptr)
822 assert(args->N == 1);
823 int *valid = args->valid;
824 if (valid[0] != -1) {
828 RTCHit *hit = (RTCHit *)args->hit;
829 ray->hit.primID = hit->primID;
833 if (ray->hit.primID == ray->ignorePrimID) {
bool isOccluded(RTCOcclusionRay &ray)
Check if a ray intersects the target body.
void initMesh(pcl::PolygonMesh::Ptr mesh)
Internalize a PointCloudLibrary polygon mesh in the target shape.
pcl::PolygonMesh::Ptr readDSK(FileName file)
Read a NAIF type 2 DSK file into a PointCloudLibrary polygon mesh.
static void occlusionFilter(const RTCFilterFunctionNArguments *args)
Filter function for collecting multiple primitiveIDs This function is called by the Embree library du...
int numberOfPolygons() const
Return the number of polygons in the target shape.
int numberOfVertices() const
Return the number of vertices in the target shape.
virtual ~EmbreeTargetShape()
Desctructor.
bool isValid() const
Return if a valid mesh is internalized and ready for use.
RTCDevice m_device
!< The point cloud representation of the target.
void addVertices(int geomID)
Adds the vertices from the internalized vertex point cloud to the Embree scene.
static void multiHitFilter(const RTCFilterFunctionNArguments *args)
Filter function for collecting multiple hits during ray intersection.
pcl::PolygonMesh::Ptr readPC(FileName file)
Read a PointCloudLibrary file into a PointCloudLibrary polygon mesh.
pcl::PolygonMesh::Ptr m_mesh
!< The name of the target.
RTCScene m_scene
!< The Embree device for rendering the scene.
void addIndices(int geomID)
Adds the polygon vertex indices from the internalized polygon mesh to the Embree scene.
RayHitInformation getHitInformation(RTCMultiHitRay &ray, int hitIndex)
Extract the intersection point and unit surface normal from an RTCMultiHitRay that has been intersect...
RTCBounds sceneBounds() const
Returns the bounds of the Embree scene.
void intersectRay(RTCMultiHitRay &ray)
Intersect a ray with the target shape.
EmbreeTargetShape()
Default empty constructor.
pcl::PointCloud< pcl::PointXYZ > m_cloud
!< A boost shared pointer to the polygon mesh representation of the target.
QString name() const
Return the name of the target shape.
double maximumSceneDistance() const
Return the maximum distance within the scene.
File name manipulation and expansion.
@ User
A type of error that could only have occurred due to a mistake on the user's part (e....
@ Programmer
This error is for when a programmer made an API call that was illegal.
@ Io
A type of error that occurred when performing an actual I/O operation.
static Vector vector(double v0, double v1, double v2)
Constructs a 3 dimensional vector with the given component values.
static double magnitude(const Vector &vector)
Computes the magnitude (i.e., the length) of the given vector using the Euclidean norm (L2 norm).
boost::numeric::ublas::vector< double > Vector
Definition for an Isis::LinearAlgebra::Vector of doubles.
static Vector normalize(const Vector &vector)
Returns a unit vector that is codirectional with the given vector by dividing each component of the v...
static void CheckErrors(bool resetNaif=true)
This method looks for any naif errors that might have occurred.
Container for cube-like labels.
This is free and unencumbered software released into the public domain.
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Container for a tin, or triangular polygon.
int v0
The index of the first vertex in the tin.
float y
Vertex y position.
float x
Vertex x position.
float z
Vertex z position.
Struct for capturing multiple intersections when using embree::rtcintersectscene.
RTCMultiHitRay()
Default constructor for RTCMultiHitRay.
int lastHit
Index of the last hit in the hit containers.
Struct for capturing occluded plates when using embree::rtcintersectscene.
RTCOcclusionRay()
Default constructor for RTCOcclussionRay.
unsigned ignorePrimID
IDs of the primitives (trinagles) which should be ignored.
int lastHit
Index of the last hit in the hit containers.