| 438 | } |
| 439 | |
| 440 | std::optional<glm::dmat4x4> getNodeTransform(const CesiumGltf::Node& node) { |
| 441 | if (!node.matrix.empty() && node.matrix.size() < 16) { |
| 442 | return std::nullopt; |
| 443 | } |
| 444 | |
| 445 | // clang-format off |
| 446 | // This is column-major, just like glm and glTF |
| 447 | static constexpr std::array<double, 16> identityMatrix = { |
| 448 | 1.0, 0.0, 0.0, 0.0, |
| 449 | 0.0, 1.0, 0.0, 0.0, |
| 450 | 0.0, 0.0, 1.0, 0.0, |
| 451 | 0.0, 0.0, 0.0, 1.0}; |
| 452 | // clang-format on |
| 453 | |
| 454 | const std::vector<double>& matrix = node.matrix; |
| 455 | |
| 456 | if (node.matrix.size() >= 16 && !std::equal( |
| 457 | identityMatrix.begin(), |
| 458 | identityMatrix.end(), |
| 459 | matrix.begin())) { |
| 460 | return glm::dmat4x4( |
| 461 | glm::dvec4(matrix[0], matrix[1], matrix[2], matrix[3]), |
| 462 | glm::dvec4(matrix[4], matrix[5], matrix[6], matrix[7]), |
| 463 | glm::dvec4(matrix[8], matrix[9], matrix[10], matrix[11]), |
| 464 | glm::dvec4(matrix[12], matrix[13], matrix[14], matrix[15])); |
| 465 | } |
| 466 | |
| 467 | if (!node.translation.empty() || !node.rotation.empty() || |
| 468 | !node.scale.empty()) { |
| 469 | glm::dmat4x4 translation(1.0); |
| 470 | if (node.translation.size() >= 3) { |
| 471 | translation[3] = glm::dvec4( |
| 472 | node.translation[0], |
| 473 | node.translation[1], |
| 474 | node.translation[2], |
| 475 | 1.0); |
| 476 | } else if (!node.translation.empty()) { |
| 477 | return std::nullopt; |
| 478 | } |
| 479 | |
| 480 | glm::dquat rotationQuat(1.0, 0.0, 0.0, 0.0); |
| 481 | if (node.rotation.size() >= 4) { |
| 482 | rotationQuat[0] = node.rotation[0]; |
| 483 | rotationQuat[1] = node.rotation[1]; |
| 484 | rotationQuat[2] = node.rotation[2]; |
| 485 | rotationQuat[3] = node.rotation[3]; |
| 486 | } else if (!node.rotation.empty()) { |
| 487 | return std::nullopt; |
| 488 | } |
| 489 | |
| 490 | glm::dmat4x4 scale(1.0); |
| 491 | if (node.scale.size() >= 3) { |
| 492 | scale[0].x = node.scale[0]; |
| 493 | scale[1].y = node.scale[1]; |
| 494 | scale[2].z = node.scale[2]; |
| 495 | } else if (!node.scale.empty()) { |
| 496 | return std::nullopt; |
| 497 | } |
no test coverage detected