#1 正二十面体生成:
const double R = 1.0
const double m=sqrt(50-10*sqrt(5))/10*R;
const double m=sqrt(50+10*sqrt(5))/10*R;
// 添加顶点
OpenMesh::Vec3d vertices[] = {
{m, 0, n}, {m, 0, -n}, {-m, 0, n}, {-m, 0, -n}, {0, n, m}, {0, -n, m},
{0, n, -m}, {0, -n, -m}, {n, m, 0}, {-n, m, 0}, {n, -m, 0}, {-n, -m, 0}
};
std::vector<MyMesh::VertexHandle> vertexHandles;
std::vector<MyMesh::VertexHandle> faceVertices;
for (const auto& vertex : vertices) {
vertexHandles.push_back(mesh.add_vertex(MyMesh::Point(vertex[0], vertex[1], vertex[2])));
}
// 添加三角面片
int faces[][3] = {
{6, 4, 8}, {9, 4, 6}, {6, 3, 9}, {6, 1, 3}, {6, 8, 1},
{8, 10, 1}, {8, 0, 10}, {8, 4, 0}, {4, 2, 0}, {4, 9, 2},
{9, 11, 2}, {9, 3, 11}, {3, 1, 7}, {1, 10, 7}, {10, 0, 5},
{0, 2, 5}, {2, 11, 5}, {3, 7, 11}, {5, 11, 7}, {10, 5, 7}
};
for (const auto& face : faces) {
faceVertices.clear();
for (int i = 0; i < 3; ++i) {
faceVertices.push_back(vertexHandles[face[i]]);
}
mesh.add_face(faceVertices);
}
mesh.request_face_normals();
mesh.request_vertex_normals();
mesh.update_normals();
结果(Libigl下的显示):
#2 - Loop细分
这里直接采用OpenMesh自带的细分器,有兴趣可以自己写细分算法(参考:https://blog.youkuaiyun.com/qq_31804159/article/details/109147352)【后期考虑自己重学一遍】;
OpenMesh自带工具:
【代码文档】https://www.graphics.rwth-aachen.de/media/openmesh_static/Documentations/OpenMesh-7.1-Documentation/a01186.html
【实现方式】https://github.com/otherlab/openmesh/blob/master/Doc/subdivider.docu
//头文件要加的
#include <OpenMesh/Tools/Subdivider/Uniform/LoopT.hh>
OpenMesh::Subdivider::Uniform::LoopT<MyMesh> loopsuber;
loopsuber.attach(mesh);
loopsuber(4); //迭代了4次
结果:
这里的可视化工具用的Libigl,同时也有OpenGL的代码,后期该项目结束了再上传上使用说明.
源码:
#include <iostream>
#include <igl/readOFF.h>
#include <igl/opengl/glfw/Viewer.h>
#include <OpenMesh/Core/IO/MeshIO.hh>
#include <OpenMesh/Tools/Subdivider/Uniform/LoopT.hh>
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
#include <GL/glut.h>
#include <math.h>
#include <Windows.h>
#include <string>
#include <vector>
typedef OpenMesh::TriMesh_ArrayKernelT<> MyMesh;
using namespace std;
Eigen::MatrixXd V;
Eigen::MatrixXi F;
int main(int argc, char* argv[])
{
MyMesh mesh;
const double R = 1.0;
const double m = sqrt(50 - 10 * sqrt(5)) / 10 * R;
const double n = sqrt(50 + 10 * sqrt(5)) / 10 * R;
// 添加顶点
OpenMesh::Vec3d vertices_20[] = {
{m,0,n} ,{m,0,-n},{-m,0,n},{-m,0,-n},{0,n,m},{0,-n,m},
{0,n,-m},{0,-n,-m},{n,m,0},{-n,m,0},{n,-m,0},{-n,-m,0}
};
vector<MyMesh::VertexHandle> vertex20Handles;
std::vector<MyMesh::VertexHandle> face20Vertices;
for (const auto& vertex : vertices_20)
{
vertex20Handles.push_back(mesh.add_vertex(MyMesh::Point(vertex[0], vertex[1], vertex[2])));
}
// 添加三角面片
int faces[][3] = {
{6, 4, 8}, {9, 4, 6}, {6, 3, 9}, {6, 1, 3}, {6, 8, 1},
{8, 10, 1}, {8, 0, 10}, {8, 4, 0}, {4, 2, 0}, {4, 9, 2},
{9, 11, 2}, {9, 3, 11}, {3, 1, 7}, {1, 10, 7}, {10, 0, 5},
{0, 2, 5}, {2, 11, 5}, {3, 7, 11}, {5, 11, 7}, {10, 5, 7}
};
for (const auto& face : faces)
{
face20Vertices.clear();
for (int i = 0; i < 3; ++i) {
face20Vertices.push_back(vertex20Handles[face[i]]);
}
mesh.add_face(face20Vertices);
}
mesh.request_face_normals();
mesh.request_vertex_normals();
mesh.update_normals();
OpenMesh::Subdivider::Uniform::LoopT<MyMesh> loopsuber;
loopsuber.attach(mesh);
loopsuber(4);
const std::string file_saved = "test1.off";
// write mesh to studot
if (!OpenMesh::IO::write_mesh(mesh, file_saved))
{
std::cerr << "Error: cannot write mesh to" << file_saved << std::endl;
return 1;
}
//IGL Viewer
// Load a mesh in OFF format
igl::readOFF(file_saved, V, F);
Plot the mesh
igl::opengl::glfw::Viewer viewer;
viewer.data().set_mesh(V, F);
viewer.launch();
return 0;
}