Browse Source

embree templates

Former-commit-id: 1c63909cab3a74888aaa7175acb0f3a4427ed123
Alec Jacobson (jalec 12 years ago
parent
commit
6d8fce08d3

+ 42 - 11
include/igl/embree/EmbreeIntersector.cpp

@@ -7,7 +7,7 @@ template <
 typename PointMatrixType,
 typename FaceMatrixType,
 typename RowVector3>
-EmbreeIntersector < PointMatrixType, FaceMatrixType, RowVector3>
+igl::EmbreeIntersector < PointMatrixType, FaceMatrixType, RowVector3>
 ::EmbreeIntersector(const PointMatrixType & V, const FaceMatrixType & F)
 {
   static bool inited = false;
@@ -41,7 +41,7 @@ template <
 typename PointMatrixType,
 typename FaceMatrixType,
 typename RowVector3>
-EmbreeIntersector < PointMatrixType, FaceMatrixType, RowVector3>
+igl::EmbreeIntersector < PointMatrixType, FaceMatrixType, RowVector3>
 ::~EmbreeIntersector()
 {
 	embree::rtcFreeMemory();
@@ -52,12 +52,12 @@ typename PointMatrixType,
 typename FaceMatrixType,
 typename RowVector3>
 bool 
-EmbreeIntersector < PointMatrixType, FaceMatrixType, RowVector3>
+igl::EmbreeIntersector < PointMatrixType, FaceMatrixType, RowVector3>
 ::intersectRay(const RowVector3& origin, const RowVector3& direction, embree::Hit &hit) const
 {
-	embree::Ray ray(toVec3f(origin), toVec3f(direction), 1e-4f);
-	_intersector->intersect(ray, hit);
-	return hit ; 
+  embree::Ray ray(toVec3f(origin), toVec3f(direction), 1e-4f);
+  _intersector->intersect(ray, hit);
+  return hit ; 
 }
 
 template <
@@ -65,16 +65,47 @@ typename PointMatrixType,
 typename FaceMatrixType,
 typename RowVector3>
 bool 
-EmbreeIntersector < PointMatrixType, FaceMatrixType, RowVector3>
+igl::EmbreeIntersector < PointMatrixType, FaceMatrixType, RowVector3>
+::intersectRay(
+  const RowVector3& origin, 
+  const RowVector3& direction, 
+  std::vector<embree::Hit > &hits) const
+{
+  hits.clear();
+  embree::Hit hit;
+  embree::Vec3f o = toVec3f(origin);
+  embree::Vec3f d = toVec3f(direction);
+  while(true)
+  {
+    embree::Ray ray(o,d,embree::zero);
+    _intersector->intersect(ray, hit);
+    if(hit)
+    {
+      hits.push_back(hit);
+      o = o+hit.t*d;
+    }else
+    {
+      break;
+    }
+  }
+  return hits.empty();
+}
+
+template <
+typename PointMatrixType,
+typename FaceMatrixType,
+typename RowVector3>
+bool 
+igl::EmbreeIntersector < PointMatrixType, FaceMatrixType, RowVector3>
 ::intersectSegment(const RowVector3& a, const RowVector3& ab, embree::Hit &hit) const
 {
-	embree::Ray ray(toVec3f(a), toVec3f(ab), embree::zero, embree::one);
-	_intersector->intersect(ray, hit);
-	return hit ; 
+  embree::Ray ray(toVec3f(a), toVec3f(ab), embree::zero, embree::one);
+  _intersector->intersect(ray, hit);
+  return hit ; 
 }
 
 #ifndef IGL_HEADER_ONLY
 // Explicit template instanciation
 #include <Eigen/Core>
-template class EmbreeIntersector<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, 3, 1, 0, 3, 1> >;
+template class igl::EmbreeIntersector<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, 3, 1, 0, 3, 1> >;
 #endif

+ 62 - 18
include/igl/embree/EmbreeIntersector.h

@@ -1,5 +1,5 @@
-#ifndef EMBREE_INTERSECTOR_H
-#define EMBREE_INTERSECTOR_H
+#ifndef IGL_EMBREE_INTERSECTOR_H
+#define IGL_EMBREE_INTERSECTOR_H
 
 #undef interface
 #undef near
@@ -7,26 +7,70 @@
 
 #include "common/intersector.h"
 #include "common/accel.h"
+#include <vector>
 //#include "types.h"
 
-template <
-typename PointMatrixType,
-typename FaceMatrixType,
-typename RowVector3>
-class EmbreeIntersector
+namespace igl
 {
-public:
-  EmbreeIntersector(const PointMatrixType & V, const FaceMatrixType & F);
-  virtual ~EmbreeIntersector();
+  template <
+  typename PointMatrixType,
+  typename FaceMatrixType,
+  typename RowVector3>
+  class EmbreeIntersector
+  {
+  public:
+    // V  #V by 3 list of vertex positions
+    // F  #F by 3 list of Oriented triangles
+    //
+    // Note: this will only find front-facing hits. To consider all hits then
+    // pass [F;fliplr(F)]
+    EmbreeIntersector(const PointMatrixType & V, const FaceMatrixType & F);
+    virtual ~EmbreeIntersector();
   
-  bool intersectRay(const RowVector3& origin, const RowVector3& direction, embree::Hit &hit) const;
-  bool intersectSegment(const RowVector3& a, const RowVector3& ab, embree::Hit &hit) const;
+    // Given a ray find the first *front-facing* hit
+    // 
+    // Inputs:
+    //   origin  3d origin point of ray
+    //   direction  3d (not necessarily normalized) direction vector of ray
+    // Output:
+    //   hit  embree information about hit
+    // Returns true if and only if there was a hit
+    bool intersectRay(
+      const RowVector3& origin, 
+      const RowVector3& direction,
+      embree::Hit &hit) const;
+    // Given a ray find the all *front-facing* hits in order
+    // 
+    // Inputs:
+    //   origin  3d origin point of ray
+    //   direction  3d (not necessarily normalized) direction vector of ray
+    // Output:
+    //   hit  embree information about hit
+    // Returns true if and only if there was a hit
+    bool intersectRay(
+      const RowVector3& origin, 
+      const RowVector3& direction, 
+      std::vector<embree::Hit > &hits) const;
   
-private:
-  embree::BuildTriangle *triangles;
-  embree::BuildVertex *vertices;
-  embree::Ref<embree::Accel> _accel;
-  embree::Ref<embree::Intersector> _intersector;
-};
+    // Given a ray find the first *front-facing* hit
+    // 
+    // Inputs:
+    //   a  3d first end point of segment
+    //   ab  3d vector from a to other endpoint b
+    // Output:
+    //   hit  embree information about hit
+    // Returns true if and only if there was a hit
+    bool intersectSegment(const RowVector3& a, const RowVector3& ab, embree::Hit &hit) const;
+    
+  private:
+    embree::BuildTriangle *triangles;
+    embree::BuildVertex *vertices;
+    embree::Ref<embree::Accel> _accel;
+    embree::Ref<embree::Intersector> _intersector;
+  };
+}
+#ifdef IGL_HEADER_ONLY
+#  include "EmbreeIntersector.cpp"
+#endif
 
 #endif //EMBREE_INTERSECTOR_H

+ 10 - 3
include/igl/embree/bone_visible.cpp

@@ -20,9 +20,13 @@ void bone_visible(
   using namespace std;
   using namespace Eigen;
   flag.resize(V.rows());
+  // "double sided lighting"
+  Eigen::PlainObjectBase<DerivedF> FF;
+  FF.resize(F.rows()*2,F.cols());
+  FF << F, F.rowwise().reverse();
   // Initialize intersector
   const EmbreeIntersector<MatrixXd,MatrixXi,Vector3d> ei = 
-        EmbreeIntersector<MatrixXd,MatrixXi,Vector3d>(V,F);
+        EmbreeIntersector<MatrixXd,MatrixXi,Vector3d>(V,FF);
   const double sd_norm = (s-d).norm();
   // loop over mesh vertices
   // TODO: openmp?
@@ -64,9 +68,11 @@ void bone_visible(
     const Vector3d dir = (Vv-projv)*1.0;
     if(ei.intersectSegment(projv,dir, hit))
     {
+      // mod for double sided lighting
+      const int fi = hit.id0 % F.rows();
+
       //if(v == 1228-1)
       //{
-      //  int fi = hit.id0;
       //  Vector3d bc,P;
       //  bc << 1 - hit.u - hit.v, hit.u, hit.v; // barycentric
       //  P = V.row(F(fi,0))*bc(0) + 
@@ -75,10 +81,11 @@ void bone_visible(
       //  cout<<(fi+1)<<endl;
       //  cout<<bc.transpose()<<endl;
       //  cout<<P.transpose()<<endl;
+      //  cout<<hit.t<<endl;
+      //  cout<<(projv + dir*hit.t).transpose()<<endl;
       //  cout<<Vv.transpose()<<endl;
       //}
 
-      const int fi = hit.id0; // face id
       // Assume hit is valid, so not visible
       flag(v) = false;
       // loop around corners of triangle

+ 13 - 3
include/igl/embree/bone_visible.h

@@ -1,9 +1,13 @@
-#ifndef BONE_VISIBLE_H
-#define BONE_VISIBLE_H
+#ifndef IGL_BONE_VISIBLE_H
+#define IGL_BONE_VISIBLE_H
 #include <Eigen/Core>
 //
 // BONE_VISIBLE  test whether vertices of mesh are "visible" to a given bone,
-// where "visible" is defined as in [Baran & Popovic 07].
+// where "visible" is defined as in [Baran & Popovic 07]. Instead of checking
+// whether each point can see *any* of the bone, we just check if each point
+// can see its own projection onto the bone segment. In other words, we project
+// each vertex v onto the bone, projv. Then we check if there are any
+// intersections between the line segment (projv-->v) and the mesh.
 //
 // [flag] = bone_visible(V,F,s,d);
 //
@@ -15,6 +19,9 @@
 // Output:
 //    flag  #V by 1 list of bools (true) visible, (false) obstructed
 //
+// Note: This checks for hits along the segment which are facing in *any*
+// direction from the ray.
+//
 template <
   typename DerivedV, 
   typename DerivedF, 
@@ -26,4 +33,7 @@ void bone_visible(
   const Eigen::PlainObjectBase<DerivedSD> & s,
   const Eigen::PlainObjectBase<DerivedSD> & d,
   Eigen::PlainObjectBase<Derivedflag>  & flag);
+#ifdef IGL_HEADER_ONLY
+#  include "bone_visible.cpp"
+#endif
 #endif

+ 6 - 0
include/igl/matlab/mexStream.h

@@ -1,3 +1,5 @@
+#ifndef IGL_MEX_STREAM_H
+#define IGL_MEX_STREAM_H
 #include <iostream>
 namespace igl
 {
@@ -21,3 +23,7 @@ namespace igl
       virtual int overflow(int c = EOF);
   }; 
 }
+#ifdef IGL_HEADER_ONLY
+#  include "mexStream.cpp"
+#endif
+#endif

+ 1 - 1
matlab-to-eigen.html

@@ -196,7 +196,7 @@
 
       <tr class=d1>
         <td><pre><code>B = fliplr(A)<br>B = flipud(A)</code></pre></td>
-        <td><pre><code>B = A.rowwize().reverse().eval()<br>B =
+        <td><pre><code>B = A.rowwise().reverse().eval()<br>B =
 	A.colwise().reverse().eval()</code></pre></td>
         <td>The <code>.eval()</code> is not necessary if A != B</td>
       </tr>