~mht/surcut

852da4cc1a896d12d0d7d8847c17c143c41d6bce — Martin Hafskjold Thoresen 5 years ago 93d5da9
Fix NaN case where removal dir and face normal were oposite
5 files changed, 27 insertions(+), 40 deletions(-)

M arap-mold.cpp
M arap-mold.h
M main.cpp
M mesh.cpp
M mesh.h
M arap-mold.cpp => arap-mold.cpp +10 -21
@@ 1,5 1,4 @@
#include "igl/arap_rhs.h"
#include "igl/colon.h"
#include "igl/columnize.h"
#include "igl/cotmatrix.h"
#include "igl/covariance_scatter_matrix.h"


@@ 146,7 145,6 @@ bool arap::precomputation(const Mesh &mesh, arap::Data &data) {
  assert(G_sum_dim.cols() == data.CSM.rows());
  // For us, this is a no op
  data.CSM = (G_sum_dim * data.CSM).eval();
  SDbg(data.CSM);

  arap_rhs(V, F, data.dim, eff_energy, data.K);
  if (flat) {


@@ 160,14 158,9 @@ bool arap::precomputation(const Mesh &mesh, arap::Data &data) {
    const double h = data.h;
    assert(h != 0);
    SparseMatrix<double> M;
    Dbg(V);
    Dbg(F);
    igl::massmatrix(V, F, igl::MASSMATRIX_TYPE_DEFAULT, data.M);
    SDbg(data.M);
    const double dw = (1. / data.ym) * (h * h);
    SparseMatrix<double> DQ = dw * 1. / (h * h) * data.M;
    SDbg(Q);
    SDbg(DQ);
    Q += DQ;
    // Dummy external forces
    data.f_ext = MatrixXd::Zero(n, data.dim);


@@ 177,16 170,8 @@ bool arap::precomputation(const Mesh &mesh, arap::Data &data) {
  return min_quad_with_fixed_precompute(Q, b, SparseMatrix<double>(), true, data.solver_data);
}

// # Note: if ran with `use_dynamics` you must set `ARAPData::U0` to be your
// initial `U` before calling this. Otherwise it'll be 0, an you will have a bad
// time.
void arap::iter(
    const Mesh &mesh,
    const arap::Args &args,
    const Eigen::MatrixXd &bc,
    arap::Data &data,
    Eigen::MatrixXd &U
    ) {
void arap::iter(const Mesh &mesh, const arap::Args &args, const Eigen::MatrixXd &bc,
                arap::Data &data, Eigen::MatrixXd &U) {
  using namespace Eigen;
  using namespace std;



@@ 227,13 212,11 @@ void arap::iter(
  // THIS NORMALIZATION IS IMPORTANT TO GET SINGLE PRECISION SVD CODE TO WORK
  // CORRECTLY.
  StackCovMats /= StackCovMats.array().abs().maxCoeff();
  Dbg(StackCovMats);

  const int Rdim = data.dim;
  // This is a big matrix, which contains stacked 3x3 rotation matrices for each
  // *tet* in the mesh.
  MatrixXd Rotations(Rdim, data.CSM.rows());
  Dbg(Rotations);

  if (Rdim == 2) {
    igl::fit_rotations_planar(StackCovMats, Rotations);


@@ 241,6 224,8 @@ void arap::iter(
    igl::fit_rotations(StackCovMats, true, Rotations);
  }

  NO_NANS(Rotations);

  if (!args.skip_mold_rotations) { /* ~~ Moldability ~~ */
    // 1. Go through all the boundary faces of the tet mesh
    // 2. Skip if the face satisfies direction constraint


@@ 305,7 290,11 @@ void arap::iter(
        auto remove_dir = *data.mht_plane_n;
        if (data.orientation->at(face_i) == Orientation::Below)
          remove_dir = -remove_dir;
        if (face_normal == -remove_dir)
          continue;

        Eigen::Vector3d rotation_axis = face_normal.cross(remove_dir).normalized();

        auto x = remove_dir.dot(face_normal);
        auto angle_between = atan2(1.0, x);



@@ 421,7 410,7 @@ void arap::iter(
    // -h*data.vel = -V0+Vm1)
    // -V0-h*data.vel = -2V0+Vm1
    const double dw = (1. / data.ym) * (h * h);
    Dl = dw * (1. / (h * h) * data.M * (-data.U0 - h * data.vel) - data.f_ext);
    Dl = dw * (1. / (h * h) * data.M * (-mesh.rest_state - h * data.vel) - data.f_ext);
  }

  VectorXd Rcol;


@@ 448,6 437,6 @@ void arap::iter(

  if (data.with_dynamics) {
    // Keep track of velocity for next time
    data.vel = (U - data.U0) / data.h;
    data.vel = (U - mesh.rest_state) / data.h;
  }
}

M arap-mold.h => arap-mold.h +6 -12
@@ 97,10 97,10 @@ struct Data {
};

struct Args {
  bool should_blend;  /* whether to blend rotations with neighbors  */
  float blend;        /* blend factor [0, 1] */
  bool slerp_2_rots;  /* SLERP rotations to join 2. Otherwise multiply by 0.5 */
  bool rotate_before; /* Rotate normal before checking moldability */
  bool should_blend;        /* whether to blend rotations with neighbors  */
  float blend;              /* blend factor [0, 1] */
  bool slerp_2_rots;        /* SLERP rotations to join 2. Otherwise multiply by 0.5 */
  bool rotate_before;       /* Rotate normal before checking moldability */
  bool skip_mold_rotations; /* Don't do the rotation stuff to it make moldable */

  Args() : should_blend(false), blend(0.0), slerp_2_rots(false), rotate_before(false){};


@@ 116,19 116,13 @@ struct Args {
//   b  #b list of "boundary" fixed vertex indices into V
// Outputs:
//   data  struct containing necessary precomputation
bool precomputation(const Mesh &, Data &data); 
bool precomputation(const Mesh &, Data &data);

// Inputs:
//   bc  #b by dim list of boundary conditions
//   data  struct containing necessary precomputation and parameters
//   U  #V by dim initial guess
void iter(
    const Mesh &,
    const Args &,
    const Eigen::MatrixXd &bc,
    Data &data,
    Eigen::MatrixXd &U
    );
void iter(const Mesh &, const Args &, const Eigen::MatrixXd &bc, Data &data, Eigen::MatrixXd &U);

Moldable::Enum is_moldable(Eigen::Vector3d &remove_dir, std::vector<bool> &is_point_above,
                           Eigen::MatrixXi &faces, int face, Eigen::Vector3d normal,

M main.cpp => main.cpp +11 -5
@@ 57,6 57,8 @@ bool show_forces = false;
// Don't use the ARAP enforcing moldability.  (only makes sense to use wiht `stitching`).
bool regular_arap = false;

int iteration_count = 0;

// Cut plane and point with `float`, for ImGui.
Eigen::Vector3f fplane_p;
Eigen::Vector3f fplane_n;


@@ 102,6 104,7 @@ void draw_menu(Mesh &mesh) {
    if (ImGui::Button("Stop ARAP"))
      run_arap = false;
  }
  ImGui::Text("iter count: %d", iteration_count);

  if (ImGui::Button("Reset")) {
    mesh.vertices = mesh.rest_state;


@@ 172,6 175,7 @@ void draw_menu(Mesh &mesh) {

// Perform one ARAP step.
void step_arap(Mesh &mesh) {
  iteration_count++;
  Eigen::MatrixXd bc(BOUNDARY_SIZE, 3);
  for (int i = 0; i < BOUNDARY_SIZE; i++)
    bc.row(i) = mesh.rest_state.row(mesh.boundary(i));


@@ 210,7 214,8 @@ void compute_things(Mesh &mesh, bool only_plane) {
    for (int f = 0; f < mesh.faces.rows(); f++) {
      double dot;
      Eigen::Vector3d removal_dir = plane_n;
      moldable[f] = arap::is_moldable(removal_dir, is_point_above, mesh.faces, f, mesh.normals.row(f), &dot);
      moldable[f] =
          arap::is_moldable(removal_dir, is_point_above, mesh.faces, f, mesh.normals.row(f), &dot);
      if (moldable[f] == arap::Moldable::Crossing) {
        orientation[f] = arap::Orientation::Crossing;
      } else {


@@ 353,7 358,7 @@ void draw_plane(Viewer &viewer, Mesh &mesh) {

  if (show_forces) {
    viewer.data().add_edges(mesh.vertices, mesh.vertices + mesh.forces,
        Eigen::RowVector3d(1.0, 0.0, 1.0));
                            Eigen::RowVector3d(1.0, 0.0, 1.0));
  }
}



@@ 369,7 374,8 @@ int ray_intersect(Ray ray, int src_vertex, Mesh &mesh) {
  int best_vertex = -1;

  for (int f = 0; f < mesh.faces.rows(); f++) {
    int res = intersect3D_RayTriangle(ray, mesh.normals.row(f), f, mesh.vertices, mesh.faces, &collision_point);
    int res = intersect3D_RayTriangle(ray, mesh.normals.row(f), f, mesh.vertices, mesh.faces,
                                      &collision_point);
    if (res != 1)
      continue;



@@ 505,8 511,8 @@ int main(int argc, char *argv[]) {
  arap_data.mht_tf2t = mesh.face2tets;
  arap_data.mht_plane_p = &plane_p;
  arap_data.mht_plane_n = &plane_n;
  arap_data.mht_tet_rotations =
      std::vector<Eigen::Quaternion<double>>(mesh.tets.rows(), Eigen::Quaternion<double>(1, 0, 0, 0));
  arap_data.mht_tet_rotations = std::vector<Eigen::Quaternion<double>>(
      mesh.tets.rows(), Eigen::Quaternion<double>(1, 0, 0, 0));
  arap_data.vert_is_above = &is_point_above;
  arap_data.moldable = &moldable;
  arap_data.orientation = &orientation;

M mesh.cpp => mesh.cpp +0 -1
@@ 172,4 172,3 @@ void mesh_print_sizes(Mesh &mesh) {
  Dbg(mesh.boundary);
  Dbg(mesh.forces);
}


M mesh.h => mesh.h +0 -1
@@ 3,7 3,6 @@
#define Dbg(x) printf("%20s: %6zu by %6zu\n", #x, x.rows(), x.cols())
#define SDbg(x) printf("%20s: %6d by %6d\n", #x, x.rows(), x.cols())


#include <Eigen/Core>

using Eigen::MatrixXd;