| 1414 | } // namespace |
| 1415 | |
| 1416 | GltfUtilities::IntersectResult GltfUtilities::intersectRayGltfModel( |
| 1417 | const CesiumGeometry::Ray& ray, |
| 1418 | const CesiumGltf::Model& gltf, |
| 1419 | bool cullBackFaces, |
| 1420 | const glm::dmat4x4& gltfTransform) { |
| 1421 | // We can't currently intersect a ray with a model if the model has any funny |
| 1422 | // business with its vertex positions or if it uses instancing. |
| 1423 | for (const std::string& unsupportedExtension : |
| 1424 | intersectGltfUnsupportedExtensions) { |
| 1425 | if (gltf.isExtensionRequired(unsupportedExtension)) { |
| 1426 | return IntersectResult{ |
| 1427 | std::nullopt, |
| 1428 | {fmt::format( |
| 1429 | "Cannot intersect a ray with a glTF model with the {} extension.", |
| 1430 | unsupportedExtension)}}; |
| 1431 | } |
| 1432 | } |
| 1433 | |
| 1434 | glm::dmat4x4 rootTransform = applyRtcCenter(gltf, gltfTransform); |
| 1435 | rootTransform = applyGltfUpAxisTransform(gltf, rootTransform); |
| 1436 | |
| 1437 | IntersectResult result; |
| 1438 | |
| 1439 | gltf.forEachPrimitiveInScene( |
| 1440 | -1, |
| 1441 | [ray, cullBackFaces, rootTransform, &result]( |
| 1442 | const CesiumGltf::Model& model, |
| 1443 | const CesiumGltf::Node& /*node*/, |
| 1444 | const CesiumGltf::Mesh& mesh, |
| 1445 | const CesiumGltf::MeshPrimitive& primitive, |
| 1446 | const glm::dmat4& nodeTransform) { |
| 1447 | // Ignore non-triangles. Points and lines have no area to intersect |
| 1448 | bool isTriangleMode = |
| 1449 | primitive.mode == MeshPrimitive::Mode::TRIANGLES || |
| 1450 | primitive.mode == MeshPrimitive::Mode::TRIANGLE_STRIP || |
| 1451 | primitive.mode == MeshPrimitive::Mode::TRIANGLE_FAN; |
| 1452 | if (!isTriangleMode) |
| 1453 | return; |
| 1454 | |
| 1455 | // Skip primitives that can't access positions |
| 1456 | auto positionAccessorIt = primitive.attributes.find("POSITION"); |
| 1457 | if (positionAccessorIt == primitive.attributes.end()) { |
| 1458 | result.warnings.emplace_back( |
| 1459 | "Skipping mesh without a position attribute"); |
| 1460 | return; |
| 1461 | } |
| 1462 | int positionAccessorID = positionAccessorIt->second; |
| 1463 | const Accessor* pPositionAccessor = |
| 1464 | Model::getSafe(&model.accessors, positionAccessorID); |
| 1465 | if (!pPositionAccessor) { |
| 1466 | result.warnings.emplace_back( |
| 1467 | "Skipping mesh with an invalid position accessor id"); |
| 1468 | return; |
| 1469 | } |
| 1470 | |
| 1471 | // From the glTF spec, the POSITION accessor must use VEC3 |
| 1472 | // But we should still protect against malformed gltfs |
| 1473 | if (pPositionAccessor->type != AccessorSpec::Type::VEC3) { |
nothing calls this directly
no test coverage detected