Ver código fonte

added a function that projects a mesh onto another using embree

Former-commit-id: b75d35532774e1a24cc359ba67b8c388df4d01b9
Daniele Panozzo 11 anos atrás
pai
commit
4582a4f49d

+ 40 - 0
include/igl/barycentric2global.cpp

@@ -0,0 +1,40 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2013 Daniele Panozzo <daniele.panozzo@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 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#include "barycentric2global.h"
+
+// For error printing
+#include <cstdio>
+#include <vector>
+
+namespace igl
+{
+  template <typename Scalar, typename Index>
+  IGL_INLINE Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic> barycentric2global(
+    const Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic> & V, 
+    const Eigen::Matrix<Index,Eigen::Dynamic,Eigen::Dynamic>  & F, 
+    const Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic> & bc)
+  {
+    Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic> R;
+    R.resize(bc.rows(),3);
+
+    for (unsigned i=0; i<R.rows(); ++i)
+    {
+      unsigned id = round(bc(i,0));
+      double u   = bc(i,1);  
+      double v   = bc(i,2);
+
+      if (id != -1)
+        R.row(i) = V.row(F(id,0)) +
+                  ((V.row(F(id,1)) - V.row(F(id,0))) * u +
+                   (V.row(F(id,2)) - V.row(F(id,0))) * v  );
+      else
+        R.row(i) << 0,0,0;
+    }
+    return R;
+  }
+}

+ 41 - 0
include/igl/barycentric2global.h

@@ -0,0 +1,41 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2013 Daniele Panozzo <daniele.panozzo@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 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_BARYCENTRIC2GLOBAL_H
+#define IGL_BARYCENTRIC2GLOBAL_H
+#include <igl/igl_inline.h>
+
+#include <Eigen/Dense>
+#include <Eigen/Sparse>
+
+namespace igl 
+{
+	// Converts barycentric coordinates in the embree form to 3D coordinates
+	// Embree stores barycentric coordinates as triples: fid, bc1, bc2
+	// fid is the id of a face, bc1 is the displacement of the point wrt the 
+	// first vertex v0 and the edge v1-v0. Similarly, bc2 is the displacement
+	// wrt v2-v0.
+  	// 
+  	// Input:
+  	// V:  #Vx3 Vertices of the mesh
+  	// F:  #Fxe Faces of the mesh
+  	// bc: #Xx3 Barycentric coordinates, one row per point
+  	//
+  	// Output:
+  	// #X: #Xx3 3D coordinates of all points in bc
+  template <typename Scalar, typename Index>
+  IGL_INLINE Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic> barycentric2global(
+    const Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic> & V, 
+	  const Eigen::Matrix<Index,Eigen::Dynamic,Eigen::Dynamic>   & F, 
+    const Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>  & bc);
+}
+
+#ifdef IGL_HEADER_ONLY
+#  include "barycentric2global.cpp"
+#endif
+
+#endif

+ 97 - 0
include/igl/embree/project_mesh.cpp

@@ -0,0 +1,97 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2013 Daniele Panozzo <daniele.panozzo@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 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#include "project_mesh.h"
+
+// For error printing
+#include <cstdio>
+#include <vector>
+
+#include <igl/per_vertex_normals.h>
+#include <igl/embree/EmbreeIntersector.h>
+
+template <typename ScalarMatrix, typename IndexMatrix>
+IGL_INLINE ScalarMatrix igl::project_mesh(
+   const ScalarMatrix & V_source,
+   const IndexMatrix  & F_source,
+   const ScalarMatrix & V_target,
+   const IndexMatrix  & F_target
+)
+{
+  // Compute normals for the tri
+  Eigen::MatrixXd ray_dir;
+  igl::per_vertex_normals(V_source, F_source, ray_dir);
+
+  return project_points_on_mesh(V_source,ray_dir,V_target,F_target);
+}
+
+template <typename ScalarMatrix, typename IndexMatrix>
+IGL_INLINE ScalarMatrix igl::project_points_on_mesh
+(
+ const ScalarMatrix & V_source,
+ const ScalarMatrix  & N_source,
+ const ScalarMatrix & V_target,
+ const IndexMatrix  & F_target
+)
+{
+
+  double tol = 0.00001;
+  
+  Eigen::MatrixXd ray_pos = V_source;
+  Eigen::MatrixXd ray_dir = N_source;
+
+  // Allocate matrix for the result
+  ScalarMatrix R;
+  R.resize(V_source.rows(), 3);
+  
+  // Initialize embree
+  igl::EmbreeIntersector embree;
+  embree.init(V_target.template cast<float>(),F_target.template cast<int>());
+
+  // Shoot rays from the source to the target
+  for (unsigned i=0; i<ray_pos.rows(); ++i)
+  {
+    igl::Hit A,B;
+    
+    // Shoot ray A
+    Eigen::RowVector3d A_pos = ray_pos.row(i) + tol * ray_dir.row(i);
+    Eigen::RowVector3d A_dir = -ray_dir.row(i);
+    
+    bool A_hit = embree.intersectRay(A_pos.cast<float>(), A_dir.cast<float>(),A);
+    
+    Eigen::RowVector3d B_pos = ray_pos.row(i) - tol * ray_dir.row(i);
+    Eigen::RowVector3d B_dir = ray_dir.row(i);
+    
+    bool B_hit = embree.intersectRay(B_pos.cast<float>(), B_dir.cast<float>(),B);
+    
+    
+    int choice = -1;
+    
+    if (A_hit && ! B_hit)
+      choice = 0;
+    else if (!A_hit && B_hit)
+      choice = 1;
+    else if (A_hit && B_hit)
+      choice = A.t > B.t;
+    
+    Eigen::RowVector3d temp;
+
+    if (choice == -1)
+      temp << -1, 0, 0;
+    else if (choice == 0)
+      temp << A.id, A.u, A.v;
+    else if (choice == 1)
+      temp << B.id, B.u, B.v;
+
+    R.row(i) = temp;
+    
+  }
+
+  return R;
+
+}
+

+ 75 - 0
include/igl/embree/project_mesh.h

@@ -0,0 +1,75 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2013 Daniele Panozzo <daniele.panozzo@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 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_PROJECTMESH_H
+#define IGL_PROJECTMESH_H
+#include <igl/igl_inline.h>
+
+#include <Eigen/Dense>
+#include <Eigen/Sparse>
+#include <vector>
+
+namespace igl 
+{
+
+  // Project the triangle mesh V_source, F_source onto the triangle mesh
+  // V_target,F_target.
+  // A ray is casted for every vertex in the normal direction and its opposite.
+  //
+  // Input:
+  // V_source: #Vx3 Vertices of the source mesh
+  // F_source: #Fx3 Faces of the source mesh
+  // V_target: #V2x3 Vertices of the target mesh
+  // F_target: #F2x3 Faces of the target mesh
+  //
+  // Output:
+  // #Vx3 matrix of baricentric coordinate. Each row corresponds to 
+  // a vertex of the projected mesh and it has the following format:
+  // id b1 b2. id is the id of a face of the source mesh. b1 and b2 are 
+  // the barycentric coordinates wrt the first two edges of the triangle
+  // To convert to standard global coordinates, see barycentric2global.h
+  template <typename ScalarMatrix, typename IndexMatrix>
+  IGL_INLINE ScalarMatrix project_mesh
+  (
+		const ScalarMatrix & V_source,
+  	const IndexMatrix  & F_source,
+    const ScalarMatrix & V_target,
+    const IndexMatrix  & F_target
+	);
+
+  // Project the point cloud V_source onto the triangle mesh
+  // V_target,F_target. 
+  // A ray is casted for every vertex in the direction specified by 
+  // N_source and its opposite.
+  //
+  // Input:
+  // V_source: #Vx3 Vertices of the source mesh
+  // N_source: #Vx3 Normals of the point cloud
+  // V_target: #V2x3 Vertices of the target mesh
+  // F_target: #F2x3 Faces of the target mesh
+  //
+  // Output:
+  // #Vx3 matrix of baricentric coordinate. Each row corresponds to 
+  // a vertex of the projected mesh and it has the following format:
+  // id b1 b2. id is the id of a face of the source mesh. b1 and b2 are 
+  // the barycentric coordinates wrt the first two edges of the triangle
+  // To convert to standard global coordinates, see barycentric2global.h
+  template <typename ScalarMatrix, typename IndexMatrix>
+  IGL_INLINE ScalarMatrix project_points_on_mesh
+  (
+   const ScalarMatrix & V_source,
+   const ScalarMatrix  & N_source,
+   const ScalarMatrix & V_target,
+   const IndexMatrix  & F_target
+   );
+
+}
+#ifdef IGL_HEADER_ONLY
+#  include "project_mesh.cpp"
+#endif
+
+#endif