14#ifdef LAGRANGE_WITH_ASSIMP
16#include <lagrange/fs/filesystem.h>
17#include <lagrange/create_mesh.h>
18#include <lagrange/attributes/attribute_utils.h>
19#include <lagrange/MeshTrait.h>
20#include <lagrange/Logger.h>
21#include <lagrange/fs/file_utils.h>
22#include <lagrange/legacy/inline.h>
24#include <assimp/Importer.hpp>
25#include <assimp/scene.h>
26#include <assimp/mesh.h>
27#include <assimp/material.h>
28#include <assimp/postprocess.h>
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);
42 std::enable_if_t<lagrange::MeshTraitHelper::is_mesh<MeshType>::value>* =
nullptr>
43std::vector<std::unique_ptr<MeshType>> load_mesh_assimp(
const lagrange::fs::path& filename);
44template <
typename MeshType>
45std::vector<std::unique_ptr<MeshType>> load_mesh_assimp_from_memory(
49template <
typename MeshType>
50std::vector<std::unique_ptr<MeshType>> extract_meshes_assimp(
const aiScene* scene);
51template <
typename MeshType>
52std::unique_ptr<MeshType> convert_mesh_assimp(
const aiMesh* mesh);
54inline std::unique_ptr<aiScene> load_scene_assimp(
const lagrange::fs::path& filename)
56 Assimp::Importer importer;
57 const aiScene* scene = importer.ReadFile(filename.string(), 0);
59 logger().error(
"Error loading scene: {}", importer.GetErrorString());
63 return std::unique_ptr<aiScene>(importer.GetOrphanedScene());
66inline std::unique_ptr<aiScene> load_scene_assimp_from_memory(
const void* buffer,
size_t size)
68 Assimp::Importer importer;
72 const aiScene* scene = importer.ReadFileFromMemory(buffer, size, aiProcess_Triangulate);
75 logger().error(
"Error loading scene: {}", importer.GetErrorString());
79 return std::unique_ptr<aiScene>(importer.GetOrphanedScene());
83 std::enable_if_t<lagrange::MeshTraitHelper::is_mesh<MeshType>::value>* >
84std::vector<std::unique_ptr<MeshType>> load_mesh_assimp(
const lagrange::fs::path& filename)
86 static_assert(MeshTrait<MeshType>::is_mesh(),
"Input type is not Mesh");
88 std::unique_ptr<aiScene> scene = load_scene_assimp(filename);
90 return extract_meshes_assimp<MeshType>(scene.get());
93template <
typename MeshType>
94std::vector<std::unique_ptr<MeshType>> load_mesh_assimp_from_memory(
const void* buffer,
size_t size)
96 static_assert(MeshTrait<MeshType>::is_mesh(),
"Input type is not Mesh");
98 std::unique_ptr<aiScene> scene = load_scene_assimp_from_memory(buffer, size);
100 return extract_meshes_assimp<MeshType>(scene.get());
103template <
typename MeshType>
104std::vector<std::unique_ptr<MeshType>> extract_meshes_assimp(
const aiScene* scene)
106 static_assert(MeshTrait<MeshType>::is_mesh(),
"Input type is not Mesh");
107 std::vector<std::unique_ptr<MeshType>> ret;
111 for (
unsigned int i = 0; i < scene->mNumMeshes; ++i) {
112 const aiMesh* mesh = scene->mMeshes[i];
113 ret.emplace_back(convert_mesh_assimp<MeshType>(mesh));
118template <
typename MeshType>
119std::unique_ptr<MeshType> convert_mesh_assimp(
const aiMesh* mesh)
121 static_assert(MeshTrait<MeshType>::is_mesh(),
"Input type is not Mesh");
123 using VertexArray =
typename MeshType::VertexArray;
124 using FacetArray =
typename MeshType::FacetArray;
127 unsigned int nvpf = 0;
128 bool triangulate =
false;
129 for (
unsigned int j = 0; j < mesh->mNumFaces; ++j) {
130 const aiFace& face = mesh->mFaces[j];
132 nvpf = face.mNumIndices;
133 }
else if (face.mNumIndices != nvpf) {
134 logger().warn(
"Facets with varying number of vertices detected, triangulating");
140 if (FacetArray::ColsAtCompileTime != Eigen::Dynamic && FacetArray::ColsAtCompileTime != nvpf) {
142 "FacetArray cannot hold facets with n!={} vertex per facet, triangulating",
143 static_cast<int>(FacetArray::ColsAtCompileTime));
149 unsigned int num_output_facets = mesh->mNumFaces;
151 num_output_facets = 0;
152 for (
unsigned int j = 0; j < mesh->mNumFaces; ++j) {
153 const aiFace& face = mesh->mFaces[j];
154 num_output_facets += face.mNumIndices - 2;
158 VertexArray vertices(mesh->mNumVertices, 3);
159 for (
unsigned int j = 0; j < mesh->mNumVertices; ++j) {
160 const aiVector3D& vec = mesh->mVertices[j];
161 vertices(j, 0) = vec.x;
162 vertices(j, 1) = vec.y;
163 vertices(j, 2) = vec.z;
166 FacetArray faces(num_output_facets, nvpf);
167 for (
unsigned int j = 0, f = 0; j < mesh->mNumFaces; ++j) {
168 const aiFace& face = mesh->mFaces[j];
170 for (
unsigned int k = 2; k < face.mNumIndices; ++k) {
171 faces.row(f++) << face.mIndices[0], face.mIndices[k - 1], face.mIndices[k];
174 for (
unsigned int k = 0; k < face.mNumIndices; ++k) {
175 faces(j, k) = face.mIndices[k];
178 assert(f <= num_output_facets);
181 auto lagrange_mesh =
create_mesh(std::move(vertices), std::move(faces));
183 if (mesh->HasTextureCoords(0)) {
184 typename MeshType::UVArray uvs(mesh->mNumVertices, 2);
185 typename MeshType::UVIndices uv_indices = lagrange_mesh->get_facets();
187 assert(mesh->GetNumUVChannels() == 1);
188 assert(mesh->mNumUVComponents[0] == 2);
189 for (
unsigned int j = 0; j < mesh->mNumVertices; ++j) {
190 const aiVector3D& vec = mesh->mTextureCoords[0][j];
197 lagrange_mesh->initialize_uv(std::move(uvs), std::move(uv_indices));
198 map_indexed_attribute_to_corner_attribute(*lagrange_mesh,
"uv");
201 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