【笔记】Libigl从入门到放弃

Libigl是一个轻量级的C++库,专注于离散几何处理,包括网格表示、法向量计算、可视化等功能。它使用Eigen库编码向量和矩阵,仅依赖C++标准库和Eigen。Libigl的可视化模块基于OpenGL,提供了一个glfw-based Viewer,支持多网格、多视图和交互操作。此外,库中还包括了标量场的可视化、键盘鼠标交互、高斯曲率和平均曲率的计算。该库对于几何建模和计算非常有用。

主要内容

  • Libigl基本知识
  • 离散几何参量与算子

Libigl基本知识

Libigl设计原则

  1. 没有复杂的数据类型。只使用矩阵和向量;
  2. 尽可能减少对外部库的依赖
  3. 只有头文件(也可以做一个静态编译库)
  4. 函数封装性

下载Libigl

git clone https://github.com/libigl/libigl.git

Ligigl核心功能只依赖C++标准库和Eigen

但是编译起来还是挺费劲的,哈!

Mesh表示

Libigl使用Eigen库编码向量和矩阵

Eigen参考指南: Dense matrixSpase matrix

一个三角网格编码为一对矩阵:

Eigen::MatrixXd V;
Eigen::MatrixXi F;
  • V是#N*3的矩阵,每一行存储一个顶点(xyz);
  • F是连通关系,每一行存储组成三角形的三个顶点的下标
  • F中顶点的下标顺序决定了三角形的朝向

这种编码方式的好处是:

  1. 节约内存和缓冲
  2. 使用下标而不是指针,调试起来很简约
  3. 数据很容易复制和序列化

Libigl提供从用网格格式的I/O函数

例如,读取off文件并写出obj文件

igl::readOFF(path, V, F);
igl::writeOBJ(name, V, F);

可视化表面

Libigl使用glfw-based OpenGL 3.2 viewer来可视化surface。同时提供了glfw的相关性质

// Plot a mesh
igl::opengl::glfw::Viewer viewer;
viewer.data().set_mesh(V, F);
viewer.launch();
  • set_mesh()把网格数据拷贝给viewer,launch()创建一个glfw的窗口
  • 默认相机模式是2-axis,可以改成3-axis trackboall模式:
viewer.core().set_rotation_type(igl::opengl::ViewerCore::ROTATION_TYPE_TRACKBALL);
  • 可以使用标准OpenGL代码来扩展Viewer

使用键鼠进行交互

通过在Viewer中注册事件触发器的回调函数,实现键鼠交互。支持以下几种类型:

bool (*callback_pre_draw)(Viewer& viewer);
bool (*callback_post_draw)(Viewer& viewer);
bool (*callback_mouse_down)(Viewer& viewer, int button, int modifier);
bool (*callback_mouse_up)(Viewer& viewer, int button, int modifier);
bool (*callback_mouse_move)(Viewer& viewer, int mouse_x, int mouse_y);
bool (*callback_mouse_scroll)(Viewer& viewer, float delta_y);
bool (*callback_key_down)(Viewer& viewer, unsigned char key, int modifiers);
bool (*callback_key_up)(Viewer& viewer, unsigned char key, int modifiers);
  • 使用键盘的最简单的例子就是通过按键,在不同网格模型之间切换
  • 在初始化Viewer后,注册回调函数
viewer.callback_key_down = &key_down;
  • 按键事件,在绘制新的mesh前记得要先清楚之前的mesh
bool key_down(igl::opengl::glfw::Viewer& viewer, unsigned char key, int modifier)
{
  if (key == '1')
  {
    viewer.data().clear();
    viewer.data().set_mesh(V1, F1);
    viewer.core.align_camera_center(V1,F1);
  }
  else if (key == '2')
  {
    viewer.data().clear();
    viewer.data().set_mesh(V2, F2);
    viewer.core.align_camera_center(V2,F2);
  }
  return false;
}

标量场的可视化

通过set_colors()可以为顶点或者面附着颜色

viewer.data().set_colors(C);
  • C是一个#C*3的矩阵,每一行是RGB值;C的行数必须和面片的数目顶点的数据相等。viewer根据数量自动决定是把颜色加到顶点还是面片上

逐顶点的标量场可以直接使用set_data

viewer.data().set_data(D);
  • D是#V*1的向量,每个顶点一个值;set_data会在三角形内线性插值出颜色;这个颜色是通过一个colormap查找得到的;默认的colormap是igl::COLOR_MAP_TYPE_VIRIDIS,有21个离散区间;可以自定义colormapset_colormap

Overlays (勉强翻译成图示)

Viewer还支持点、线和文本标签的可视化

viwer.data().add_points(P, Eigen::RowVector3d(r,g,b));
  • 绘制点,坐标是P的每一行,颜色统一是rgb;点的大小可以统一设置viewer.data().point_size
viewer.data().add_edges(P1,P2,Eigen::RowVector3d(r,g,b));
  • 绘制线,连接P1和P2的对应行的坐标,P1和P2必须是同大小
viewer.data().add_label(p, str);
  • 绘制标签,在位置p,字符串是str

例子105:使用Eigen快速找到模型的bounding box

Viewer菜单

Libigl使用Dear ImGui实现了默认菜单;也可以自制新的界面

例子106:自制菜单

多个网格

Libigl的Viewer提供绘制多个网格的功能。通过viewer.selected_data_index选择网格;默认index是0

例子107:绘制多个网格,使用键盘切换

多个视图

Libigl的Viewer提供基本的多视点绘制网格的功能

  • 通过View::append_core()可以添加view core。最多可以添加31个cores,每个core指派了一个unsigned int的id,通过Viewer::core(id)可以访问到
  • 如果有多于一个的view core,用户需要指定每个视窗的大小、位置。还需要明确当窗口大小变化时,这个视窗怎么跟着变

举个栗子:左右俩窗口


                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值