size_t RawModel::CalculateNormals()

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();
}