Quadric Error Metrics三位网格精简算法实现

用Qt实现,具体算法内容可自行百度。算法只对原始边进行了收缩,其后,新增边的处理存在bug,导致模型出现空洞,若有大佬知晓原因,望告知。

void MeshSimplifying(){
    //网格简化操作
    if(minHeap.empty())
        return();
    else{
        Vertex *one=minHeap.top()->first;
        Vertex *two=minHeap.top()->second;
        Vertex *fine=minHeap.top()->final;
        pair<int,int> st=minHeap.top()->match;

        if(one->IsSimplified||two->IsSimplified){
              minHeap.pop();
              return;
        }
        one->IsSimplified=true;
        two->IsSimplified=true;
        Face *face1;
        Face *face2;

        if(mesh->MAPedge.count(make_pair(st.first,st.second))!=0)
        face1=mesh->MAPedge[make_pair(st.first,st.second)]->IncFace;
        else return;
        if(mesh->MAPedge.count(make_pair(st.second,st.first))!=0)
        face2=mesh->MAPedge[make_pair(st.second,st.first)]->IncFace;
        else return;
        face1->live=false;
        face2->live=false;
       int number=fine->ID;
        halfEdge* it;

        for(set<int>::iterator pp=one->neighbors.begin() ;pp!=one->neighbors.end();pp++){

            if(mesh->MAPedge.count(make_pair(st.first,*pp))!=0){
            it=mesh->MAPedge[make_pair(st.first,*pp)];
            if(it->IncFace->live){
                if(it!=NULL){
                    mesh->MAPedge.insert(map<pair<int,int>,halfEdge*>::value_type(make_pair(number,*pp),it));
                    it->origin=fine;
                    fine->edge=it;
                    fine->neighbors.insert(*pp);
                    if(*pp<mesh->nverts){
                         mesh->verts[*pp].neighbors.insert(number);
                         if(mesh->verts[*pp].neighbors.count(st.first)!=0)
                             mesh->verts[*pp].neighbors.erase(st.first);
                    }else{
                         addVertices[*pp].neighbors.insert(number);
                         if(addVertices[*pp].neighbors.count(st.first)!=0)
                            addVertices[*pp].neighbors.erase(st.first);
                    }
                      VertexPairs* a=computePosition(make_pair(number,*pp),it);
                     twiceHeap.push(a);
                     //该面的法向量计算

                     Face& face=*it->IncFace;
                     for(int index=0;index<face.nverts;index++){
                         if(face.record[index]==st.first){
                             face.record[index]=number;
                             break;}
                     }

                     face.normal[0] = face.normal[1] = face.normal[2] = 0;
                     Vertex *v1;
                      Vertex *v2;
                     for (int i = 0; i < face.nverts; i++) {
                         if(face.record[i]<mesh->nverts){
                               v1 = &mesh->verts[face.record[i]];
                         }else{
                             v1=&addVertices[face.record[i]];
                         }
                         if(face.record[(i+1)%face.nverts]<mesh->nverts){
                               v2 = &mesh->verts[face.record[(i+1)%face.nverts]];
                         }else{
                             v2=&addVertices[face.record[(i+1)%face.nverts]];
                         }
                       face.normal[0] += (v1->y - v2->y) * (v1->z + v2->z);
                       face.normal[1] += (v1->z - v2->z) * (v1->x + v2->x);
                       face.normal[2] += (v1->x - v2->x) * (v1->y + v2->y);
                     }
                     // Normalize normal for face
                     float squared_normal_length = 0.0;
                     squared_normal_length += face.normal[0]*face.normal[0];
                     squared_normal_length += face.normal[1]*face.normal[1];
                     squared_normal_length += face.normal[2]*face.normal[2];
                     float normal_length = sqrt(squared_normal_length);
                     if (normal_length > 1.0E-6) {
                       face.normal[0] /= normal_length;
                       face.normal[1] /= normal_length;
                       face.normal[2] /= normal_length;
                     }
                     mesh->MAPedge.erase(make_pair(st.first,*pp));
                }
            }
            }
             if(mesh->MAPedge.count(make_pair(*pp,st.first))!=0){
                 it=mesh->MAPedge[make_pair(*pp,st.first)];
                 if(it->IncFace->live){
                     if(it!=NULL){
                         if(it->IncFace->live){
                             Face &face=*it->IncFace;
                             for(int index=0;index<face.nverts;index++){
                                 if(face.record[index]==st.first){
                                     face.record[index]=number;
                                     break;}
                             }
                         }
                          mesh->MAPedge.insert(map<pair<int,int>,halfEdge*>::value_type(make_pair(*pp,number),it));
                          //if(*pp!=st.second)
                            mesh->MAPedge.erase(make_pair(*pp,st.first));
                     }
                 }
             }
        }
          for(set<int>::iterator pp=two->neighbors.begin() ;pp!=two->neighbors.end();pp++){
           if(mesh->MAPedge.count(make_pair(st.second,*pp))!=0){
           it=mesh->MAPedge[make_pair(st.second,*pp)];
           if(it->IncFace->live){
               if(it!=NULL){
                   mesh->MAPedge.insert(map<pair<int,int>,halfEdge*>::value_type(make_pair(number,*pp),it));


                   it->origin=fine;

                   fine->neighbors.insert(*pp);
                   if(*pp<mesh->nverts){
                        mesh->verts[*pp].neighbors.insert(number);
                        if(mesh->verts[*pp].neighbors.count(st.second)!=0)
                            mesh->verts[*pp].neighbors.erase(st.second);
                   }else{
                        addVertices[*pp].neighbors.insert(number);
                        if(addVertices[*pp].neighbors.count(st.second)!=0)
                           addVertices[*pp].neighbors.erase(st.second);
                   }

                     VertexPairs* a=computePosition(make_pair(number,*pp),it);
                     twiceHeap.push(a);
                    //计算该面的法向量
                    Face &face=*it->IncFace;
                    face=*it->IncFace;

                     for(int index=0;index<face.nverts;index++){
                         if(face.record[index]==st.second){
                             face.record[index]=number;
                             break;}
                     }
                    face.normal[0] = face.normal[1] = face.normal[2] = 0;
                    Vertex *v1;
                     Vertex *v2;
                    for (int i = 0; i < face.nverts; i++) {
                        if(face.record[i]<mesh->nverts){
                              v1 = &mesh->verts[face.record[i]];
                        }else{
                            v1=&addVertices[face.record[i]];
                        }
                        if(face.record[(i+1)%face.nverts]<mesh->nverts){
                              v2 = &mesh->verts[face.record[(i+1)%face.nverts]];
                        }else{
                            v2=&addVertices[face.record[(i+1)%face.nverts]];
                        }
                      face.normal[0] += (v1->y - v2->y) * (v1->z + v2->z);
                      face.normal[1] += (v1->z - v2->z) * (v1->x + v2->x);
                      face.normal[2] += (v1->x - v2->x) * (v1->y + v2->y);
                    }
                    // Normalize normal for face
                    float squared_normal_length = 0.0;
                    squared_normal_length += face.normal[0]*face.normal[0];
                    squared_normal_length += face.normal[1]*face.normal[1];
                    squared_normal_length += face.normal[2]*face.normal[2];
                    float normal_length = sqrt(squared_normal_length);
                    if (normal_length > 1.0E-6) {
                      face.normal[0] /= normal_length;
                      face.normal[1] /= normal_length;
                      face.normal[2] /= normal_length;
                    }
                    mesh->MAPedge.erase(make_pair(st.second,*pp));
                   }
           }
           }
           if(mesh->MAPedge.count(make_pair(*pp,st.second))!=0){
             it=mesh->MAPedge[make_pair(*pp,st.second)];

                 if(it!=NULL){
                     if(it->IncFace->live){
                         Face& face=*it->IncFace;
                          for(int index=0;index<face.nverts;index++){
                              if(face.record[index]==st.second){
                                  face.record[index]=number;
                                  break;}
                          }
                     mesh->MAPedge.insert(map<pair<int,int>,halfEdge*>::value_type(make_pair(*pp,number),it));
                      mesh->MAPedge.erase(make_pair(*pp,st.second));
                 }
             }
           }
         }
          minHeap.pop();
    }
}
      原模型: :处理后的模型


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值