@@ 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;
@@ 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[]) {