update.cpp 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. #include "update.h"
  2. #include <igl/heat_geodesics.h>
  3. #include <igl/unproject_onto_mesh.h>
  4. bool update(
  5. const Eigen::MatrixXd & V,
  6. const Eigen::MatrixXi & F,
  7. const double t,
  8. const double x,
  9. const double y,
  10. const Eigen::Matrix4f& view,
  11. const Eigen::Matrix4f& proj,
  12. const Eigen::Vector4f& viewport,
  13. const igl::HeatGeodesicsData<double>& data,
  14. Eigen::VectorXd& D)
  15. {
  16. int fid;
  17. Eigen::Vector3f bc;
  18. // Cast a ray in the view direction starting from the mouse position
  19. if(igl::unproject_onto_mesh(Eigen::Vector2f(x,y), view,
  20. proj, viewport, V, F, fid, bc))
  21. {
  22. // if big mesh, just use closest vertex. Otherwise, blend distances to
  23. // vertices of face using barycentric coordinates.
  24. if(F.rows()>100000)
  25. {
  26. // 3d position of hit
  27. const Eigen::RowVector3d m3 =
  28. V.row(F(fid,0))*bc(0) + V.row(F(fid,1))*bc(1) + V.row(F(fid,2))*bc(2);
  29. int cid = 0;
  30. Eigen::Vector3d(
  31. (V.row(F(fid,0))-m3).squaredNorm(),
  32. (V.row(F(fid,1))-m3).squaredNorm(),
  33. (V.row(F(fid,2))-m3).squaredNorm()).minCoeff(&cid);
  34. const int vid = F(fid,cid);
  35. igl::heat_geodesics_solve(data,(Eigen::VectorXi(1,1)<<vid).finished(),D);
  36. }else
  37. {
  38. D = Eigen::VectorXd::Zero(V.rows());
  39. for(int cid = 0;cid<3;cid++)
  40. {
  41. const int vid = F(fid,cid);
  42. Eigen::VectorXd Dc;
  43. igl::heat_geodesics_solve(data,(Eigen::VectorXi(1,1)<<vid).finished(),Dc);
  44. D += Dc*bc(cid);
  45. }
  46. }
  47. return true;
  48. }
  49. return false;
  50. }