M CMakeLists.txt => CMakeLists.txt +4 -0
@@ 29,4 29,8 @@ add_executable(size mesh.cpp size.cpp)
target_link_libraries(size igl::core igl::tetgen)
target_compile_options(size PRIVATE -g -O2 -Wall -Werror -Wpedantic -DDEBUG)
+add_executable(2obj 2obj.cpp)
+target_link_libraries(2obj igl::core)
+target_compile_options(2obj PRIVATE -g -O2 -Wall -Werror -Wpedantic -DDEBUG)
+
igl_download_tutorial_data()
M README.md => README.md +20 -0
@@ 10,3 10,23 @@
- Handle intersections when having forces
+
+## Scripts
+
+Convert all files from one format to `obj`:
+
+```bash
+OUT_DIR="./meshes"
+FMT="ply"
+DIR="./libigl/tutorial/data"
+MODELS=$(find "$DIR" -type f -iname "*.$FMT")
+for model in $MODELS; do
+ f=${model##*/}
+ build/2obj $model "$OUT_DIR"/${f/$FMT/obj}
+done
+```
+
+Get scores from the output of `find-good-models.sh`:
+```
+awk '/file/ {printf "%45s", $0} /score/{print $0}'
+```
M evaluate.cpp => evaluate.cpp +11 -9
@@ 73,20 73,22 @@ double score_mesh(Mesh &mesh, int iterations, int range) {
Vector3d plane_point;
{ /* Find the point on which the cut plane is */
- std::vector<Vector3d> projecteds;
- std::vector<double> dots;
+ Vector3d moldables(0, 0, 0), non_moldables(0, 0, 0);
+ int n_moldables = 0, n_non_moldables = 0;
for (int f = 0; f < mesh.faces.rows(); f++) { /* O(F) */
Vector3d normal = mesh.normals.row(f);
if (normal.dot(dir) >= 0.0) {
- Vector3d center = face_center(mesh, f);
- double dot = center.dot(dir);
- Vector3d projected = dir * dot;
- dots.push_back(dot);
- projecteds.push_back(center - projected);
+ moldables += face_center(mesh, f);
+ n_moldables++;
+ } else {
+ non_moldables += face_center(mesh, f);
+ n_non_moldables++;
}
}
- double avg_dot = avg(dots, 0.0);
- plane_point = avg(projecteds, Vector3d(0.0, 0.0, 0.0)) + avg_dot * dir;
+ moldables /= n_moldables;
+ non_moldables /= n_non_moldables;
+
+ plane_point = (moldables + non_moldables) / 2.0;
}
double moldable_area = 0.0;
M find-good-models.sh => find-good-models.sh +7 -2
@@ 1,8 1,13 @@
#!/bin/bash
-MODEL_DIR="./libigl/tutorial/data"
+MODEL_DIR="./meshes"
MODELS=$(find "$MODEL_DIR" -type f -iname "*.obj")
for model in $MODELS; do
- build/size -t $model && build/evaluate $model -i1
+ build/size -t $model 2>/dev/null
+ if [[ $? == 0 ]]; then
+ build/evaluate $model -i100 -r8
+ else
+ printf ">> File '%s' failed\n" "$model"
+ fi
done
M main.cpp => main.cpp +14 -14
@@ 57,7 57,7 @@ void update_vectors() {
plane_n = fplane_n.cast<double>().normalized();
}
-void update_viewer(Mesh &mesh) {
+void update_viewer(Viewer &viewer, Mesh &mesh) {
forces_colors = MatrixXd::Zero(mesh.vertices.rows(), 3);
for (int v = 0; v < mesh.vertices.rows(); v++) {
auto force = mesh.forces.row(v);
@@ 69,9 69,14 @@ void update_viewer(Mesh &mesh) {
forces_colors(v, i) = c[i];
}
+ draw_plane(viewer, mesh);
viewer.data().set_mesh(mesh.vertices, mesh.faces);
viewer.data().set_normals(mesh.normals);
viewer.data().set_colors(mesh.face_colors);
+
+ if (show_forces) {
+ viewer.data().add_edges(mesh.vertices, forces_endpoints, forces_colors);
+ }
}
// Draw the custom menu
@@ 125,7 130,6 @@ void draw_menu(Mesh &mesh) {
if (ImGui::Button("Step ARAP")) {
step_arap(mesh);
- update_viewer(mesh);
}
// Attempt at remeshing: Doesn't really work, since we probably need to tell it that we should
@@ 158,6 162,7 @@ void draw_menu(Mesh &mesh) {
mesh.forces = MatrixXd::Zero(mesh.vertices.rows(), mesh.vertices.cols());
recompute |= true;
}
+
if (stitching) {
ImGui::Indent();
ImGui::Checkbox("Show Forces", &show_forces);
@@ 165,7 170,8 @@ void draw_menu(Mesh &mesh) {
recompute |= true;
if (ImGui::Checkbox("Force ~ Area", &area_force))
recompute |= true;
- if (ImGui::SliderFloat("Distance Cutoff", &force_dist_cutoff, 0.1, 10.0, "%.2f"))
+ ImGui::Checkbox("Distance Cutoff", &force_cutoff);
+ if (force_cutoff && ImGui::SliderFloat("Distance Cutoff", &force_dist_cutoff, 0.1, 10.0, "%.2f"))
recompute |= true;
ImGui::Unindent();
}
@@ 207,7 213,6 @@ void draw_menu(Mesh &mesh) {
if (recompute) {
compute_things(mesh);
- update_viewer(mesh);
}
}
@@ 264,10 269,6 @@ void draw_plane(Viewer &viewer, Mesh &mesh) {
Eigen::RowVector3d c(1.0, 1.0, 1.0);
viewer.data().add_edges(planeEA, planeEB, c);
-
- if (show_forces) {
- viewer.data().add_edges(mesh.vertices, forces_endpoints, forces_colors);
- }
}
int main(int argc, char *argv[]) {
@@ 333,7 334,6 @@ int main(int argc, char *argv[]) {
menu.callback_draw_viewer_menu = [&menu]() { menu.draw_viewer_menu(); };
viewer.callback_pre_draw = [&mesh](Viewer &viewer) {
- draw_plane(viewer, mesh);
if (run_with_update) {
if (step_arap(mesh) == StepReturn::Converged) {
mesh.rest_state = mesh.vertices;
@@ 345,7 345,7 @@ int main(int argc, char *argv[]) {
step_arap(mesh);
}
}
- update_viewer(mesh);
+ update_viewer(viewer, mesh);
return false;
};
@@ 354,12 354,12 @@ int main(int argc, char *argv[]) {
run_arap = !run_arap;
} else if (key == '.') {
step_arap(mesh);
- update_viewer(mesh);
+ update_viewer(viewer, mesh);
} else if (key == 'R') {
mesh.vertices = mesh.rest_state = tetmesh_out.vertices;
arap::precomputation(mesh, arap_data);
compute_things(mesh);
- update_viewer(mesh);
+ update_viewer(viewer, mesh);
} else if (key == 'P') {
Eigen::Matrix<unsigned char, Eigen::Dynamic, Eigen::Dynamic> R(1280, 800);
Eigen::Matrix<unsigned char, Eigen::Dynamic, Eigen::Dynamic> G(1280, 800);
@@ 372,10 372,10 @@ int main(int argc, char *argv[]) {
};
viewer.data().clear();
- viewer.data().set_face_based(true);
+ // viewer.data().set_face_based(true);
+ viewer.data().set_mesh(mesh.vertices, mesh.faces);
viewer.core().is_animating = true;
compute_things(mesh);
- update_viewer(mesh);
viewer.launch();
}
M surcut.cpp => surcut.cpp +6 -3
@@ 11,6 11,7 @@ std::vector<double> dots;
bool regular_arap = false;
float force_scale = 1.0;
bool area_force = false;
+bool force_cutoff = false;
float force_dist_cutoff = 1.0;
int iteration_count = 0;
bool stitching = false;
@@ 253,8 254,9 @@ void compute_things(Mesh &mesh, double scale, bool only_plane) {
Vector3d other_vertex = mesh.vertices.row(other_i);
auto force_direction = other_vertex - vertex;
- if (force_direction.norm() > scale * force_dist_cutoff)
- continue;
+ if (force_cutoff)
+ if (force_direction.norm() > scale * force_dist_cutoff)
+ continue;
// XXX(todo): what should the magnitude of the force be? Should probably take a closer look
// at the dynamics implementation in `arap-mold.cpp`.
@@ 264,8 266,9 @@ void compute_things(Mesh &mesh, double scale, bool only_plane) {
force_direction * area * (double)force_scale * force_direction.squaredNorm() / scale;
mesh.forces.row(v) += force;
- if (forces_endpoints_ptr)
+ if (forces_endpoints_ptr) {
forces_endpoints_ptr->row(v) = other_vertex;
+ }
mesh.forces.row(other_i) -= force; // Should this depend on area of `other_i`?
}
}
M surcut.h => surcut.h +2 -0
@@ 25,6 25,8 @@ extern bool regular_arap;
extern float force_scale;
// Multiply forces with the face area
extern bool area_force;
+// Perform force distance cutoff
+extern bool force_cutoff;
// Force distance cutoff
extern float force_dist_cutoff;
// The number of ARAP iterations performed