// In short, the reason for the complexity of this function is: // - creates a list of vertices where every vertex has a unique position (UV ignored) // - doesn't allow the same poly normal to be added to the same vertex twice void PolyMesh::CalculateNormals() { vector<Vector3> vertPos; vector<int> old2new; GenerateUniqueVectors(verts, vertPos, old2new); vector<vector<int> > new2old; new2old.resize(vertPos.size()); for (unsigned int a=0;a<old2new.size();a++) new2old[old2new[a]].push_back(a); vector<std::vector<Vector3> > normals; normals.resize(vertPos.size()); for (unsigned int a=0;a<poly.size();a++) { Poly *pl = poly[a]; Plane plane; plane.MakePlane( vertPos[old2new[pl->verts[0]]], vertPos[old2new[pl->verts[1]]], vertPos[old2new[pl->verts[2]]]); Vector3 plnorm = plane.GetVector(); for (unsigned int b=0;b<pl->verts.size();b++) { vector<Vector3>& norms = normals[old2new[pl->verts[b]]]; unsigned int c; for (c=0;c<norms.size();c++) if (norms[c] == plnorm) break; if (c == norms.size()) norms.push_back(plnorm); } } for (unsigned int a=0;a<normals.size();a++) { Vector3 sum; vector<Vector3>& vn = normals[a]; for(unsigned int b=0;b<vn.size();b++) sum+=vn[b]; if (sum.length()>0.0f) sum.normalize (); vector<int>& vlist=new2old[a]; for(unsigned int b=0;b<vlist.size();b++) verts[vlist[b]].normal = sum; } }
void MdlObject::CalculateNormals() { vector<Vector3> normals; normals.resize(verts.size()); for (int a=0;a<poly.size();a++) { Poly *pl = poly[a]; Plane plane; plane.MakePlane(verts[pl->verts [0]].pos,verts[pl->verts[1]].pos,verts[pl->verts[2]].pos); for (int b=0;b<pl->verts.size();b++) normals[pl->verts[b]] += plane.GetVector (); } for (int a=0;a<verts.size();a++) { if (normals[a].length()>0.0f) normals[a].normalize (); verts[a].normal=normals[a]; } }
void PolyMesh::CalculateNormals2(float maxSmoothAngle) { float ang_c = cosf (M_PI * maxSmoothAngle / 180.0f); vector<Vector3> vertPos; vector<int> old2new; GenerateUniqueVectors(verts, vertPos, old2new); vector<vector<int> > new2old; new2old.resize(vertPos.size()); for (unsigned int a=0;a<old2new.size();a++) new2old[old2new[a]].push_back(a); // Calculate planes std::vector <Plane> polyPlanes; polyPlanes.resize (poly.size()); for (unsigned int a=0;a<poly.size();a++) polyPlanes[a] = poly[a]->CalcPlane (verts); // Determine which faces are using which unique vertex std::vector <FaceVert> faceVerts; // one per unique vertex faceVerts.resize (old2new.size ()); for (unsigned int a=0;a<poly.size();a++) { Poly *pl = poly[a]; for (unsigned int v=0;v<pl->verts.size();v++) faceVerts[old2new[pl->verts[v]]].adjacentFaces.push_back (a); } // Calculate normals int cnorm = 0; for (unsigned int a=0;a<poly.size();a++) cnorm += poly[a]->verts.size(); std::vector <Vector3> normals; normals.resize (cnorm); cnorm = 0; for (unsigned int a=0;a<poly.size();a++) { Poly *pl = poly[a]; for (unsigned int v=0;v<pl->verts.size();v++) { FaceVert& fv = faceVerts[old2new[pl->verts[v]]]; std::vector<Vector3> vnormals; vnormals.push_back(polyPlanes[a].GetVector()); for (unsigned int adj = 0; adj < fv.adjacentFaces.size(); adj ++) { // Same poly? if (fv.adjacentFaces [adj] == int(a)) continue; Plane adjPlane = polyPlanes[fv.adjacentFaces[adj]]; // Spring 3DO style smoothing float dot = adjPlane.GetVector ().dot (polyPlanes[a].GetVector()); // logger.Print("Dot: %f\n",dot); if (dot < ang_c) continue; // see if the normal is unique for this vertex bool isUnique = true; for (unsigned int norm = 0; norm < vnormals.size(); norm ++) if (vnormals[norm] == adjPlane.GetVector ()) { isUnique = false; break; } if (isUnique) vnormals.push_back (adjPlane.GetVector()); } Vector3 normal; for (unsigned int n=0;n<vnormals.size();n++) normal += vnormals[n]; if (normal.length () > 0.0f) normal.normalize (); normals [cnorm ++] = normal; } } // Create a new set of vertices with the calculated normals std::vector <Vertex> newVertices; newVertices.reserve(poly.size()*4); // approximate cnorm = 0; for (unsigned int a=0;a<poly.size();a++) { Poly *pl = poly[a]; for (unsigned int v=0;v<pl->verts.size();v++) { /*FaceVert &fv = faceVerts[old2new[pl->verts[v]]];*/ Vertex nv = verts[pl->verts[v]]; nv.normal = normals[cnorm++]; newVertices.push_back (nv); pl->verts [v] = newVertices.size () - 1; } } // Optimize verts = newVertices; Optimize(&PolyMesh::IsEqualVertexTCNormal); }