簡體   English   中英

無法計算頂點法線(在C ++中,對於openGL項目)

[英]Trouble Calculating Vertex Normals (in C++, for openGL project)

我有一個項目,我必須讀取OBJ文件並使用GLUT顯示模型。 我正在閱讀並顯示模型很好,但我無法正常工作。 我已經將所有面孔保存在3個vtx [](= points)數組的Faces []數組中,其中x,y,z和法線也帶有x,y,z坐標。 我計算對應於每個面的3個頂點中的每個頂點的2個向量,得到它們的叉積,我對其進行歸一化,然后將其x,y,z coodrdinates加到Normal參數中(這樣,如果有多個,對於每個頂點法線,我們將它們添加到所有法線向量的平均值之類的東西中,然后再次歸一化。 當我打印出一些法線坐標以查看會發生什么時,它以x,y,z打印出0,0,(有點怪異)。 無論如何,這是代碼。

     for (int i = 0 ; i<triangle_index; i++)
    {
        float ux,uy,uz,vx,vy,vz,nn,nx,ny,nz;

    //get vectors from first vertex of face
        ux= Faces[triangle_index].vtx[1].x - Faces[triangle_index].vtx[0].x ;
        uy= Faces[triangle_index].vtx[1].y - Faces[triangle_index].vtx[0].y ;
        uz= Faces[triangle_index].vtx[1].z - Faces[triangle_index].vtx[0].z ;

        vx= Faces[triangle_index].vtx[2].x - Faces[triangle_index].vtx[0].x ;
        vy= Faces[triangle_index].vtx[2].y - Faces[triangle_index].vtx[0].y ;
        vz= Faces[triangle_index].vtx[2].z - Faces[triangle_index].vtx[0].z ;
   //CrossProduct 
        nx = (uy*vz) - (vy*uz);
        ny = (vx*uz) - (ux*vz);
        nz = (ux*vy) - (uy*vx);
   //Length         
        nn = sqrt((nx*nx)+(ny*ny)+(nz*nz));
   //Normalize                  
        nx = nx/nn;
        ny = ny/nn;
        nz = nz/nn;
    //Save to Vertex.Normal (plus any previous data)
    Faces[triangle_index].vtx[0].norm.x =(Faces[triangle_index].vtx[0].norm.x + nx);
    Faces[triangle_index].vtx[0].norm.y =(Faces[triangle_index].vtx[0].norm.y + ny);
    Faces[triangle_index].vtx[0].norm.z =(Faces[triangle_index].vtx[0].norm.z + nz);

  //get length again 

  nn =  sqrt((Faces[triangle_index].vtx[0].norm.x*Faces[triangle_index].vtx[0].norm.x)+(Faces[triangle_index].vtx[0].norm.y*Faces[triangle_index].vtx[0].norm.y)+(Faces[triangle_index].vtx[0].norm.z*Faces[triangle_index].vtx[0].norm.z));

    //Normalize again

        Faces[triangle_index].vtx[0].norm.x =(Faces[triangle_index].vtx[0].norm.x)/nn;
        Faces[triangle_index].vtx[0].norm.y =(Faces[triangle_index].vtx[0].norm.y)/nn;
        Faces[triangle_index].vtx[0].norm.z =(Faces[triangle_index].vtx[0].norm.z)/nn;

   //---------------Same For Second Vertex of the Same Face---------------------------/

        ux= Faces[triangle_index].vtx[2].x - Faces[triangle_index].vtx[1].x ;
        uy= Faces[triangle_index].vtx[2].y - Faces[triangle_index].vtx[1].y ;
        uz= Faces[triangle_index].vtx[2].z - Faces[triangle_index].vtx[1].z ;

        vx= Faces[triangle_index].vtx[0].x - Faces[triangle_index].vtx[1].x ;
        vy= Faces[triangle_index].vtx[0].y - Faces[triangle_index].vtx[1].y ;
        vz= Faces[triangle_index].vtx[0].z - Faces[triangle_index].vtx[1].z ;

        nx = (uy*vz) - (vy*uz);
        ny = (vx*uz) - (ux*vz);
        nz = (ux*vy) - (uy*vx);

        nn = sqrt((nx*nx)+(ny*ny)+(nz*nz));

        nx = nx/nn;
        ny = ny/nn;
        nz = nz/nn;

        Faces[triangle_index].vtx[1].norm.x =(Faces[triangle_index].vtx[1].norm.x + nx);
        Faces[triangle_index].vtx[1].norm.y =(Faces[triangle_index].vtx[1].norm.y + ny);
        Faces[triangle_index].vtx[1].norm.z =(Faces[triangle_index].vtx[1].norm.z + nz);

    nn =sqrt((Faces[triangle_index].vtx[1].norm.x*Faces[triangle_index].vtx[1].norm.x)+(Faces[triangle_index].vtx[1].norm.y*Faces[triangle_index].vtx[1].norm.y)+(Faces[triangle_index].vtx[1].norm.z*Faces[triangle_index].vtx[1].norm.z));

        Faces[triangle_index].vtx[1].norm.x =(Faces[triangle_index].vtx[1].norm.x)/nn;
        Faces[triangle_index].vtx[1].norm.y =(Faces[triangle_index].vtx[1].norm.y)/nn;
        Faces[triangle_index].vtx[1].norm.z =(Faces[triangle_index].vtx[1].norm.z)/nn;
    //------------------Again for number three--------------------------------
    ux= Faces[triangle_index].vtx[0].x - Faces[triangle_index].vtx[2].x ;
    uy= Faces[triangle_index].vtx[0].y - Faces[triangle_index].vtx[2].y ;
    uz= Faces[triangle_index].vtx[0].z - Faces[triangle_index].vtx[2].z ;

    vx= Faces[triangle_index].vtx[1].x - Faces[triangle_index].vtx[2].x ;
    vy= Faces[triangle_index].vtx[1].y - Faces[triangle_index].vtx[2].y ;
    vz= Faces[triangle_index].vtx[1].z - Faces[triangle_index].vtx[2].z ;

    nx = (uy*vz) - (vy*uz);
    ny = (vx*uz) - (ux*vz);
    nz = (ux*vy) - (uy*vx);

    nn = sqrt((nx*nx)+(ny*ny)+(nz*nz));

    nx = nx/nn;
    ny = ny/nn;
    nz = nz/nn;

    Faces[triangle_index].vtx[2].norm.x =(Faces[triangle_index].vtx[2].norm.x + nx);
    Faces[triangle_index].vtx[2].norm.y =(Faces[triangle_index].vtx[2].norm.y + ny);
    Faces[triangle_index].vtx[2].norm.z =(Faces[triangle_index].vtx[2].norm.z + nz);

    nn =  sqrt((Faces[triangle_index].vtx[2].norm.x*Faces[triangle_index].vtx[2].norm.x)+(Faces[triangle_index].vtx[2].norm.y*Faces[triangle_index].vtx[2].norm.y)+(Faces[triangle_index].vtx[2].norm.z*Faces[triangle_index].vtx[2].norm.z));

    Faces[triangle_index].vtx[2].norm.x =(Faces[triangle_index].vtx[2].norm.x)/nn;
    Faces[triangle_index].vtx[2].norm.y =(Faces[triangle_index].vtx[2].norm.y)/nn;
    Faces[triangle_index].vtx[2].norm.z =(Faces[triangle_index].vtx[2].norm.z)/nn;

   } 

如果我添加此循環只是為了查看法線計算后發生的情況

for (int i =0 ; i<100;i++)
cout << "n "<<  Faces[i].vtx[0].norm.x<< " "<< Faces[i].vtx[0].norm.x <<" "<<  Faces[i].vtx[0].norm.x <<"\n";

我得到norm.x,y,z的全零。 誰能看到代碼有什么問題嗎?

您在所有地方都在使用triangle_index進行數組索引:

    ux= Faces[triangle_index].vtx[1].x - Faces[triangle_index].vtx[0].x ;
    uy= Faces[triangle_index].vtx[1].y - Faces[triangle_index].vtx[0].y ;
    uz= Faces[triangle_index].vtx[1].z - Faces[triangle_index].vtx[0].z ;

我認為您想改用循環索引:

    ux= Faces[i].vtx[1].x - Faces[i].vtx[0].x ;
    uy= Faces[i].vtx[1].y - Faces[i].vtx[0].y ;
    uz= Faces[i].vtx[1].z - Faces[i].vtx[0].z ;

您需要在整個循環中解決此問題。

同樣,要正確平均頂點的法線,只應在此循環中對其進行累加,然后在新的第二個循環中對其進行歸一化。 也就是說,將這兩步分為兩步:

    Faces[i].vtx[0].norm.x += nx;
    Faces[i].vtx[0].norm.y += ny;
    Faces[i].vtx[0].norm.z += nz;

    nn = sqrt( (Faces[i].vtx[0].norm.x*Faces[i].vtx[0].norm.x)
             + (Faces[i].vtx[0].norm.y*Faces[i].vtx[0].norm.y)
             + (Faces[i].vtx[0].norm.z*Faces[i].vtx[0].norm.z) );

    Faces[i].vtx[0].norm.x /= nn;
    Faces[i].vtx[0].norm.y /= nn;
    Faces[i].vtx[0].norm.z /= nn;

這樣,與該頂點重合的每個三角形都具有相等的權重。

您的代碼很可能是完全有效的,而問題可能出在法線方向上。 如果在同一平面上有兩個三角形的某個點相交,則在頂點處計算的法線可能是相反的方向(例如,如果這些點在XY平面中,則可以有一個法線[0 0 1],而其他[0 0 -1]),具體取決於頂點的順序。

當您將這兩個向量相加時,您可能會得到一個長度為零的向量,這將在規范化過程中給您帶來麻煩。

我將檢查向量的長度,並可能選擇“主導方向”以防止出現此問題。 或始終分配三角形的值“其質心最接近頂點”或“具有最低X,Y值的質心”-等等。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM