Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**********************************************************
- *
- * FUNCTION smoothNormals (dword*)
- *
- * This member function calculates normals for
- * faces subject to smoothing groups. It is called once a
- * mesh has been imported from a .3DS file. An array of
- * 32 bit integers with m_nFaceCount (the number of faces
- * loaded) elements is passed. Each of these integers is
- * a flag list loaded straight from the 3DS file, where bit
- * 0 flags whether or not the face is in smoothing group 1,
- * bit 1 is for group 2, etc.
- * It is a brute-force algorithm of order approx O(n^2) with
- * poor performance scaling (about 3 minutes to calculate
- * normals for 50000 polygon model on an AMD Athlon x2 4200+).
- * But for models <10000 polys it performs sufficiently.
- *
- * Author: Ryan Wheeler (gastrop0d)
- * Date: 16/06/2008
- *
- *********************************************************/
- void SynMesh::smoothNormals(dword *_pFaceSmoothGroups)
- {
- if(isEmpty() || _pFaceSmoothGroups == NULL)
- return;
- dword nCurrentFace;
- dword nCurrentIndex;
- //MaxSmoothGroups number of vectors which store which faces are in which smooth groups
- vector<Face*> faceGroups[GFX_MAX_SMOOTHGROUPS];
- //compile a list of lists of faces which have common smoothing groups
- for(nCurrentFace=0; nCurrentFace<m_nFaceCount; nCurrentFace++)
- {
- //loop through all smoothing groups
- for(word nCurrentGroup=0; nCurrentGroup<GFX_MAX_SMOOTHGROUPS; nCurrentGroup++)
- {
- //if current face is flagged in current group
- if(_pFaceSmoothGroups[nCurrentFace] & (1<<nCurrentGroup))
- {
- //add face to current group list
- faceGroups[nCurrentGroup].push_back(&m_pFaces[nCurrentFace]);
- }
- }
- }
- Vector newNormal;
- Vector currentVertex;
- dword nCurrentVertex;
- word nCurrentGroup;
- word l;
- Face *pCurrentFace = NULL;
- Face *pProspectFace = NULL;
- Vertex *pProspectVert = NULL;
- //list of indices that will need to have their normal
- //updated, once current normal has been calculated
- vector<Index*> indicesPending;
- for(nCurrentGroup=0; nCurrentGroup<GFX_MAX_SMOOTHGROUPS; nCurrentGroup++)
- {
- for(nCurrentFace=0; nCurrentFace<faceGroups[nCurrentGroup].size(); nCurrentFace++)
- {
- pCurrentFace = faceGroups[nCurrentGroup][nCurrentFace];
- //loop through each index of current face
- for(nCurrentIndex=0; nCurrentIndex<pCurrentFace->nIndexCount; nCurrentIndex++)
- {
- //if we haven't touched this index before
- if(pCurrentFace->pIndices[nCurrentIndex].normal.x == 0.0f &&
- pCurrentFace->pIndices[nCurrentIndex].normal.y == 0.0f &&
- pCurrentFace->pIndices[nCurrentIndex].normal.z == 0.0f)
- {
- //we've found a new normal to calculate, so initialise our
- //working variables ready to begin calculation
- indicesPending.clear();
- newNormal.x = 0;
- newNormal.y = 0;
- newNormal.z = 0;
- nCurrentVertex = pCurrentFace->pIndices[nCurrentIndex].vert;
- currentVertex.x = m_pVertices[nCurrentVertex].x;
- currentVertex.y = m_pVertices[nCurrentVertex].y;
- currentVertex.z = m_pVertices[nCurrentVertex].z;
- //loop through every face in group and find ones
- //which have indices equivalent to current one
- for(dword nProspectFace=0; nProspectFace<faceGroups[nCurrentGroup].size(); nProspectFace++)
- {
- pProspectFace = faceGroups[nCurrentGroup][nProspectFace];
- //look at each index in prospect face
- for(l=0; l<pProspectFace->nIndexCount; l++)
- {
- pProspectVert = &m_pVertices[pProspectFace->pIndices[l].vert];
- //is prospect vertex the same as current vertex?
- if(pProspectVert->x == currentVertex.x &&
- pProspectVert->y == currentVertex.y &&
- pProspectVert->z == currentVertex.z)
- {
- //add index to pending indices list
- indicesPending.push_back(&pProspectFace->pIndices[l]);
- //add face normal to accumulated normal data (for averaging)
- newNormal.x += pProspectFace->normal.x;
- newNormal.y += pProspectFace->normal.y;
- newNormal.z += pProspectFace->normal.z;
- }
- }
- }
- //divide each vector component by how many vectors we added together
- //in order to complete the averaging process
- newNormal.x /= indicesPending.size();
- newNormal.y /= indicesPending.size();
- newNormal.z /= indicesPending.size();
- //make normal unit-vector
- normalize_vector_f(&newNormal.x, &newNormal.y, &newNormal.z);
- //now assign calculated normal to all indices we have listed
- //as needing it
- for(l=0; l<indicesPending.size(); l++)
- {
- indicesPending[l]->normal.x = newNormal.x;
- indicesPending[l]->normal.y = newNormal.y;
- indicesPending[l]->normal.z = newNormal.z;
- }
- }
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement