Cómo unificar la orientación normal.

He estado intentando realizar una malla que tiene todas las caras normales orientadas hacia afuera. Para darme cuenta de esto, cargo una malla desde un archivo * .ctm, luego recorro todos los triángulos para determinar la normal usando un producto cruzado y, si la normal apunta a la dirección z negativa, doy vuelta v1 y v2 orientación normal). Una vez hecho esto, guardo el resultado en un archivo * .ctm y lo veo con Meshlab.

El resultado en Meshlab todavía muestra que las normales están apuntando en dirección z positiva y negativa (se puede ver en los triángulos negros). Además, al ver las normales en Meshlab, realmente están apuntando hacia atrás.

¿Alguien me puede dar algún consejo sobre cómo resolver esto?

El código fuente de la parte de normalización es:

pcl::PointCloud<pcl::PointXYZRGBA>::Ptr cloud1 (new pcl::PointCloud<pcl::PointXYZRGBA> ());
pcl::fromROSMsg (meshFixed.cloud,*cloud1);for(std::vector<pcl::Vertices>::iterator it = meshFixed.polygons.begin(); it != meshFixed.polygons.end(); ++it)
{
    alglib::real_2d_array v0;
    double _v0[] = {cloud1->points[it->vertices[0]].x,cloud1->points[it->vertices[0]].y,cloud1->points[it->vertices[0]].z};
    v0.setcontent(3,1,_v0); //3 rows, 1col
    alglib::real_2d_array v1;
    double _v1[] = {cloud1->points[it->vertices[1]].x,cloud1->points[it->vertices[1]].y,cloud1->points[it->vertices[1]].z};
    v1.setcontent(3,1,_v1); //3 rows, 1col
    alglib::real_2d_array v2;
    double _v2[] = {cloud1->points[it->vertices[2]].x,cloud1->points[it->vertices[2]].y,cloud1->points[it->vertices[2]].z};
    v2.setcontent(1,3,_v2); //3 rows, 1col
    alglib::real_2d_array normal;
    normal = cross(v1-v0,v2-v0);
    //if z<0 change indices order v1->v2 and v2->v1
    alglib::real_2d_array normalizedNormal;
    if(normal[2][0]<0)
    {
            int index1,index2;
            index1 = it->vertices[1];
            index2 = it->vertices[2];
            it->vertices[1] = index2;
            it->vertices[2] = index1;
            //make normal of length 1
            double normalScaling = 1.0/sqrt(dot(normal,normal));
            normal[0][0] = -1*normal[0][0];
            normal[1][0] = -1*normal[1][0];
            normal[2][0] = -1*normal[2][0];
            normalizedNormal = normalScaling * normal;
    }
    else
    {
            //make normal of length 1
            double normalScaling = 1.0/sqrt(dot(normal,normal));
            normalizedNormal = normalScaling * normal;
    }
    //add to normal cloud
    pcl::Normal pclNormalizedNormal;
    pclNormalizedNormal.normal_x = normalizedNormal[0][0];
    pclNormalizedNormal.normal_y = normalizedNormal[1][0];
    pclNormalizedNormal.normal_z = normalizedNormal[2][0];
    normalsFixed.push_back(pclNormalizedNormal);
} 

El resultado de este código es:

He encontrado algún código en la biblioteca VCG para orientar las normales de cara y vértice. Después de usar esto, una gran parte de la malla tiene normales de cara correctas, pero no todas.

El nuevo código:

// VCG library implementation
    MyMesh m;
    // Convert pcl::PolygonMesh to VCG MyMesh
    m.Clear();
    // Create temporary cloud in to have handy struct object
    pcl::PointCloud<pcl::PointXYZRGBA>::Ptr cloud1 (new pcl::PointCloud<pcl::PointXYZRGBA> ());
    pcl::fromROSMsg (meshFixed.cloud,*cloud1);
    // Now convert the vertices to VCG MyMesh
    int vertCount = cloud1->width*cloud1->height;
    vcg::tri::Allocator<MyMesh>::AddVertices(m, vertCount);
    for(unsigned int i=0;i<vertCount;++i)
        m.vert[i].P()=vcg::Point3f(cloud1->points[i].x,cloud1->points[i].y,cloud1->points[i].z);
    // Now convert the polygon indices to VCG MyMesh => make VCG faces..
    int triCount = meshFixed.polygons.size();
    if(triCount==1)
    {
        if(meshFixed.polygons[0].vertices[0]==0 && meshFixed.polygons[0].vertices[1]==0 && meshFixed.polygons[0].vertices[2]==0)
            triCount=0;
    }
    Allocator<MyMesh>::AddFaces(m, triCount);
    for(unsigned int i=0;i<triCount;++i)
    {
        m.face[i].V(0)=&m.vert[meshFixed.polygons[i].vertices[0]];
        m.face[i].V(1)=&m.vert[meshFixed.polygons[i].vertices[1]];
        m.face[i].V(2)=&m.vert[meshFixed.polygons[i].vertices[2]];
    }

    vcg::tri::UpdateBounding<MyMesh>::Box(m);
    vcg::tri::UpdateNormal<MyMesh>::PerFace(m);
    vcg::tri::UpdateNormal<MyMesh>::PerVertexNormalizedPerFace(m);
    printf("Input mesh  vn:%i fn:%i\n",m.VN(),m.FN());

    // Start to flip all normals to outside
    vcg::face::FFAdj<MyMesh>::FFAdj();
    vcg::tri::UpdateTopology<MyMesh>::FaceFace(m);
    bool oriented, orientable;
    if ( vcg::tri::Clean<MyMesh>::CountNonManifoldEdgeFF(m)>0 ) {
        std::cout << "Mesh has some not 2-manifold faces, Orientability requires manifoldness" << std::endl; // text
        return; // can't continue, mesh can't be processed
    }
    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 convert VCG back to pcl::PolygonMesh
    pcl::PointCloud<pcl::PointXYZRGBA>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZRGBA>);
    cloud->is_dense = false;
    cloud->width = vertCount;
    cloud->height = 1;
    cloud->points.resize (vertCount);
    // Now fill the pointcloud of the mesh
    for(int i=0; i<vertCount; i++)
    {
        cloud->points[i].x = m.vert[i].P()[0];
        cloud->points[i].y = m.vert[i].P()[1];
        cloud->points[i].z = m.vert[i].P()[2];
    }
    pcl::toROSMsg(*cloud,meshFixed.cloud);
    std::vector<pcl::Vertices> polygons;
    // Now fill the indices of the triangles/faces of the mesh
    for(int i=0; i<triCount; i++)
    {
        pcl::Vertices vertices;
        vertices.vertices.push_back(m.face[i].V(0)-&*m.vert.begin());
        vertices.vertices.push_back(m.face[i].V(1)-&*m.vert.begin());
        vertices.vertices.push_back(m.face[i].V(2)-&*m.vert.begin());
        polygons.push_back(vertices);
    }
    meshFixed.polygons = polygons;

Lo que resulta en: (Meshlab todavía muestra que los normales están enfrentados en ambos lados)

Respuestas a la pregunta(1)

Su respuesta a la pregunta