| 452 | } |
| 453 | |
| 454 | [[nodiscard]] std::optional<glm::vec3> tensorToVisualizerTranslation(const PyTensor& py_tensor) { |
| 455 | const auto& tensor = py_tensor.tensor(); |
| 456 | if (!tensor.is_valid() || tensor.ndim() != 1 || tensor.size(0) != 3) { |
| 457 | return std::nullopt; |
| 458 | } |
| 459 | |
| 460 | try { |
| 461 | const auto cpu = tensor.to(core::Device::CPU).to(core::DataType::Float32).contiguous(); |
| 462 | const auto* const data = static_cast<const float*>(cpu.data_ptr()); |
| 463 | if (!data) { |
| 464 | return std::nullopt; |
| 465 | } |
| 466 | |
| 467 | const glm::vec3 translation{data[0], data[1], data[2]}; |
| 468 | if (!std::isfinite(translation.x) || !std::isfinite(translation.y) || !std::isfinite(translation.z)) { |
| 469 | return std::nullopt; |
| 470 | } |
| 471 | return translation; |
| 472 | } catch (const std::exception& e) { |
| 473 | LOG_DEBUG("render_view translation conversion failed: {}", e.what()); |
| 474 | } catch (...) { |
| 475 | LOG_DEBUG("render_view translation conversion failed: unknown error"); |
| 476 | } |
| 477 | return std::nullopt; |
| 478 | } |
| 479 | |
| 480 | [[nodiscard]] std::optional<core::Tensor> renderViewOnViewerThread( |
| 481 | const glm::mat3& rotation, |