112 const std::string& filepath,
113 const std::vector<Kakshya::MeshData>& meshes,
118 if (meshes.empty()) {
123 for (
const auto& m : meshes) {
129 set_error(
"MeshData vertex stride is not the canonical MeshVertex layout");
134 const auto ext = extension_of(filepath);
135 std::string format_id = options.
format_id;
136 if (format_id.empty()) {
137 format_id = default_format_id(ext);
139 if (format_id.empty()) {
140 set_error(
"No format_id resolved for extension '" + ext
141 +
"', pass ModelWriteOptions::format_id explicitly");
150 scene.mRootNode =
new aiNode();
152 scene.mNumMaterials =
static_cast<unsigned int>(meshes.size());
153 scene.mMaterials =
new aiMaterial*[scene.mNumMaterials];
155 scene.mNumMeshes =
static_cast<unsigned int>(meshes.size());
156 scene.mMeshes =
new aiMesh*[scene.mNumMeshes];
158 scene.mRootNode->mNumMeshes = scene.mNumMeshes;
159 scene.mRootNode->mMeshes =
new unsigned int[scene.mNumMeshes];
161 for (
unsigned int mi = 0; mi < scene.mNumMeshes; ++mi) {
162 const auto& mesh_data = meshes[mi];
163 const auto info = submesh_info_for(mesh_data);
165 auto* mat =
new aiMaterial();
168 : (!info.material_name.empty() ? info.material_name :
"material_" + std::to_string(mi));
169 aiString ai_mat_name(mat_name);
170 mat->AddProperty(&ai_mat_name, AI_MATKEY_NAME);
171 if (!info.diffuse_path.empty()) {
172 aiString tex_path(info.diffuse_path);
173 mat->AddProperty(&tex_path, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));
175 scene.mMaterials[mi] = mat;
177 auto* mesh =
new aiMesh();
178 mesh->mMaterialIndex = mi;
179 mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
180 mesh->mName = aiString(!info.name.empty() ? info.name :
"mesh_" + std::to_string(mi));
182 const auto* vb = std::get_if<std::vector<uint8_t>>(&mesh_data.vertex_variant);
183 const auto* ib = std::get_if<std::vector<uint32_t>>(&mesh_data.index_variant);
188 mesh->mNumVertices =
static_cast<unsigned int>(vertex_count);
189 mesh->mVertices =
new aiVector3D[vertex_count];
190 mesh->mNormals =
new aiVector3D[vertex_count];
191 mesh->mTangents =
new aiVector3D[vertex_count];
192 mesh->mTextureCoords[0] =
new aiVector3D[vertex_count];
193 mesh->mNumUVComponents[0] = 2;
194 mesh->mColors[0] =
new aiColor4D[vertex_count];
196 for (
size_t v = 0; v < vertex_count; ++v) {
197 const auto& mv = verts[v];
198 mesh->mVertices[v] = aiVector3D(mv.position.x, mv.position.y, mv.position.z);
199 mesh->mNormals[v] = aiVector3D(mv.normal.x, mv.normal.y, mv.normal.z);
200 mesh->mTangents[v] = aiVector3D(mv.tangent.x, mv.tangent.y, mv.tangent.z);
201 mesh->mTextureCoords[0][v] = aiVector3D(mv.uv.x, mv.uv.y, 0.0F);
202 mesh->mColors[0][v] = aiColor4D(mv.color.x, mv.color.y, mv.color.z, 1.0F);
205 const size_t face_count = ib->size() / 3;
206 mesh->mNumFaces =
static_cast<unsigned int>(face_count);
207 mesh->mFaces =
new aiFace[face_count];
208 for (
size_t f = 0; f < face_count; ++f) {
209 auto& face = mesh->mFaces[f];
210 face.mNumIndices = 3;
211 face.mIndices =
new unsigned int[3] {
218 scene.mMeshes[mi] = mesh;
219 scene.mRootNode->mMeshes[mi] = mi;
225 Assimp::Exporter exporter;
226 const auto ret = exporter.Export(&scene, format_id, resolved);
228 if (ret != AI_SUCCESS) {
231 "AssimpModelWriter: export failed for '{}' (format '{}'): {}",
237 "AssimpModelWriter: wrote '{}', {} mesh(es), format '{}'",
238 resolved, meshes.size(), format_id);