| 450 | } |
| 451 | |
| 452 | SceneBuilder::ProcessedMesh SceneBuilder::processMesh(const Mesh& mesh_, MeshAttributeIndices* pAttributeIndices, std::vector<float4>* pTangents) const |
| 453 | { |
| 454 | // This function preprocesses a mesh into the final runtime representation. |
| 455 | // Note the function needs to be thread safe. The following steps are performed: |
| 456 | // - Error checking |
| 457 | // - Compute tangent space if needed |
| 458 | // - Merge identical vertices, compute new indices (optional) |
| 459 | // - Validate final vertex data |
| 460 | // - Compact vertices/indices into runtime format |
| 461 | |
| 462 | // Copy the mesh desc so we can update it. The caller retains the ownership of the data. |
| 463 | Mesh mesh = mesh_; |
| 464 | ProcessedMesh processedMesh; |
| 465 | |
| 466 | processedMesh.name = mesh.name; |
| 467 | processedMesh.topology = mesh.topology; |
| 468 | processedMesh.pMaterial = mesh.pMaterial; |
| 469 | processedMesh.isFrontFaceCW = mesh.isFrontFaceCW; |
| 470 | processedMesh.isAnimated = mesh.isAnimated; |
| 471 | processedMesh.skeletonNodeId = mesh.skeletonNodeId; |
| 472 | |
| 473 | // Error checking. |
| 474 | auto throw_on_missing_element = [&](const std::string& element) |
| 475 | { |
| 476 | FALCOR_THROW("Error when adding the mesh '{}' to the scene. The mesh is missing {}.", mesh.name, element); |
| 477 | }; |
| 478 | |
| 479 | auto missing_element_warning = [&](const std::string& element) |
| 480 | { |
| 481 | logWarning("The mesh '{}' is missing the element {}. This is not an error, the element will be filled with zeros which may result in incorrect rendering.", mesh.name, element); |
| 482 | }; |
| 483 | |
| 484 | if (mesh.topology != Vao::Topology::TriangleList) FALCOR_THROW("Error when adding the mesh '{}' to the scene. Only triangle list topology is supported.", mesh.name); |
| 485 | if (mesh.pMaterial == nullptr) throw_on_missing_element("material"); |
| 486 | |
| 487 | if (mesh.faceCount == 0) throw_on_missing_element("faces"); |
| 488 | if (mesh.vertexCount == 0) throw_on_missing_element("vertices"); |
| 489 | if (mesh.indexCount == 0 || !mesh.pIndices) throw_on_missing_element("indices"); |
| 490 | if (mesh.indexCount != mesh.faceCount * 3) FALCOR_THROW("Error when adding the mesh '{}' to the scene. Unexpected face/vertex count.", mesh.name); |
| 491 | |
| 492 | if (mesh.positions.pData == nullptr) throw_on_missing_element("positions"); |
| 493 | if (mesh.normals.pData == nullptr) missing_element_warning("normals"); |
| 494 | if (mesh.texCrds.pData == nullptr) missing_element_warning("texture coordinates"); |
| 495 | |
| 496 | if (mesh.hasBones()) |
| 497 | { |
| 498 | if (mesh.boneIDs.pData == nullptr) throw_on_missing_element("bone IDs"); |
| 499 | if (mesh.boneWeights.pData == nullptr) throw_on_missing_element("bone weights"); |
| 500 | } |
| 501 | |
| 502 | // Generate tangent space if that's required. |
| 503 | std::vector<float4> localTangents; |
| 504 | if (!pTangents) |
| 505 | pTangents = &localTangents; |
| 506 | if (!(is_set(mFlags, Flags::UseOriginalTangentSpace) || mesh.useOriginalTangentSpace) || !mesh.tangents.pData) |
| 507 | { |
| 508 | generateTangents(mesh, *pTangents); |
| 509 | } |
no test coverage detected