How to unify normal orientation

后端 未结 1 1061
再見小時候
再見小時候 2021-01-12 12:13

I\'ve been trying to realize a mesh that has all face normals pointing outward. In order to realize this, I load a mesh from a *.ctm file, then walk over all triangles to de

相关标签:
1条回答
  • 2021-01-12 13:06

    I finally solved the problem. So I'm still using VCG library. From the above new code I slightly updated the following section:

    vcg::tri::Clean<MyMesh>::OrientCoherentlyMesh(m, oriented,orientable);
    //vcg::tri::Clean<MyMesh>::FlipNormalOutside(m);
    //vcg::tri::Clean<MyMesh>::FlipMesh(m);
    //vcg::tri::UpdateTopology<MyMesh>::FaceFace(m);
    //vcg::tri::UpdateTopology<MyMesh>::TestFaceFace(m);
    vcg::tri::UpdateNormal<MyMesh>::PerVertexNormalizedPerFace(m);
    vcg::tri::UpdateNormal<MyMesh>::PerVertexFromCurrentFaceNormal(m);
    

    Now I've updated the vcg::tri::Clean<MyMesh>::OrientCoherentlyMesh() function in clean.h. Here the update is to orient the first polygon of a group correctly. Also after swapping the edge the normal of the face is calculated and updated.

    static void OrientCoherentlyMesh(MeshType &m, bool &Oriented, bool &Orientable)
    {
        RequireFFAdjacency(m);
        assert(&Oriented != &Orientable);
        assert(m.face.back().FFp(0));    // This algorithms require FF topology initialized
    
        Orientable = true;
        Oriented = true;
    
        tri::UpdateSelection<MeshType>::FaceClear(m);
        std::stack<FacePointer> faces;
    
        for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
        {
            if (!fi->IsD() && !fi->IsS())
            {
                // each face put in the stack is selected (and oriented)
                fi->SetS();
                // New section of code to orient the initial face correctly
                if(fi->N()[2]>0.0)
                {
                    face::SwapEdge<FaceType,true>(*fi, 0);
                    face::ComputeNormal(*fi);
                }
                // End of new code section.
                faces.push(&(*fi));
    
                // empty the stack
                while (!faces.empty())
                {
                    FacePointer fp = faces.top();
                    faces.pop();
    
                    // make consistently oriented the adjacent faces
                    for (int j = 0; j < 3; j++)
                    {
                       //get one of the adjacent face
                       FacePointer fpaux = fp->FFp(j);
                       int iaux = fp->FFi(j);
    
                       if (!fpaux->IsD() && fpaux != fp && face::IsManifold<FaceType>(*fp, j))
                       {              
                          if (!CheckOrientation(*fpaux, iaux))
                          {
                              Oriented = false;
    
                              if (!fpaux->IsS())
                              {
                                   face::SwapEdge<FaceType,true>(*fpaux, iaux);
                                   // New line to update face normal
                                   face::ComputeNormal(*fpaux);
                                   // end of new section.
                                   assert(CheckOrientation(*fpaux, iaux));
                              }
                              else
                              {
                                   Orientable = false;
                                   break;
                              }
                           }
    
                           // put the oriented face into the stack
    
                           if (!fpaux->IsS())
                           {
                                fpaux->SetS();
                                faces.push(fpaux);
                           }
                       }
                   }
               }
           }
           if (!Orientable) break;
        }
    }
    

    Besides I also updated the function bool CheckOrientation(FaceType &f, int z) to perform a calculation based on normal z-direction.

    template <class FaceType>
    bool CheckOrientation(FaceType &f, int z)
    {
        // Added next section to calculate the difference between normal z-directions
        FaceType *original = f.FFp(z);
        double nf2,ng2;
        nf2=f.N()[2];
        ng2=original->N()[2];
        // End of additional section
        if (IsBorder(f, z))
            return true;
        else
        {
            FaceType *g = f.FFp(z);
            int gi = f.FFi(z);
            // changed if statement from: if (f.V0(z) == g->V1(gi))
            if (nf2/abs(nf2)==ng2/abs(ng2))
                return true;
            else
                return false;
        }
    }
    

    The result is as I expect and desire from the algorithm:

    enter image description here

    0 讨论(0)
提交回复
热议问题