in src/raw/RawModel.cpp [683:729]
size_t RawModel::CalculateNormals(bool onlyBroken) {
Vec3f averagePos = Vec3f{0.0f};
std::set<int> brokenVerts;
for (int vertIx = 0; vertIx < vertices.size(); vertIx++) {
RawVertex& vertex = vertices[vertIx];
averagePos += (vertex.position / (float)vertices.size());
if (onlyBroken && (vertex.normal.LengthSquared() >= FLT_MIN)) {
continue;
}
vertex.normal = Vec3f{0.0f};
if (onlyBroken) {
brokenVerts.emplace(vertIx);
}
}
for (auto& triangle : triangles) {
bool relevant = false;
for (int vertIx : triangle.verts) {
relevant |= (brokenVerts.count(vertIx) > 0);
}
if (!relevant) {
continue;
}
Vec3f faceNormal = this->getFaceNormal(triangle.verts);
for (int vertIx : triangle.verts) {
if (!onlyBroken || brokenVerts.count(vertIx) > 0) {
vertices[vertIx].normal += faceNormal;
}
}
}
for (int vertIx = 0; vertIx < vertices.size(); vertIx++) {
if (onlyBroken && brokenVerts.count(vertIx) == 0) {
continue;
}
RawVertex& vertex = vertices[vertIx];
if (vertex.normal.LengthSquared() < FLT_MIN) {
vertex.normal = vertex.position - averagePos;
if (vertex.normal.LengthSquared() < FLT_MIN) {
vertex.normal = Vec3f{0.0f, 1.0f, 0.0f};
continue;
}
}
vertex.normal.Normalize();
}
return onlyBroken ? brokenVerts.size() : vertices.size();
}