unproject_in_mesh.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
  4. //
  5. // This Source Code Form is subject to the terms of the Mozilla Public License
  6. // v. 2.0. If a copy of the MPL was not distributed with this file, You can
  7. // obtain one at http://mozilla.org/MPL/2.0/.
  8. #include "unproject_in_mesh.h"
  9. #include "EmbreeIntersector.h"
  10. #include <igl/unproject.h>
  11. #include <vector>
  12. #ifndef IGL_OPENGL_4
  13. template <
  14. typename Derivedobj>
  15. IGL_INLINE int igl::unproject_in_mesh(
  16. const int x,
  17. const int y,
  18. const igl::EmbreeIntersector & ei,
  19. Eigen::PlainObjectBase<Derivedobj> & obj)
  20. {
  21. std::vector<igl::Hit> hits;
  22. return igl::unproject_in_mesh(x,y,ei,obj,hits);
  23. }
  24. template <
  25. typename Derivedobj>
  26. IGL_INLINE int igl::unproject_in_mesh(
  27. const int x,
  28. const int y,
  29. const igl::EmbreeIntersector & ei,
  30. Eigen::PlainObjectBase<Derivedobj> & obj,
  31. std::vector<igl::Hit > & hits)
  32. {
  33. using namespace igl;
  34. using namespace std;
  35. using namespace Eigen;
  36. // Source and direction on screen
  37. Vector3f win_s = Vector3f(x,y,0);
  38. Vector3f win_d(x,y,1);
  39. // Source, destination and direction in world
  40. Vector3f s,d,dir;
  41. unproject(win_s,s);
  42. unproject(win_d,d);
  43. dir = d-s;
  44. // Shoot ray, collect all hits (could just collect first two)
  45. int num_rays_shot;
  46. hits.clear();
  47. ei.intersectRay(s,dir,hits,num_rays_shot);
  48. switch(hits.size())
  49. {
  50. case 0:
  51. break;
  52. case 1:
  53. {
  54. obj = (s + dir*hits[0].t).cast<typename Derivedobj::Scalar>();
  55. break;
  56. }
  57. case 2:
  58. default:
  59. {
  60. obj = 0.5*((s + dir*hits[0].t) + (s + dir*hits[1].t)).cast<typename Derivedobj::Scalar>();
  61. break;
  62. }
  63. }
  64. return hits.size();
  65. }
  66. #endif
  67. template <typename Derivedobj>
  68. IGL_INLINE int igl::unproject_in_mesh(
  69. const Eigen::Vector2f& pos,
  70. const Eigen::Matrix4f& model,
  71. const Eigen::Matrix4f& proj,
  72. const Eigen::Vector4f& viewport,
  73. const igl::EmbreeIntersector & ei,
  74. Eigen::PlainObjectBase<Derivedobj> & obj,
  75. std::vector<igl::Hit > & hits)
  76. {
  77. using namespace igl;
  78. using namespace std;
  79. using namespace Eigen;
  80. // Source and direction on screen
  81. Vector3f win_s(pos(0),pos(1),0);
  82. Vector3f win_d(pos(0),pos(1),1);
  83. // Source, destination and direction in world
  84. Vector3f s,d,dir;
  85. s = igl::unproject(win_s,model,proj,viewport);
  86. d = igl::unproject(win_d,model,proj,viewport);
  87. dir = d-s;
  88. // Shoot ray, collect all hits (could just collect first two)
  89. int num_rays_shot;
  90. hits.clear();
  91. ei.intersectRay(s,dir,hits,num_rays_shot);
  92. switch(hits.size())
  93. {
  94. case 0:
  95. break;
  96. case 1:
  97. {
  98. obj = (s + dir*hits[0].t).cast<typename Derivedobj::Scalar>();
  99. break;
  100. }
  101. case 2:
  102. default:
  103. {
  104. obj = 0.5*((s + dir*hits[0].t) + (s + dir*hits[1].t)).cast<typename Derivedobj::Scalar>();
  105. break;
  106. }
  107. }
  108. return hits.size();
  109. }
  110. IGL_INLINE bool igl::unproject_in_mesh(
  111. const Eigen::Vector2f& pos,
  112. const Eigen::MatrixXi& F,
  113. const Eigen::Matrix4f& model,
  114. const Eigen::Matrix4f& proj,
  115. const Eigen::Vector4f& viewport,
  116. const igl::EmbreeIntersector & ei,
  117. int& fid,
  118. int& vid)
  119. {
  120. using namespace std;
  121. using namespace Eigen;
  122. MatrixXd obj;
  123. vector<igl::Hit> hits;
  124. unproject_in_mesh(pos,model,proj,viewport,ei,obj,hits);
  125. if (hits.size()> 0)
  126. {
  127. Vector3d bc(1.0-hits[0].u-hits[0].v, hits[0].u, hits[0].v);
  128. int i;
  129. bc.maxCoeff(&i);
  130. fid = hits[0].id;
  131. vid = F(fid,i);
  132. return true;
  133. }
  134. return false;
  135. }
  136. #ifndef IGL_OPENLGL_4
  137. #ifdef IGL_STATIC_LIBRARY
  138. template int igl::unproject_in_mesh<Eigen::Matrix<double, 3, 1, 0, 3, 1> >(int, int, igl::EmbreeIntersector const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> >&, std::vector<igl::Hit, std::allocator<igl::Hit> >&);
  139. template int igl::unproject_in_mesh<Eigen::Matrix<double, 3, 1, 0, 3, 1> >(int, int, igl::EmbreeIntersector const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> >&);
  140. #endif
  141. #endif