14#ifdef LAGRANGE_WITH_ASSIMP
16 #include <lagrange/Logger.h>
17 #include <lagrange/MeshTrait.h>
18 #include <lagrange/attributes/attribute_utils.h>
19 #include <lagrange/create_mesh.h>
20 #include <lagrange/fs/file_utils.h>
21 #include <lagrange/fs/filesystem.h>
22 #include <lagrange/legacy/inline.h>
24 #include <assimp/material.h>
25 #include <assimp/mesh.h>
26 #include <assimp/postprocess.h>
27 #include <assimp/scene.h>
28 #include <assimp/Importer.hpp>
38std::unique_ptr<aiScene> load_scene_assimp(
const lagrange::fs::path& filename);
39std::unique_ptr<aiScene> load_scene_assimp_from_memory(
const void* buffer,
size_t size);
43 std::enable_if_t<lagrange::MeshTraitHelper::is_mesh<MeshType>::value>* =
nullptr>
44std::vector<std::unique_ptr<MeshType>> load_mesh_assimp(
const lagrange::fs::path& filename);
45template <
typename MeshType>
46std::vector<std::unique_ptr<MeshType>> load_mesh_assimp_from_memory(
50template <
typename MeshType>
51std::vector<std::unique_ptr<MeshType>> extract_meshes_assimp(
const aiScene* scene);
52template <
typename MeshType>
53std::unique_ptr<MeshType> convert_mesh_assimp(
const aiMesh* mesh);
55inline std::unique_ptr<aiScene> load_scene_assimp(
const lagrange::fs::path& filename)
57 Assimp::Importer importer;
58 const aiScene* scene = importer.ReadFile(filename.string(), 0);
60 logger().error(
"Error loading scene: {}", importer.GetErrorString());
64 return std::unique_ptr<aiScene>(importer.GetOrphanedScene());
67inline std::unique_ptr<aiScene> load_scene_assimp_from_memory(
const void* buffer,
size_t size)
69 Assimp::Importer importer;
73 const aiScene* scene = importer.ReadFileFromMemory(buffer, size, aiProcess_Triangulate);
76 logger().error(
"Error loading scene: {}", importer.GetErrorString());
80 return std::unique_ptr<aiScene>(importer.GetOrphanedScene());
85 std::enable_if_t<lagrange::MeshTraitHelper::is_mesh<MeshType>::value>* >
86std::vector<std::unique_ptr<MeshType>> load_mesh_assimp(
const lagrange::fs::path& filename)
88 static_assert(MeshTrait<MeshType>::is_mesh(),
"Input type is not Mesh");
90 std::unique_ptr<aiScene> scene = load_scene_assimp(filename);
92 return extract_meshes_assimp<MeshType>(scene.get());
95template <
typename MeshType>
96std::vector<std::unique_ptr<MeshType>> load_mesh_assimp_from_memory(
const void* buffer,
size_t size)
98 static_assert(MeshTrait<MeshType>::is_mesh(),
"Input type is not Mesh");
100 std::unique_ptr<aiScene> scene = load_scene_assimp_from_memory(buffer, size);
102 return extract_meshes_assimp<MeshType>(scene.get());
105template <
typename MeshType>
106std::vector<std::unique_ptr<MeshType>> extract_meshes_assimp(
const aiScene* scene)
108 static_assert(MeshTrait<MeshType>::is_mesh(),
"Input type is not Mesh");
109 std::vector<std::unique_ptr<MeshType>> ret;
113 for (
unsigned int i = 0; i < scene->mNumMeshes; ++i) {
114 const aiMesh* mesh = scene->mMeshes[i];
115 ret.emplace_back(convert_mesh_assimp<MeshType>(mesh));
120template <
typename MeshType>
121std::unique_ptr<MeshType> convert_mesh_assimp(
const aiMesh* mesh)
123 static_assert(MeshTrait<MeshType>::is_mesh(),
"Input type is not Mesh");
125 using VertexArray =
typename MeshType::VertexArray;
126 using FacetArray =
typename MeshType::FacetArray;
129 unsigned int nvpf = 0;
130 bool triangulate =
false;
131 for (
unsigned int j = 0; j < mesh->mNumFaces; ++j) {
132 const aiFace& face = mesh->mFaces[j];
134 nvpf = face.mNumIndices;
135 }
else if (face.mNumIndices != nvpf) {
136 logger().warn(
"Facets with varying number of vertices detected, triangulating");
142 if (FacetArray::ColsAtCompileTime != Eigen::Dynamic && FacetArray::ColsAtCompileTime != nvpf) {
144 "FacetArray cannot hold facets with n!={} vertex per facet, triangulating",
145 static_cast<int>(FacetArray::ColsAtCompileTime));
151 unsigned int num_output_facets = mesh->mNumFaces;
153 num_output_facets = 0;
154 for (
unsigned int j = 0; j < mesh->mNumFaces; ++j) {
155 const aiFace& face = mesh->mFaces[j];
156 num_output_facets += face.mNumIndices - 2;
160 VertexArray vertices(mesh->mNumVertices, 3);
161 for (
unsigned int j = 0; j < mesh->mNumVertices; ++j) {
162 const aiVector3D& vec = mesh->mVertices[j];
163 vertices(j, 0) = vec.x;
164 vertices(j, 1) = vec.y;
165 vertices(j, 2) = vec.z;
168 FacetArray faces(num_output_facets, nvpf);
169 for (
unsigned int j = 0, f = 0; j < mesh->mNumFaces; ++j) {
170 const aiFace& face = mesh->mFaces[j];
172 for (
unsigned int k = 2; k < face.mNumIndices; ++k) {
173 faces.row(f++) << face.mIndices[0], face.mIndices[k - 1], face.mIndices[k];
176 for (
unsigned int k = 0; k < face.mNumIndices; ++k) {
177 faces(j, k) = face.mIndices[k];
180 assert(f <= num_output_facets);
183 auto lagrange_mesh =
create_mesh(std::move(vertices), std::move(faces));
185 if (mesh->HasTextureCoords(0)) {
186 typename MeshType::UVArray uvs(mesh->mNumVertices, 2);
187 typename MeshType::UVIndices uv_indices = lagrange_mesh->get_facets();
189 assert(mesh->GetNumUVChannels() == 1);
190 assert(mesh->mNumUVComponents[0] == 2);
191 for (
unsigned int j = 0; j < mesh->mNumVertices; ++j) {
192 const aiVector3D& vec = mesh->mTextureCoords[0][j];
199 lagrange_mesh->initialize_uv(std::move(uvs), std::move(uv_indices));
200 map_indexed_attribute_to_corner_attribute(*lagrange_mesh,
"uv");
203 return lagrange_mesh;
LA_CORE_API spdlog::logger & logger()
Retrieves the current logger.
Definition Logger.cpp:40
Mesh input/output.
Definition detect_file_format.h:18
auto create_mesh(const Eigen::MatrixBase< DerivedV > &vertices, const Eigen::MatrixBase< DerivedF > &facets)
This function create a new mesh given the vertex and facet arrays by copying data into the Mesh objec...
Definition create_mesh.h:39