MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
ModelReader.hpp
Go to the documentation of this file.
1#pragma once
2
5
6namespace MayaFlux::Core {
7class VKImage;
8}
9
10namespace MayaFlux::Buffers {
11class MeshBuffer;
12}
13
15class MeshNetwork;
16}
17
18namespace MayaFlux::IO {
19
20/**
21 * @brief Callable that maps a raw material texture path to a GPU image.
22 *
23 * Receives the path exactly as stored in the model file. The default
24 * resolver resolves relative to the model file's directory via
25 * ImageReader::load_texture.
26 */
27using TextureResolver = std::function<std::shared_ptr<Core::VKImage>(const std::string& path)>;
28
29/**
30 * @class ModelReader
31 * @brief Assimp-backed loader for 3D model files.
32 *
33 * Produces vector<Kakshya::MeshData> — one entry per assimp mesh in the
34 * imported scene. Each MeshData owns its vertex bytes (vector<uint8_t> in
35 * the canonical 60-byte interleaved MeshVertex format) and index array
36 * (vector<uint32_t>). Submesh identity is preserved in the single-entry case
37 * via MeshData::submeshes (a RegionGroup named "submeshes" with one Region).
38 * Multi-mesh files produce one MeshData per aiMesh, each with its own
39 * single-submesh RegionGroup.
40 *
41 * Supported formats: glTF 2.0 (.glb, .gltf), OBJ, FBX, PLY, STL, DAE,
42 * and any other format Assimp supports on the target platform.
43 *
44 * Post-processing applied unconditionally:
45 * - aiProcess_Triangulate: all faces become triangles
46 * - aiProcess_GenSmoothNormals: generate normals if absent
47 * - aiProcess_CalcTangentSpace: tangent + bitangent from UVs
48 * - aiProcess_FlipUVs: V-flip to match Vulkan UV convention
49 * - aiProcess_JoinIdenticalVertices: deduplicate vertices
50 * - aiProcess_SortByPType: isolate TRIANGLE primitives
51 *
52 * FileReader contract:
53 * create_container() and load_into_container() are no-ops for this reader;
54 * mesh data does not go through the SignalSourceContainer streaming path.
55 * Use load() or the IOManager::load_mesh() convenience wrapper instead.
56 */
57class MAYAFLUX_API ModelReader : public FileReader {
58public:
60 ~ModelReader() override;
61
62 // -------------------------------------------------------------------------
63 // Primary API — use these
64 // -------------------------------------------------------------------------
65
66 /**
67 * @brief Load all meshes from a file in one call.
68 *
69 * Opens, imports, extracts, and closes in a single synchronous operation.
70 * Returns an empty vector on failure; check get_last_error().
71 *
72 * @param filepath Path to the model file.
73 * @return One MeshData per aiMesh in the scene, in scene order.
74 */
75 [[nodiscard]] std::vector<Kakshya::MeshData> load(const std::string& filepath);
76
77 /**
78 * @brief Load all meshes after open() has already been called.
79 *
80 * Extracts from the currently imported scene. Returns empty if no scene
81 * is loaded. Does not call close().
82 *
83 * @return One MeshData per aiMesh in the scene.
84 */
85 [[nodiscard]] std::vector<Kakshya::MeshData> extract_meshes() const;
86
87 /**
88 * @brief Construct one MeshBuffer per mesh in the currently loaded scene.
89 *
90 * Calls extract_meshes() internally. Returns empty if no scene is loaded.
91 * setup_processors() and setup_rendering() are left to the caller.
92 *
93 * If resolver is provided, it is called with the raw diffuse path from each
94 * mesh's material. The returned VKImage is bound via bind_diffuse_texture().
95 * Null resolver skips texture binding entirely.
96 *
97 * @param resolver Optional texture resolver.
98 * @return One MeshBuffer per aiMesh in scene order.
99 */
100 [[nodiscard]] std::vector<std::shared_ptr<Buffers::MeshBuffer>>
101 create_mesh_buffers(const TextureResolver& resolver = nullptr) const;
102
103 /**
104 * @brief Construct a MeshNetwork from all meshes in the currently loaded scene.
105 *
106 * One MeshSlot per aiMesh, named from aiMesh::mName (or "mesh_N" if unnamed).
107 * Each slot's MeshWriterNode holds the extracted vertex and index data.
108 *
109 * If resolver is provided, it is called with the raw diffuse path from each
110 * mesh's material. The returned VKImage is assigned to slot.diffuse_texture.
111 * Null resolver skips texture binding entirely.
112 *
113 * Requires open(). Does not call close().
114 *
115 * @param resolver Optional texture resolver.
116 * @return Populated MeshNetwork, or nullptr if no scene is loaded.
117 */
118 [[nodiscard]] std::shared_ptr<Nodes::Network::MeshNetwork>
119 create_mesh_network(const TextureResolver& resolver = nullptr) const;
120
121 // -------------------------------------------------------------------------
122 // FileReader interface
123 // -------------------------------------------------------------------------
124
125 [[nodiscard]] bool can_read(const std::string& filepath) const override;
126
127 bool open(const std::string& filepath,
128 FileReadOptions options = FileReadOptions::ALL) override;
129
130 void close() override;
131
132 [[nodiscard]] bool is_open() const override { return m_is_open; }
133
134 [[nodiscard]] std::optional<FileMetadata> get_metadata() const override;
135
136 [[nodiscard]] std::vector<FileRegion> get_regions() const override;
137
138 std::vector<Kakshya::DataVariant> read_all() override;
139
140 std::vector<Kakshya::DataVariant> read_region(const FileRegion& region) override;
141
142 /**
143 * @brief No-op. Mesh data does not use SignalSourceContainer.
144 * @return nullptr always.
145 */
146 std::shared_ptr<Kakshya::SignalSourceContainer> create_container() override;
147
148 /**
149 * @brief No-op. Mesh data does not use SignalSourceContainer.
150 * @return false always.
151 */
152 bool load_into_container(
153 std::shared_ptr<Kakshya::SignalSourceContainer> container) override;
154
155 [[nodiscard]] std::vector<uint64_t> get_read_position() const override;
156
157 bool seek(const std::vector<uint64_t>& position) override;
158
159 [[nodiscard]] std::vector<std::string> get_supported_extensions() const override;
160
161 [[nodiscard]] std::type_index get_data_type() const override
162 {
163 return typeid(std::vector<uint8_t>);
164 }
165
166 [[nodiscard]] std::type_index get_container_type() const override
167 {
168 return typeid(void);
169 }
170
171 [[nodiscard]] std::string get_last_error() const override { return m_last_error; }
172
173 [[nodiscard]] bool supports_streaming() const override { return false; }
174 [[nodiscard]] uint64_t get_preferred_chunk_size() const override { return 0; }
175 [[nodiscard]] size_t get_num_dimensions() const override { return 0; }
176 [[nodiscard]] std::vector<uint64_t> get_dimension_sizes() const override { return {}; }
177
178private:
179 struct Impl;
180 std::unique_ptr<Impl> m_impl;
181
182 bool m_is_open { false };
183 mutable std::string m_last_error;
184
185 [[nodiscard]] Kakshya::MeshData extract_single_mesh(
186 const void* ai_mesh,
187 const void* ai_scene,
188 std::string_view mesh_name,
189 std::string_view material_name) const;
190
191 void set_error(std::string msg) const { m_last_error = std::move(msg); }
192};
193
194} // namespace MayaFlux::IO
glm::vec3 position
Abstract interface for reading various file formats into containers.
std::unique_ptr< Impl > m_impl
std::type_index get_data_type() const override
Get the data type this reader produces.
std::string get_last_error() const override
Get the last error message.
void set_error(std::string msg) const
std::vector< uint64_t > get_dimension_sizes() const override
Get size of each dimension in the file data.
std::type_index get_container_type() const override
Get the container type this reader creates.
bool is_open() const override
Check if a file is currently open.
size_t get_num_dimensions() const override
Get the dimensionality of the file data.
uint64_t get_preferred_chunk_size() const override
Get the preferred chunk size for streaming.
bool supports_streaming() const override
Check if streaming is supported for the current file.
Assimp-backed loader for 3D model files.
FileReadOptions
Generic options for file reading behavior.
std::function< std::shared_ptr< Core::VKImage >(const std::string &path)> TextureResolver
Callable that maps a raw material texture path to a GPU image.
Definition Creator.hpp:17
auto create_container(Args &&... args) -> std::shared_ptr< ContainerType >
creates a new container of the specified type
Definition Depot.hpp:41
Generic region descriptor for any file type.
Owning CPU-side representation of a loaded or generated mesh.
Definition MeshData.hpp:33