简介

没有 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

posted on 2022-03-03 16:27  HDU李少帅  阅读(178)  评论(0编辑  收藏  举报