summaryrefslogtreecommitdiff
path: root/src/gltf_loader.cpp
blob: 2b3818f4d97e26792ad55c96acb3e279ed2bd2bd (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include "gltf_loader.h"
#include "spdlog/spdlog.h"

enum class SceneFileType {
    GLTF,
    GLB,
    UNKNOWN,
};

bool load_gltf(const std::string_view path, iris::Scene &scene) {
    tinygltf::Model model;
    tinygltf::TinyGLTF loader;

    std::string error;
    std::string warning;

    SceneFileType file_type = [&path] {
        if (path.find_last_of(".") != std::string::npos) {
            std::string_view extension = path.substr(path.find_last_of(".") + 1);
            if (extension == "glb") {
                return SceneFileType::GLB;
            } else if (extension == "gltf") {
                return SceneFileType::GLTF;
            }
        }
        return SceneFileType::UNKNOWN;
    }();
    switch (file_type) {
        case SceneFileType::GLTF:
            if (!loader.LoadASCIIFromFile(&model, &error, &warning, path.data())) {
                spdlog::error("Failed to load glTF file: {}", error);
                return false;
            }
            break;
        case SceneFileType::GLB:
            if (!loader.LoadBinaryFromFile(&model, &error, &warning, path.data())) {
                spdlog::error("Failed to load glTF file: {}", error);
                return false;
            }
            break;
        case SceneFileType::UNKNOWN:
            spdlog::error("Unknown file type: {}", path);
            return false;
    }

    spdlog::info("loaded glTF file {} has:\n"
        "{} accessors\n"
        "{} animations\n"
        "{} buffers\n"
        "{} bufferViews\n"
        "{} materials\n"
        "{} meshes\n"
        "{} nodes\n"
        "{} textures\n"
        "{} images\n"
        "{} skins\n"
        "{} samplers\n"
        "{} cameras\n"
        "{} scenes\n"
        "{} lights",
        path,
        model.accessors.size(),
        model.animations.size(),
        model.buffers.size(),
        model.bufferViews.size(),
        model.materials.size(),
        model.meshes.size(),
        model.nodes.size(),
        model.textures.size(),
        model.images.size(),
        model.skins.size(),
        model.samplers.size(),
        model.cameras.size(),
        model.scenes.size(),
        model.lights.size());

    for (const auto &mesh : model.meshes) {
        iris::Mesh<float> iris_mesh;
        for (const auto &primitive : mesh.primitives) {
            const auto &position_accessor = model.accessors[primitive.attributes.at("POSITION")];
            const auto &position_buffer_view = model.bufferViews[position_accessor.bufferView];
            const auto &position_buffer = model.buffers[position_buffer_view.buffer];
            const auto &position_data = reinterpret_cast<const float *>(position_buffer.data.data() + position_buffer_view.byteOffset + position_accessor.byteOffset);

            const auto &index_accessor = model.accessors[primitive.indices];
            const auto &index_buffer_view = model.bufferViews[index_accessor.bufferView];
            const auto &index_buffer = model.buffers[index_buffer_view.buffer];
            const auto &index_data = reinterpret_cast<const uint32_t *>(index_buffer.data.data() + index_buffer_view.byteOffset + index_accessor.byteOffset);

            iris_mesh.vertices.insert(iris_mesh.vertices.end(), position_data, position_data + position_accessor.count * 3);
            iris_mesh.indices.insert(iris_mesh.indices.end(), index_data, index_data + index_accessor.count);
        }
        scene.meshes.push_back(iris_mesh);
    }
    return true;
}