40#ifndef TESSERACT_SCENE_GRAPH_MESH_PARSER_H
41#define TESSERACT_SCENE_GRAPH_MESH_PARSER_H
47#include <assimp/scene.h>
48#include <assimp/Importer.hpp>
49#include <assimp/postprocess.h>
51#ifdef TESSERACT_ASSIMP_USE_PBRMATERIAL
52#include <assimp/pbrmaterial.h>
55#include <console_bridge/console.h>
61#include <boost/filesystem/path.hpp>
78 const aiMatrix4x4& parent_transform,
79 const Eigen::Vector3d&
scale,
83 bool material_and_texture)
85 std::vector<std::shared_ptr<T>>
meshes;
86 meshes.reserve(node->mNumMeshes);
90 for (
unsigned int j = 0;
j < node->mNumMeshes; ++
j)
92 auto vertices = std::make_shared<tesseract_common::VectorVector3d>();
93 auto triangles = std::make_shared<Eigen::VectorXi>();
94 std::shared_ptr<tesseract_common::VectorVector3d> vertex_normals =
nullptr;
95 std::shared_ptr<tesseract_common::VectorVector4d> vertex_colors =
nullptr;
97 std::shared_ptr<std::vector<MeshTexture::Ptr>> textures =
nullptr;
99 const aiMesh* a = scene->mMeshes[node->mMeshes[
j]];
100 vertices->reserve(a->mNumVertices);
101 for (
unsigned int i = 0; i < a->mNumVertices; ++i)
104 vertices->push_back(Eigen::Vector3d(
static_cast<double>(
v.x) *
scale(0),
105 static_cast<double>(
v.y) *
scale(1),
106 static_cast<double>(
v.z) *
scale(2)));
109 long triangle_count = 0;
110 std::vector<int> local_triangles;
111 local_triangles.reserve(a->mNumFaces);
112 for (
unsigned int i = 0; i < a->mNumFaces; ++i)
114 if (a->mFaces[i].mNumIndices >= 3)
117 local_triangles.push_back(
static_cast<int>(a->mFaces[i].mNumIndices));
118 for (
size_t k = 0; k < a->mFaces[i].mNumIndices; ++k)
119 local_triangles.push_back(
static_cast<int>(a->mFaces[i].mIndices[k]));
123 CONSOLE_BRIDGE_logDebug(
"Mesh had a face with less than three vertices: %s",
resource->getUrl().c_str());
127 triangles->resize(
static_cast<long>(local_triangles.size()));
128 for (
long i = 0; i < triangles->size(); ++i)
129 (*triangles)[i] = local_triangles[
static_cast<size_t>(i)];
131 if (normals && a->HasNormals())
133 vertex_normals = std::make_shared<tesseract_common::VectorVector3d>();
134 vertex_normals->reserve(a->mNumVertices);
135 for (
unsigned int i = 0; i < a->mNumVertices; ++i)
138 vertex_normals->push_back(Eigen::Vector3d(
static_cast<double>(
v.x) *
scale(0),
139 static_cast<double>(
v.y) *
scale(1),
140 static_cast<double>(
v.z) *
scale(2)));
144 if (vertex_colors && a->HasVertexColors(0))
146 vertex_colors = std::make_shared<tesseract_common::VectorVector4d>();
147 vertex_colors->reserve(a->mNumVertices);
148 for (
unsigned int i = 0; i < a->mNumVertices; ++i)
150 aiColor4D
v = a->mColors[0][i];
151 vertex_colors->push_back(Eigen::Vector4d(
152 static_cast<double>(
v.r),
static_cast<double>(
v.g),
static_cast<double>(
v.b),
static_cast<double>(
v.a)));
156 if (material_and_texture)
158 aiMaterial* mat = scene->mMaterials[a->mMaterialIndex];
160 Eigen::Vector4d base_color;
161 double metallic = 0.0;
162 double roughness = 0.5;
163 Eigen::Vector4d emissive;
165 aiColor4D pbr_base_color;
166#ifdef TESSERACT_ASSIMP_USE_PBRMATERIAL
167 if (mat->Get(AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_FACTOR, pbr_base_color) == AI_SUCCESS)
170 base_color = Eigen::Vector4d(pbr_base_color.r, pbr_base_color.g, pbr_base_color.b, pbr_base_color.a);
171 float metallicFactor{ 0 };
172 if (mat->Get(AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR, metallicFactor) == AI_SUCCESS)
174 metallic = metallicFactor;
176 float roughnessFactor{ 0.5 };
177 if (mat->Get(AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR, roughnessFactor) == AI_SUCCESS)
179 roughness = roughnessFactor;
181 aiColor4D pbr_emissive_color;
182 if (mat->Get(AI_MATKEY_COLOR_EMISSIVE, pbr_emissive_color) == AI_SUCCESS)
185 Eigen::Vector4d(pbr_emissive_color.r, pbr_emissive_color.g, pbr_emissive_color.b, pbr_emissive_color.a);
192 aiColor4D diffuse_color;
193 if (mat->Get(AI_MATKEY_COLOR_DIFFUSE, diffuse_color) == AI_SUCCESS)
195 base_color = Eigen::Vector4d(diffuse_color.r, diffuse_color.g, diffuse_color.b, diffuse_color.a);
198 aiColor4D emissive_color;
199 if (mat->Get(AI_MATKEY_COLOR_EMISSIVE, emissive_color) == AI_SUCCESS)
201 emissive = Eigen::Vector4d(emissive_color.r, emissive_color.g, emissive_color.b, emissive_color.a);
205 material = std::make_shared<MeshMaterial>(base_color, metallic, roughness, emissive);
207 for (
unsigned int i = 0; i < a->GetNumUVChannels(); i++)
209 if (a->HasTextureCoords(i))
212 aiTextureMapping mapping{ aiTextureMapping_OTHER };
213 unsigned int uvIndex{ 0 };
214 if (mat->GetTexture(aiTextureType_DIFFUSE, i, &texName, &mapping, &uvIndex) == AI_SUCCESS)
219 const char* texNamec = texName.C_Str();
220 if (
'*' == *texNamec)
222 int tex_index = std::atoi(texNamec + 1);
223 if (0 > tex_index || scene->mNumTextures <=
static_cast<unsigned>(tex_index))
225 auto* texture_data = scene->mTextures[tex_index];
227 std::string file_type = texture_data->achFormatHint;
228 if (file_type ==
"jpg" || file_type ==
"png")
230 texture_image = std::make_shared<tesseract_common::BytesResource>(
231 "data://", (
const uint8_t*)texture_data->pcData, texture_data->mWidth);
245 std::string texName_str(texName.C_Str());
246 auto tex_resource =
resource->locateResource(texName_str);
251 texture_image = tex_resource;
253 aiVector3D* tex_coords = a->mTextureCoords[i];
254 for (
unsigned int j = 0;
j < a->mNumVertices; ++
j)
256 aiVector3D
v = tex_coords[
j];
257 uvs.push_back(Eigen::Vector2d(
static_cast<double>(
v.x),
static_cast<double>(
v.y)));
259 auto tex = std::make_shared<MeshTexture>(
260 texture_image, std::make_shared<tesseract_common::VectorVector2d>(std::move(uvs)));
263 textures = std::make_shared<std::vector<MeshTexture::Ptr>>();
265 textures->push_back(tex);
272 meshes.push_back(std::make_shared<T>(vertices,
274 static_cast<int>(triangle_count),
283 for (
unsigned int n = 0; n < node->mNumChildren; ++n)
285 std::vector<std::shared_ptr<T>> child_meshes = extractMeshData<T>(
287 meshes.insert(
meshes.end(), child_meshes.begin(), child_meshes.end());
304 const Eigen::Vector3d&
scale,
308 bool material_and_texture)
310 if (!scene->HasMeshes())
312 CONSOLE_BRIDGE_logWarn(
"Assimp reports scene in %s has no meshes",
resource->getUrl().c_str());
313 return std::vector<std::shared_ptr<T>>();
315 std::vector<std::shared_ptr<T>>
meshes = extractMeshData<T>(
316 scene, scene->mRootNode, aiMatrix4x4(),
scale,
resource, normals, vertex_colors, material_and_texture);
319 CONSOLE_BRIDGE_logWarn(
"There are no meshes in the scene %s",
resource->getUrl().c_str());
320 return std::vector<std::shared_ptr<T>>();
341 Eigen::Vector3d
scale = Eigen::Vector3d(1, 1, 1),
342 bool triangulate =
false,
343 bool flatten =
false,
344 bool normals =
false,
345 bool vertex_colors =
false,
346 bool material_and_texture =
false)
349 Assimp::Importer importer;
354 unsigned int ai_config_pp_rcv_flags = aiComponent_TANGENTS_AND_BITANGENTS | aiComponent_BONEWEIGHTS |
355 aiComponent_ANIMATIONS | aiComponent_LIGHTS | aiComponent_CAMERAS;
358 ai_config_pp_rcv_flags |= aiComponent_NORMALS;
362 ai_config_pp_rcv_flags |= aiComponent_COLORS;
364 if (!material_and_texture)
366 ai_config_pp_rcv_flags |= aiComponent_TEXCOORDS | aiComponent_TEXTURES | aiComponent_MATERIALS;
368 importer.SetPropertyInteger(AI_CONFIG_PP_RVC_FLAGS, (
int)ai_config_pp_rcv_flags);
371 const aiScene* scene =
nullptr;
373 scene = importer.ReadFile(
path.c_str(),
374 aiProcess_Triangulate | aiProcess_JoinIdenticalVertices | aiProcess_SortByPType |
375 aiProcess_RemoveComponent);
377 scene = importer.ReadFile(
path.c_str(),
378 aiProcess_JoinIdenticalVertices | aiProcess_SortByPType | aiProcess_RemoveComponent);
382 CONSOLE_BRIDGE_logError(
"Could not load mesh from \"%s\": %s",
path.c_str(), importer.GetErrorString());
383 return std::vector<std::shared_ptr<T>>();
392 scene->mRootNode->mTransformation = aiMatrix4x4();
398 importer.ApplyPostProcessing(aiProcess_OptimizeMeshes | aiProcess_OptimizeGraph);
402 importer.ApplyPostProcessing(aiProcess_OptimizeGraph);
405 return createMeshFromAsset<T>(scene,
scale,
nullptr, normals, vertex_colors, material_and_texture);
423 Eigen::Vector3d
scale = Eigen::Vector3d(1, 1, 1),
424 bool triangulate =
false,
425 bool flatten =
false,
426 bool normals =
false,
427 bool vertex_colors =
false,
428 bool material_and_texture =
false)
431 return std::vector<std::shared_ptr<T>>();
433 const char* hint =
nullptr;
434 std::string hint_storage;
436 std::string resource_url =
resource->getUrl();
437 std::regex hint_re(
"^.*\\.([A-Za-z0-9]{1,8})$");
438 std::smatch hint_match;
439 if (std::regex_match(resource_url, hint_match, hint_re))
441 if (hint_match.size() == 2)
443 hint_storage = hint_match[1].str();
444 hint = hint_storage.c_str();
448 std::vector<uint8_t>
data =
resource->getResourceContents();
452 return createMeshFromPath<T>(
453 resource->getFilePath(),
scale, triangulate, flatten, normals, vertex_colors, material_and_texture);
455 return std::vector<std::shared_ptr<T>>();
459 Assimp::Importer importer;
464 unsigned int ai_config_pp_rcv_flags = aiComponent_TANGENTS_AND_BITANGENTS | aiComponent_BONEWEIGHTS |
465 aiComponent_ANIMATIONS | aiComponent_LIGHTS | aiComponent_CAMERAS;
468 ai_config_pp_rcv_flags |= aiComponent_NORMALS;
472 ai_config_pp_rcv_flags |= aiComponent_COLORS;
474 if (!material_and_texture)
476 ai_config_pp_rcv_flags |= aiComponent_TEXCOORDS | aiComponent_TEXTURES | aiComponent_MATERIALS;
478 importer.SetPropertyInteger(AI_CONFIG_PP_RVC_FLAGS, (
int)ai_config_pp_rcv_flags);
481 const aiScene* scene =
nullptr;
483 scene = importer.ReadFileFromMemory(
data.data(),
485 aiProcess_Triangulate | aiProcess_JoinIdenticalVertices |
486 aiProcess_SortByPType | aiProcess_RemoveComponent,
490 importer.ReadFileFromMemory(
data.data(),
492 aiProcess_JoinIdenticalVertices | aiProcess_SortByPType | aiProcess_RemoveComponent,
497 CONSOLE_BRIDGE_logError(
498 "Could not load mesh from \"%s\": %s",
resource->getUrl().c_str(), importer.GetErrorString());
499 return std::vector<std::shared_ptr<T>>();
507 scene->mRootNode->mTransformation = aiMatrix4x4();
513 importer.ApplyPostProcessing(aiProcess_OptimizeMeshes | aiProcess_OptimizeGraph);
517 importer.ApplyPostProcessing(aiProcess_OptimizeGraph);
520 return createMeshFromAsset<T>(scene,
scale,
resource, normals, vertex_colors, material_and_texture);
540 const uint8_t* bytes,
542 Eigen::Vector3d
scale = Eigen::Vector3d(1, 1, 1),
543 bool triangulate =
false,
544 bool flatten =
false,
545 bool normals =
false,
546 bool vertex_colors =
false,
547 bool material_and_texture =
false)
549 std::shared_ptr<tesseract_common::Resource>
resource =
550 std::make_shared<tesseract_common::BytesResource>(url, bytes, bytes_len);
551 return tesseract_geometry::createMeshFromResource<T>(
552 resource,
scale, triangulate, flatten, normals, vertex_colors, material_and_texture);
std::shared_ptr< Resource > Ptr
Definition: resource_locator.h:101
std::shared_ptr< MeshMaterial > Ptr
Definition: mesh_material.h:63
results transform[0]
Definition: collision_core_unit.cpp:144
CollisionMarginData data(default_margin)
Definition: collision_margin_data_unit.cpp:34
double scale
Definition: collision_margin_data_unit.cpp:133
#define TESSERACT_COMMON_IGNORE_WARNINGS_PUSH
Definition: macros.h:71
Tesseract Mesh Material read from a mesh file.
Definition: create_convex_hull.cpp:36
AlignedVector< Eigen::Vector2d > VectorVector2d
Definition: types.h:65
Definition: geometry.h:39
std::vector< std::shared_ptr< T > > createMeshFromPath(const std::string &path, Eigen::Vector3d scale=Eigen::Vector3d(1, 1, 1), bool triangulate=false, bool flatten=false, bool normals=false, bool vertex_colors=false, bool material_and_texture=false)
Create a mesh using assimp from file path.
Definition: mesh_parser.h:340
std::vector< std::shared_ptr< T > > createMeshFromAsset(const aiScene *scene, const Eigen::Vector3d &scale, tesseract_common::Resource::Ptr resource, bool normals, bool vertex_colors, bool material_and_texture)
Create list of meshes from the assimp scene.
Definition: mesh_parser.h:303
std::vector< std::shared_ptr< T > > extractMeshData(const aiScene *scene, const aiNode *node, const aiMatrix4x4 &parent_transform, const Eigen::Vector3d &scale, tesseract_common::Resource::Ptr resource, bool normals, bool vertex_colors, bool material_and_texture)
Definition: mesh_parser.h:76
static std::vector< std::shared_ptr< T > > createMeshFromBytes(const std::string &url, const uint8_t *bytes, size_t bytes_len, Eigen::Vector3d scale=Eigen::Vector3d(1, 1, 1), bool triangulate=false, bool flatten=false, bool normals=false, bool vertex_colors=false, bool material_and_texture=false)
Create a mesh from byte array.
Definition: mesh_parser.h:539
std::vector< std::shared_ptr< T > > createMeshFromResource(tesseract_common::Resource::Ptr resource, Eigen::Vector3d scale=Eigen::Vector3d(1, 1, 1), bool triangulate=false, bool flatten=false, bool normals=false, bool vertex_colors=false, bool material_and_texture=false)
Create a mesh using assimp from resource.
Definition: mesh_parser.h:422
Locate and retrieve resource data.
Resource::Ptr resource
Definition: resource_locator_unit.cpp:59
v
Definition: tesseract_common_unit.cpp:369
std::vector< Mesh::Ptr > meshes
Definition: tesseract_geometry_unit.cpp:306
JointDynamics j
Definition: tesseract_scene_graph_joint_unit.cpp:15
m material
Definition: tesseract_scene_graph_link_unit.cpp:74
tesseract_common::fs::path path
Definition: tesseract_srdf_unit.cpp:1992