简介
没有 cc 细分好。
参考链接
http://graphics.stanford.edu/courses/cs468-10-fall/LectureSlides/10_Subdivision.pdf 非常好对于细分的介绍
细分示意图
codeTip
代码实现过程,比较潦草。主要看第一张示意图,由于openmesh在加面的时候需要判断面的法向,做的比较粗糙,但是对于立方体的细分是支持的。
code
#include "doo_sabin_surface_subdivision.h"
#include <iostream>
#include <unordered_map>
#include <QInputDialog>
/**
* @description: 构造函数
* @param {type}
* @return {type}
*/
DS::DS(Data* data_) : Strategy(data_) {
times = 1;
genCube();
}
/**
* @description: 析构函数
* @param {type}
* @return {type}
*/
DS::~DS() {}
/*!
* Computes the weight factor for the ith vertex of a face with k
* vertices. The formula of Doo and Sabin is used.
*
* @param i Index of vertex in face (0, 1, ..., k-1)
* @param k Number of vertices
*
* @return Weight
*/
inline double DS::weights_doo_sabin(size_t k, size_t i)
{
if (i == 0)
return(0.25 + 5.0 / (4.0 * k));
else
return((3.0 + 2.0 * cos(2 * M_PI * i / k)) / (4.0 * k));
}
/**
* @description: 一整套流程
* @param {type}
* @return {int} 管线运行是否成功
*/
bool DS::Run() {
times = QInputDialog::getInt(this, "Surface Mesh", "Please input times",
1, 1, 1000, 1);
for (int i = 0; i <= times; i++) {
if (i == 0) {
char a[20];
sprintf(a, "output%d.off", i);
genMesh(a);
}
else {
genFacePoint();
genEdgePoint();
genVertexPoint();
connectPoints();
char a[20];
sprintf(a, "output%d.off", i);
genMesh(a);
}
// 清空变量
std::cout << "[DEBUG] 迭代了第 " << i << " 次。" << std::endl;
}
getResult();
return true;
}
/**
* @description: 生成一个立方体(四边形网格)
* @param {type}
* @return {type}
*/
void DS::genCube()
{
MyMesh::VertexHandle vhandle[9];
vhandle[0] = mesh.add_vertex(MyMesh::Point(-1, -1, 1));
vhandle[1] = mesh.add_vertex(MyMesh::Point(1, -1, 1));
vhandle[2] = mesh.add_vertex(MyMesh::Point(1, 1, 1));
vhandle[3] = mesh.add_vertex(MyMesh::Point(-1, 1, 1));
vhandle[4] = mesh.add_vertex(MyMesh::Point(-1, -1, -1));
vhandle[5] = mesh.add_vertex(MyMesh::Point(1, -1, -1));
vhandle[6] = mesh.add_vertex(MyMesh::Point(1, 1, -1));
vhandle[7] = mesh.add_vertex(MyMesh::Point(-1, 1, -1));
std::vector<MyMesh::VertexHandle> face_vhandles;
face_vhandles.push_back(vhandle[0]);
face_vhandles.push_back(vhandle[1]);
face_vhandles.push_back(vhandle[2]);
face_vhandles.push_back(vhandle[3]);
mesh.add_face(face_vhandles);
face_vhandles.clear();
face_vhandles.push_back(vhandle[7]);
face_vhandles.push_back(vhandle[6]);
face_vhandles.push_back(vhandle[5]);
face_vhandles.push_back(vhandle[4]);
mesh.add_face(face_vhandles);
face_vhandles.clear();
face_vhandles.push_back(vhandle[1]);
face_vhandles.push_back(vhandle[0]);
face_vhandles.push_back(vhandle[4]);
face_vhandles.push_back(vhandle[5]);
mesh.add_face(face_vhandles);
face_vhandles.clear();
face_vhandles.push_back(vhandle[2]);
face_vhandles.push_back(vhandle[1]);
face_vhandles.push_back(vhandle[5]);
face_vhandles.push_back(vhandle[6]);
mesh.add_face(face_vhandles);
face_vhandles.clear();
face_vhandles.push_back(vhandle[3]);
face_vhandles.push_back(vhandle[2]);
face_vhandles.push_back(vhandle[6]);
face_vhandles.push_back(vhandle[7]);
mesh.add_face(face_vhandles);
face_vhandles.clear();
face_vhandles.push_back(vhandle[0]);
face_vhandles.push_back(vhandle[3]);
face_vhandles.push_back(vhandle[7]);
face_vhandles.push_back(vhandle[4]);
mesh.add_face(face_vhandles);
}
/**
* @description: 生成所有面点
* @param {type} TODO
* @return {type}
*/
void DS::genFacePoint()
{
facePoints.clear();
for (const auto& fh : mesh.faces())
{
OpenMesh::Vec3d facePoint(0, 0, 0);
int facePointsNumber = 0;
for (const auto& fvh : mesh.fv_range(fh))
{
OpenMesh::DefaultTraits::Point point = mesh.point(fvh);
facePoint += point;
facePointsNumber++;
}
facePoint /= facePointsNumber;
facePoints[fh.idx()] = facePoint;
}
}
/**
* @description: 生成所有的边点暂时不考虑hole 就是全是日子结构的
* @param {type}
* @return {type}
*/
void DS::genEdgePoint()
{
edgePoints.clear();
for (auto e_it = mesh.edges_begin(); e_it != mesh.edges_end(); ++e_it)
{
// 得到边所代表的半边
OpenMesh::HalfedgeHandle heh1 = mesh.halfedge_handle(*e_it, 0); // 默认一个方向的半边
OpenMesh::Vec3d edgePoint(0, 0, 0);
int edgePointsNumber = 0;
OpenMesh::DefaultTraits::Point pointV = mesh.point(mesh.from_vertex_handle(heh1)); // 这条(半)边的起点
OpenMesh::DefaultTraits::Point pointW = mesh.point(mesh.to_vertex_handle(heh1)); // 这条(半)边的终点
edgePoints[heh1.idx()] = (pointV + pointW) / 2.0;
}
}
/**
* @description: 生成新的顶点
* @param {type}
* @return {type}
*/
void DS::genVertexPoint()
{
vertexPoints.clear();
vertexPoints_.clear();
// 原始点接触的面的所有的面点的均值
for (auto v_it = mesh.vertices_begin(); v_it != mesh.vertices_end(); v_it++)
{
OpenMesh::Vec3d originPoint = (OpenMesh::Vec3d)mesh.point(*v_it);
OpenMesh::Vec3d facePoint(0, 0, 0);
int faceNumber = 0;
std::vector<OpenMesh::Vec3d> facePoints_;
std::vector<OpenMesh::Vec3d> edgePoints_;
for (auto vf_it = mesh.vf_iter(*v_it); vf_it.is_valid(); ++vf_it)
{ //这个顶点所带有的面迭代器
facePoints_.push_back(facePoints[(*vf_it).idx()]);
}
// 原始点接触的边的中间点的值的均值 * 2
OpenMesh::Vec3d edgePoint(0, 0, 0);
int edgeNumber = 0;
for (auto vv_it = mesh.vv_begin(*v_it); vv_it != mesh.vv_end(*v_it); vv_it++) { // 为啥还有孤立点?
OpenMesh::Vec3d point = (OpenMesh::Vec3d)mesh.point(*vv_it);
edgePoints_.push_back((point + originPoint) / 2.0);
}
int index = 0;
for (auto vf_it = mesh.vf_iter(*v_it); vf_it.is_valid(); ++vf_it)
{ //这个顶点所带有的面迭代器
vertexPoints_[(*v_it).idx()].push_back(1.0/4.0*(originPoint + edgePoints_[index] +
edgePoints_[(index - 1 + edgePoints_.size())% edgePoints_.size()] + facePoints_[index]));
index++;
}
}
}
/**
* @description: 连接面点和边点 (要严格的封闭的四边形)
* @param {type}
* @return {type}
*/
void DS::connectPoints() {
if (!mesh.has_vertex_status()) mesh.request_vertex_status();
if (!mesh.has_face_status()) mesh.request_face_status();
if (!mesh.has_edge_status()) mesh.request_edge_status();
std::vector<MyMesh::VertexHandle> vertexDelHandle;// 存储将要删除的顶点
for (const auto& v : mesh.vertices()) {
vertexDelHandle.push_back(v);
}
// 加入所有新增节点
std::vector<MyMesh::VertexHandle> facePointsHandle;
std::vector<std::vector<MyMesh::VertexHandle>> faceHandles;
std::map<OpenMesh::Vec3d, MyMesh::VertexHandle> out;
for (const auto& v : vertexPoints_) {
std::vector<MyMesh::VertexHandle> facePointHandle;
for (const auto& vv : v.second) {
facePointHandle.push_back(mesh.add_vertex((OpenMesh::DefaultTraits::Point)vv));
out[vv] = facePointHandle[facePointHandle.size() - 1];
}
faceHandles.push_back(facePointHandle);
}
std::vector<std::vector<MyMesh::VertexHandle>> faceEdgeHandles;
std::vector<std::vector<MyMesh::VertexHandle>> faceFaceHandles;
// 距离边最近的四个顶点构成一个面
int iindex = 0;
for (auto e_it = mesh.edges_begin(); e_it != mesh.edges_end(); ++e_it)
{
// 得到边所代表的半边
OpenMesh::HalfedgeHandle heh1 = mesh.halfedge_handle(*e_it, 0); // 默认一个方向的半边
OpenMesh::Vec3d edgePoint(0, 0, 0);
int edgePointsNumber = 0;
OpenMesh::DefaultTraits::Point pointV = mesh.point(mesh.from_vertex_handle(heh1)); // 这条(半)边的起点
OpenMesh::DefaultTraits::Point pointW = mesh.point(mesh.to_vertex_handle(heh1)); // 这条(半)边的终点
std::vector<OpenMesh::Vec3d> vs;
for (const auto& vt : vertexPoints_[mesh.from_vertex_handle(heh1).idx()]) {
vs.push_back(vt);
}
for (const auto& vt : vertexPoints_[mesh.to_vertex_handle(heh1).idx()]) {
vs.push_back(vt);
}
sort(vs.begin(), vs.end(), [=](const auto& a, const auto& b) {
return (a - edgePoints[heh1.idx()]).norm() < (b - edgePoints[heh1.idx()]).norm();
});
// 再对这些顶点进行排序, 按照
sort(vs.begin(), vs.begin()+4, [=](const auto& a, const auto& b) {
return (a - vs[0]).norm() < (b - vs[0]).norm();
});
std::vector<MyMesh::VertexHandle> vvs;
faceEdgeHandles.push_back(vvs);
faceEdgeHandles[iindex].push_back(out[vs[0]]);
faceEdgeHandles[iindex].push_back(out[vs[2]]);
faceEdgeHandles[iindex].push_back(out[vs[3]]);
faceEdgeHandles[iindex].push_back(out[vs[1]]);
iindex++;
}
iindex = 0;
for (const auto& fh : mesh.faces())
{
OpenMesh::Vec3d facePoint(0, 0, 0);
int facePointsNumber = 0;
std::vector<OpenMesh::Vec3d> vs;
int ix = 0;
for (const auto& fvh : mesh.fv_range(fh))
{
ix++;
for (const auto& vt : vertexPoints_[(fvh).idx()]) {
vs.push_back(vt);
}
}
// 选取最近的四个顶点
sort(vs.begin(), vs.end(), [=](const auto& a, const auto& b) {
return (a - facePoints[fh.idx()]).norm() < (b - facePoints[fh.idx()]).norm();
});
// 再对这些顶点进行排序, 按照
sort(vs.begin(), vs.begin() + 4, [=](const auto& a, const auto& b) {
return (a - vs[0]).norm() < (b - vs[0]).norm();
});
std::vector<MyMesh::VertexHandle> vvs;
faceFaceHandles.push_back(vvs);
if (ix == 3) {
faceFaceHandles[iindex].push_back(out[vs[0]]);
faceFaceHandles[iindex].push_back(out[vs[1]]);
faceFaceHandles[iindex].push_back(out[vs[2]]);
}
else {
faceFaceHandles[iindex].push_back(out[vs[0]]);
faceFaceHandles[iindex].push_back(out[vs[2]]);
faceFaceHandles[iindex].push_back(out[vs[3]]);
faceFaceHandles[iindex].push_back(out[vs[1]]);
}
iindex++;
}
std::vector<std::vector<MyMesh::VertexHandle>> v;
int i = 0;
std::vector<MyMesh::FaceHandle> faceDelHandle;// 存储将要删除的面
for (const auto& fh : mesh.faces()) {
faceDelHandle.push_back(fh);
}
// 开始新增顶点的面
for (const auto& fvh : faceHandles) {
mesh.add_face(fvh);
}
// 开始新增边的面
int indexx = 0;
for (const auto& fvh : faceEdgeHandles) {
if (mesh.add_face(fvh)==OpenMesh::FaceHandle(-1)) {
auto tmp = faceEdgeHandles[indexx][1];
faceEdgeHandles[indexx][1] = faceEdgeHandles[indexx][3];
faceEdgeHandles[indexx][3] = tmp;
mesh.add_face(fvh);
}
indexx++;
}
// 开始新增面的面
indexx = 0;
for (const auto& fvh : faceFaceHandles) {
if (mesh.add_face(fvh) == OpenMesh::FaceHandle(-1)) {
if (faceFaceHandles[indexx].size() == 4) {
auto tmp = faceFaceHandles[indexx][1];
faceFaceHandles[indexx][1] = faceFaceHandles[indexx][3];
faceFaceHandles[indexx][3] = tmp;
}
else if(faceFaceHandles[indexx].size() == 3){
auto tmp = faceFaceHandles[indexx][1];
faceFaceHandles[indexx][1] = faceFaceHandles[indexx][2];
faceFaceHandles[indexx][2] = tmp;
}
mesh.add_face(fvh);
}
indexx++;
}
//// 开始删除面
for (int i = 0; i < faceDelHandle.size(); i++) {
mesh.delete_face(faceDelHandle[i], true);
}
//开始删除顶点
for (int i = 0; i < vertexDelHandle.size(); i++) {
mesh.delete_vertex(vertexDelHandle[i], true);
}
mesh.garbage_collection();
if (mesh.has_vertex_status()) mesh.release_vertex_status();
if (mesh.has_face_status()) mesh.release_face_status();
if (mesh.has_edge_status()) mesh.release_edge_status();
}
/**
* @description: 输出新网格
* @param {string} name 文件名称 默认 output.obj
* @return {type}
*/
void DS::genMesh(std::string name) {
if (name == "") {
name = "output.off";
}
try {
if (!OpenMesh::IO::write_mesh(mesh, name)) {
std::cerr << "Cannot write mesh to file 'output.off'" << std::endl;
return;
}
}
catch (std::exception& e) {
std::cerr << e.what() << std::endl;
return;
}
}
void DS::getResult() {
//if (getData()->edges.size() == 0) {
// getData()->edges.push_back(std::vector<V3f>());
//}
getData()->edges.push_back(std::vector<V3f>());
for (auto e_it = mesh.edges_begin(); e_it != mesh.edges_end(); ++e_it)
{
// 得到边所代表的半边
OpenMesh::HalfedgeHandle heh1 = mesh.halfedge_handle(*e_it, 0); // 默认一个方向的半边
OpenMesh::Vec3d edgePoint(0, 0, 0);
int edgePointsNumber = 0;
OpenMesh::DefaultTraits::Point pointV = mesh.point(mesh.from_vertex_handle(heh1)); // 这条(半)边的起点
OpenMesh::DefaultTraits::Point pointW = mesh.point(mesh.to_vertex_handle(heh1)); // 这条(半)边的终点
getData()->edges[0].push_back({ pointV[0], pointV[1], pointV[2] });
getData()->edges[0].push_back({ pointW[0], pointW[1], pointW[2] });
}
}
#pragma once
#include "strategy.h"
#include "qwidget.h"
#include <OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh>
#include <OpenMesh/Core/IO/MeshIO.hh>
#include <map>
//typedef struct FFACE {
// int faceId;
// int edgeId1;
// int vertexId;
// int edgeId2;
//}FFACE;
class DS :public Strategy, public QWidget
{
Q_OBJECT
private:
typedef OpenMesh::PolyMesh_ArrayKernelT<> MyMesh;
MyMesh mesh;
std::map<int, OpenMesh::Vec3d> facePoints;
std::map<int, OpenMesh::Vec3d> edgePoints;
std::map<int, OpenMesh::Vec3d> vertexPoints;
std::map<int, std::vector<OpenMesh::Vec3d>> vertexPoints_;
int times;
public:
DS(Data* data_);
~DS();
double weights_doo_sabin(size_t k, size_t i);
void genCube();
void genFacePoint();
void genEdgePoint();
void genVertexPoint();
void connectPoints();
void genMesh(std::string name);
bool Run();
void getResult();
};
image
---------------------------我的天空里没有太阳,总是黑夜,但并不暗,因为有东西代替了太阳。虽然没有太阳那么明亮,但对我来说已经足够。凭借着这份光,我便能把黑夜当成白天。我从来就没有太阳,所以不怕失去。
--------《白夜行》