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 8 of 8

Thread: Problem with declaring vertex normals

Hybrid View

  1. #1
    Junior Member Newbie
    Join Date
    Jan 2011
    Posts
    18

    Problem with declaring vertex normals

    Hello,
    I'm programming a small game with BulletPhysics and OpenGL (2.1).
    Yesterday I added lighting to the game, so I needed normals for the objects, too.
    But I've got a problem with that:
    I'm creating a cuboid with the following code:
    Code :
    m_vVertices.pObj = new CVector3D[8];
    GLfloat corners[] = {-vHalfExtents.x, vHalfExtents.y, vHalfExtents.z,
    		vHalfExtents.x, vHalfExtents.y, vHalfExtents.z,
    		vHalfExtents.x, -vHalfExtents.y, vHalfExtents.z,
    		-vHalfExtents.x, -vHalfExtents.y, vHalfExtents.z,
    		-vHalfExtents.x, vHalfExtents.y, -vHalfExtents.z,
    		vHalfExtents.x, vHalfExtents.y, -vHalfExtents.z,
    		vHalfExtents.x, -vHalfExtents.y, -vHalfExtents.z,
    		-vHalfExtents.x, -vHalfExtents.y, -vHalfExtents.z};
    for (int i = 0; i < 8; ++i)
    {
    	m_vVertices.pObj[i].x = corners[i*3];
    	m_vVertices.pObj[i].y = corners[i*3+1];
    	m_vVertices.pObj[i].z = corners[i*3+2];
    }
     
    m_VertexIndices.pObj = new GLuint[6*4];
    GLubyte indices[] = {0, 1, 2, 3,
    		4, 5, 1, 0,
    		3, 2, 6, 7,
    		5, 4, 7, 6,
    		1, 5, 6, 2,
    		4, 0, 3, 7};
    for (int i = 0; i < 24; ++i)
    {
    	m_VertexIndices.pObj[i] = indices[i];
    }

    Later, I'm rendering with this code:

    Code :
    glEnableClientState(GL_VERTEX_ARRAY);
     
    glVertexPointer(3, GL_FLOAT, 0, static_cast<void*>(m_vVertices.pObj));
    glDrawElements(GL_QUADS, 24, GL_UNSIGNED_INT,
    		static_cast<void*>(m_VertexIndices.pObj));
     
    glDisableClientState(GL_VERTEX_ARRAY);

    But when I wanted to add normals, I had a problem: As far as I know OpenGL doesn't support surface normals, only vertex normals.
    But because I'm reusing shared vertices with the help of an index array, I can't specify normals per vertex beacause - dependent on which face a vertex belongs to - each vertex can have different normals. Is there a way I can still use indices to specify the order of the vertices drawn or do I have to declare shared vertices multiple times (for every face needed)?

    Thank you for your answers in advance!

  2. #2
    Junior Member Newbie
    Join Date
    Jan 2011
    Posts
    18

    Re: Problem with declaring vertex normals

    OK, I've just noticed that I misunderstood what vertex normals are ( http://www.opengl.org/discussion_boards/...;gonew=1#UNREAD : "for the normal at a vertex, sum the normals for all the triangles it is shared by; divided by the number of triangles; then normalise this vector" ).
    So I tried it with the following code:

    Code :
    m_vNormals.pObj = new CVector3D[8];
    // Every vertex normal is set here
    for (size_t i = 0; i < 8; ++i)
    {
    	size_t  iNumI = 0; // number of this vertex in the indices
    	GLubyte *pIndices = 0; // locations where the vertex appears
    	CVector3D vVertNorm = CVector3D(0.0f, 0.0f, 0.0f); // the normal
    	for (size_t ii = 0; ii < 24; ++ii)
    	{
    		if (m_VertexIndices.pObj[ii] == i) ++iNumI; // number of this vertex is determined
    	}
    	pIndices = new GLubyte[iNumI];
    	size_t  iNumICounter = 0;
    	for (size_t ii = 0; ii < 24; ++ii)
    	{
    		// if this vertex appears in this location
    		if (m_VertexIndices.pObj[ii] == i)
    		{
    			pIndices[iNumICounter] = ii;
    			++iNumICounter;
    		}
    	}
    	for (size_t j = 0; j < iNumI; ++j)
    	{
    		size_t uiStartPos = pIndices[j]/4;
    		cerr << "uiStartPos: " << uiStartPos << "; iNumI: " << iNumI << endl;
    		CVector3D vAB = m_vVertices.pObj[m_VertexIndices.pObj[uiStartPos+1]]-m_vVertices.pObj[m_VertexIndices.pObj[uiStartPos]];
    		CVector3D vAC = m_vVertices.pObj[m_VertexIndices.pObj[uiStartPos+2]]-m_vVertices.pObj[m_VertexIndices.pObj[uiStartPos]];
    		vVertNorm += Vector3DNormalize(Vector3DCross(vAB, vAC));
    	}
    	vVertNorm /= iNumI;
    	vVertNorm = Vector3DNormalize(vVertNorm);
    	m_vVertices.pObj[i] = vVertNorm;
    	delete[] pIndices;
    }

    But it showed some very strange result and doesn't seem to be correct.

    Does somebody know what I've done wrong?

  3. #3
    Advanced Member Frequent Contributor
    Join Date
    Jan 2012
    Location
    Australia
    Posts
    738

    Re: Problem with declaring vertex normals

    ok I check my code and I was wrong about the divide.

    I have tried to make your code look like mine - beware it may not compile

    Code :
    CVector  normal[8], temp;
     
    for (int i = 0; i < 8; i++)
    {
      normal[i].x = normal[i].y = normal[i].z = 0;
    }
     
    for (int i = 0; i < 24; i += 3)
    {
      CVector3D vAB = m_vVertices.pObj[m_VertexIndices.pObj[i+1]]-m_vVertices.pObj[m_VertexIndices.pObj[i];
      CVector3D vAC = m_vVertices.pObj[m_VertexIndices.pObj[i+2]]-m_vVertices.pObj[m_VertexIndices.pObj[i];
      // normal for triangle face
      temp = Vector3DCross(vAB, vAC);
      // add normal to all vertices in triangle
      for (int j = 0; j < 3; j++)
      {
        normal[m_VertexIndices.pObj[i+1]] += temp
      }
    }
    // normalise vertex normals
    for (int i = 0; i < 8; i++)
    {
      Vector3DNormalize(normal);
    }

  4. #4
    Junior Member Newbie
    Join Date
    Jan 2011
    Posts
    18

    Re: Problem with declaring vertex normals

    Yes, the code seems to work (with some small corrections). But the faces seem to be drawn in a wrong way (only the faces inside seem to be drawn).
    But it doesn't seem to help to to put a minus sign in front of "normal" (code:
    Code :
    // normalise vertex normals
    for (int i = 0; i < 8; i++)
    {
    	normal[i] = Vector3DNormalize(normal[i]);
    	m_vNormals.pObj[i] = -normal[i];
    }
    ).
    Does someone know what I have to change in the code so that it works correctly?

  5. #5
    Advanced Member Frequent Contributor
    Join Date
    Jan 2012
    Location
    Australia
    Posts
    738

    Re: Problem with declaring vertex normals

    The normal has a direction, so it can point in or out depending on the order of the vertices. You can reverse the normal by reversing the cross product

    if Vector3DCross(vAB, vAC) points in, then Vector3DCross(vAC, vAB) points out.

    Google a bit on normals and you find something with a diagram.

  6. #6
    Junior Member Newbie
    Join Date
    Jan 2011
    Posts
    18

    Re: Problem with declaring vertex normals

    I've tried it with reversed normals but it didn't seem to help ( here you can see the results (the right picture uses vAB, vAC and the left picture vAC, vAB): http://dl.dropbox.com/u/32334047/VertexNormals.png ).
    Here the output of the program that produces the right image (with "cerr << (m_vNormals.pObj[i]).x << "; " << (m_vNormals.pObj[i]).y << "; " << (m_vNormals.pObj[i]).z << endl;"):
    Code :
    0; 0; 1
    -0.707107; 0; -0.707107
    -0.0499376; -0.998752; 0
    1; 0; 0
    0; -1; -2.48353e-09
    -nan; -nan; -nan
    0; 1; 0
    -nan; -nan; -nan
    And here the output of the program that produces the left image:
    Code :
    0; 0; -1
    0.707107; 0; 0.707107
    0.0499376; 0.998752; 0
    -1; 0; 0
    0; 1; 2.48353e-09
    -nan; -nan; -nan
    0; -1; 0
    -nan; -nan; -nan

Posting Permissions

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