| 1865 | } |
| 1866 | |
| 1867 | [[nodiscard]] std::optional<glm::mat4> cameraVisualizerTransform( |
| 1868 | const lfs::core::Camera& camera, |
| 1869 | const glm::mat4& scene_transform) { |
| 1870 | auto rotation_tensor = camera.R(); |
| 1871 | auto translation_tensor = camera.T(); |
| 1872 | if (!rotation_tensor.is_valid() || !translation_tensor.is_valid()) { |
| 1873 | return std::nullopt; |
| 1874 | } |
| 1875 | if (rotation_tensor.device() != lfs::core::Device::CPU) { |
| 1876 | rotation_tensor = rotation_tensor.cpu(); |
| 1877 | } |
| 1878 | if (translation_tensor.device() != lfs::core::Device::CPU) { |
| 1879 | translation_tensor = translation_tensor.cpu(); |
| 1880 | } |
| 1881 | if (rotation_tensor.dtype() != lfs::core::DataType::Float32 || |
| 1882 | translation_tensor.dtype() != lfs::core::DataType::Float32 || |
| 1883 | rotation_tensor.numel() < 9 || translation_tensor.numel() < 3) { |
| 1884 | return std::nullopt; |
| 1885 | } |
| 1886 | |
| 1887 | const float* const rotation = rotation_tensor.ptr<float>(); |
| 1888 | const float* const translation = translation_tensor.ptr<float>(); |
| 1889 | if (!rotation || !translation) { |
| 1890 | return std::nullopt; |
| 1891 | } |
| 1892 | |
| 1893 | glm::mat4 world_to_camera(1.0f); |
| 1894 | for (int row = 0; row < 3; ++row) { |
| 1895 | for (int col = 0; col < 3; ++col) { |
| 1896 | world_to_camera[col][row] = rotation[row * 3 + col]; |
| 1897 | } |
| 1898 | world_to_camera[3][row] = translation[row]; |
| 1899 | } |
| 1900 | |
| 1901 | return scene_transform * glm::inverse(world_to_camera) * |
| 1902 | lfs::rendering::DATA_TO_VISUALIZER_CAMERA_AXES_4; |
| 1903 | } |
| 1904 | |
| 1905 | [[nodiscard]] std::vector<glm::mat4> resolveCameraSceneTransforms( |
| 1906 | const SceneManager& scene_manager, |