请选择 进入手机版 | 继续访问电脑版

山东大学计算机图形学实验(Opengl实现):Loop Subdivision算法对模型进行

[复制链接]
丶禁飞 发表于 2021-1-1 10:30:37 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题
一、实验目标/要求:
The goal of this assignment is to try your hand at various mesh processing tasks. A half-edge mesh adjacency data structure is provided, along with a very simple .obj mesh parser. As you modify the triangle mesh, it is critical that the manifold properties of the input surface are maintained, and that the adjacency data structure remains consistent. Throughout this assignment you are asked to consider the efficiency of various mesh operations: is it quadratic, linear, logarithmic, constant, etc? It’s ok if you don’t always implement the most efficient strategy (which may require additional data structures).
(上面的的意思大概就是使用Loop Subdivision算法对简单模型进行细分。)
二、实现效果:
第一组


第二组


第三组


三、实现方法/思路:

  • 先更新原来的旧顶点,根据旧顶点信息盘算出新顶点位置信息并将盘算的新位置信息和原来的点组成pair并储存在一个新的vector中(即下面算法中的update)。(另:此处要注意内部顶点和界限点的更新方式,公式不要堕落)
  • 分别根据内部边和和界限边差异的处理方式算出插入的新点的位置信息,然后直接向原来的点vector(即vertices)中插入(用addVertex函数)新顶点。
  • 使用步调1)中的vector(即update)来更新旧顶点的位置信息(用一个for循环和setPos函数即可)。
  • 新建一个暂时三角形面片的哈希表来存储旧三角形面片信息(即下面算法中的tempTriangles),然后清除旧三角形面片信息(triangles.clear())和边信息(edges.clear()),然后再使用暂时的三角形面片哈希表重构新的三角形面片信息和新的边信息(边信息是随着三角形面片信息的更新而更新的,不用管)。
  • 修复一下这边信息,即为原来crease值不为零的边及其“衍生”的边重新附上crease值。
  • 清空vertex_parents(这个玩意儿是通过一条边的两个端点去找边上所产生的新点的,在插入新店的步调(即步调2)中进行准备,用在重构三角形面片信息的步调(即步调4中),为下一次细分做准备。
  算法代码如下:
(只包罗算法部分的代码,不包罗别的部分的代码,太多了,懒得整,嘿嘿)

  1. void Mesh::LoopSubdivision(){    printf("Subdivide the mesh!\n");    //store new position of old vertex in update.    //(Traversal of all vertices)    std::vector update;    for (edgeshashtype::iterator eIterator1 = edges.begin();        eIterator1 != edges.end(); eIterator1++)    {        Edge* e = eIterator1->second;        Edge* temp = e->getNext();        Vec3f newPosition(0, 0, 0);        std::vector neighborVertices;        while (temp->getOpposite() != NULL && temp->getOpposite() != e)        {            neighborVertices.push_back(temp->getEndVertex());            temp = temp->getOpposite()->getNext();        }        if (temp->getOpposite() == NULL)        {            neighborVertices.clear();            Vertex* v1 = temp->getEndVertex();            assert(temp->getStartVertex() == e->getEndVertex());            temp = e;            while (temp->getOpposite() != NULL)            {                temp = temp->getOpposite()->getNext()->getNext();            }            Vertex* v2 = temp->getStartVertex();            assert(temp->getEndVertex() == e->getEndVertex());            newPosition = newPosition = 3.0 / 4.0 * e->getEndVertex()->getPos() + 1.0 / 8.0 * (v1->getPos() + v2->getPos());        }        else        {            //degree of current vertex            int degree = neighborVertices.size();            //beta is a constant used to get new inner vertex position            float beta = (5.0 / 8.0 - std::pow(3.0 / 8.0 + 1.0 / 4.0 * std::cos(2 * std::acos(-1) / degree), 2)) / degree;            for (int k = 0; k < degree; k++)                newPosition += beta * neighborVertices[k]->getPos();            newPosition += (1.0 - degree * beta) * e->getEndVertex()->getPos();        }        update.push_back(std::make_pair(e->getEndVertex(), newPosition));    }    //add new vertices    for (edgeshashtype::iterator eIterator2 = edges.begin();        eIterator2 != edges.end(); eIterator2++)    {        Edge* e = eIterator2->second;        Vec3f newVertexPos(0, 0, 0);        if (e->getOpposite() != NULL)        {            if (getChildVertex(e->getStartVertex(), e->getEndVertex()) != NULL) continue;//每条内部边只加一个点            newVertexPos = 3.0 / 8.0 * (e->getEndVertex()->getPos() + e->getStartVertex()->getPos())            + 1.0 / 8.0 * (e->getNext()->getEndVertex()->getPos() + e->getOpposite()->getNext()->getEndVertex()->getPos());        }        else            newVertexPos = 1.0 / 2.0 * (e->getStartVertex()->getPos() + e->getEndVertex()->getPos());        Vertex* newVertex = addVertex(newVertexPos);        if (newVertex != NULL) setParentsChild(e->getStartVertex(), e->getEndVertex(), newVertex);    }    //refresh old vertex position    for (int i = 0; i < update.size(); i++)         update[i].first->setPos(update[i].second);    //add triangle mesh    triangleshashtype tempTriangles = triangles;    triangles.clear();//clear old triangle meshes    edges.clear();//clear information of old edges    triangleshashtype::iterator tIterator = tempTriangles.begin();    for (; tIterator != tempTriangles.end(); tIterator++)    {        Triangle* t = tIterator->second;        Vertex* v1, * v2, * v3, * c12, * c23, * c13;        v1 = (*t)[0]; v2 = (*t)[1]; v3 = (*t)[2];        c12 = getChildVertex(v1, v2);        c23 = getChildVertex(v2, v3);        c13 = getChildVertex(v1, v3);        if (c12 == NULL || c23 == NULL || c13 == NULL) break;        addTriangle(c12, c23, c13);        addTriangle(v1, c12, c13);        addTriangle(v2, c23, c12);        addTriangle(v3, c13, c23);    }    //set crease    for (edgeshashtype::iterator eIterator3 = edges.begin();        eIterator3 != edges.end(); eIterator3++)    {        Edge* e = eIterator3->second;        std::pair ePair = eIterator3->first;        if (vertex_parents.find(ePair) == vertex_parents.end()) continue;        if (e->getCrease())        {            Vertex* childVertex = vertex_parents.find(ePair)->second;            assert(edges.find(std::make_pair(e->getStartVertex(), childVertex)) != edges.end());            edges.find(std::make_pair(e->getStartVertex(), childVertex))->second->setCrease(e->getCrease());            assert(edges.find(std::make_pair(childVertex, e->getEndVertex())) != edges.end());            edges.find(std::make_pair(childVertex, e->getEndVertex()))->second->setCrease(e->getCrease());        }    }    vertex_parents.clear();}
复制代码
四、实验感受与体会:
原来的模型干干巴巴的,麻麻赖赖的,一点儿都不圆润,盘它!


来源:https://blog.csdn.net/Tzankho/article/details/111940563
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

发布主题

专注素材教程免费分享
全国免费热线电话

18768367769

周一至周日9:00-23:00

反馈建议

27428564@qq.com 在线QQ咨询

扫描二维码关注我们

Powered by Discuz! X3.4© 2001-2013 Comsenz Inc.( 蜀ICP备2021001884号-1 )