23#ifndef VCL_IO_CAMERA_GLTF_LOAD_H
24#define VCL_IO_CAMERA_GLTF_LOAD_H
26#include <vclib/io/file_info.h>
28#include <vclib/space/core.h>
40inline tinygltf::Model loadTinyGltfCameraModel(
const std::string& filename)
42 tinygltf::TinyGLTF loader;
43 tinygltf::Model model;
44 std::string err, warn;
49 ret = loader.LoadASCIIFromFile(&model, &err, &warn, filename);
50 else if (ext ==
".glb")
51 ret = loader.LoadBinaryFromFile(&model, &err, &warn, filename);
53 throw UnknownFileFormatException(ext);
56 throw std::runtime_error(
57 "Failed to load glTF cameras: " + err +
58 (warn.empty() ?
"" :
" " + warn));
64template<CameraConcept CameraType = Camera<
float>>
65inline std::vector<CameraType> loadCamerasGltf(
const std::string& filename)
67 using Scalar =
typename CameraType::ScalarType;
68 tinygltf::Model model = detail::loadTinyGltfCameraModel(filename);
70 std::vector<CameraType> cams;
71 cams.reserve(model.cameras.size());
73 for (
size_t cameraIdx = 0; cameraIdx < model.cameras.size(); ++cameraIdx) {
74 const tinygltf::Camera& gltfCamera = model.cameras[cameraIdx];
77 if (gltfCamera.type ==
"perspective") {
78 camera.projectionMode() = CameraType::ProjectionMode::PERSPECTIVE;
79 camera.fieldOfView() = gltfCamera.perspective.yfov * 180.0 / M_PI;
81 camera.aspectRatio() = gltfCamera.perspective.aspectRatio;
82 camera.nearPlane() = gltfCamera.perspective.znear;
83 camera.farPlane() = gltfCamera.perspective.zfar;
85 else if (gltfCamera.type ==
"orthographic") {
86 camera.projectionMode() = CameraType::ProjectionMode::ORTHO;
87 camera.verticalHeight() = gltfCamera.orthographic.ymag * 2.0;
89 camera.aspectRatio() =
90 gltfCamera.orthographic.xmag / gltfCamera.orthographic.ymag;
91 camera.nearPlane() = gltfCamera.orthographic.znear;
92 camera.farPlane() = gltfCamera.orthographic.zfar;
95 bool foundNode =
false;
96 for (
const auto& node : model.nodes) {
97 if (node.camera ==
static_cast<int>(cameraIdx)) {
100 if (node.matrix.size() == 16) {
109 if (node.translation.size() == 3) {
113 node.translation[2]);
115 if (node.rotation.size() == 4) {
122 if (node.scale.size() == 3) {
124 node.scale[0], node.scale[1], node.scale[2]);
129 affine.translate(translation);
130 affine.rotate(rotation);
132 mat = affine.matrix();
135 typename CameraType::PointType eye(
136 mat(0, 3), mat(1, 3), mat(2, 3));
139 typename CameraType::PointType forward(
140 -mat(0, 2), -mat(1, 2), -mat(2, 2));
141 forward = forward.normalized();
143 typename CameraType::PointType up(
144 mat(0, 1), mat(1, 1), mat(2, 1));
145 camera.up() = up.normalized();
148 camera.center() = eye + forward *
distance;
156 throw std::runtime_error(
157 "Invalid glTF camera: no node references camera index " +
158 std::to_string(cameraIdx));
161 cams.push_back(camera);
164 assert(cams.size() == model.cameras.size());
169template<CameraConcept CameraType = Camera<
float>>
170inline CameraType loadCameraGltf(
171 const std::string& filename,
174 auto cams = loadCamerasGltf<CameraType>(filename);
175 if (cameraIdx >= cams.size())
176 throw std::out_of_range(
177 "Camera index " + std::to_string(cameraIdx) +
178 " is out of range. Total cameras: " + std::to_string(cams.size()));
179 return cams[cameraIdx];
static std::string extension(const std::string &filename)
Get the extension of a file.
Definition file_info.h:260
The Point class represents an N-dimensional point containing N scalar values.
Definition point.h:55
A class representing a line segment in n-dimensional space. The class is parameterized by a PointConc...
Definition segment.h:41
Segment()
Default constructor. Creates a segment with endpoints at the origin.
Definition segment.h:66
auto distance(const PointType &point0, const PointType &point1)
Compute the distance between two Points of any dimension.
Definition distance.h:45
Quaternion< double > Quaterniond
A convenience alias for Quaternion with double-precision floating-point components.
Definition quaternion.h:201
Point3< double > Point3d
A convenience alias for a 3-dimensional Point with double-precision floating-point components.
Definition point.h:780