Results 1 to 9 of 9

Thread: averaging face normals

  1. #1
    Guest

    averaging face normals

    I have created a class that reads a 3d studio asc file into a standard format ( list of verticies , list of faces , list of models) and i have successfully calculated the normals for the faces. this works fine when i render the model but I want to be able to make it look smooth.

    i have written a piece of code to calculate vertex normals based on the average of the normals for each of the faces that share a particulatr vertex.

    this gives me a horrible result (all the faces are shaded in a very strange way) and i cant work out whats wrong.

    can anyone help?

    kev.

    here is the code:

    void C3DImportedASCObject::CalculateVertexNormals()
    {
    if(m_numModels > -1) {
    for(int ii=0; ii<=m_numModels; ii++) {
    for(int jj=0; jj<m_model[ii].numFaces; jj++) {

    // set the vertex normal to the sum of all the shared face normals
    for(int kk=0; kk<3; kk++) {
    m_model[ii].faceList[jj].vertex[kk]->normal[0] +=
    m_model[ii].faceList[jj].normal[0];
    m_model[ii].faceList[jj].vertex[kk]->normal[1] +=
    m_model[ii].faceList[jj].normal[1];
    m_model[ii].faceList[jj].vertex[kk]->normal[2] +=
    m_model[ii].faceList[jj].normal[2];

    m_model[ii].faceList[jj].vertex[kk]->m_numSharedFaces++;
    }
    }

    // average the vertex normals
    for(int ll=0;ll<m_model[ii].numVertices;ll++) {
    m_model[ii].vertexList[ll].normal[0] = m_model[ii].vertexList[ll].normal[0] /
    m_model[ii].vertexList[ll].m_numSharedFaces;
    m_model[ii].vertexList[ll].normal[1] = m_model[ii].vertexList[ll].normal[1] /
    m_model[ii].vertexList[ll].m_numSharedFaces;
    m_model[ii].vertexList[ll].normal[2] = m_model[ii].vertexList[ll].normal[2] /
    m_model[ii].vertexList[ll].m_numSharedFaces;

    Normalise(m_model[ii].vertexList[ll].normal[0],
    m_model[ii].vertexList[ll].normal[1],
    m_model[ii].vertexList[ll].normal[2]);
    }

    }
    }
    }

  2. #2

    Re: averaging face normals

    You don't have to divide the vertex normals by the number of shared faces before the normalization. The direction of the vector stays the same, so you only need to normalize.

    Anyway, your method seems to be ok. It is possible that
    a) your rendering code does something wrong
    b) 'Normalise' function is not working correctly (not likely, your face normal calculation works)
    c) the face normals haven't been calculated before the vertex normal calculation (not likely)

    So, I'd say it's a.

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

    Re: averaging face normals

    Hmm, doesn't .ASC files contain vertexnormals? I'm pretty sure it does. If so, there is no need to calculate your own normals

    Think I have some code at home for importing .ASC files with vertexnormals.

  4. #4
    kevin
    Guest

    Re: averaging face normals

    the .asc file has AB:1 BC:1 CA:1 for every face - this is the only info i havent used to construct my model and i'm not sure what it means.

    i've tried it without dividing by the number of faces and it still messes up.

    this is the code for the draw:

    void CGLImportedASCObject: raw()
    {
    float normal[3];
    for(int nn=0;nn<=m_numModels;nn++) {
    for(int ii=0;ii<m_model[nn].numFaces;ii++)
    {
    glBegin(GL_TRIANGLES);
    float surface[] =
    {(float)m_model[nn].faceList[ii].colour[0]/255,
    (float)m_model[nn].faceList[ii].colour[1]/255,
    (float)m_model[nn].faceList[ii].colour[2]/255,
    (float)m_model[nn].faceList[ii].colour[3]/255};

    glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,surfa ce);

    // Used for face normals
    // glNormal3fv(m_model[nn].faceList[ii].normal);

    for(int jj=0; jj<3; jj++)
    {
    // Used for vertex normals
    glNormal3fv(m_model[nn].faceList[ii].vertex[jj]->normal);
    glVertex3fv(m_model[nn].faceList[ii].vertex[jj]->point);
    }
    glEnd();
    }
    }
    }

    any ideas?

  5. #5
    Senior Member Frequent Contributor
    Join Date
    Feb 2000
    Location
    France
    Posts
    880

    Re: averaging face normals

    I can't find any *BIG* bug in your code but here is an advice for normals troubles :

    When you display your model, display the normals as well (scale them if you want to see something !).

    That would be something like that :

    glBegin(GL_LINES);
    glVertex3d(v.x,v.y,v.z);
    glVertex3d(v.x+scale*n.x,v.y+scale*n.y,v.z+scale*n .z);
    glEnd();

    If there is a big inconsistency in your normals, you will immediately see it.

    If your normals seems OK, perhaps it's a lighting problem...

    Eric

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

    Re: averaging face normals

    Oops, forgot something : did you specify glShadeModel(GL_SMOOTH) somewhere in your code ???

    Eric

  7. #7
    Senior Member Regular Contributor
    Join Date
    Feb 2000
    Location
    milano, italy
    Posts
    282

    Re: averaging face normals

    to create vertex normals there are two basic approaches, imo: use smoothing groups and don't use soothing groups

    SG's are a way to identify surfaces into meshes.
    a cube has 6 surfaces, a sphere has one, a cylinder has 3 surfaces...
    a torus have one surface, like the sphere.

    surfaces can be made of any number of polygons, and vertex normals for a given SG have to be evaluated separately from the other polygons, not belonging to the same SG.

    this leads to the fact that vertices that lay on the seam between two different SG have more than one normal.

    if your model is, for simplicity, a sphere (any object with a single surface), you don't have to mess with SG's.

    if your model is more complex, to say, a cube with a cylinder coming out the center of a cube's face, then you can't simply average normals from faces wich share a vertex.

    you will get wrong lighting.

    if your model is complex, you have to care abous SG's, and it's a bit complex...

    to avoid troubles, i suggest you to use 3D studio MAX scene ascii export files (.ASE): they have multiple normals for vertices.

    Dolo/\/\ightY
    Dolo/\/\ightY

  8. #8

    Re: averaging face normals

    Originally posted by kevin:
    the .asc file has AB:1 BC:1 CA:1 for every face - this is the only info i havent used to construct my model and i'm not sure what it means.
    These are boolean flags used to determine which edges to draw when rendering a wireframe of the model.

  9. #9
    kevin
    Guest

    Re: averaging face normals

    Originally posted by Eric:
    Oops, forgot something : did you specify glShadeModel(GL_SMOOTH) somewhere in your code ???

    Eric
    Agraaaaaaaaahah - i cant believe i have been so dumb!

    I was trying to render it with vertex normals and i forgot to change the shade model from flat to smooth. i've changed it to smooth and it works just fine! - thanks for all your help.

Similar Threads

  1. vertex normals or face normals
    By infinitecmdz in forum OpenGL: Basic Coding
    Replies: 2
    Last Post: 02-20-2004, 09:35 AM
  2. is it possible to have vertex normals or even face normals using triangle strips nt
    By wildeyedboyfromfreecloud in forum OpenGL: Advanced Coding
    Replies: 63
    Last Post: 03-19-2002, 11:42 PM
  3. Averaging normals
    By Questions Burner in forum OpenGL: Basic Coding
    Replies: 6
    Last Post: 01-06-2002, 08:49 PM
  4. Face Normals vs. Vertex Normals
    By detzel in forum OpenGL: Advanced Coding
    Replies: 6
    Last Post: 03-05-2001, 10:50 AM
  5. Averaging normals
    By efesar in forum OpenGL: Basic Coding
    Replies: 1
    Last Post: 04-11-2000, 05:16 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Proudly hosted by Digital Ocean