Advertisement
Guest User

gastrop0d

a guest
Jun 15th, 2008
157
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.75 KB | None | 0 0
  1. /**********************************************************
  2.  *
  3.  * FUNCTION smoothNormals (dword*)
  4.  *
  5.  * This member function calculates normals for
  6.  * faces subject to smoothing groups. It is called once a
  7.  * mesh has been imported from a .3DS file. An array of
  8.  * 32 bit integers with m_nFaceCount (the number of faces
  9.  * loaded) elements is passed. Each of these integers is
  10.  * a flag list loaded straight from the 3DS file, where bit
  11.  * 0 flags whether or not the face is in smoothing group 1,
  12.  * bit 1 is for group 2, etc.
  13.  * It is a brute-force algorithm of order approx O(n^2) with
  14.  * poor performance scaling (about 3 minutes to calculate
  15.  * normals for 50000 polygon model on an AMD Athlon x2 4200+).
  16.  * But for models <10000 polys it performs sufficiently.
  17.  *
  18.  * Author: Ryan Wheeler (gastrop0d)
  19.  * Date: 16/06/2008
  20.  *
  21.  *********************************************************/
  22.  
  23. void SynMesh::smoothNormals(dword *_pFaceSmoothGroups)
  24. {
  25.     if(isEmpty() || _pFaceSmoothGroups == NULL)
  26.         return;
  27.  
  28.     dword nCurrentFace;
  29.     dword nCurrentIndex;
  30.  
  31.     //MaxSmoothGroups number of vectors which store which faces are in which smooth groups
  32.     vector<Face*> faceGroups[GFX_MAX_SMOOTHGROUPS];
  33.  
  34.     //compile a list of lists of faces which have common smoothing groups
  35.     for(nCurrentFace=0; nCurrentFace<m_nFaceCount; nCurrentFace++)
  36.     {
  37.         //loop through all smoothing groups
  38.         for(word nCurrentGroup=0; nCurrentGroup<GFX_MAX_SMOOTHGROUPS; nCurrentGroup++)
  39.         {
  40.             //if current face is flagged in current group
  41.             if(_pFaceSmoothGroups[nCurrentFace] & (1<<nCurrentGroup))
  42.             {
  43.                 //add face to current group list
  44.                 faceGroups[nCurrentGroup].push_back(&m_pFaces[nCurrentFace]);
  45.             }
  46.         }
  47.     }
  48.  
  49.     Vector newNormal;
  50.     Vector currentVertex;
  51.    
  52.     dword nCurrentVertex;
  53.    
  54.     word nCurrentGroup;
  55.     word l;
  56.    
  57.     Face *pCurrentFace = NULL;
  58.     Face *pProspectFace = NULL;
  59.     Vertex *pProspectVert = NULL;
  60.    
  61.     //list of indices that will need to have their normal
  62.     //updated, once current normal has been calculated
  63.     vector<Index*> indicesPending;
  64.  
  65.     for(nCurrentGroup=0; nCurrentGroup<GFX_MAX_SMOOTHGROUPS; nCurrentGroup++)
  66.     {
  67.         for(nCurrentFace=0; nCurrentFace<faceGroups[nCurrentGroup].size(); nCurrentFace++)
  68.         {
  69.             pCurrentFace = faceGroups[nCurrentGroup][nCurrentFace];
  70.  
  71.             //loop through each index of current face
  72.             for(nCurrentIndex=0; nCurrentIndex<pCurrentFace->nIndexCount; nCurrentIndex++)
  73.             {
  74.                 //if we haven't touched this index before
  75.                 if(pCurrentFace->pIndices[nCurrentIndex].normal.x == 0.0f &&
  76.                     pCurrentFace->pIndices[nCurrentIndex].normal.y == 0.0f &&
  77.                     pCurrentFace->pIndices[nCurrentIndex].normal.z == 0.0f)
  78.                 {
  79.                     //we've found a new normal to calculate, so initialise our
  80.                     //working variables ready to begin calculation
  81.  
  82.                     indicesPending.clear();
  83.  
  84.                     newNormal.x = 0;
  85.                     newNormal.y = 0;
  86.                     newNormal.z = 0;
  87.  
  88.                     nCurrentVertex = pCurrentFace->pIndices[nCurrentIndex].vert;
  89.  
  90.                     currentVertex.x = m_pVertices[nCurrentVertex].x;
  91.                     currentVertex.y = m_pVertices[nCurrentVertex].y;
  92.                     currentVertex.z = m_pVertices[nCurrentVertex].z;
  93.  
  94.                     //loop through every face in group and find ones
  95.                     //which have indices equivalent to current one
  96.                     for(dword nProspectFace=0; nProspectFace<faceGroups[nCurrentGroup].size(); nProspectFace++)
  97.                     {
  98.                         pProspectFace = faceGroups[nCurrentGroup][nProspectFace];
  99.  
  100.                         //look at each index in prospect face
  101.                         for(l=0; l<pProspectFace->nIndexCount; l++)
  102.                         {
  103.                             pProspectVert = &m_pVertices[pProspectFace->pIndices[l].vert];
  104.  
  105.                             //is prospect vertex the same as current vertex?
  106.                             if(pProspectVert->x == currentVertex.x &&
  107.                                 pProspectVert->y == currentVertex.y &&
  108.                                 pProspectVert->z == currentVertex.z)
  109.                             {
  110.                                 //add index to pending indices list
  111.                                 indicesPending.push_back(&pProspectFace->pIndices[l]);
  112.  
  113.                                 //add face normal to accumulated normal data (for averaging)
  114.                                 newNormal.x += pProspectFace->normal.x;
  115.                                 newNormal.y += pProspectFace->normal.y;
  116.                                 newNormal.z += pProspectFace->normal.z;
  117.                             }
  118.                         }
  119.                     }
  120.  
  121.                     //divide each vector component by how many vectors we added together
  122.                     //in order to complete the averaging process
  123.                     newNormal.x /= indicesPending.size();
  124.                     newNormal.y /= indicesPending.size();
  125.                     newNormal.z /= indicesPending.size();
  126.  
  127.                     //make normal unit-vector
  128.                     normalize_vector_f(&newNormal.x, &newNormal.y, &newNormal.z);
  129.  
  130.                     //now assign calculated normal to all indices we have listed
  131.                     //as needing it
  132.                     for(l=0; l<indicesPending.size(); l++)
  133.                     {
  134.                         indicesPending[l]->normal.x = newNormal.x;
  135.                         indicesPending[l]->normal.y = newNormal.y;
  136.                         indicesPending[l]->normal.z = newNormal.z;
  137.                     }
  138.                 }
  139.             }
  140.         }
  141.     }
  142. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement