~mht/surcut

f153ab9c30ac2f65facfddadb33cb209b3b8e06b — Martin Hafskjold Thoresen 4 years ago 9e36f62
Just move closest along `drag_dir`.

This sort of works, but must be scaled correctly. Also, tried to just
remesh to forget about self intersections, but that didn't work out.
Perhaps there's a tetgen option to fix that.
2 files changed, 58 insertions(+), 32 deletions(-)

M arap-mold.h
M main.cpp
M arap-mold.h => arap-mold.h +1 -0
@@ 56,6 56,7 @@ struct Data {
  // XXX(debug): Register rotation angles for all faces
  std::vector<double> mht_face_mold_angle;
  std::vector<double> mht_face_arap_angle;
  // XXX(todo): remove this, and rather have `main` make color from the `dot`.
  std::vector<int> mht_face_classes;
  // if `with_dynamics` is on, we need the initial `U0` across ARAP steps.
  Eigen::MatrixXd U0;

M main.cpp => main.cpp +57 -32
@@ 23,6 23,7 @@ bool key_down(Viewer &, unsigned char, int);
void draw_menu();
void update_vectors();
void ensure_moldability();
void remesh();

// Model data
Eigen::MatrixXd V;


@@ 96,15 97,18 @@ void draw_menu() {
    if (ImGui::Button("Stop ARAP"))
      run_arap = false;
  }

  if (ImGui::Button("Reset"))
    U = TV;
  if (ImGui::Button("Step ARAP")) {

  if (ImGui::Button("Step ARAP"))
    step_arap();
  }

  if (ImGui::Button("Ensure Moldability")) {
  if (ImGui::Button("Ensure Moldability"))
    ensure_moldability();
  }

  if (ImGui::Button("Remesh"))
    remesh();

  ImGui::Checkbox("Blend rotations", &arap_args.should_blend);
  if (arap_args.should_blend) {


@@ 320,6 324,27 @@ void ensure_moldability() {
    return -1;
  };

  auto closest_vertex = [](Eigen::Vector3d dir, int f) {
    double x = dir.dot(U.row(TF(f, 0)));
    double y = dir.dot(U.row(TF(f, 1)));
    double z = dir.dot(U.row(TF(f, 2)));
    if (x <= y && x <= z)
      return 0;
    if (y <= x && y <= z)
      return 1;
    if (z <= x && z <= y)
      return 2;
    { /* XXX(debug) */
      std::cerr << dir << std::endl << std::endl;
      std::cerr << U.row(TF(f, 0)) << std::endl << std::endl;
      std::cerr << U.row(TF(f, 1)) << std::endl << std::endl;
      std::cerr << U.row(TF(f, 2)) << std::endl << std::endl;
      fprintf(stderr, "%lf %lf %lf\n", x, y, z);
    }
    assert(false && "This is impossible (closest_vertex)");
    return -1;
  };

  // auto highest_vertex = [](int f) {
  //   double x = plane_n.dot(U.row(TF(f, 0)));
  //   double y = plane_n.dot(U.row(TF(f, 1)));


@@ 355,7 380,6 @@ void ensure_moldability() {
    if (moldable != arap::NO)
      continue;
    auto drag_dir = (normal - plane_n.dot(normal) * plane_n).normalized();

    { /* XXX(debug): NaN check */
      if (drag_dir[0] != drag_dir[0]) {
        std::cerr << drag_dir << std::endl;


@@ 366,38 390,39 @@ void ensure_moldability() {
      }
    }

    auto closest = closest_vertex(removal_dir, face);
    U.row(TF(face, closest)) += drag_dir * 0.01;

    // auto top = highest_vertex(face);
    auto far = furthest_vertex(drag_dir, face);
    // Next we need to find out if we have to move two vertices or just one: if the highest point
    // is furthest along the removal direction, we must move both remaining vertices. Otherwise, we
    // just need to move one.
    // if (top == far) {
    //   if (top == 0) {
    //     U.row(TF(face, 1)) + ;
    //   } else if (top == 1) {
    //   } else {
    //   }
    // } else {
    //   if (top == 0) {
    //   } else if (top == 1) {
    //   } else {
    //   }
    // }

    // XXX(debug): this is just for testing
    if (far == 0) {
      U.row(TF(face, 1)) += drag_dir * 0.01;
      U.row(TF(face, 2)) += drag_dir * 0.01;
    } else if (far == 1) {
      U.row(TF(face, 0)) += drag_dir * 0.01;
      U.row(TF(face, 2)) += drag_dir * 0.01;
    } else {
      U.row(TF(face, 0)) += drag_dir * 0.01;
      U.row(TF(face, 1)) += drag_dir * 0.01;
    }
    (void) far;

    // XXX(todo): check neighboring faces of these vertices and add to `indices` as needed.
  }

  igl::per_face_normals(TV, TF, N);
}

// Remesh the model based on the deformed version.
// WARNING: THIS WILL DESTROY THE ORIGINAL MODEL, SO `reset` DOES NOTHING!
void remesh() {
  TetmeshIn tetmesh_in;
  TetmeshOut tetmesh_out;
  tetmesh_in.vertices = &U;
  tetmesh_in.faces = &TF;

  int error = make_tetmesh(tetmesh_in, tetmesh_out);
  if (error) {
    std::cerr << "[ERR] tetesh returned " << error << std::endl;
    exit(1);
  }

  TV = tetmesh_out.vertices;
  U = TV;
  TT = tetmesh_out.tets;
  TF = tetmesh_out.faces;
  TF2T = tetmesh_out.face2tets;
  TT2F = tetmesh_out.tet2faces;
}

int main(int argc, char *argv[]) {