Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 6 of 6

Thread: Unify triangles orientation.

  1. #1
    Advanced Member Frequent Contributor
    Join Date
    Feb 2000
    Location
    France
    Posts
    880

    Unify triangles orientation.

    Hi there !

    I was almost sad not to have anything to ask and, as you already guessed, I have a new problem !

    I am still working on my post-processor for CFD results. DON'T GO AWAY : the question is not linked to CFD !

    Well, I have used the Marching Cubes algorithm to build an iso-surface from one of our models. The thing is, some faces are correctly orientated, others aren't. It is not a problem for displaying as I do not cull faces (for some obscure reasons !). But it is a problem for normal smoothing !

    So my question is: is there a way of unifying my triangles orientation ? The linked question is: when OpenGL culls a face, how does it compute the value that tells it if the face is front or back facing ???
    I thought it was a combination of cross and dot products but I can't get it right (stupid me !).

    Thanks to anyone who can help (and the others as well ! )

    Best regards.

    Eric

    P.S. : I have just subscribed to fortunecity for 100Mb free web site. I might use it to log the most common questions I receive from this discussion forum (I won't publish sources that are sent to me: I would rewrite a sample app). Is anyone interested ? First topics would cover selection, rotation, MFC/Glut...

  2. #2
    Senior Member OpenGL Guru
    Join Date
    Feb 2000
    Location
    Sweden
    Posts
    2,982

    Re: Unify triangles orientation.

    Ccan at least tell you how OpenGL does the face culling. It's usually performed by determin the vertex order as projected on the screen. For example, if the projected triangle's vertices is in clockwise order, and you have told OpenGL to cull backfaces, and a frontface is GL_CW, the then the triangle is visible. (Uh, hope that was correct )

    And the other problem... well, maybe I can say something. But first I have to ask you: Do you ALWAYS get the normal correct but the vertex order is wrong sometimes, or is the normal wrong (inverted?) for all wrong oriented triangles? If it's the first case, you can calculate the normal from the vertices you got, and see if the angle between the actual normal is greater than 90 degrees, if so, the triangle is oriented wrong, and just swap two veritces to get them in correct order. If it's the other case, don't ask me .

  3. #3
    Advanced Member Frequent Contributor
    Join Date
    Feb 2000
    Location
    France
    Posts
    880

    Re: Unify triangles orientation.

    Hi Bob !

    Thanks for the hint on OpenGL culling ! I hoped it was done at 3D level but suspected it was actually done after projection...

    Concerning the normals, I actually calculate them from the vertices i.e. when I have a problem, it is because of the vertices orientation... What I am looking for is a method to unify such a mesh (3DS Max has got a function for it... But even this one does not always work !).

    I have solved my problem in another way. I'll try to explain it !

    Basically, what I want to do is smooth my mesh.

    Here is the routine I use:

    /****** AWFUL ROUTINE START ******/

    int i,i1,i2,j;

    for (i1=0;i1<m_iNObjects;i1++)
    {
    C_SurfaceFace *pFace1=(C_SurfaceFace*) m_pObjects[i1];
    for (i2=i1+1;i2<m_iNObjects;i2++)
    {
    C_SurfaceFace *pFace2=(C_SurfaceFace*) m_pObjects[i2];
    if (pFace1->m_vNormal.CalculateAngle(pFace2->m_vNormal)<SmoothAngle)
    {
    for (j=0;j<3;j++)
    {
    HGL_Vector3Df vVector;
    vVector=pFace1->m_ptVertices[j]-pFace2->m_ptVertices[0];
    if (vVector.Norm()<DistanceTolerance)
    {
    if (pFace1->m_vNormals[j].DotProduct(pFace2->m_vNormal)>0)
    pFace1->m_vNormals[j]=pFace1->m_vNormals[j]+pFace2->m_vNormal*pFace2->m_fArea;
    else
    pFace1->m_vNormals[j]=pFace1->m_vNormals[j]+pFace2->m_vNormal*pFace2->m_fArea*(-1);
    if (pFace2->m_vNormals[0].DotProduct(pFace1->m_vNormal)>0)
    pFace2->m_vNormals[0]=pFace2->m_vNormals[0]+pFace1->m_vNormal*pFace1->m_fArea;
    else
    pFace2->m_vNormals[0]=pFace2->m_vNormals[0]+pFace1->m_vNormal*pFace1->m_fArea*(-1);
    }
    vVector=pFace1->m_ptVertices[j]-pFace2->m_ptVertices[1];
    if (vVector.Norm()<DistanceTolerance)
    {
    if (pFace1->m_vNormals[j].DotProduct(pFace2->m_vNormal)>0)
    pFace1->m_vNormals[j]=pFace1->m_vNormals[j]+pFace2->m_vNormal*pFace2->m_fArea;
    else
    pFace1->m_vNormals[j]=pFace1->m_vNormals[j]+pFace2->m_vNormal*pFace2->m_fArea*(-1);
    if (pFace2->m_vNormals[1].DotProduct(pFace1->m_vNormal)>0)
    pFace2->m_vNormals[1]=pFace2->m_vNormals[1]+pFace1->m_vNormal*pFace1->m_fArea;
    else
    pFace2->m_vNormals[1]=pFace2->m_vNormals[1]+pFace1->m_vNormal*pFace1->m_fArea*(-1);
    }
    vVector=pFace1->m_ptVertices[j]-pFace2->m_ptVertices[2];
    if (vVector.Norm()<DistanceTolerance)
    {
    if (pFace1->m_vNormals[j].DotProduct(pFace2->m_vNormal)>0)
    pFace1->m_vNormals[j]=pFace1->m_vNormals[j]+pFace2->m_vNormal*pFace2->m_fArea;
    else
    pFace1->m_vNormals[j]=pFace1->m_vNormals[j]+pFace2->m_vNormal*pFace2->m_fArea*(-1);
    if (pFace2->m_vNormals[2].DotProduct(pFace1->m_vNormal)>0)
    pFace2->m_vNormals[2]=pFace2->m_vNormals[2]+pFace1->m_vNormal*pFace1->m_fArea;
    else
    pFace2->m_vNormals[2]=pFace2->m_vNormals[2]+pFace1->m_vNormal*pFace1->m_fArea*(-1);
    }
    }
    }
    }
    }
    for (i=0;i<m_iNObjects;i++)
    {
    C_SurfaceFace *pFace=(C_SurfaceFace*) m_pObjects[i];
    if (pFace->m_vNormals[0].DotProduct(pFace->m_vNormal)>0)
    pFace->m_vNormals[0]=pFace->m_vNormals[0]+pFace->m_vNormal*pFace->m_fArea;
    else
    pFace->m_vNormals[0]=pFace->m_vNormals[0]+pFace->m_vNormal*pFace->m_fArea*(-1);
    if (pFace->m_vNormals[1].DotProduct(pFace->m_vNormal)>0)
    pFace->m_vNormals[1]=pFace->m_vNormals[1]+pFace->m_vNormal*pFace->m_fArea;
    else
    pFace->m_vNormals[1]=pFace->m_vNormals[1]+pFace->m_vNormal*pFace->m_fArea*(-1);
    if (pFace->m_vNormals[2].DotProduct(pFace->m_vNormal)>0)
    pFace->m_vNormals[2]=pFace->m_vNormals[2]+pFace->m_vNormal*pFace->m_fArea;
    else
    pFace->m_vNormals[2]=pFace->m_vNormals[2]+pFace->m_vNormal*pFace->m_fArea*(-1);
    pFace->m_vNormals[0].Normalize();
    pFace->m_vNormals[1].Normalize();
    pFace->m_vNormals[2].Normalize();
    }

    /****** AWFUL ROUTINE END ******/

    As you can see, before I add any face normal to a vertex normal, I check if they are orientated the same way (DotProduct). If they aren't I add the opposite of the face normal (or I substract the normal, as you prefer !).

    With this algorithm, all problems are gone ! But I still can not cull the faces...

    A funny thing is that these tests would enable me to reorientate the faces correctly ! (which means I was trying to do A to achieve B and I finally managed to do B which would enable me to achieve A !).

    If it sounds a bit obscure, I could gibe some more explanations !

  4. #4
    Senior Member OpenGL Pro
    Join Date
    Oct 2000
    Location
    Fargo, ND
    Posts
    1,755

    Re: Unify triangles orientation.

    What are you using as your rendering primitives? If you are using GL_TRIANGLE_STRIPS you should be aware of how those are used to calculate the front/back face. I'm going from memory here, but I think it's close. Say you have 10 vertices, which we'll just number 1-10. If you were to pass those 10 vertices in a strip like so...

    1, 2, 3, 4, 5, 6, 7, 8, 9, 10

    The actual triangles that are created from that are in an order something like this...

    (1,2,3) (3,2,4) (3,4,5) (5,4,6) (5,6,7) (7,6,8) (7,8,9) (9,8,10)

    Notice that the orders of the vertices alternate. It does this so that the winding order (CW vs CCW) stays the same for some the most common useage of strips.
    Deiussum
    Software Engineer and OpenGL enthusiast

  5. #5
    Guest

    Re: Unify triangles orientation.

    The other problem is "unify the winding order
    TO WHAT?"

    How is the computer to know which direction
    you want the normal to point in? There has
    to be something in your algorithm that
    determines this when you create the triangles
    and you have to get the algorithm right.

    You _could_ define an arbitrary "middle" of
    the mesh and face all triangles "out" from
    this "middle" but that may not yield correct
    results for very convex meshes (or for even
    mildly convex meshes in some cases). Thus,
    only YOU can know for sure which way each
    triangle is MEANT to go -- so express that
    knowledge already! :-)

  6. #6
    Advanced Member Frequent Contributor
    Join Date
    Feb 2000
    Location
    France
    Posts
    880

    Re: Unify triangles orientation.

    Yes bgl, I know that and I guess this is my main problem !

    I have tried to do it from the center of the mesh but it does not always work: the iso-surface I have is not always convex (or is not always a fraction of a convex one if you prefer !). The only solution here is to surface-tesselate (???) my big one. I mean find the sub-surfaces that are a fraction of a convex one... Could be done with the curving radius of the surface (well, in french it is called "rayon de courbure" and I do not know the english translation...).

    I guess I will stick to the algorithm described above for the moment (i.e. check if the normals point in the same direction adn add/subtract according to that !). I do not really need to re-orientate the faces as I do not want to cull anyway !

    Thanks to all of you for your help !

    To Deiussum: in the current algorithm, I do not use strips but I have a stripper object that I made for importing ASE files. I will probably use it to optimize the mesh !

    Best regards.

    Eric

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •