| 420 | } |
| 421 | |
| 422 | [[nodiscard]] std::optional<glm::mat3> tensorToVisualizerRotation(const PyTensor& py_tensor) { |
| 423 | const auto& tensor = py_tensor.tensor(); |
| 424 | if (!tensor.is_valid() || tensor.ndim() != 2 || tensor.size(0) != 3 || tensor.size(1) != 3) { |
| 425 | return std::nullopt; |
| 426 | } |
| 427 | |
| 428 | try { |
| 429 | const auto cpu = tensor.to(core::Device::CPU).to(core::DataType::Float32).contiguous(); |
| 430 | const auto* const data = static_cast<const float*>(cpu.data_ptr()); |
| 431 | if (!data) { |
| 432 | return std::nullopt; |
| 433 | } |
| 434 | |
| 435 | glm::mat3 rotation{}; |
| 436 | for (int row = 0; row < 3; ++row) { |
| 437 | for (int col = 0; col < 3; ++col) { |
| 438 | const float value = data[row * 3 + col]; |
| 439 | if (!std::isfinite(value)) { |
| 440 | return std::nullopt; |
| 441 | } |
| 442 | rotation[col][row] = value; |
| 443 | } |
| 444 | } |
| 445 | return rotation; |
| 446 | } catch (const std::exception& e) { |
| 447 | LOG_DEBUG("render_view rotation conversion failed: {}", e.what()); |
| 448 | } catch (...) { |
| 449 | LOG_DEBUG("render_view rotation conversion failed: unknown error"); |
| 450 | } |
| 451 | return std::nullopt; |
| 452 | } |
| 453 | |
| 454 | [[nodiscard]] std::optional<glm::vec3> tensorToVisualizerTranslation(const PyTensor& py_tensor) { |
| 455 | const auto& tensor = py_tensor.tensor(); |