This repository has been archived on 2024-12-30. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.
2024CG-project-render/include/QuadViewer.h
github-classroom[bot] 5985bb8445
Initial commit
2024-10-24 10:26:51 +00:00

141 lines
4.6 KiB
C++

#ifndef QUADVIEWER_H
#define QUADVIEWER_H
#include <igl/opengl/glfw/Viewer.h>
#include <Eigen/Core>
#include <cassert>
#include <string>
class QuadViewer
{
public:
igl::opengl::glfw::Viewer viewer;
std::function<bool(igl::opengl::glfw::Viewer& viewer, unsigned int key, int modifiers)> callback_key_pressed;
bool show_lines;
public:
QuadViewer():show_lines(true),
// Important to initialize function
callback_key_pressed([](igl::opengl::glfw::Viewer& viewer, unsigned int key, int modifiers)->bool{return false;})
{
std::cout<<R"(QuadViewer usage:
F,f [disabled]
L,l Show/hide quad eges
U,u Show/hide texture
)";
viewer.data().show_lines = false;
viewer.callback_key_pressed = [this](
igl::opengl::glfw::Viewer & /*viewer*/,
unsigned int key,
int modifier)->bool
{
if(!callback_key_pressed(viewer,key,modifier))
{
switch(key)
{
default:
return false;
case 'F':
case 'f':
// Disable Toggling "face based" since we want control of quad-mesh
// appearance
break;
case 'L':
case 'l':
// Usurp the Toggling "show lines" and map to showing overlay instead
show_lines = !show_lines;
viewer.data().show_overlay = show_lines;
break;
case 'U':
case 'u':
viewer.data().show_texture = !viewer.data().show_texture;
break;
}
}
return true;
};
}
// Set the mesh of .data() to be an exploded version of the given quad mesh
//
// Inputs:
// V #V by 3 mesh vertex positions
// F #F by 4 quad indices into V
void set_mesh(
const Eigen::MatrixXd & V,
const Eigen::MatrixXd & UV,
const Eigen::MatrixXd & NV,
const Eigen::MatrixXi & F)
{
assert((UV.rows() == 0 || V.rows() == UV.rows()) && "V and UV should have same #rows");
assert((NV.rows() == 0 || V.rows() == NV.rows()) && "V and NV should have same #rows");
// libigl Viewer does not handle quad meshes well by default
// Explode the quad mesh into quad soup. Then each quad can have smooth
// normals: faceted-quad appearance
Eigen::MatrixXd FV(F.rows()*4,V.cols());
Eigen::MatrixXd FUV,FNV;
if(UV.rows() != 0) FUV.resize(F.rows()*4,UV.cols());
if(NV.rows() != 0) FNV.resize(F.rows()*4,NV.cols());
Eigen::MatrixXi FF(F.rows(),4);
for(int f = 0;f<F.rows();f++)
{
for(int c = 0;c<4;c++)
{
FF(f,c) = c+f*4;
FV.row(FF(f,c)) = V.row(F(f,c));
if(UV.rows() != 0) FUV.row(FF(f,c)) = UV.row(F(f,c));
if(NV.rows() != 0) FNV.row(FF(f,c)) = NV.row(F(f,c));
}
}
Eigen::MatrixXi T(FF.rows()*2,3);
T<<
FF.col(0), FF.col(1), FF.col(2),
FF.col(0), FF.col(2), FF.col(3);
viewer.data().clear();
viewer.data().set_mesh(FV,T);
if(NV.rows() != 0) viewer.data().set_normals(FNV);
if(UV.rows() != 0) viewer.data().set_uv(FUV);
viewer.data().set_face_based(false);
Eigen::MatrixXi E(FF.rows()*4,2);
E<<
FF.col(0), FF.col(1),
FF.col(1), FF.col(2),
FF.col(2), FF.col(3),
FF.col(3), FF.col(0);
viewer.data().set_edges(FV,E,Eigen::RowVector3d(0,0,0));
}
// Wrapper without UV and NV
void set_mesh(
const Eigen::MatrixXd & V,
const Eigen::MatrixXi & F)
{
return set_mesh(V,Eigen::MatrixXd(),Eigen::MatrixXd(),F);
}
// Explode all data to be per-corner so libigl viewer can handle it.
void set_mesh(
const Eigen::MatrixXd & V,
const Eigen::MatrixXi & F,
const Eigen::MatrixXd & UV,
const Eigen::MatrixXi & UF,
const Eigen::MatrixXd & NV,
const Eigen::MatrixXi & NF)
{
Eigen::MatrixXd vV(F.rows()*F.cols(),V.cols());
Eigen::MatrixXd vUV(F.rows()*F.cols(),UV.cols());
Eigen::MatrixXd vNV(F.rows()*F.cols(),NV.cols());
Eigen::MatrixXi vF(F.rows(),F.cols());
for(int f = 0;f<F.rows();f++)
{
for(int c = 0;c<F.cols();c++)
{
const int vi = f*F.cols()+c;
vV.row(vi) = V.row(F(f,c));
vUV.row(vi) = UV.row(UF(f,c));
vNV.row(vi) = NV.row(NF(f,c));
vF(f,c) = vi;
}
}
set_mesh(vV,vUV,vNV,vF);
}
// Pass through to igl::opengl::glfw::Viewer::launch
int launch(bool fullscreen = false)
{ return viewer.launch(fullscreen); }
};
#endif