Prusa Slicer 2.6.0
Loading...
Searching...
No Matches
igl::embree Namespace Reference

Classes

class  EmbreeIntersector
 

Functions

template<typename DerivedP , typename DerivedN , typename DerivedS >
IGL_INLINE void ambient_occlusion (const EmbreeIntersector &ei, const Eigen::PlainObjectBase< DerivedP > &P, const Eigen::PlainObjectBase< DerivedN > &N, const int num_samples, Eigen::PlainObjectBase< DerivedS > &S)
 
template<typename DerivedV , typename DerivedF , typename DerivedP , typename DerivedN , typename DerivedS >
IGL_INLINE void ambient_occlusion (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedP > &P, const Eigen::PlainObjectBase< DerivedN > &N, const int num_samples, Eigen::PlainObjectBase< DerivedS > &S)
 
IGL_INLINE bool bone_heat (const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, const Eigen::MatrixXd &C, const Eigen::VectorXi &P, const Eigen::MatrixXi &BE, const Eigen::MatrixXi &CE, Eigen::MatrixXd &W)
 
template<typename DerivedV , typename DerivedF , typename DerivedSD , typename Derivedflag >
IGL_INLINE void bone_visible (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedSD > &s, const Eigen::PlainObjectBase< DerivedSD > &d, Eigen::PlainObjectBase< Derivedflag > &flag)
 
template<typename DerivedV , typename DerivedF , typename DerivedSD , typename Derivedflag >
IGL_INLINE void bone_visible (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const EmbreeIntersector &ei, const Eigen::PlainObjectBase< DerivedSD > &s, const Eigen::PlainObjectBase< DerivedSD > &d, Eigen::PlainObjectBase< Derivedflag > &flag)
 
template<typename ScalarMatrix , typename IndexMatrix >
IGL_INLINE ScalarMatrix line_mesh_intersection (const ScalarMatrix &V_source, const ScalarMatrix &N_source, const ScalarMatrix &V_target, const IndexMatrix &F_target)
 
template<typename DerivedV , typename DerivedF , typename DerivedI , typename DerivedC >
IGL_INLINE void reorient_facets_raycast (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, int rays_total, int rays_minimum, bool facet_wise, bool use_parity, bool is_verbose, Eigen::PlainObjectBase< DerivedI > &I, Eigen::PlainObjectBase< DerivedC > &C)
 
template<typename DerivedV , typename DerivedF , typename DerivedFF , typename DerivedI >
IGL_INLINE void reorient_facets_raycast (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedFF > &FF, Eigen::PlainObjectBase< DerivedI > &I)
 
template<typename DerivedP , typename DerivedN , typename DerivedS >
IGL_INLINE void shape_diameter_function (const EmbreeIntersector &ei, const Eigen::PlainObjectBase< DerivedP > &P, const Eigen::PlainObjectBase< DerivedN > &N, const int num_samples, Eigen::PlainObjectBase< DerivedS > &S)
 
template<typename DerivedV , typename DerivedF , typename DerivedP , typename DerivedN , typename DerivedS >
IGL_INLINE void shape_diameter_function (const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedP > &P, const Eigen::PlainObjectBase< DerivedN > &N, const int num_samples, Eigen::PlainObjectBase< DerivedS > &S)
 
template<typename Derivedobj >
IGL_INLINE int unproject_in_mesh (const Eigen::Vector2f &pos, const Eigen::Matrix4f &model, const Eigen::Matrix4f &proj, const Eigen::Vector4f &viewport, const EmbreeIntersector &ei, Eigen::PlainObjectBase< Derivedobj > &obj, std::vector< igl::Hit > &hits)
 
template<typename Derivedobj >
IGL_INLINE int unproject_in_mesh (const Eigen::Vector2f &pos, const Eigen::Matrix4f &model, const Eigen::Matrix4f &proj, const Eigen::Vector4f &viewport, const EmbreeIntersector &ei, Eigen::PlainObjectBase< Derivedobj > &obj)
 
IGL_INLINE bool unproject_onto_mesh (const Eigen::Vector2f &pos, const Eigen::MatrixXi &F, const Eigen::Matrix4f &model, const Eigen::Matrix4f &proj, const Eigen::Vector4f &viewport, const EmbreeIntersector &ei, int &fid, Eigen::Vector3f &bc)
 
IGL_INLINE bool unproject_onto_mesh (const Eigen::Vector2f &pos, const Eigen::MatrixXi &F, const Eigen::Matrix4f &model, const Eigen::Matrix4f &proj, const Eigen::Vector4f &viewport, const EmbreeIntersector &ei, int &fid, int &vid)
 

Variables

static bool EmbreeIntersector_inited = false
 

Function Documentation

◆ ambient_occlusion() [1/2]

template<typename DerivedV , typename DerivedF , typename DerivedP , typename DerivedN , typename DerivedS >
IGL_INLINE void igl::embree::ambient_occlusion ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedP > &  P,
const Eigen::PlainObjectBase< DerivedN > &  N,
const int  num_samples,
Eigen::PlainObjectBase< DerivedS > &  S 
)
48{
49 using namespace Eigen;
51 ei.init(V.template cast<float>(),F.template cast<int>());
52 ambient_occlusion(ei,P,N,num_samples,S);
53}
Definition EmbreeIntersector.h:34
void init(const PointMatrixType &V, const FaceMatrixType &F, bool isStatic=false)
Definition EmbreeIntersector.h:257
Definition LDLT.h:16
IGL_INLINE void ambient_occlusion(const std::function< bool(const Eigen::Vector3f &, const Eigen::Vector3f &) > &shoot_ray, const Eigen::PlainObjectBase< DerivedP > &P, const Eigen::PlainObjectBase< DerivedN > &N, const int num_samples, Eigen::PlainObjectBase< DerivedS > &S)
Definition ambient_occlusion.cpp:22

References igl::ambient_occlusion(), and igl::embree::EmbreeIntersector::init().

+ Here is the call graph for this function:

◆ ambient_occlusion() [2/2]

template<typename DerivedP , typename DerivedN , typename DerivedS >
IGL_INLINE void igl::embree::ambient_occlusion ( const EmbreeIntersector ei,
const Eigen::PlainObjectBase< DerivedP > &  P,
const Eigen::PlainObjectBase< DerivedN > &  N,
const int  num_samples,
Eigen::PlainObjectBase< DerivedS > &  S 
)
23{
24 const auto & shoot_ray = [&ei](
25 const Eigen::Vector3f& s,
26 const Eigen::Vector3f& dir)->bool
27 {
28 igl::Hit hit;
29 const float tnear = 1e-4f;
30 return ei.intersectRay(s,dir,hit,tnear);
31 };
32 return igl::ambient_occlusion(shoot_ray,P,N,num_samples,S);
33}
bool intersectRay(const Eigen::RowVector3f &origin, const Eigen::RowVector3f &direction, Hit &hit, float tnear=0, float tfar=std::numeric_limits< float >::infinity(), int mask=0xFFFFFFFF) const
Definition EmbreeIntersector.h:362
Definition Hit.h:18

References igl::ambient_occlusion(), and igl::embree::EmbreeIntersector::intersectRay().

+ Here is the call graph for this function:

◆ bone_heat()

bool igl::embree::bone_heat ( const Eigen::MatrixXd &  V,
const Eigen::MatrixXi &  F,
const Eigen::MatrixXd &  C,
const Eigen::VectorXi &  P,
const Eigen::MatrixXi &  BE,
const Eigen::MatrixXi &  CE,
Eigen::MatrixXd &  W 
)
25{
26 using namespace std;
27 using namespace Eigen;
28 assert(CE.rows() == 0 && "Cage edges not supported.");
29 assert(C.cols() == V.cols() && "V and C should have same #cols");
30 assert(BE.cols() == 2 && "BE should have #cols=2");
31 assert(F.cols() == 3 && "F should contain triangles.");
32 assert(V.cols() == 3 && "V should contain 3D positions.");
33
34 const int n = V.rows();
35 const int np = P.rows();
36 const int nb = BE.rows();
37 const int m = np + nb;
38
39 // "double sided lighting"
40 MatrixXi FF;
41 FF.resize(F.rows()*2,F.cols());
42 FF << F, F.rowwise().reverse();
43 // Initialize intersector
45 ei.init(V.cast<float>(),F.cast<int>());
46
47 typedef Matrix<bool,Dynamic,1> VectorXb;
48 typedef Matrix<bool,Dynamic,Dynamic> MatrixXb;
49 MatrixXb vis_mask(n,m);
50 // Distances
51 MatrixXd D(n,m);
52 // loop over points
53 for(int j = 0;j<np;j++)
54 {
55 const Vector3d p = C.row(P(j));
56 D.col(j) = (V.rowwise()-p.transpose()).rowwise().norm();
57 VectorXb vj;
58 bone_visible(V,F,ei,p,p,vj);
59 vis_mask.col(j) = vj;
60 }
61
62 // loop over bones
63 for(int j = 0;j<nb;j++)
64 {
65 const Vector3d s = C.row(BE(j,0));
66 const Vector3d d = C.row(BE(j,1));
67 VectorXd t,sqrD;
68 project_to_line_segment(V,s,d,t,sqrD);
69 D.col(np+j) = sqrD.array().sqrt();
70 VectorXb vj;
71 bone_visible(V,F,ei,s,d,vj);
72 vis_mask.col(np+j) = vj;
73 }
74
75 if(CE.rows() > 0)
76 {
77 cerr<<"Error: Cage edges are not supported. Ignored."<<endl;
78 }
79
80 MatrixXd PP = MatrixXd::Zero(n,m);
81 VectorXd min_D;
82 VectorXd Hdiag = VectorXd::Zero(n);
83 VectorXi J;
84 mat_min(D,2,min_D,J);
85 for(int i = 0;i<n;i++)
86 {
87 PP(i,J(i)) = 1;
88 if(vis_mask(i,J(i)))
89 {
90 double hii = pow(min_D(i),-2.);
91 Hdiag(i) = (hii>1e10?1e10:hii);
92 }
93 }
95 cotmatrix(V,F,L);
96 massmatrix(V,F,MASSMATRIX_TYPE_DEFAULT,M);
97 const auto & H = Hdiag.asDiagonal();
98 Q = (-L+M*H);
99 SimplicialLLT <SparseMatrix<double > > llt;
100 llt.compute(Q);
101 switch(llt.info())
102 {
103 case Eigen::Success:
104 break;
106 cerr<<"Error: Numerical issue."<<endl;
107 return false;
108 default:
109 cerr<<"Error: Other."<<endl;
110 return false;
111 }
112
113 const auto & rhs = M*H*PP;
114 W = llt.solve(rhs);
115 return true;
116}
The matrix class, also used for vectors and row-vectors.
Definition Matrix.h:180
ComputationInfo info() const
Reports whether previous computation was successful.
Definition SimplicialCholesky.h:107
SimplicialLLT & compute(const MatrixType &matrix)
Definition SimplicialCholesky.h:364
A versatible sparse matrix representation.
Definition SparseMatrix.h:98
const Solve< Derived, Rhs > solve(const MatrixBase< Rhs > &b) const
Definition SparseSolverBase.h:88
@ NumericalIssue
Definition Constants.h:434
@ Success
Definition Constants.h:432
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half pow(const half &a, const half &b)
Definition Half.h:477
IGL_INLINE void bone_visible(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, const Eigen::PlainObjectBase< DerivedSD > &s, const Eigen::PlainObjectBase< DerivedSD > &d, Eigen::PlainObjectBase< Derivedflag > &flag)
Definition bone_visible.cpp:20
IGL_INLINE void cotmatrix(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, Eigen::SparseMatrix< Scalar > &L)
Definition cotmatrix.cpp:19
IGL_INLINE void mat_min(const Eigen::DenseBase< DerivedX > &X, const int dim, Eigen::PlainObjectBase< DerivedY > &Y, Eigen::PlainObjectBase< DerivedI > &I)
Definition mat_min.cpp:11
IGL_INLINE void project_to_line_segment(const Eigen::MatrixBase< DerivedP > &P, const Eigen::MatrixBase< DerivedS > &S, const Eigen::MatrixBase< DerivedD > &D, Eigen::PlainObjectBase< Derivedt > &t, Eigen::PlainObjectBase< DerivedsqrD > &sqrD)
Definition project_to_line_segment.cpp:18
IGL_INLINE void massmatrix(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const MassMatrixType type, Eigen::SparseMatrix< Scalar > &M)
Definition massmatrix.cpp:17
STL namespace.
#define L(s)
Definition I18N.hpp:18

References bone_visible(), Eigen::SimplicialLLT< _MatrixType, _UpLo, _Ordering >::compute(), igl::cotmatrix(), Eigen::SimplicialCholeskyBase< Derived >::info(), igl::embree::EmbreeIntersector::init(), L, igl::massmatrix(), igl::MASSMATRIX_TYPE_DEFAULT, igl::mat_min(), Eigen::NumericalIssue, igl::project_to_line_segment(), Eigen::SparseSolverBase< Derived >::solve(), and Eigen::Success.

+ Here is the call graph for this function:

◆ bone_visible() [1/2]

template<typename DerivedV , typename DerivedF , typename DerivedSD , typename Derivedflag >
IGL_INLINE void igl::embree::bone_visible ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedSD > &  s,
const Eigen::PlainObjectBase< DerivedSD > &  d,
Eigen::PlainObjectBase< Derivedflag > &  flag 
)
26{
27 // "double sided lighting"
29 FF.resize(F.rows()*2,F.cols());
30 FF << F, F.rowwise().reverse();
31 // Initialize intersector
33 ei.init(V.template cast<float>(),FF.template cast<int>());
34 return bone_visible(V,F,ei,s,d,flag);
35}
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void resize(Index rows, Index cols)
Definition PlainObjectBase.h:279

References bone_visible(), igl::embree::EmbreeIntersector::init(), and Eigen::PlainObjectBase< Derived >::resize().

Referenced by bone_heat(), and bone_visible().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ bone_visible() [2/2]

template<typename DerivedV , typename DerivedF , typename DerivedSD , typename Derivedflag >
IGL_INLINE void igl::embree::bone_visible ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const EmbreeIntersector ei,
const Eigen::PlainObjectBase< DerivedSD > &  s,
const Eigen::PlainObjectBase< DerivedSD > &  d,
Eigen::PlainObjectBase< Derivedflag > &  flag 
)
49{
50 using namespace std;
51 using namespace Eigen;
52 flag.resize(V.rows());
53 const double sd_norm = (s-d).norm();
54 // Embree seems to be parallel when constructing but not when tracing rays
55#pragma omp parallel for
56 // loop over mesh vertices
57 for(int v = 0;v<V.rows();v++)
58 {
59 const Vector3d Vv = V.row(v);
60 // Project vertex v onto line segment sd
61 //embree.intersectSegment
62 double t,sqrd;
63 Vector3d projv;
64 // degenerate bone, just snap to s
65 if(sd_norm < DOUBLE_EPS)
66 {
67 t = 0;
68 sqrd = (Vv-s).array().pow(2).sum();
69 projv = s;
70 }else
71 {
72 // project onto (infinite) line
74 Vv(0),Vv(1),Vv(2),s(0),s(1),s(2),d(0),d(1),d(2),
75 projv(0),projv(1),projv(2),t,sqrd);
76 // handle projections past endpoints
77 if(t<0)
78 {
79 t = 0;
80 sqrd = (Vv-s).array().pow(2).sum();
81 projv = s;
82 } else if(t>1)
83 {
84 t = 1;
85 sqrd = (Vv-d).array().pow(2).sum();
86 projv = d;
87 }
88 }
89 igl::Hit hit;
90 // perhaps 1.0 should be 1.0-epsilon, or actually since we checking the
91 // incident face, perhaps 1.0 should be 1.0+eps
92 const Vector3d dir = (Vv-projv)*1.0;
93 if(ei.intersectSegment(
94 projv.template cast<float>(),
95 dir.template cast<float>(),
96 hit))
97 {
98 // mod for double sided lighting
99 const int fi = hit.id % F.rows();
100
101 //if(v == 1228-1)
102 //{
103 // Vector3d bc,P;
104 // bc << 1 - hit.u - hit.v, hit.u, hit.v; // barycentric
105 // P = V.row(F(fi,0))*bc(0) +
106 // V.row(F(fi,1))*bc(1) +
107 // V.row(F(fi,2))*bc(2);
108 // cout<<(fi+1)<<endl;
109 // cout<<bc.transpose()<<endl;
110 // cout<<P.transpose()<<endl;
111 // cout<<hit.t<<endl;
112 // cout<<(projv + dir*hit.t).transpose()<<endl;
113 // cout<<Vv.transpose()<<endl;
114 //}
115
116 // Assume hit is valid, so not visible
117 flag(v) = false;
118 // loop around corners of triangle
119 for(int c = 0;c<F.cols();c++)
120 {
121 if(F(fi,c) == v)
122 {
123 // hit self, so no hits before, so vertex v is visible
124 flag(v) = true;
125 break;
126 }
127 }
128 // Hit is actually past v
129 if(!flag(v) && (hit.t*hit.t*dir.squaredNorm())>sqrd)
130 {
131 flag(v) = true;
132 }
133 }else
134 {
135 // no hit so vectex v is visible
136 flag(v) = true;
137 }
138 }
139}
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index rows() const
Definition PlainObjectBase.h:151
bool intersectSegment(const Eigen::RowVector3f &a, const Eigen::RowVector3f &ab, Hit &hit, int mask=0xFFFFFFFF) const
Definition EmbreeIntersector.h:545
@ F
Definition libslic3r.h:102
float t
Definition Hit.h:22
IGL_INLINE void project_to_line(const Eigen::MatrixBase< DerivedP > &P, const Eigen::MatrixBase< DerivedS > &S, const Eigen::MatrixBase< DerivedD > &D, Eigen::PlainObjectBase< Derivedt > &t, Eigen::PlainObjectBase< DerivedsqrD > &sqrD)
Definition project_to_line.cpp:18
int id
Definition Hit.h:19

References igl::DOUBLE_EPS, igl::Hit::id, igl::embree::EmbreeIntersector::intersectSegment(), igl::project_to_line(), Eigen::PlainObjectBase< Derived >::resize(), Eigen::PlainObjectBase< Derived >::rows(), and igl::Hit::t.

+ Here is the call graph for this function:

◆ line_mesh_intersection()

template<typename ScalarMatrix , typename IndexMatrix >
IGL_INLINE ScalarMatrix igl::embree::line_mesh_intersection ( const ScalarMatrix &  V_source,
const ScalarMatrix &  N_source,
const ScalarMatrix &  V_target,
const IndexMatrix &  F_target 
)
26{
27
28 double tol = 0.00001;
29
30 Eigen::MatrixXd ray_pos = V_source;
31 Eigen::MatrixXd ray_dir = N_source;
32
33 // Allocate matrix for the result
34 ScalarMatrix R;
35 R.resize(V_source.rows(), 3);
36
37 // Initialize embree
38 EmbreeIntersector embree;
39 embree.init(V_target.template cast<float>(),F_target.template cast<int>());
40
41 // Shoot rays from the source to the target
42 for (unsigned i=0; i<ray_pos.rows(); ++i)
43 {
44 igl::Hit A,B;
45 // Shoot ray A
46 Eigen::RowVector3d A_pos = ray_pos.row(i) + tol * ray_dir.row(i);
47 Eigen::RowVector3d A_dir = -ray_dir.row(i);
48
49 bool A_hit = embree.intersectBeam(A_pos.cast<float>(), A_dir.cast<float>(),A);
50
51 Eigen::RowVector3d B_pos = ray_pos.row(i) - tol * ray_dir.row(i);
52 Eigen::RowVector3d B_dir = ray_dir.row(i);
53
54 bool B_hit = embree.intersectBeam(B_pos.cast<float>(), B_dir.cast<float>(),B);
55
56
57 int choice = -1;
58
59 if (A_hit && ! B_hit)
60 choice = 0;
61 else if (!A_hit && B_hit)
62 choice = 1;
63 else if (A_hit && B_hit)
64 choice = A.t > B.t;
65
66 Eigen::RowVector3d temp;
67
68 if (choice == -1)
69 temp << -1, 0, 0;
70 else if (choice == 0)
71 temp << A.id, A.u, A.v;
72 else if (choice == 1)
73 temp << B.id, B.u, B.v;
74
75 R.row(i) = temp;
76
77 }
78
79 return R;
80
81}
bool intersectBeam(const Eigen::RowVector3f &origin, const Eigen::RowVector3f &direction, Hit &hit, float tnear=0, float tfar=std::numeric_limits< float >::infinity(), int mask=0xFFFFFFFF, int geoId=-1, bool closestHit=true, unsigned int samples=4) const
Definition EmbreeIntersector.h:393
float u
Definition Hit.h:21
float v
Definition Hit.h:21

References igl::Hit::id, igl::embree::EmbreeIntersector::init(), igl::embree::EmbreeIntersector::intersectBeam(), igl::Hit::t, igl::Hit::u, and igl::Hit::v.

+ Here is the call graph for this function:

◆ reorient_facets_raycast() [1/2]

template<typename DerivedV , typename DerivedF , typename DerivedFF , typename DerivedI >
IGL_INLINE void igl::embree::reorient_facets_raycast ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
Eigen::PlainObjectBase< DerivedFF > &  FF,
Eigen::PlainObjectBase< DerivedI > &  I 
)
231{
232 const int rays_total = F.rows()*100;
233 const int rays_minimum = 10;
234 const bool facet_wise = false;
235 const bool use_parity = false;
236 const bool is_verbose = false;
237 Eigen::VectorXi C;
239 V,F,rays_total,rays_minimum,facet_wise,use_parity,is_verbose,I,C);
240 // Conservative in case FF = F
241 FF.conservativeResize(F.rows(),F.cols());
242 for(int i = 0;i<I.rows();i++)
243 {
244 if(I(i))
245 {
246 FF.row(i) = (F.row(i).reverse()).eval();
247 }else
248 {
249 FF.row(i) = F.row(i);
250 }
251 }
252}
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void conservativeResize(Index rows, Index cols)
Definition PlainObjectBase.h:390
IGL_INLINE void reorient_facets_raycast(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, int rays_total, int rays_minimum, bool facet_wise, bool use_parity, bool is_verbose, Eigen::PlainObjectBase< DerivedI > &I, Eigen::PlainObjectBase< DerivedC > &C)
Definition reorient_facets_raycast.cpp:24

References Eigen::PlainObjectBase< Derived >::conservativeResize(), reorient_facets_raycast(), and Eigen::PlainObjectBase< Derived >::rows().

+ Here is the call graph for this function:

◆ reorient_facets_raycast() [2/2]

template<typename DerivedV , typename DerivedF , typename DerivedI , typename DerivedC >
IGL_INLINE void igl::embree::reorient_facets_raycast ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
int  rays_total,
int  rays_minimum,
bool  facet_wise,
bool  use_parity,
bool  is_verbose,
Eigen::PlainObjectBase< DerivedI > &  I,
Eigen::PlainObjectBase< DerivedC > &  C 
)
34{
35 using namespace Eigen;
36 using namespace std;
37 assert(F.cols() == 3);
38 assert(V.cols() == 3);
39
40 // number of faces
41 const int m = F.rows();
42
43 MatrixXi FF = F;
44 if (facet_wise) {
45 C.resize(m);
46 for (int i = 0; i < m; ++i) C(i) = i;
47
48 } else {
49 if (is_verbose) cout << "extracting patches... ";
50 bfs_orient(F,FF,C);
51 }
52 if (is_verbose) cout << (C.maxCoeff() + 1) << " components. ";
53
54 // number of patches
55 const int num_cc = C.maxCoeff()+1;
56
57 // Init Embree
58 EmbreeIntersector ei;
59 ei.init(V.template cast<float>(),FF);
60
61 // face normal
62 MatrixXd N;
63 per_face_normals(V,FF,N);
64
65 // face area
67 doublearea(V,FF,A);
68 double area_total = A.sum();
69
70 // determine number of rays per component according to its area
71 VectorXd area_per_component;
72 area_per_component.setZero(num_cc);
73 for (int f = 0; f < m; ++f)
74 {
75 area_per_component(C(f)) += A(f);
76 }
77 VectorXi num_rays_per_component(num_cc);
78 for (int c = 0; c < num_cc; ++c)
79 {
80 num_rays_per_component(c) = max<int>(static_cast<int>(rays_total * area_per_component(c) / area_total), rays_minimum);
81 }
82 rays_total = num_rays_per_component.sum();
83
84 // generate all the rays
85 if (is_verbose) cout << "generating rays... ";
86 uniform_real_distribution<float> rdist;
87 mt19937 prng;
88 prng.seed(time(nullptr));
89 vector<int > ray_face;
90 vector<Vector3f> ray_ori;
91 vector<Vector3f> ray_dir;
92 ray_face.reserve(rays_total);
93 ray_ori .reserve(rays_total);
94 ray_dir .reserve(rays_total);
95 for (int c = 0; c < num_cc; ++c)
96 {
97 if (area_per_component[c] == 0)
98 {
99 continue;
100 }
101 vector<int> CF; // set of faces per component
102 vector<double> CF_area;
103 for (int f = 0; f < m; ++f)
104 {
105 if (C(f)==c)
106 {
107 CF.push_back(f);
108 CF_area.push_back(A(f));
109 }
110 }
111 // discrete distribution for random selection of faces with probability proportional to their areas
112 discrete_distribution<int> ddist(CF.size(), 0, CF.size(), [&](double i){ return CF_area[static_cast<int>(i)]; }); // simple ctor of (Iter, Iter) not provided by the stupid VC11/12
113 for (int i = 0; i < num_rays_per_component[c]; ++i)
114 {
115 int f = CF[ddist(prng)]; // select face with probability proportional to face area
116 float s = rdist(prng); // random barycentric coordinate (reference: Generating Random Points in Triangles [Turk, Graphics Gems I 1990])
117 float t = rdist(prng);
118 float sqrt_t = sqrtf(t);
119 float a = 1 - sqrt_t;
120 float b = (1 - s) * sqrt_t;
121 float c = s * sqrt_t;
122 Vector3f p = a * V.row(FF(f,0)).template cast<float>().eval() // be careful with the index!!!
123 + b * V.row(FF(f,1)).template cast<float>().eval()
124 + c * V.row(FF(f,2)).template cast<float>().eval();
125 Vector3f n = N.row(f).cast<float>();
126 if (n.isZero()) continue;
127 // random direction in hemisphere around n (avoid too grazing angle)
128 Vector3f d;
129 while (true) {
130 d = random_dir().cast<float>();
131 float ndotd = n.dot(d);
132 if (fabsf(ndotd) < 0.1f)
133 {
134 continue;
135 }
136 if (ndotd < 0)
137 {
138 d *= -1.0f;
139 }
140 break;
141 }
142 ray_face.push_back(f);
143 ray_ori .push_back(p);
144 ray_dir .push_back(d);
145
146 if (is_verbose && ray_face.size() % (rays_total / 10) == 0) cout << ".";
147 }
148 }
149 if (is_verbose) cout << ray_face.size() << " rays. ";
150
151 // per component voting: first=front, second=back
152 vector<pair<float, float>> C_vote_distance(num_cc, make_pair(0, 0)); // sum of distance between ray origin and intersection
153 vector<pair<int , int >> C_vote_infinity(num_cc, make_pair(0, 0)); // number of rays reaching infinity
154 vector<pair<int , int >> C_vote_parity(num_cc, make_pair(0, 0)); // sum of parity count for each ray
155
156 if (is_verbose) cout << "shooting rays... ";
157#pragma omp parallel for
158 for (int i = 0; i < (int)ray_face.size(); ++i)
159 {
160 int f = ray_face[i];
161 Vector3f o = ray_ori [i];
162 Vector3f d = ray_dir [i];
163 int c = C(f);
164
165 // shoot ray toward front & back
166 vector<Hit> hits_front;
167 vector<Hit> hits_back;
168 int num_rays_front;
169 int num_rays_back;
170 ei.intersectRay(o, d, hits_front, num_rays_front);
171 ei.intersectRay(o, -d, hits_back , num_rays_back );
172 if (!hits_front.empty() && hits_front[0].id == f) hits_front.erase(hits_front.begin());
173 if (!hits_back .empty() && hits_back [0].id == f) hits_back .erase(hits_back .begin());
174
175 if (use_parity) {
176#pragma omp atomic
177 C_vote_parity[c].first += hits_front.size() % 2;
178#pragma omp atomic
179 C_vote_parity[c].second += hits_back .size() % 2;
180
181 } else {
182 if (hits_front.empty())
183 {
184#pragma omp atomic
185 C_vote_infinity[c].first++;
186 } else {
187#pragma omp atomic
188 C_vote_distance[c].first += hits_front[0].t;
189 }
190
191 if (hits_back.empty())
192 {
193#pragma omp atomic
194 C_vote_infinity[c].second++;
195 } else {
196#pragma omp atomic
197 C_vote_distance[c].second += hits_back[0].t;
198 }
199 }
200 }
201
202 I.resize(m);
203 for(int f = 0; f < m; ++f)
204 {
205 int c = C(f);
206 if (use_parity) {
207 I(f) = C_vote_parity[c].first > C_vote_parity[c].second ? 1 : 0; // Ideally, parity for the front/back side should be 1/0 (i.e., parity sum for all rays should be smaller on the front side)
208
209 } else {
210 I(f) = (C_vote_infinity[c].first == C_vote_infinity[c].second && C_vote_distance[c].first < C_vote_distance[c].second) ||
211 C_vote_infinity[c].first < C_vote_infinity[c].second
212 ? 1 : 0;
213 }
214 // To account for the effect of bfs_orient
215 if (F.row(f) != FF.row(f))
216 I(f) = 1 - I(f);
217 }
218 if (is_verbose) cout << "done!" << endl;
219}
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index cols() const
Definition PlainObjectBase.h:153
EIGEN_DEVICE_FUNC Derived & setZero(Index size)
Definition CwiseNullaryOp.h:515
bool empty(const BoundingBoxBase< PointType, PointsType > &bb)
Definition BoundingBox.hpp:229
IGL_INLINE Eigen::Vector3d random_dir()
Definition random_dir.cpp:12
IGL_INLINE void bfs_orient(const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedFF > &FF, Eigen::PlainObjectBase< DerivedC > &C)
Definition bfs_orient.cpp:14
S::iterator begin(S &sh, const PathTag &)
Definition geometry_traits.hpp:614

References igl::bfs_orient(), Eigen::PlainObjectBase< Derived >::cols(), igl::doublearea(), igl::embree::EmbreeIntersector::init(), igl::embree::EmbreeIntersector::intersectRay(), igl::per_face_normals(), igl::random_dir(), Eigen::PlainObjectBase< Derived >::resize(), and Eigen::PlainObjectBase< Derived >::setZero().

Referenced by reorient_facets_raycast().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ shape_diameter_function() [1/2]

template<typename DerivedV , typename DerivedF , typename DerivedP , typename DerivedN , typename DerivedS >
IGL_INLINE void igl::embree::shape_diameter_function ( const Eigen::PlainObjectBase< DerivedV > &  V,
const Eigen::PlainObjectBase< DerivedF > &  F,
const Eigen::PlainObjectBase< DerivedP > &  P,
const Eigen::PlainObjectBase< DerivedN > &  N,
const int  num_samples,
Eigen::PlainObjectBase< DerivedS > &  S 
)
54{
55 using namespace Eigen;
57 ei.init(V.template cast<float>(),F.template cast<int>());
58 shape_diameter_function(ei,P,N,num_samples,S);
59}
IGL_INLINE void shape_diameter_function(const EmbreeIntersector &ei, const Eigen::PlainObjectBase< DerivedP > &P, const Eigen::PlainObjectBase< DerivedN > &N, const int num_samples, Eigen::PlainObjectBase< DerivedS > &S)
Definition shape_diameter_function.cpp:17

References igl::embree::EmbreeIntersector::init(), and shape_diameter_function().

+ Here is the call graph for this function:

◆ shape_diameter_function() [2/2]

template<typename DerivedP , typename DerivedN , typename DerivedS >
IGL_INLINE void igl::embree::shape_diameter_function ( const EmbreeIntersector ei,
const Eigen::PlainObjectBase< DerivedP > &  P,
const Eigen::PlainObjectBase< DerivedN > &  N,
const int  num_samples,
Eigen::PlainObjectBase< DerivedS > &  S 
)
23{
24 const auto & shoot_ray = [&ei](
25 const Eigen::Vector3f& s,
26 const Eigen::Vector3f& dir)->double
27 {
28 igl::Hit hit;
29 const float tnear = 1e-4f;
30 if(ei.intersectRay(s,dir,hit,tnear))
31 {
32 return hit.t;
33 }else
34 {
35 return std::numeric_limits<double>::infinity();
36 }
37 };
38 return igl::shape_diameter_function(shoot_ray,P,N,num_samples,S);
39}
IGL_INLINE void shape_diameter_function(const std::function< double(const Eigen::Vector3f &, const Eigen::Vector3f &) > &shoot_ray, const Eigen::PlainObjectBase< DerivedP > &P, const Eigen::PlainObjectBase< DerivedN > &N, const int num_samples, Eigen::PlainObjectBase< DerivedS > &S)
Definition shape_diameter_function.cpp:25

References igl::embree::EmbreeIntersector::intersectRay(), igl::shape_diameter_function(), and igl::Hit::t.

Referenced by shape_diameter_function().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ unproject_in_mesh() [1/2]

template<typename Derivedobj >
IGL_INLINE int igl::embree::unproject_in_mesh ( const Eigen::Vector2f &  pos,
const Eigen::Matrix4f &  model,
const Eigen::Matrix4f &  proj,
const Eigen::Vector4f &  viewport,
const EmbreeIntersector ei,
Eigen::PlainObjectBase< Derivedobj > &  obj 
)
45{
46 std::vector<igl::Hit> hits;
47 return unproject_in_mesh(pos,model,proj,viewport,ei,obj,hits);
48}
IGL_INLINE int unproject_in_mesh(const Eigen::Vector2f &pos, const Eigen::Matrix4f &model, const Eigen::Matrix4f &proj, const Eigen::Vector4f &viewport, const EmbreeIntersector &ei, Eigen::PlainObjectBase< Derivedobj > &obj, std::vector< igl::Hit > &hits)
Definition unproject_in_mesh.cpp:15

References unproject_in_mesh().

+ Here is the call graph for this function:

◆ unproject_in_mesh() [2/2]

template<typename Derivedobj >
IGL_INLINE int igl::embree::unproject_in_mesh ( const Eigen::Vector2f &  pos,
const Eigen::Matrix4f &  model,
const Eigen::Matrix4f &  proj,
const Eigen::Vector4f &  viewport,
const EmbreeIntersector ei,
Eigen::PlainObjectBase< Derivedobj > &  obj,
std::vector< igl::Hit > &  hits 
)
23{
24 using namespace std;
25 using namespace Eigen;
26 const auto & shoot_ray = [&ei](
27 const Eigen::Vector3f& s,
28 const Eigen::Vector3f& dir,
29 std::vector<igl::Hit> & hits)
30 {
31 int num_rays_shot;
32 ei.intersectRay(s,dir,hits,num_rays_shot);
33 };
34 return igl::unproject_in_mesh(pos,model,proj,viewport,shoot_ray,obj,hits);
35}
IGL_INLINE int unproject_in_mesh(const Eigen::Vector2f &pos, const Eigen::Matrix4f &model, const Eigen::Matrix4f &proj, const Eigen::Vector4f &viewport, const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< Derivedobj > &obj, std::vector< igl::Hit > &hits)
Definition unproject_in_mesh.cpp:57

References igl::embree::EmbreeIntersector::intersectRay(), and igl::unproject_in_mesh().

Referenced by unproject_in_mesh().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ unproject_onto_mesh() [1/2]

IGL_INLINE bool igl::embree::unproject_onto_mesh ( const Eigen::Vector2f &  pos,
const Eigen::MatrixXi &  F,
const Eigen::Matrix4f &  model,
const Eigen::Matrix4f &  proj,
const Eigen::Vector4f &  viewport,
const EmbreeIntersector ei,
int &  fid,
Eigen::Vector3f &  bc 
)
22{
23 using namespace std;
24 using namespace Eigen;
25 const auto & shoot_ray = [&ei](
26 const Eigen::Vector3f& s,
27 const Eigen::Vector3f& dir,
28 igl::Hit & hit)->bool
29 {
30 return ei.intersectRay(s,dir,hit);
31 };
32 return igl::unproject_onto_mesh(pos,model,proj,viewport,shoot_ray,fid,bc);
33}
IGL_INLINE bool unproject_onto_mesh(const Eigen::Vector2f &pos, const Eigen::Matrix4f &model, const Eigen::Matrix4f &proj, const Eigen::Vector4f &viewport, const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, int &fid, Eigen::PlainObjectBase< Derivedbc > &bc)
Definition unproject_onto_mesh.cpp:15

References igl::embree::EmbreeIntersector::intersectRay(), and igl::unproject_onto_mesh().

Referenced by unproject_onto_mesh().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ unproject_onto_mesh() [2/2]

IGL_INLINE bool igl::embree::unproject_onto_mesh ( const Eigen::Vector2f &  pos,
const Eigen::MatrixXi &  F,
const Eigen::Matrix4f &  model,
const Eigen::Matrix4f &  proj,
const Eigen::Vector4f &  viewport,
const EmbreeIntersector ei,
int &  fid,
int &  vid 
)
44{
45 Eigen::Vector3f bc;
46 if(!igl::embree::unproject_onto_mesh(pos,F,model,proj,viewport,ei,fid,bc))
47 {
48 return false;
49 }
50 int i;
51 bc.maxCoeff(&i);
52 vid = F(fid,i);
53 return true;
54}
IGL_INLINE bool unproject_onto_mesh(const Eigen::Vector2f &pos, const Eigen::MatrixXi &F, const Eigen::Matrix4f &model, const Eigen::Matrix4f &proj, const Eigen::Vector4f &viewport, const EmbreeIntersector &ei, int &fid, Eigen::Vector3f &bc)
Definition unproject_onto_mesh.cpp:13

References unproject_onto_mesh().

+ Here is the call graph for this function:

Variable Documentation

◆ EmbreeIntersector_inited