Эх сурвалжийг харах

refactored embreeintersector with default constructor and init

Former-commit-id: 437cd9610f45c7194f5cf3737c8fd12124281b73
Alec Jacobson (jalec 11 жил өмнө
parent
commit
3bd87ec377

+ 0 - 3
examples/ambient-occlusion-mex/mexFunction.cpp

@@ -1,10 +1,7 @@
 #include "parse_rhs.h"
 
 #include <igl/matlab/mexStream.h>
-#include <igl/matlab/MatlabWorkspace.h>
-#include <igl/embree/EmbreeIntersector.h>
 #include <igl/embree/ambient_occlusion.h>
-#include <igl/matlab_format.h>
 
 #include <igl/read.h>
 #include <igl/per_vertex_normals.h>

+ 3 - 4
examples/ambient-occlusion/example.cpp

@@ -48,7 +48,7 @@ Eigen::MatrixXd V,N,C,mid;
 Eigen::MatrixXi F;
 // Bounding box diagonal length
 double bbd;
-igl::EmbreeIntersector<Eigen::MatrixXd::Scalar,Eigen::MatrixXi::Scalar> * ei;
+igl::EmbreeIntersector<Eigen::MatrixXd::Scalar,Eigen::MatrixXi::Scalar> ei;
 // Running ambient occlusion
 Eigen::VectorXd S;
 int tot_num_samples = 0;
@@ -154,7 +154,7 @@ void display()
     }
     VectorXd Si;
     const int num_samples = 20;
-    ambient_occlusion(*ei,V,N,num_samples,Si);
+    ambient_occlusion(ei,V,N,num_samples,Si);
     S *= (double)tot_num_samples;
     S += Si*(double)num_samples;
     tot_num_samples += num_samples;
@@ -373,7 +373,7 @@ int main(int argc, char * argv[])
   bbd = (V.colwise().maxCoeff() - V.colwise().minCoeff()).maxCoeff();
 
   // Init embree
-  ei = new EmbreeIntersector<MatrixXd::Scalar,MatrixXi::Scalar>(V,F);
+  ei.init(V,F);
 
   // Init glut
   glutInit(&argc,argv);
@@ -405,6 +405,5 @@ int main(int argc, char * argv[])
   glutMotionFunc(mouse_drag);
   glutPassiveMotionFunc((GLUTmousemotionfun)TwEventMouseMotionGLUT);
   glutMainLoop();
-  delete ei;
   return 0;
 }

+ 2 - 0
examples/embree/Makefile

@@ -9,6 +9,8 @@ all: example
 .PHONY: example
 
 LIBIGL=../../
+#LIBIGL_INC=-I$(LIBIGL)/include -DIGL_HEADER_ONLY
+#LIBIGL_LIB=
 LIBIGL_INC=-I$(LIBIGL)/include
 LIBIGL_LIB=-L$(LIBIGL)/lib -ligl -liglembree
 

+ 3 - 12
examples/embree/example.cpp

@@ -1,4 +1,3 @@
-#define IGL_HEADER_ONLY
 #include <igl/embree/EmbreeIntersector.h>
 #include <igl/OpenGL_convenience.h>
 #include <igl/per_face_normals.h>
@@ -38,7 +37,7 @@ double bbd;
 // Faces
 Eigen::MatrixXi F;
 // Embree intersection structure
-igl::EmbreeIntersector<double,int> * ei;
+igl::EmbreeIntersector<double,int> ei;
 // Hits collected
 std::vector<igl::Hit > hits;
 // Ray information, "projection screen" corners
@@ -327,7 +326,7 @@ void mouse_move(int mouse_x, int mouse_y)
   // Shoot ray at unprojected mouse in view direction
   dir = d-s;
   int num_rays_shot;
-  ei->intersectRay(s,dir,hits,num_rays_shot);
+  ei.intersectRay(s,dir,hits,num_rays_shot);
   for(vector<igl::Hit>::iterator hit = hits.begin();
       hit != hits.end();
       hit++)
@@ -417,12 +416,6 @@ void mouse_drag(int mouse_x, int mouse_y)
 }
 
 
-void cleanup()
-{
-  using namespace std;
-  delete ei;
-}
-
 void key(unsigned char key, int mouse_x, int mouse_y)
 {
   using namespace std;
@@ -431,7 +424,6 @@ void key(unsigned char key, int mouse_x, int mouse_y)
     // Ctrl-c and esc exit
     case char(3):
     case char(27):
-      cleanup();
       exit(0);
     default:
       cout<<"Unknown key command: "<<key<<" "<<int(key)<<endl;
@@ -471,7 +463,7 @@ int main(int argc, char * argv[])
     V.colwise().minCoeff()).maxCoeff();
 
   // Init embree
-  ei = new EmbreeIntersector<double,int>(V,F);
+  ei.init(V,F);
 
   // Init glut
   glutInit(&argc,argv);
@@ -485,6 +477,5 @@ int main(int argc, char * argv[])
   glutMotionFunc(mouse_drag);
   glutPassiveMotionFunc(mouse_move);
   glutMainLoop();
-  cleanup();
   return 0;
 }

+ 116 - 31
include/igl/embree/EmbreeIntersector.h

@@ -9,9 +9,7 @@
 
 #include "Hit.h"
 #include <Eigen/Core>
-#include <embree/include/embree.h>
-#include <embree/include/intersector1.h>
-#include <embree/common/ray.h>
+#include "Embree_convenience.h"
 #include <vector>
 
 namespace igl
@@ -21,19 +19,45 @@ namespace igl
   typename Index>
   class EmbreeIntersector
   {
+  public:
+    // Initialize embree engine. This will be called on instance `init()`
+    // calls. If already inited then this function does nothing: it is harmless
+    // to call more than once.
+    static void global_init();
+  private:
+    // Deinitialize the embree engine. This should probably never be called by
+    // the user. Hence it's private. Do you really want to do this?
+    static void global_deinit();
+  public:
     typedef Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic> PointMatrixType;
     typedef Eigen::Matrix<Index,Eigen::Dynamic,Eigen::Dynamic>  FaceMatrixType;
     typedef Eigen::Matrix<Scalar,1,3> RowVector3;
   public:
-    // V  #V by 3 list of vertex positions
-    // F  #F by 3 list of Oriented triangles
-    EmbreeIntersector(
-      const PointMatrixType & V = PointMatrixType(),
-      const FaceMatrixType & F = FaceMatrixType(),
+    EmbreeIntersector();
+  private:
+    // Copying and assignment are not allowed.
+    EmbreeIntersector(const EmbreeIntersector & that);
+    EmbreeIntersector operator=(const EmbreeIntersector &);
+  public:
+    virtual ~EmbreeIntersector();
+      
+    // Initialize with a given mesh.
+    //
+    // Inputs:
+    //   V  #V by 3 list of vertex positions
+    //   F  #F by 3 list of Oriented triangles
+    // Side effects:
+    //   The first time this is ever called the embree engine is initialized.
+    void init(
+      const PointMatrixType & V,
+      const FaceMatrixType & F,
       const char* structure = "default",
       const char* builder = "default",
       const char* traverser = "default");
-    virtual ~EmbreeIntersector();
+    // Deinitialize embree datasctructures for current mesh.  Also called on
+    // destruction: no need to call if you just want to init() once and
+    // destroy.
+    void deinit();
   
     // Given a ray find the first hit
     // 
@@ -87,6 +111,16 @@ namespace igl
 
 // Implementation
 #include <igl/EPS.h>
+// This unfortunately cannot be a static field of EmbreeIntersector because it
+// would depend on the template and then we might end up with initializing
+// embree twice. If only there was a way to ask embree if it's already
+// initialized...
+namespace igl
+{
+  // Keeps track of whether the **Global** Embree intersector has been
+  // initialized. This should never been done at the global scope.
+  static bool EmbreeIntersector_inited = false;
+}
 
 template <typename RowVector3>
 inline embree::Vector3f toVector3f(const RowVector3 &p) { return embree::Vector3f((float)p[0], (float)p[1], (float)p[2]); }
@@ -94,34 +128,80 @@ inline embree::Vector3f toVector3f(const RowVector3 &p) { return embree::Vector3
 template <
 typename Scalar,
 typename Index>
-igl::EmbreeIntersector < Scalar, Index>
-::EmbreeIntersector(const PointMatrixType & V,
-                    const FaceMatrixType & F,
-                    const char* structure,
-                    const char* builder,
-                    const char* traverser)
-  :
-    mesh(NULL),
-    triangles(NULL),
-    vertices(NULL),
-    intersector(NULL)
+void igl::EmbreeIntersector < Scalar, Index>::global_init()
 {
-  using namespace std;
-  static bool inited = false;
-  if(!inited)
+  if(!EmbreeIntersector_inited)
   {
     embree::rtcInit();
 #ifdef IGL_VERBOSE
     embree::rtcSetVerbose(3);
 #endif
     embree::rtcStartThreads();
-    inited = true;
+    EmbreeIntersector_inited = true;
   }
+}
+
+template <
+typename Scalar,
+typename Index>
+void igl::EmbreeIntersector < Scalar, Index>::global_deinit()
+{
+  EmbreeIntersector_inited = false;
+  embree::rtcStopThreads();
+  embree::rtcExit();
+  embree::rtcFreeMemory();
+}
+
+template <
+typename Scalar,
+typename Index>
+igl::EmbreeIntersector < Scalar, Index>::EmbreeIntersector()
+  :
+  mesh(NULL),
+  triangles(NULL),
+  vertices(NULL),
+  intersector(NULL)
+{
+}
+
+template <
+typename Scalar,
+typename Index>
+igl::EmbreeIntersector < Scalar, Index>::EmbreeIntersector(
+  const EmbreeIntersector & that)
+{
+  assert(false && "Copying EmbreeIntersector is not allowed");
+}
+
+template <
+typename Scalar,
+typename Index>
+igl::EmbreeIntersector <Scalar,Index> 
+igl::EmbreeIntersector < Scalar, Index>::operator=(
+  const EmbreeIntersector<Scalar, Index> & that)
+{
+  assert(false && "Assigning an EmbreeIntersector is not allowed");
+  return *this;
+}
+
 
-   if(V.size() == 0 || F.size() == 0)
-   {
-     return;
-   }
+template <
+typename Scalar,
+typename Index>
+void igl::EmbreeIntersector < Scalar, Index>::init(
+  const PointMatrixType & V,
+  const FaceMatrixType & F,
+  const char* structure,
+  const char* builder,
+  const char* traverser)
+{
+  using namespace std;
+  global_init();
+
+  if(V.size() == 0 || F.size() == 0)
+  {
+    return;
+  }
   
   mesh = embree::rtcNewTriangleMesh(F.rows(),V.rows(),structure);
 
@@ -152,12 +232,17 @@ typename Scalar,
 typename Index>
 igl::EmbreeIntersector < Scalar, Index>
 ::~EmbreeIntersector()
+{
+  deinit();
+}
+
+template <
+typename Scalar,
+typename Index>
+void igl::EmbreeIntersector < Scalar, Index>::deinit()
 {
   embree::rtcDeleteIntersector1(intersector);
   embree::rtcDeleteGeometry(mesh);
-//  embree::rtcStopThreads();
-//  embree::rtcExit();
-//  embree::rtcFreeMemory();
 }
 
 template <

+ 3 - 1
include/igl/embree/Embree_convenience.h

@@ -16,7 +16,9 @@
 // This is a hack
 #  pragma GCC system_header
 #endif
-#include <common/ray.h>
+#include <embree/include/embree.h>
+#include <embree/include/intersector1.h>
+#include <embree/common/ray.h>
 #ifdef __GNUC__
 #  if __GNUC__ >= 4
 #    if __GNUC_MINOR__ >= 6

+ 3 - 5
include/igl/embree/ambient_occlusion.cpp

@@ -68,11 +68,9 @@ void igl::ambient_occlusion(
   using namespace Eigen;
   EmbreeIntersector<
     typename DerivedV::Scalar,
-    typename DerivedF::Scalar > * ei = new EmbreeIntersector<
-    typename DerivedV::Scalar,
-    typename DerivedF::Scalar >(V,F);
-  ambient_occlusion(*ei,P,N,num_samples,S);
-  delete ei;
+    typename DerivedF::Scalar > ei;
+  ei.init(V,F);
+  ambient_occlusion(ei,P,N,num_samples,S);
 }
 
 #ifndef IGL_HEADER_ONLY

+ 2 - 2
include/igl/embree/bone_visible.cpp

@@ -26,8 +26,8 @@ IGL_INLINE void igl::bone_visible(
   FF.resize(F.rows()*2,F.cols());
   FF << F, F.rowwise().reverse();
   // Initialize intersector
-  const EmbreeIntersector<double,int> ei = 
-        EmbreeIntersector<double,int>(V,FF);
+  EmbreeIntersector<double,int> ei;
+  ei.init(V,FF);
   const double sd_norm = (s-d).norm();
   // Embree seems to be parallel when constructing but not when tracing rays
 #pragma omp parallel for

+ 2 - 1
include/igl/embree/orient_outward_ao.cpp

@@ -32,7 +32,8 @@ IGL_INLINE void igl::orient_outward_ao(
   MatrixXi F2;
   F2.resize(F.rows()*2,F.cols());
   F2 << F, F.rowwise().reverse().eval();
-  EmbreeIntersector<typename DerivedV::Scalar, typename DerivedF::Scalar> ei(V,F2);
+  EmbreeIntersector<typename DerivedV::Scalar, typename DerivedF::Scalar> ei;
+  ei.init(V,F2);
   
   // number of faces
   const int m = F.rows();