* PlainObject -> MatrixBase * template igl::Hit * vector input intersect rays with multiple hits * initialize * initialize * only write if hit * fix templates * template me baby * templates * my god. so many PlainObject -> Matrix; Derived -> PlainMatrix<Derived> * Options doesn't exist for Maps/Refs * templates; windows size_t shinanigans * Derived->PlainMatrix * windows template * derived -> plainvector * options * fix templating * std types * fix windingnumbertree tempalting * further fix windingnumbertree tempalting * Xi->XI * templating * clean up and template some of the decimation code; eventually gave up on templating outer functions * rm needless cast * attempt to fix index templating in boolean code * remove debugging casts * more templatin hell * debug kruft * vector resize * assert * int -> template * int -> template * int -> template * templating away more Xi * templating away more 3i * formatting * vector * plainmatrix * plainmatrix * bug * templating MSH io * remove use of Map * zero default tags * bug fix * file debug flags * __1:: * better typing * knn tempalte * note * templating * reorder scaf inputs * fix build * doc * templates * messier than I thought * doc * Xi -> XI * use templated type * 1x1 is always symmetric * use index type * split intrinsic * templating * template internal
127 lines
3.3 KiB
C++
127 lines
3.3 KiB
C++
#include <igl/triangle/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>
|
|
|
|
|
|
Eigen::MatrixXd V;
|
|
Eigen::MatrixXi F;
|
|
Eigen::MatrixXd V_uv;
|
|
igl::Timer timer;
|
|
igl::triangle::SCAFData scaf_data;
|
|
|
|
bool show_uv = false;
|
|
float uv_scale = 0.2f;
|
|
|
|
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::triangle::scaf_solve(1,scaf_data);
|
|
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, all_bnds, F_filled);
|
|
igl::harmonic(F_filled, bnd, bnd_uv ,1, uv_init);
|
|
uv_init.conservativeResize(V.rows(), 2);
|
|
}
|
|
|
|
Eigen::VectorXi b; Eigen::MatrixXd bc;
|
|
igl::triangle::scaf_precompute(V, F, uv_init, igl::MappingEnergyType::SYMMETRIC_DIRICHLET, b, bc, 0, scaf_data);
|
|
|
|
// 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();
|
|
}
|