Files
igl/tutorial/710_SCAF/main.cpp
T
Zhongshi 2726464472 Adding 2D version of SCAF for Bijective Maps and a tutorial (#752)
* Add scaf code

Add the tutorial entry

Tutorial entry for SCAF. still need polishing

Put -4 in the energy computation of scaf:SymmD

* 🏫 Insert SCAF to 711

Fixes in tutorial.md

updating tutorial.html

Fix for gcc 4.8

Remove 4.1

Refactoring scaf WIP

Further refactoring WIP

Code Cleaning

* 🔨 Improve SLIM interface

* ♻️ refactor SCAF with less lines

* ♻️ refactor harmonic with boundary

*  Add direct signature for scaf

* 📝 Change tutorial order wip

* 🏫 Timer in SLIM tutorial makes more sense

*  Add direct interface for SLIM

* 🎨 format SCAF code.

* 🐍 Python binding for slim and scaf

* 🐍 expose SLIMData (maybe elevate its status more in the future)

* 👽 🐍 deprecate PYBIND11_PLUGIN

*  harmonic with holes

* ♻️ SCAF, Decouple Initialization to tutorial

* 🏫 SCAF tutorial improvement

* 🏫 Tutorial order; insert scaf

* 🎨 Removing Adjusted_grad

*     🏫 Inserted SCAF, not messing around with tutorials order until the new page is online

* 💚 Fix for static build

* ♻️ Uniform SLIM and SCAF and  python binding canonical

* 🐛 Change in ScafData

* 🍎 Fix namespace for build

*  Introduced Mapping Energy Type to replace adhoc SLIMEnergy

* ♻️ Refactor subroutines from SLIM

* Revert python changes

* leave fill hole outside harmonic

* Revert Python changes

* hole fill

* Minor Fixes for SCAF

SCAF->IGL_SCAF
Topological_hole_fill 
"<igl/XXX>" in slim tutorial


Former-commit-id: 4edf5dede5
2018-10-14 17:55:36 -04:00

128 lines
3.5 KiB
C++
Executable File

#include <igl/scaf.h>
#include <igl/arap.h>
#include <igl/boundary_loop.h>
#include <igl/harmonic.h>
#include <igl/map_vertices_to_circle.h>
#include <igl/readOBJ.h>
#include <igl/Timer.h>
#include <igl/opengl/glfw/Viewer.h>
#include <igl/MappingEnergyType.h>
#include <igl/doublearea.h>
#include <igl/PI.h>
#include <igl/flipped_triangles.h>
#include <igl/topological_hole_fill.h>
#include "tutorial_shared_path.h"
Eigen::MatrixXd V;
Eigen::MatrixXi F;
Eigen::MatrixXd V_uv;
igl::Timer timer;
igl::SCAFData scaf_data;
bool show_uv = false;
float uv_scale = 0.2;
bool key_down(igl::opengl::glfw::Viewer& viewer, unsigned char key, int modifier)
{
if (key == '1')
show_uv = false;
else if (key == '2')
show_uv = true;
if (key == ' ')
{
timer.start();
igl::scaf_solve(scaf_data, 1);
std::cout << "time = " << timer.getElapsedTime() << std::endl;
}
const auto& V_uv = uv_scale * scaf_data.w_uv.topRows(V.rows());
if (show_uv)
{
viewer.data().clear();
viewer.data().set_mesh(V_uv,F);
viewer.data().set_uv(V_uv);
viewer.core.align_camera_center(V_uv,F);
}
else
{
viewer.data().set_mesh(V,F);
viewer.data().set_uv(V_uv);
viewer.core.align_camera_center(V,F);
}
viewer.data().compute_normals();
return false;
}
int main(int argc, char *argv[])
{
using namespace std;
// Load a mesh in OFF format
igl::readOBJ(TUTORIAL_SHARED_PATH "/camel_b.obj", V, F);
Eigen::MatrixXd bnd_uv, uv_init;
Eigen::VectorXd M;
igl::doublearea(V, F, M);
std::vector<std::vector<int>> all_bnds;
igl::boundary_loop(F, all_bnds);
// Heuristic primary boundary choice: longest
auto primary_bnd = std::max_element(all_bnds.begin(), all_bnds.end(), [](const std::vector<int> &a, const std::vector<int> &b) { return a.size()<b.size(); });
Eigen::VectorXi bnd = Eigen::Map<Eigen::VectorXi>(primary_bnd->data(), primary_bnd->size());
igl::map_vertices_to_circle(V, bnd, bnd_uv);
bnd_uv *= sqrt(M.sum() / (2 * igl::PI));
if (all_bnds.size() == 1)
{
if (bnd.rows() == V.rows()) // case: all vertex on boundary
{
uv_init.resize(V.rows(), 2);
for (int i = 0; i < bnd.rows(); i++)
uv_init.row(bnd(i)) = bnd_uv.row(i);
}
else
{
igl::harmonic(V, F, bnd, bnd_uv, 1, uv_init);
if (igl::flipped_triangles(uv_init, F).size() != 0)
igl::harmonic(F, bnd, bnd_uv, 1, uv_init); // fallback uniform laplacian
}
}
else
{
// if there is a hole, fill it and erase additional vertices.
all_bnds.erase(primary_bnd);
Eigen::MatrixXi F_filled;
igl::topological_hole_fill(F, bnd, all_bnds, F_filled);
igl::harmonic(F_filled, bnd, bnd_uv ,1, uv_init);
uv_init = uv_init.topRows(V.rows());
}
Eigen::VectorXi b; Eigen::MatrixXd bc;
igl::scaf_precompute(V, F, uv_init, scaf_data, igl::MappingEnergyType::SYMMETRIC_DIRICHLET, b, bc, 0);
// Plot the mesh
igl::opengl::glfw::Viewer viewer;
viewer.data().set_mesh(V, F);
const auto& V_uv = uv_scale * scaf_data.w_uv.topRows(V.rows());
viewer.data().set_uv(V_uv);
viewer.callback_key_down = &key_down;
// Enable wireframe
viewer.data().show_lines = true;
// Draw checkerboard texture
viewer.data().show_texture = true;
std::cerr << "Press space for running an iteration." << std::endl;
std::cerr << "Press 1 for Mesh 2 for UV" << std::endl;
// Launch the viewer
viewer.launch();
}