|
@@ -21,8 +21,8 @@
|
|
#include <Eigen/Core>
|
|
#include <Eigen/Core>
|
|
#include <Eigen/Geometry>
|
|
#include <Eigen/Geometry>
|
|
|
|
|
|
-#include <embree2/rtcore.h>
|
|
|
|
-#include <embree2/rtcore_ray.h>
|
|
|
|
|
|
+#include <embree3/rtcore.h>
|
|
|
|
+#include <embree3/rtcore_ray.h>
|
|
#include <iostream>
|
|
#include <iostream>
|
|
#include <vector>
|
|
#include <vector>
|
|
|
|
|
|
@@ -177,7 +177,7 @@ namespace igl
|
|
bool initialized;
|
|
bool initialized;
|
|
|
|
|
|
inline void createRay(
|
|
inline void createRay(
|
|
- RTCRay& ray,
|
|
|
|
|
|
+ RTCRayHit& ray,
|
|
const Eigen::RowVector3f& origin,
|
|
const Eigen::RowVector3f& origin,
|
|
const Eigen::RowVector3f& direction,
|
|
const Eigen::RowVector3f& direction,
|
|
float tnear,
|
|
float tnear,
|
|
@@ -199,29 +199,28 @@ namespace igl
|
|
{
|
|
{
|
|
// Keeps track of whether the **Global** Embree intersector has been
|
|
// Keeps track of whether the **Global** Embree intersector has been
|
|
// initialized. This should never been done at the global scope.
|
|
// initialized. This should never been done at the global scope.
|
|
- static bool EmbreeIntersector_inited = false;
|
|
|
|
|
|
+ static RTCDevice g_device = nullptr;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
inline void igl::embree::EmbreeIntersector::global_init()
|
|
inline void igl::embree::EmbreeIntersector::global_init()
|
|
{
|
|
{
|
|
- if(!EmbreeIntersector_inited)
|
|
|
|
|
|
+ if(!g_device)
|
|
{
|
|
{
|
|
- rtcInit();
|
|
|
|
- if(rtcGetError() != RTC_NO_ERROR)
|
|
|
|
|
|
+ g_device = rtcNewDevice (NULL);
|
|
|
|
+ if(rtcGetDeviceError (g_device) != RTC_ERROR_NONE)
|
|
std::cerr << "Embree: An error occurred while initializing embree core!" << std::endl;
|
|
std::cerr << "Embree: An error occurred while initializing embree core!" << std::endl;
|
|
#ifdef IGL_VERBOSE
|
|
#ifdef IGL_VERBOSE
|
|
else
|
|
else
|
|
std::cerr << "Embree: core initialized." << std::endl;
|
|
std::cerr << "Embree: core initialized." << std::endl;
|
|
#endif
|
|
#endif
|
|
- EmbreeIntersector_inited = true;
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
inline void igl::embree::EmbreeIntersector::global_deinit()
|
|
inline void igl::embree::EmbreeIntersector::global_deinit()
|
|
{
|
|
{
|
|
- EmbreeIntersector_inited = false;
|
|
|
|
- rtcExit();
|
|
|
|
|
|
+ rtcReleaseDevice (g_device);
|
|
|
|
+ g_device = nullptr;
|
|
}
|
|
}
|
|
|
|
|
|
inline igl::embree::EmbreeIntersector::EmbreeIntersector()
|
|
inline igl::embree::EmbreeIntersector::EmbreeIntersector()
|
|
@@ -287,43 +286,49 @@ inline void igl::embree::EmbreeIntersector::init(
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ RTCBuildQuality buildQuality = isStatic ? RTC_BUILD_QUALITY_HIGH : RTC_BUILD_QUALITY_MEDIUM;
|
|
|
|
+
|
|
// create a scene
|
|
// create a scene
|
|
- RTCSceneFlags flags = RTC_SCENE_ROBUST | RTC_SCENE_HIGH_QUALITY;
|
|
|
|
- if(isStatic)
|
|
|
|
- flags = flags | RTC_SCENE_STATIC;
|
|
|
|
- scene = rtcNewScene(flags,RTC_INTERSECT1);
|
|
|
|
|
|
+ scene = rtcNewScene(g_device);
|
|
|
|
+ rtcSetSceneFlags(scene, RTC_SCENE_FLAG_ROBUST);
|
|
|
|
+ rtcSetSceneBuildQuality(scene, buildQuality);
|
|
|
|
|
|
for(int g=0;g<(int)V.size();g++)
|
|
for(int g=0;g<(int)V.size();g++)
|
|
{
|
|
{
|
|
// create triangle mesh geometry in that scene
|
|
// create triangle mesh geometry in that scene
|
|
- geomID = rtcNewTriangleMesh(scene,RTC_GEOMETRY_STATIC,F[g]->rows(),V[g]->rows(),1);
|
|
|
|
|
|
+ RTCGeometry geom_0 = rtcNewGeometry (g_device, RTC_GEOMETRY_TYPE_TRIANGLE);
|
|
|
|
+ rtcSetGeometryBuildQuality(geom_0,buildQuality);
|
|
|
|
+ rtcSetGeometryTimeStepCount(geom_0,1);
|
|
|
|
+ geomID = rtcAttachGeometry(scene,geom_0);
|
|
|
|
+ rtcReleaseGeometry(geom_0);
|
|
|
|
|
|
// fill vertex buffer
|
|
// fill vertex buffer
|
|
- vertices = (Vertex*)rtcMapBuffer(scene,geomID,RTC_VERTEX_BUFFER);
|
|
|
|
|
|
+ vertices = (Vertex*)rtcSetNewGeometryBuffer(geom_0,RTC_BUFFER_TYPE_VERTEX,0,RTC_FORMAT_FLOAT3,4*sizeof(float),V[g]->rows());
|
|
for(int i=0;i<(int)V[g]->rows();i++)
|
|
for(int i=0;i<(int)V[g]->rows();i++)
|
|
{
|
|
{
|
|
vertices[i].x = (float)V[g]->coeff(i,0);
|
|
vertices[i].x = (float)V[g]->coeff(i,0);
|
|
vertices[i].y = (float)V[g]->coeff(i,1);
|
|
vertices[i].y = (float)V[g]->coeff(i,1);
|
|
vertices[i].z = (float)V[g]->coeff(i,2);
|
|
vertices[i].z = (float)V[g]->coeff(i,2);
|
|
}
|
|
}
|
|
- rtcUnmapBuffer(scene,geomID,RTC_VERTEX_BUFFER);
|
|
|
|
|
|
+
|
|
|
|
|
|
// fill triangle buffer
|
|
// fill triangle buffer
|
|
- triangles = (Triangle*) rtcMapBuffer(scene,geomID,RTC_INDEX_BUFFER);
|
|
|
|
|
|
+ triangles = (Triangle*) rtcSetNewGeometryBuffer(geom_0,RTC_BUFFER_TYPE_INDEX,0,RTC_FORMAT_UINT3,3*sizeof(int),F[g]->rows());
|
|
for(int i=0;i<(int)F[g]->rows();i++)
|
|
for(int i=0;i<(int)F[g]->rows();i++)
|
|
{
|
|
{
|
|
triangles[i].v0 = (int)F[g]->coeff(i,0);
|
|
triangles[i].v0 = (int)F[g]->coeff(i,0);
|
|
triangles[i].v1 = (int)F[g]->coeff(i,1);
|
|
triangles[i].v1 = (int)F[g]->coeff(i,1);
|
|
triangles[i].v2 = (int)F[g]->coeff(i,2);
|
|
triangles[i].v2 = (int)F[g]->coeff(i,2);
|
|
}
|
|
}
|
|
- rtcUnmapBuffer(scene,geomID,RTC_INDEX_BUFFER);
|
|
|
|
|
|
+
|
|
|
|
|
|
- rtcSetMask(scene,geomID,masks[g]);
|
|
|
|
|
|
+ rtcSetGeometryMask(geom_0,masks[g]);
|
|
|
|
+ rtcCommitGeometry(geom_0);
|
|
}
|
|
}
|
|
|
|
|
|
- rtcCommit(scene);
|
|
|
|
|
|
+ rtcCommitScene(scene);
|
|
|
|
|
|
- if(rtcGetError() != RTC_NO_ERROR)
|
|
|
|
|
|
+ if(rtcGetDeviceError (g_device) != RTC_ERROR_NONE)
|
|
std::cerr << "Embree: An error occurred while initializing the provided geometry!" << endl;
|
|
std::cerr << "Embree: An error occurred while initializing the provided geometry!" << endl;
|
|
#ifdef IGL_VERBOSE
|
|
#ifdef IGL_VERBOSE
|
|
else
|
|
else
|
|
@@ -342,11 +347,11 @@ igl::embree::EmbreeIntersector
|
|
|
|
|
|
void igl::embree::EmbreeIntersector::deinit()
|
|
void igl::embree::EmbreeIntersector::deinit()
|
|
{
|
|
{
|
|
- if(EmbreeIntersector_inited && scene)
|
|
|
|
|
|
+ if(g_device && scene)
|
|
{
|
|
{
|
|
- rtcDeleteScene(scene);
|
|
|
|
|
|
+ rtcReleaseScene(scene);
|
|
|
|
|
|
- if(rtcGetError() != RTC_NO_ERROR)
|
|
|
|
|
|
+ if(rtcGetDeviceError (g_device) != RTC_ERROR_NONE)
|
|
{
|
|
{
|
|
std::cerr << "Embree: An error occurred while resetting!" << std::endl;
|
|
std::cerr << "Embree: An error occurred while resetting!" << std::endl;
|
|
}
|
|
}
|
|
@@ -367,23 +372,31 @@ inline bool igl::embree::EmbreeIntersector::intersectRay(
|
|
float tfar,
|
|
float tfar,
|
|
int mask) const
|
|
int mask) const
|
|
{
|
|
{
|
|
- RTCRay ray;
|
|
|
|
|
|
+ RTCRayHit ray; // EMBREE_FIXME: use RTCRay for occlusion rays
|
|
|
|
+ ray.ray.flags = 0;
|
|
createRay(ray, origin,direction,tnear,tfar,mask);
|
|
createRay(ray, origin,direction,tnear,tfar,mask);
|
|
|
|
|
|
// shot ray
|
|
// shot ray
|
|
- rtcIntersect(scene,ray);
|
|
|
|
|
|
+ {
|
|
|
|
+ RTCIntersectContext context;
|
|
|
|
+ rtcInitIntersectContext(&context);
|
|
|
|
+ rtcIntersect1(scene,&context,&ray);
|
|
|
|
+ ray.hit.Ng_x = -ray.hit.Ng_x; // EMBREE_FIXME: only correct for triangles,quads, and subdivision surfaces
|
|
|
|
+ ray.hit.Ng_y = -ray.hit.Ng_y;
|
|
|
|
+ ray.hit.Ng_z = -ray.hit.Ng_z;
|
|
|
|
+ }
|
|
#ifdef IGL_VERBOSE
|
|
#ifdef IGL_VERBOSE
|
|
- if(rtcGetError() != RTC_NO_ERROR)
|
|
|
|
|
|
+ if(rtcGetDeviceError (g_device) != RTC_ERROR_NONE)
|
|
std::cerr << "Embree: An error occurred while resetting!" << std::endl;
|
|
std::cerr << "Embree: An error occurred while resetting!" << std::endl;
|
|
#endif
|
|
#endif
|
|
|
|
|
|
- if((unsigned)ray.geomID != RTC_INVALID_GEOMETRY_ID)
|
|
|
|
|
|
+ if((unsigned)ray.hit.geomID != RTC_INVALID_GEOMETRY_ID)
|
|
{
|
|
{
|
|
- hit.id = ray.primID;
|
|
|
|
- hit.gid = ray.geomID;
|
|
|
|
- hit.u = ray.u;
|
|
|
|
- hit.v = ray.v;
|
|
|
|
- hit.t = ray.tfar;
|
|
|
|
|
|
+ hit.id = ray.hit.primID;
|
|
|
|
+ hit.gid = ray.hit.geomID;
|
|
|
|
+ hit.u = ray.hit.u;
|
|
|
|
+ hit.v = ray.hit.v;
|
|
|
|
+ hit.t = ray.ray.tfar;
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -462,22 +475,30 @@ igl::embree::EmbreeIntersector
|
|
const double eps = FLOAT_EPS;
|
|
const double eps = FLOAT_EPS;
|
|
double min_t = tnear;
|
|
double min_t = tnear;
|
|
bool large_hits_warned = false;
|
|
bool large_hits_warned = false;
|
|
- RTCRay ray;
|
|
|
|
|
|
+ RTCRayHit ray; // EMBREE_FIXME: use RTCRay for occlusion rays
|
|
|
|
+ ray.ray.flags = 0;
|
|
createRay(ray,origin,direction,tnear,tfar,mask);
|
|
createRay(ray,origin,direction,tnear,tfar,mask);
|
|
|
|
|
|
while(true)
|
|
while(true)
|
|
{
|
|
{
|
|
- ray.tnear = min_t;
|
|
|
|
- ray.tfar = tfar;
|
|
|
|
- ray.geomID = RTC_INVALID_GEOMETRY_ID;
|
|
|
|
- ray.primID = RTC_INVALID_GEOMETRY_ID;
|
|
|
|
- ray.instID = RTC_INVALID_GEOMETRY_ID;
|
|
|
|
|
|
+ ray.ray.tnear = min_t;
|
|
|
|
+ ray.ray.tfar = tfar;
|
|
|
|
+ ray.hit.geomID = RTC_INVALID_GEOMETRY_ID;
|
|
|
|
+ ray.hit.primID = RTC_INVALID_GEOMETRY_ID;
|
|
|
|
+ ray.hit.instID[0] = RTC_INVALID_GEOMETRY_ID;
|
|
num_rays++;
|
|
num_rays++;
|
|
- rtcIntersect(scene,ray);
|
|
|
|
- if((unsigned)ray.geomID != RTC_INVALID_GEOMETRY_ID)
|
|
|
|
|
|
+ {
|
|
|
|
+ RTCIntersectContext context;
|
|
|
|
+ rtcInitIntersectContext(&context);
|
|
|
|
+ rtcIntersect1(scene,&context,&ray);
|
|
|
|
+ ray.hit.Ng_x = -ray.hit.Ng_x; // EMBREE_FIXME: only correct for triangles,quads, and subdivision surfaces
|
|
|
|
+ ray.hit.Ng_y = -ray.hit.Ng_y;
|
|
|
|
+ ray.hit.Ng_z = -ray.hit.Ng_z;
|
|
|
|
+ }
|
|
|
|
+ if((unsigned)ray.hit.geomID != RTC_INVALID_GEOMETRY_ID)
|
|
{
|
|
{
|
|
// Hit self again, progressively advance
|
|
// Hit self again, progressively advance
|
|
- if(ray.primID == last_id0 || ray.tfar <= min_t)
|
|
|
|
|
|
+ if(ray.hit.primID == last_id0 || ray.ray.tfar <= min_t)
|
|
{
|
|
{
|
|
// push min_t a bit more
|
|
// push min_t a bit more
|
|
//double t_push = pow(2.0,self_hits-4)*(hit.t<eps?eps:hit.t);
|
|
//double t_push = pow(2.0,self_hits-4)*(hit.t<eps?eps:hit.t);
|
|
@@ -492,23 +513,23 @@ igl::embree::EmbreeIntersector
|
|
else
|
|
else
|
|
{
|
|
{
|
|
Hit hit;
|
|
Hit hit;
|
|
- hit.id = ray.primID;
|
|
|
|
- hit.gid = ray.geomID;
|
|
|
|
- hit.u = ray.u;
|
|
|
|
- hit.v = ray.v;
|
|
|
|
- hit.t = ray.tfar;
|
|
|
|
|
|
+ hit.id = ray.hit.primID;
|
|
|
|
+ hit.gid = ray.hit.geomID;
|
|
|
|
+ hit.u = ray.hit.u;
|
|
|
|
+ hit.v = ray.hit.v;
|
|
|
|
+ hit.t = ray.ray.tfar;
|
|
hits.push_back(hit);
|
|
hits.push_back(hit);
|
|
#ifdef IGL_VERBOSE
|
|
#ifdef IGL_VERBOSE
|
|
std::cerr<<" t: "<<hit.t<<endl;
|
|
std::cerr<<" t: "<<hit.t<<endl;
|
|
#endif
|
|
#endif
|
|
// Instead of moving origin, just change min_t. That way calculations
|
|
// Instead of moving origin, just change min_t. That way calculations
|
|
// all use exactly same origin values
|
|
// all use exactly same origin values
|
|
- min_t = ray.tfar;
|
|
|
|
|
|
+ min_t = ray.ray.tfar;
|
|
|
|
|
|
// reset t_scale
|
|
// reset t_scale
|
|
self_hits = 0;
|
|
self_hits = 0;
|
|
}
|
|
}
|
|
- last_id0 = ray.primID;
|
|
|
|
|
|
+ last_id0 = ray.hit.primID;
|
|
}
|
|
}
|
|
else
|
|
else
|
|
break; // no more hits
|
|
break; // no more hits
|
|
@@ -544,18 +565,26 @@ inline bool
|
|
igl::embree::EmbreeIntersector
|
|
igl::embree::EmbreeIntersector
|
|
::intersectSegment(const Eigen::RowVector3f& a, const Eigen::RowVector3f& ab, Hit &hit, int mask) const
|
|
::intersectSegment(const Eigen::RowVector3f& a, const Eigen::RowVector3f& ab, Hit &hit, int mask) const
|
|
{
|
|
{
|
|
- RTCRay ray;
|
|
|
|
|
|
+ RTCRayHit ray; // EMBREE_FIXME: use RTCRay for occlusion rays
|
|
|
|
+ ray.ray.flags = 0;
|
|
createRay(ray,a,ab,0,1.0,mask);
|
|
createRay(ray,a,ab,0,1.0,mask);
|
|
|
|
|
|
- rtcIntersect(scene,ray);
|
|
|
|
|
|
+ {
|
|
|
|
+ RTCIntersectContext context;
|
|
|
|
+ rtcInitIntersectContext(&context);
|
|
|
|
+ rtcIntersect1(scene,&context,&ray);
|
|
|
|
+ ray.hit.Ng_x = -ray.hit.Ng_x; // EMBREE_FIXME: only correct for triangles,quads, and subdivision surfaces
|
|
|
|
+ ray.hit.Ng_y = -ray.hit.Ng_y;
|
|
|
|
+ ray.hit.Ng_z = -ray.hit.Ng_z;
|
|
|
|
+ }
|
|
|
|
|
|
- if((unsigned)ray.geomID != RTC_INVALID_GEOMETRY_ID)
|
|
|
|
|
|
+ if((unsigned)ray.hit.geomID != RTC_INVALID_GEOMETRY_ID)
|
|
{
|
|
{
|
|
- hit.id = ray.primID;
|
|
|
|
- hit.gid = ray.geomID;
|
|
|
|
- hit.u = ray.u;
|
|
|
|
- hit.v = ray.v;
|
|
|
|
- hit.t = ray.tfar;
|
|
|
|
|
|
+ hit.id = ray.hit.primID;
|
|
|
|
+ hit.gid = ray.hit.geomID;
|
|
|
|
+ hit.u = ray.hit.u;
|
|
|
|
+ hit.v = ray.hit.v;
|
|
|
|
+ hit.t = ray.ray.tfar;
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -564,21 +593,23 @@ igl::embree::EmbreeIntersector
|
|
|
|
|
|
inline void
|
|
inline void
|
|
igl::embree::EmbreeIntersector
|
|
igl::embree::EmbreeIntersector
|
|
-::createRay(RTCRay& ray, const Eigen::RowVector3f& origin, const Eigen::RowVector3f& direction, float tnear, float tfar, int mask) const
|
|
|
|
|
|
+::createRay(RTCRayHit& ray, const Eigen::RowVector3f& origin, const Eigen::RowVector3f& direction, float tnear, float tfar, int mask) const
|
|
{
|
|
{
|
|
- ray.org[0] = origin[0];
|
|
|
|
- ray.org[1] = origin[1];
|
|
|
|
- ray.org[2] = origin[2];
|
|
|
|
- ray.dir[0] = direction[0];
|
|
|
|
- ray.dir[1] = direction[1];
|
|
|
|
- ray.dir[2] = direction[2];
|
|
|
|
- ray.tnear = tnear;
|
|
|
|
- ray.tfar = tfar;
|
|
|
|
- ray.geomID = RTC_INVALID_GEOMETRY_ID;
|
|
|
|
- ray.primID = RTC_INVALID_GEOMETRY_ID;
|
|
|
|
- ray.instID = RTC_INVALID_GEOMETRY_ID;
|
|
|
|
- ray.mask = mask;
|
|
|
|
- ray.time = 0.0f;
|
|
|
|
|
|
+ ray.ray.org_x = origin[0];
|
|
|
|
+ ray.ray.org_y = origin[1];
|
|
|
|
+ ray.ray.org_z = origin[2];
|
|
|
|
+ ray.ray.dir_x = direction[0];
|
|
|
|
+ ray.ray.dir_y = direction[1];
|
|
|
|
+ ray.ray.dir_z = direction[2];
|
|
|
|
+ ray.ray.tnear = tnear;
|
|
|
|
+ ray.ray.tfar = tfar;
|
|
|
|
+ ray.ray.id = RTC_INVALID_GEOMETRY_ID;
|
|
|
|
+ ray.ray.mask = mask;
|
|
|
|
+ ray.ray.time = 0.0f;
|
|
|
|
+
|
|
|
|
+ ray.hit.geomID = RTC_INVALID_GEOMETRY_ID;
|
|
|
|
+ ray.hit.instID[0] = RTC_INVALID_GEOMETRY_ID;
|
|
|
|
+ ray.hit.primID = RTC_INVALID_GEOMETRY_ID;
|
|
}
|
|
}
|
|
|
|
|
|
#endif //EMBREE_INTERSECTOR_H
|
|
#endif //EMBREE_INTERSECTOR_H
|