【libigl】网格布尔运算

一、网格上的布尔运算 (6.09)

ae2805792417677a3b149111f037443b.png

igl::copyleft::cgal::mesh_boolean(VA,FA,VB,FB,MESH_BOOLEAN_TYPE_UNION,VC,FC);

下图显示了两个网格上的每个布尔运算。

775bccf5eda4d953953f397f29083841.jpeg

布尔示例对 Cheburashka(红色)和 Knight(绿色)进行布尔运算。从左到右:并集、交集、集合减、对称差 (XOR)、“解析”。底行显示内表面,较深的颜色表示背面的三角形。

并、对称差和“解”的外观相同,但内部结构的处理不同。联合没有内表面:三角形不包含在输出中。对称差异是与“解析”相同的一组三角形,但内表面的方向已反转,表明操作的实体结果。“解析”操作并不是真正的布尔运算,它只是解析所有交点并将重合顶点粘合在一起的结果,保持原始三角形方向。

Libigl 还为软木塞提供了一个包装器 igl::copyleft::cork::mesh_boolean ,它通常速度更快,但并不总是健壮。

#include <igl/readOFF.h> // 引入igl库的readOFF函数,用于读取OFF文件
//#undef IGL_STATIC_LIBRARY
#include <igl/copyleft/cgal/mesh_boolean.h> // 引入igl库的mesh_boolean函数,用于进行网格布尔运算
#include <igl/opengl/glfw/Viewer.h> // 引入igl库的Viewer类,用于创建OpenGL窗口并进行渲染


#include <Eigen/Core> // 引入Eigen库的Core模块,提供了矩阵和向量的基本操作
#include <iostream> // 引入iostream库,提供了用于输入/输出的函数


Eigen::MatrixXd VA,VB,VC; // 定义三个矩阵,用于存储三个网格的顶点坐标
Eigen::VectorXi J,I; // 定义两个向量,用于存储网格布尔运算的结果
Eigen::MatrixXi FA,FB,FC; // 定义三个矩阵,用于存储三个网格的面片索引
igl::MeshBooleanType boolean_type( // 定义一个MeshBooleanType类型的变量,用于指定网格布尔运算的类型
  igl::MESH_BOOLEAN_TYPE_UNION); // 初始化为并集运算


const char * MESH_BOOLEAN_TYPE_NAMES[] = // 定义一个字符串数组,用于存储网格布尔运算类型的名称
{
  "Union",
  "Intersect",
  "Minus",
  "XOR",
  "Resolve",
};


void update(igl::opengl::glfw::Viewer &viewer) // 定义一个函数,用于更新视图
{
  igl::copyleft::cgal::mesh_boolean(VA,FA,VB,FB,boolean_type,VC,FC,J); // 对两个网格进行布尔运算,结果存储在VC, FC和J中
  Eigen::MatrixXd C(FC.rows(),3); // 定义一个矩阵,用于存储每个面片的颜色
  for(size_t f = 0;f<C.rows();f++) // 遍历所有的面片
  {
    if(J(f)<FA.rows()) // 如果当前面片属于第一个网格
    {
      C.row(f) = Eigen::RowVector3d(1,0,0); // 设置颜色为红色
    }else // 如果当前面片属于第二个网格
    {
      C.row(f) = Eigen::RowVector3d(0,1,0); // 设置颜色为绿色
    }
  }
  viewer.data().clear(); // 清除当前的数据
  viewer.data().set_mesh(VC,FC); // 设置新的网格
  viewer.data().set_colors(C); // 设置颜色
  std::cout<<"A "<<MESH_BOOLEAN_TYPE_NAMES[boolean_type]<<" B."<<std::endl; // 输出当前的布尔运算类型
}


bool key_down(igl::opengl::glfw::Viewer &viewer, unsigned char key, int mods) // 定义一个函数,用于处理键盘按下的事件
{
  switch(key) // 根据按下的键进行判断
  {
    default:
      return false;
    case '.': // 如果按下的是'.'
      boolean_type = // 切换到下一个布尔运算类型
        static_cast<igl::MeshBooleanType>(
          (boolean_type+1)% igl::NUM_MESH_BOOLEAN_TYPES);
      break;
    case ',': // 如果按下的是','
      boolean_type = // 切换到上一个布尔运算类型
        static_cast<igl::MeshBooleanType>(
          (boolean_type+igl::NUM_MESH_BOOLEAN_TYPES-1)%
          igl::NUM_MESH_BOOLEAN_TYPES);
      break;
    case '[': // 如果按下的是'['
      viewer.core().camera_dnear -= 0.1; // 将近裁剪面向摄像机方向移动
      return true;
    case ']': // 如果按下的是']'
      viewer.core().camera_dnear += 0.1; // 将近裁剪面向远离摄像机的方向移动
      return true;
  }
  update(viewer); // 更新视图
  return true;
}


int main(int argc, char *argv[]) // 主函数
{
  using namespace Eigen; // 使用Eigen命名空间
  using namespace std; // 使用std命名空间
  igl::readOFF(TUTORIAL_SHARED_PATH "/cheburashka.off",VA,FA); // 读取第一个网格
  igl::readOFF(TUTORIAL_SHARED_PATH "/decimated-knight.off",VB,FB); // 读取第二个网格
  // Plot the mesh with pseudocolors
  igl::opengl::glfw::Viewer viewer; // 创建一个Viewer对象


  // Initialize
  update(viewer); // 初始化视图


  viewer.data().show_lines = true; // 显示网格线
  viewer.callback_key_down = &key_down; // 设置键盘按下的回调函数
  viewer.core().camera_dnear = 3.9; // 设置近裁剪面的位置
  cout<<
    "Press '.' to switch to next boolean operation type."<<endl<<
    "Press ',' to switch to previous boolean operation type."<<endl<<
    "Press ']' to push near cutting plane away from camera."<<endl<<
    "Press '[' to pull near cutting plane closer to camera."<<endl<<
    "Hint: investigate _inside_ the model to see orientation changes."<<endl; // 输出提示信息
  viewer.launch(); // 启动视图
}

此段代码展示了使用libigl库进行两个3D网格模型之间的布尔运算,并在igl::opengl::glfw::Viewer中进行展示。布尔运算包括并集、交集、差集、异或和解析等操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值