|
@@ -1,10 +1,10 @@
|
|
|
// This file is part of libigl, a simple c++ geometry processing library.
|
|
|
-//
|
|
|
+//
|
|
|
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
|
|
|
// 2014 Christian Schüller <schuellchr@gmail.com>
|
|
|
-//
|
|
|
-// This Source Code Form is subject to the terms of the Mozilla Public License
|
|
|
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
|
|
+//
|
|
|
+// This Source Code Form is subject to the terms of the Mozilla Public License
|
|
|
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
|
|
// obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
// igl function interface for Embree2.2
|
|
|
//
|
|
@@ -12,22 +12,19 @@
|
|
|
// * Use igl:Hit instead of embree:Hit (where id0 -> id)
|
|
|
// * For Embree2.2
|
|
|
// * Uncomment #define __USE_RAY_MASK__ in platform.h to enable masking
|
|
|
-//
|
|
|
-// TODO: Check for NANs in the input
|
|
|
|
|
|
#ifndef IGL_EMBREE_INTERSECTOR_H
|
|
|
#define IGL_EMBREE_INTERSECTOR_H
|
|
|
|
|
|
+#include "Hit.h"
|
|
|
#include <Eigen/Geometry>
|
|
|
#include <Eigen/Core>
|
|
|
#include <Eigen/Geometry>
|
|
|
|
|
|
-#include <vector>
|
|
|
#include <embree2/rtcore.h>
|
|
|
#include <embree2/rtcore_ray.h>
|
|
|
#include <iostream>
|
|
|
-#include "Hit.h"
|
|
|
-#include <iostream>
|
|
|
+#include <vector>
|
|
|
|
|
|
namespace igl
|
|
|
{
|
|
@@ -44,7 +41,7 @@ namespace igl
|
|
|
public:
|
|
|
typedef Eigen::Matrix<float,Eigen::Dynamic,3> PointMatrixType;
|
|
|
typedef Eigen::Matrix<int,Eigen::Dynamic,3> FaceMatrixType;
|
|
|
- public:
|
|
|
+ public:
|
|
|
inline EmbreeIntersector();
|
|
|
private:
|
|
|
// Copying and assignment are not allowed.
|
|
@@ -52,7 +49,7 @@ namespace igl
|
|
|
inline EmbreeIntersector & operator=(const EmbreeIntersector &);
|
|
|
public:
|
|
|
virtual inline ~EmbreeIntersector();
|
|
|
-
|
|
|
+
|
|
|
// Initialize with a given mesh.
|
|
|
//
|
|
|
// Inputs:
|
|
@@ -81,9 +78,9 @@ namespace igl
|
|
|
// destruction: no need to call if you just want to init() once and
|
|
|
// destroy.
|
|
|
inline void deinit();
|
|
|
-
|
|
|
+
|
|
|
// Given a ray find the first hit
|
|
|
- //
|
|
|
+ //
|
|
|
// Inputs:
|
|
|
// origin 3d origin point of ray
|
|
|
// direction 3d (not necessarily normalized) direction vector of ray
|
|
@@ -94,7 +91,7 @@ namespace igl
|
|
|
// hit information about hit
|
|
|
// Returns true if and only if there was a hit
|
|
|
inline bool intersectRay(
|
|
|
- const Eigen::RowVector3f& origin,
|
|
|
+ const Eigen::RowVector3f& origin,
|
|
|
const Eigen::RowVector3f& direction,
|
|
|
Hit& hit,
|
|
|
float tnear = 0,
|
|
@@ -104,7 +101,7 @@ namespace igl
|
|
|
// Given a ray find the first hit
|
|
|
// This is a conservative hit test where multiple rays within a small radius
|
|
|
// will be tested and only the closesest hit is returned.
|
|
|
- //
|
|
|
+ //
|
|
|
// Inputs:
|
|
|
// origin 3d origin point of ray
|
|
|
// direction 3d (not necessarily normalized) direction vector of ray
|
|
@@ -127,7 +124,7 @@ namespace igl
|
|
|
bool closestHit = true) const;
|
|
|
|
|
|
// Given a ray find all hits in order
|
|
|
- //
|
|
|
+ //
|
|
|
// Inputs:
|
|
|
// origin 3d origin point of ray
|
|
|
// direction 3d (not necessarily normalized) direction vector of ray
|
|
@@ -148,7 +145,7 @@ namespace igl
|
|
|
int mask = 0xFFFFFFFF) const;
|
|
|
|
|
|
// Given a ray find the first hit
|
|
|
- //
|
|
|
+ //
|
|
|
// Inputs:
|
|
|
// a 3d first end point of segment
|
|
|
// ab 3d vector from a to other endpoint b
|
|
@@ -160,7 +157,7 @@ namespace igl
|
|
|
const Eigen::RowVector3f& ab,
|
|
|
Hit &hit,
|
|
|
int mask = 0xFFFFFFFF) const;
|
|
|
-
|
|
|
+
|
|
|
private:
|
|
|
|
|
|
struct Vertex {float x,y,z,a;};
|
|
@@ -264,10 +261,10 @@ inline void igl::EmbreeIntersector::init(
|
|
|
const std::vector<const FaceMatrixType*>& F,
|
|
|
const std::vector<int>& masks)
|
|
|
{
|
|
|
-
|
|
|
+
|
|
|
if(initialized)
|
|
|
deinit();
|
|
|
-
|
|
|
+
|
|
|
using namespace std;
|
|
|
global_init();
|
|
|
|
|
@@ -276,11 +273,11 @@ inline void igl::EmbreeIntersector::init(
|
|
|
std::cerr << "Embree: No geometry specified!";
|
|
|
return;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// create a scene
|
|
|
scene = rtcNewScene(RTC_SCENE_ROBUST | RTC_SCENE_HIGH_QUALITY,RTC_INTERSECT1);
|
|
|
|
|
|
- for(int g=0;g<V.size();g++)
|
|
|
+ for(int g=0;g<(int)V.size();g++)
|
|
|
{
|
|
|
// create triangle mesh geometry in that scene
|
|
|
geomID = rtcNewTriangleMesh(scene,RTC_GEOMETRY_STATIC,F[g]->rows(),V[g]->rows(),1);
|
|
@@ -309,7 +306,7 @@ inline void igl::EmbreeIntersector::init(
|
|
|
}
|
|
|
|
|
|
rtcCommit(scene);
|
|
|
-
|
|
|
+
|
|
|
if(rtcGetError() != RTC_NO_ERROR)
|
|
|
std::cerr << "Embree: An error occured while initializing the provided geometry!" << endl;
|
|
|
#ifdef IGL_VERBOSE
|
|
@@ -329,14 +326,21 @@ igl::EmbreeIntersector
|
|
|
|
|
|
void igl::EmbreeIntersector::deinit()
|
|
|
{
|
|
|
- rtcDeleteScene(scene);
|
|
|
+ if(scene)
|
|
|
+ {
|
|
|
+ rtcDeleteScene(scene);
|
|
|
|
|
|
- if(rtcGetError() != RTC_NO_ERROR)
|
|
|
- std::cerr << "Embree: An error occured while resetting!" << std::endl;
|
|
|
+ if(rtcGetError() != RTC_NO_ERROR)
|
|
|
+ {
|
|
|
+ std::cerr << "Embree: An error occured while resetting!" << std::endl;
|
|
|
+ }
|
|
|
#ifdef IGL_VERBOSE
|
|
|
- else
|
|
|
- std::cerr << "Embree: geometry removed." << std::endl;
|
|
|
+ else
|
|
|
+ {
|
|
|
+ std::cerr << "Embree: geometry removed." << std::endl;
|
|
|
+ }
|
|
|
#endif
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
inline bool igl::EmbreeIntersector::intersectRay(
|
|
@@ -348,16 +352,16 @@ inline bool igl::EmbreeIntersector::intersectRay(
|
|
|
int mask) const
|
|
|
{
|
|
|
RTCRay ray;
|
|
|
- createRay(ray, origin,direction,tnear,std::numeric_limits<float>::infinity(),mask);
|
|
|
-
|
|
|
+ createRay(ray, origin,direction,tnear,tfar,mask);
|
|
|
+
|
|
|
// shot ray
|
|
|
rtcIntersect(scene,ray);
|
|
|
#ifdef IGL_VERBOSE
|
|
|
if(rtcGetError() != RTC_NO_ERROR)
|
|
|
std::cerr << "Embree: An error occured while resetting!" << std::endl;
|
|
|
#endif
|
|
|
-
|
|
|
- if(ray.geomID != RTC_INVALID_GEOMETRY_ID)
|
|
|
+
|
|
|
+ if((unsigned)ray.geomID != RTC_INVALID_GEOMETRY_ID)
|
|
|
{
|
|
|
hit.id = ray.primID;
|
|
|
hit.gid = ray.geomID;
|
|
@@ -371,7 +375,7 @@ inline bool igl::EmbreeIntersector::intersectRay(
|
|
|
}
|
|
|
|
|
|
inline bool igl::EmbreeIntersector::intersectBeam(
|
|
|
- const Eigen::RowVector3f& origin,
|
|
|
+ const Eigen::RowVector3f& origin,
|
|
|
const Eigen::RowVector3f& direction,
|
|
|
Hit& hit,
|
|
|
float tnear,
|
|
@@ -388,21 +392,18 @@ inline bool igl::EmbreeIntersector::intersectBeam(
|
|
|
else
|
|
|
bestHit.t = 0;
|
|
|
|
|
|
- hasHit = (intersectRay(origin,direction,hit,tnear,tfar,mask) && (hit.gid == geoId || geoId == -1));
|
|
|
- if(hasHit)
|
|
|
+ if((hasHit = (intersectRay(origin,direction,hit,tnear,tfar,mask)) && (hit.gid == geoId || geoId == -1)))
|
|
|
bestHit = hit;
|
|
|
-
|
|
|
+
|
|
|
// sample points around actual ray (conservative hitcheck)
|
|
|
float eps= 1e-5;
|
|
|
int density = 4;
|
|
|
-
|
|
|
- Eigen::RowVector3f up; up.setRandom(1,3);
|
|
|
- while (fabs(direction.cross(up).norm()) < 1e-5)
|
|
|
- up.setRandom(1,3);
|
|
|
+
|
|
|
+ Eigen::RowVector3f up(0,1,0);
|
|
|
Eigen::RowVector3f offset = direction.cross(up).normalized();
|
|
|
|
|
|
Eigen::Matrix3f rot = Eigen::AngleAxis<float>(2*3.14159265358979/density,direction).toRotationMatrix();
|
|
|
-
|
|
|
+
|
|
|
for(int r=0;r<density;r++)
|
|
|
{
|
|
|
if(intersectRay(origin+offset*eps,direction,hit,tnear,tfar,mask) && ((closestHit && (hit.t < bestHit.t)) || (!closestHit && (hit.t > bestHit.t))) && (hit.gid == geoId || geoId == -1))
|
|
@@ -417,10 +418,10 @@ inline bool igl::EmbreeIntersector::intersectBeam(
|
|
|
return hasHit;
|
|
|
}
|
|
|
|
|
|
-inline bool
|
|
|
+inline bool
|
|
|
igl::EmbreeIntersector
|
|
|
::intersectRay(
|
|
|
- const Eigen::RowVector3f& origin,
|
|
|
+ const Eigen::RowVector3f& origin,
|
|
|
const Eigen::RowVector3f& direction,
|
|
|
std::vector<Hit > &hits,
|
|
|
int& num_rays,
|
|
@@ -451,7 +452,7 @@ igl::EmbreeIntersector
|
|
|
ray.instID = RTC_INVALID_GEOMETRY_ID;
|
|
|
num_rays++;
|
|
|
rtcIntersect(scene,ray);
|
|
|
- if(ray.geomID != RTC_INVALID_GEOMETRY_ID)
|
|
|
+ if((unsigned)ray.geomID != RTC_INVALID_GEOMETRY_ID)
|
|
|
{
|
|
|
// Hit self again, progressively advance
|
|
|
if(ray.primID == last_id0 || ray.tfar <= min_t)
|
|
@@ -489,7 +490,7 @@ igl::EmbreeIntersector
|
|
|
}
|
|
|
else
|
|
|
break; // no more hits
|
|
|
-
|
|
|
+
|
|
|
if(hits.size()>1000 && !large_hits_warned)
|
|
|
{
|
|
|
std::cout<<"Warning: Large number of hits..."<<endl;
|
|
@@ -498,10 +499,10 @@ igl::EmbreeIntersector
|
|
|
{
|
|
|
std::cout<<(hit->id+1)<<" ";
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
std::cout.precision(std::numeric_limits< double >::digits10);
|
|
|
std::cout<<"[ ";
|
|
|
-
|
|
|
+
|
|
|
for(vector<Hit>::iterator hit = hits.begin(); hit != hits.end(); hit++)
|
|
|
{
|
|
|
std::cout<<(hit->t)<<endl;;
|
|
@@ -517,16 +518,16 @@ igl::EmbreeIntersector
|
|
|
return hits.empty();
|
|
|
}
|
|
|
|
|
|
-inline bool
|
|
|
+inline bool
|
|
|
igl::EmbreeIntersector
|
|
|
::intersectSegment(const Eigen::RowVector3f& a, const Eigen::RowVector3f& ab, Hit &hit, int mask) const
|
|
|
{
|
|
|
RTCRay ray;
|
|
|
createRay(ray,a,ab,0,1.0,mask);
|
|
|
-
|
|
|
+
|
|
|
rtcIntersect(scene,ray);
|
|
|
|
|
|
- if(ray.geomID != RTC_INVALID_GEOMETRY_ID)
|
|
|
+ if((unsigned)ray.geomID != RTC_INVALID_GEOMETRY_ID)
|
|
|
{
|
|
|
hit.id = ray.primID;
|
|
|
hit.gid = ray.geomID;
|