Move SMaterial std::hash impl to its header
[minetest.git] / irr / src / CGLTFMeshFileLoader.h
blobae178565d77ee7fec10d1d80134b046298e3e5c4
1 // Minetest
2 // SPDX-License-Identifier: LGPL-2.1-or-later
4 #pragma once
6 #include "CSkinnedMesh.h"
7 #include "IMeshLoader.h"
8 #include "IReadFile.h"
9 #include "irrTypes.h"
10 #include "path.h"
11 #include "S3DVertex.h"
13 #include "tiniergltf.hpp"
15 #include <functional>
16 #include <cstddef>
17 #include <tuple>
18 #include <vector>
20 namespace irr
23 namespace scene
26 class CGLTFMeshFileLoader : public IMeshLoader
28 public:
29 CGLTFMeshFileLoader() noexcept {};
31 bool isALoadableFileExtension(const io::path &filename) const override;
33 IAnimatedMesh *createMesh(io::IReadFile *file) override;
35 private:
36 template <typename T>
37 static T rawget(const char *ptr);
39 template <class T>
40 class Accessor
42 struct BufferSource
44 const char *ptr;
45 std::size_t byteStride;
47 using Source = std::variant<BufferSource, std::vector<T>, std::tuple<>>;
49 public:
50 static Accessor sparseIndices(
51 const tiniergltf::GlTF &model,
52 const tiniergltf::AccessorSparseIndices &indices,
53 const std::size_t count);
54 static Accessor sparseValues(
55 const tiniergltf::GlTF &model,
56 const tiniergltf::AccessorSparseValues &values,
57 const std::size_t count,
58 const std::size_t defaultByteStride);
59 static Accessor base(
60 const tiniergltf::GlTF &model,
61 std::size_t accessorIdx);
62 static Accessor make(const tiniergltf::GlTF &model, std::size_t accessorIdx);
63 static constexpr tiniergltf::Accessor::Type getType();
64 static constexpr tiniergltf::Accessor::ComponentType getComponentType();
65 std::size_t getCount() const { return count; }
66 T get(std::size_t i) const;
68 private:
69 Accessor(const char *ptr, std::size_t byteStride, std::size_t count) :
70 source(BufferSource{ptr, byteStride}), count(count) {}
71 Accessor(std::vector<T> vec, std::size_t count) :
72 source(vec), count(count) {}
73 Accessor(std::size_t count) :
74 source(std::make_tuple()), count(count) {}
75 // Directly from buffer, sparse, or default-initialized
76 const Source source;
77 const std::size_t count;
80 template <typename... Ts>
81 using AccessorVariant = std::variant<Accessor<Ts>...>;
83 template <std::size_t N, typename... Ts>
84 using ArrayAccessorVariant = std::variant<Accessor<std::array<Ts, N>>...>;
86 template <std::size_t N>
87 using NormalizedValuesAccessor = ArrayAccessorVariant<N, u8, u16, f32>;
89 template <std::size_t N>
90 static NormalizedValuesAccessor<N> createNormalizedValuesAccessor(
91 const tiniergltf::GlTF &model,
92 const std::size_t accessorIdx);
94 template <std::size_t N>
95 static std::array<f32, N> getNormalizedValues(
96 const NormalizedValuesAccessor<N> &accessor,
97 const std::size_t i);
99 class MeshExtractor
101 public:
102 MeshExtractor(tiniergltf::GlTF &&model,
103 CSkinnedMesh *mesh) noexcept
104 : m_gltf_model(std::move(model)), m_irr_model(mesh) {};
106 /* Gets indices for the given mesh/primitive.
108 * Values are return in Irrlicht winding order.
110 std::optional<std::vector<u16>> getIndices(
111 const tiniergltf::MeshPrimitive &primitive) const;
113 std::optional<std::vector<video::S3DVertex>> getVertices(
114 const tiniergltf::MeshPrimitive &primitive) const;
116 std::size_t getMeshCount() const;
118 std::size_t getPrimitiveCount(const std::size_t meshIdx) const;
120 void load();
121 const std::vector<std::string> &getWarnings() {
122 return warnings;
125 private:
126 const tiniergltf::GlTF m_gltf_model;
127 CSkinnedMesh *m_irr_model;
129 std::vector<std::function<void()>> m_mesh_loaders;
130 std::vector<CSkinnedMesh::SJoint *> m_loaded_nodes;
132 std::vector<std::string> warnings;
133 void warn(const std::string &warning) {
134 warnings.push_back(warning);
137 void copyPositions(const std::size_t accessorIdx,
138 std::vector<video::S3DVertex>& vertices) const;
140 void copyNormals(const std::size_t accessorIdx,
141 std::vector<video::S3DVertex>& vertices) const;
143 void copyTCoords(const std::size_t accessorIdx,
144 std::vector<video::S3DVertex>& vertices) const;
146 void addPrimitive(const tiniergltf::MeshPrimitive &primitive,
147 const std::optional<std::size_t> skinIdx,
148 CSkinnedMesh::SJoint *parent);
150 void deferAddMesh(const std::size_t meshIdx,
151 const std::optional<std::size_t> skinIdx,
152 CSkinnedMesh::SJoint *parentJoint);
154 void loadNode(const std::size_t nodeIdx, CSkinnedMesh::SJoint *parentJoint);
156 void loadNodes();
158 void loadSkins();
160 void loadAnimation(const std::size_t animIdx);
163 tiniergltf::GlTF parseGLTF(io::IReadFile *file);
166 } // namespace scene
168 } // namespace irr