| 382 | } |
| 383 | |
| 384 | bool MeshData::GenerateNormals(float smoothingAngle) |
| 385 | { |
| 386 | if (Positions.IsEmpty() || Indices.IsEmpty()) |
| 387 | { |
| 388 | LOG(Warning, "Missing vertex or index data to generate normals."); |
| 389 | return true; |
| 390 | } |
| 391 | PROFILE_CPU(); |
| 392 | |
| 393 | const auto startTime = Platform::GetTimeSeconds(); |
| 394 | |
| 395 | const int32 vertexCount = Positions.Count(); |
| 396 | const int32 indexCount = Indices.Count(); |
| 397 | Normals.Resize(vertexCount, false); |
| 398 | smoothingAngle = Math::Clamp(smoothingAngle, 0.0f, 175.0f); |
| 399 | |
| 400 | // Compute per-face normals but store them per-vertex |
| 401 | Float3 min, max; |
| 402 | min = max = Positions[0]; |
| 403 | for (int32 i = 0; i < indexCount; i += 3) |
| 404 | { |
| 405 | const Float3 v1 = Positions[Indices[i + 0]]; |
| 406 | const Float3 v2 = Positions[Indices[i + 1]]; |
| 407 | const Float3 v3 = Positions[Indices[i + 2]]; |
| 408 | const Float3 n = ((v2 - v1) ^ (v3 - v1)); |
| 409 | |
| 410 | Normals[Indices[i + 0]] = n; |
| 411 | Normals[Indices[i + 1]] = n; |
| 412 | Normals[Indices[i + 2]] = n; |
| 413 | |
| 414 | Float3::Min(min, v1, min); |
| 415 | Float3::Min(min, v2, min); |
| 416 | Float3::Min(min, v3, min); |
| 417 | |
| 418 | Float3::Max(max, v1, max); |
| 419 | Float3::Max(max, v2, max); |
| 420 | Float3::Max(max, v3, max); |
| 421 | } |
| 422 | |
| 423 | #if USE_SPATIAL_SORT |
| 424 | // Set up a SpatialSort to quickly find all vertices close to a given position |
| 425 | Assimp::SpatialSort vertexFinder; |
| 426 | vertexFinder.Fill((const aiVector3D*)Positions.Get(), vertexCount, sizeof(Float3)); |
| 427 | std::vector<uint32> verticesFound(16); |
| 428 | #else |
| 429 | Array<int32> verticesFound(16); |
| 430 | #endif |
| 431 | const float posEpsilon = (max - min).Length() * 1e-4f; |
| 432 | |
| 433 | // Check if use the angle limit (then use the faster path) |
| 434 | if (smoothingAngle >= 175.0f) |
| 435 | { |
| 436 | BitArray<> used; |
| 437 | used.Resize(vertexCount); |
| 438 | used.SetAll(false); |
| 439 | |
| 440 | for (int32 i = 0; i < vertexCount; i++) |
| 441 | { |