qslim.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2016 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 "qslim.h"
  9. #include "collapse_edge.h"
  10. #include "connect_boundary_to_infinity.h"
  11. #include "decimate.h"
  12. #include "edge_flaps.h"
  13. #include "is_edge_manifold.h"
  14. #include "max_faces_stopping_condition.h"
  15. #include "per_vertex_point_to_plane_quadrics.h"
  16. #include "qslim_optimal_collapse_edge_callbacks.h"
  17. #include "quadric_binary_plus_operator.h"
  18. #include "remove_unreferenced.h"
  19. #include "slice.h"
  20. #include "slice_mask.h"
  21. IGL_INLINE bool igl::qslim(
  22. const Eigen::MatrixXd & V,
  23. const Eigen::MatrixXi & F,
  24. const size_t max_m,
  25. Eigen::MatrixXd & U,
  26. Eigen::MatrixXi & G,
  27. Eigen::VectorXi & J,
  28. Eigen::VectorXi & I)
  29. {
  30. using namespace igl;
  31. // Original number of faces
  32. const int orig_m = F.rows();
  33. // Tracking number of faces
  34. int m = F.rows();
  35. typedef Eigen::MatrixXd DerivedV;
  36. typedef Eigen::MatrixXi DerivedF;
  37. DerivedV VO;
  38. DerivedF FO;
  39. igl::connect_boundary_to_infinity(V,F,VO,FO);
  40. // decimate will not work correctly on non-edge-manifold meshes. By extension
  41. // this includes meshes with non-manifold vertices on the boundary since these
  42. // will create a non-manifold edge when connected to infinity.
  43. if(!is_edge_manifold(FO))
  44. {
  45. return false;
  46. }
  47. Eigen::VectorXi EMAP;
  48. Eigen::MatrixXi E,EF,EI;
  49. edge_flaps(FO,E,EMAP,EF,EI);
  50. // Quadrics per vertex
  51. typedef std::tuple<Eigen::MatrixXd,Eigen::RowVectorXd,double> Quadric;
  52. std::vector<Quadric> quadrics;
  53. per_vertex_point_to_plane_quadrics(VO,FO,EMAP,EF,EI,quadrics);
  54. // State variables keeping track of edge we just collapsed
  55. int v1 = -1;
  56. int v2 = -1;
  57. // Callbacks for computing and updating metric
  58. std::function<void(
  59. const int e,
  60. const Eigen::MatrixXd &,
  61. const Eigen::MatrixXi &,
  62. const Eigen::MatrixXi &,
  63. const Eigen::VectorXi &,
  64. const Eigen::MatrixXi &,
  65. const Eigen::MatrixXi &,
  66. double &,
  67. Eigen::RowVectorXd &)> cost_and_placement;
  68. std::function<bool(
  69. const Eigen::MatrixXd & ,/*V*/
  70. const Eigen::MatrixXi & ,/*F*/
  71. const Eigen::MatrixXi & ,/*E*/
  72. const Eigen::VectorXi & ,/*EMAP*/
  73. const Eigen::MatrixXi & ,/*EF*/
  74. const Eigen::MatrixXi & ,/*EI*/
  75. const std::set<std::pair<double,int> > & ,/*Q*/
  76. const std::vector<std::set<std::pair<double,int> >::iterator > &,/*Qit*/
  77. const Eigen::MatrixXd & ,/*C*/
  78. const int /*e*/
  79. )> pre_collapse;
  80. std::function<void(
  81. const Eigen::MatrixXd & , /*V*/
  82. const Eigen::MatrixXi & , /*F*/
  83. const Eigen::MatrixXi & , /*E*/
  84. const Eigen::VectorXi & ,/*EMAP*/
  85. const Eigen::MatrixXi & , /*EF*/
  86. const Eigen::MatrixXi & , /*EI*/
  87. const std::set<std::pair<double,int> > & , /*Q*/
  88. const std::vector<std::set<std::pair<double,int> >::iterator > &, /*Qit*/
  89. const Eigen::MatrixXd & , /*C*/
  90. const int , /*e*/
  91. const int , /*e1*/
  92. const int , /*e2*/
  93. const int , /*f1*/
  94. const int , /*f2*/
  95. const bool /*collapsed*/
  96. )> post_collapse;
  97. qslim_optimal_collapse_edge_callbacks(
  98. E,quadrics,v1,v2, cost_and_placement, pre_collapse,post_collapse);
  99. // Call to greedy decimator
  100. bool ret = decimate(
  101. VO, FO,
  102. cost_and_placement,
  103. max_faces_stopping_condition(m,orig_m,max_m),
  104. pre_collapse,
  105. post_collapse,
  106. E, EMAP, EF, EI,
  107. U, G, J, I);
  108. // Remove phony boundary faces and clean up
  109. const Eigen::Array<bool,Eigen::Dynamic,1> keep = (J.array()<orig_m);
  110. igl::slice_mask(Eigen::MatrixXi(G),keep,1,G);
  111. igl::slice_mask(Eigen::VectorXi(J),keep,1,J);
  112. Eigen::VectorXi _1,I2;
  113. igl::remove_unreferenced(Eigen::MatrixXd(U),Eigen::MatrixXi(G),U,G,_1,I2);
  114. igl::slice(Eigen::VectorXi(I),I2,1,I);
  115. return ret;
  116. }