33 #include <boost/filesystem.hpp> 34 #include <boost/algorithm/string.hpp> 36 #include <OgreMeshManager.h> 37 #include <OgreTextureManager.h> 38 #include <OgreMaterialManager.h> 39 #include <OgreTexture.h> 41 #include <OgreTechnique.h> 42 #include <OgreMaterial.h> 43 #include <OgreTextureUnitState.h> 44 #include <OgreMeshSerializer.h> 45 #include <OgreSubMesh.h> 46 #include <OgreHardwareBufferManager.h> 47 #include <OgreSharedPtr.h> 48 #include <OgreTechnique.h> 54 #if defined(ASSIMP_UNIFIED_HEADER_NAMES) 55 #include <assimp/Importer.hpp> 56 #include <assimp/scene.h> 57 #include <assimp/postprocess.h> 58 #include <assimp/IOStream.hpp> 59 #include <assimp/IOSystem.hpp> 61 #include <assimp/assimp.hpp> 62 #include <assimp/aiScene.h> 63 #include <assimp/aiPostProcess.h> 64 #include <assimp/IOStream.h> 65 #include <assimp/IOSystem.h> 68 namespace fs = boost::filesystem;
83 size_t Read(
void* buffer,
size_t size,
size_t count)
override 85 size_t to_read = size * count;
91 memcpy(buffer,
pos_, to_read);
97 size_t Write(
const void* ,
size_t ,
size_t )
override 103 aiReturn
Seek(
size_t offset, aiOrigin origin)
override 105 uint8_t* new_pos =
nullptr;
112 new_pos =
pos_ + offset;
123 return aiReturn_FAILURE;
127 return aiReturn_SUCCESS;
161 bool Exists(
const char* file)
const override 169 res = retriever_.get(file);
186 Assimp::IOStream*
Open(
const char* file,
const char* mode =
"rb")
override 188 ROS_ASSERT(mode == std::string(
"r") || mode == std::string(
"rb"));
196 res = retriever_.get(file);
206 void Close(Assimp::IOStream* stream)
override;
225 const Ogre::MeshPtr& mesh,
226 Ogre::AxisAlignedBox& aabb,
228 std::vector<Ogre::MaterialPtr>& material_table,
229 aiMatrix4x4 transform = aiMatrix4x4())
234 if (node->mParent ==
nullptr)
237 transform = node->mTransformation;
239 aiVector3D scaling, axis, pos;
241 transform.Decompose(scaling, axis, angle, pos);
243 transform = aiMatrix4x4(scaling, aiQuaternion(), pos);
246 transform *= node->mTransformation;
249 aiMatrix3x3 rotation(transform);
251 for (uint32_t i = 0; i < node->mNumMeshes; i++)
253 aiMesh* input_mesh = scene->mMeshes[node->mMeshes[i]];
255 Ogre::SubMesh* submesh = mesh->createSubMesh();
256 submesh->useSharedVertices =
false;
257 submesh->vertexData =
new Ogre::VertexData();
258 Ogre::VertexData* vertex_data = submesh->vertexData;
259 Ogre::VertexDeclaration* vertex_decl = vertex_data->vertexDeclaration;
263 vertex_decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
264 offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
267 if (input_mesh->HasNormals())
269 vertex_decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL);
270 offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
274 if (input_mesh->HasTextureCoords(0))
276 vertex_decl->addElement(0, offset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, 0);
277 offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2);
283 vertex_data->vertexCount = input_mesh->mNumVertices;
284 Ogre::HardwareVertexBufferSharedPtr vbuf =
285 Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(
286 vertex_decl->getVertexSize(0), vertex_data->vertexCount,
287 Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY,
false);
289 vertex_data->vertexBufferBinding->setBinding(0, vbuf);
290 float* vertices =
static_cast<float*
>(vbuf->lock(Ogre::HardwareBuffer::HBL_DISCARD));
293 for (uint32_t j = 0; j < input_mesh->mNumVertices; j++)
295 aiVector3D p = input_mesh->mVertices[j];
301 Ogre::Vector3 v(p.x, p.y, p.z);
303 float dist = v.length();
309 if (input_mesh->HasNormals())
311 aiVector3D n = input_mesh->mNormals[j];
319 if (input_mesh->HasTextureCoords(0))
321 *vertices++ = input_mesh->mTextureCoords[0][j].x;
322 *vertices++ = input_mesh->mTextureCoords[0][j].y;
327 submesh->indexData->indexCount = 0;
328 for (uint32_t j = 0; j < input_mesh->mNumFaces; j++)
330 aiFace& face = input_mesh->mFaces[j];
331 submesh->indexData->indexCount += face.mNumIndices;
335 if (vertex_data->vertexCount < (1 << 16))
338 submesh->indexData->indexBuffer = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(
339 Ogre::HardwareIndexBuffer::IT_16BIT, submesh->indexData->indexCount,
340 Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY,
false);
342 Ogre::HardwareIndexBufferSharedPtr ibuf = submesh->indexData->indexBuffer;
343 uint16_t* indices =
static_cast<uint16_t*
>(ibuf->lock(Ogre::HardwareBuffer::HBL_DISCARD));
346 for (uint32_t j = 0; j < input_mesh->mNumFaces; j++)
348 aiFace& face = input_mesh->mFaces[j];
349 for (uint32_t k = 0; k < face.mNumIndices; ++k)
351 *indices++ = face.mIndices[k];
364 submesh->indexData->indexBuffer = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(
365 Ogre::HardwareIndexBuffer::IT_32BIT, submesh->indexData->indexCount,
366 Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY,
false);
368 Ogre::HardwareIndexBufferSharedPtr ibuf = submesh->indexData->indexBuffer;
369 uint32_t* indices =
static_cast<uint32_t*
>(ibuf->lock(Ogre::HardwareBuffer::HBL_DISCARD));
372 for (uint32_t j = 0; j < input_mesh->mNumFaces; j++)
374 aiFace& face = input_mesh->mFaces[j];
375 for (uint32_t k = 0; k < face.mNumIndices; ++k)
377 *indices++ = face.mIndices[k];
385 submesh->setMaterialName(material_table[input_mesh->mMaterialIndex]->getName());
388 for (uint32_t i = 0; i < node->mNumChildren; ++i)
390 buildMesh(scene, node->mChildren[i], mesh, aabb, radius, material_table, transform);
396 if (!Ogre::TextureManager::getSingleton().resourceExists(resource_path))
402 res = retriever.
get(resource_path);
411 Ogre::DataStreamPtr stream(
new Ogre::MemoryDataStream(res.
data.get(), res.
size));
413 std::string extension = fs::extension(fs::path(resource_path));
415 if (extension[0] ==
'.')
417 extension = extension.substr(1, extension.size() - 1);
422 image.load(stream, extension);
423 Ogre::TextureManager::getSingleton().loadImage(
424 resource_path, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, image);
426 catch (Ogre::Exception& e)
428 ROS_ERROR(
"Could not load texture [%s]: %s", resource_path.c_str(), e.what());
444 const aiScene* scene,
445 std::vector<Ogre::MaterialPtr>& material_table_out)
447 #if BOOST_FILESYSTEM_VERSION == 3 448 std::string ext = fs::path(resource_path).extension().string();
450 std::string ext = fs::path(resource_path).extension();
452 boost::algorithm::to_lower(ext);
456 material_table_out.push_back(Ogre::MaterialManager::getSingleton().getByName(
"BaseWhiteNoLighting"));
460 for (uint32_t i = 0; i < scene->mNumMaterials; i++)
462 std::stringstream ss;
463 ss << resource_path <<
"Material" << i;
464 Ogre::MaterialPtr mat =
465 Ogre::MaterialManager::getSingleton().create(ss.str(),
ROS_PACKAGE_NAME,
true);
466 material_table_out.push_back(mat);
468 Ogre::Technique* tech = mat->getTechnique(0);
469 Ogre::Pass* pass = tech->getPass(0);
471 aiMaterial* amat = scene->mMaterials[i];
473 Ogre::ColourValue diffuse(1.0, 1.0, 1.0, 1.0);
474 Ogre::ColourValue specular(1.0, 1.0, 1.0, 1.0);
475 Ogre::ColourValue ambient(0, 0, 0, 1.0);
477 for (uint32_t j = 0; j < amat->mNumProperties; j++)
479 aiMaterialProperty* prop = amat->mProperties[j];
480 std::string propKey = prop->mKey.data;
482 if (propKey ==
"$tex.file")
485 aiTextureMapping mapping;
487 amat->GetTexture(aiTextureType_DIFFUSE, 0, &texName, &mapping, &uvIndex);
490 std::string texture_path = fs::path(resource_path).parent_path().string() +
"/" + texName.data;
492 Ogre::TextureUnitState* tu = pass->createTextureUnitState();
493 tu->setTextureName(texture_path);
495 else if (propKey ==
"$clr.diffuse")
498 amat->Get(AI_MATKEY_COLOR_DIFFUSE, clr);
499 diffuse = Ogre::ColourValue(clr.r, clr.g, clr.b);
501 else if (propKey ==
"$clr.ambient")
504 amat->Get(AI_MATKEY_COLOR_AMBIENT, clr);
505 ambient = Ogre::ColourValue(clr.r, clr.g, clr.b);
507 else if (propKey ==
"$clr.specular")
510 amat->Get(AI_MATKEY_COLOR_SPECULAR, clr);
511 specular = Ogre::ColourValue(clr.r, clr.g, clr.b);
513 else if (propKey ==
"$clr.emissive")
516 amat->Get(AI_MATKEY_COLOR_EMISSIVE, clr);
517 mat->setSelfIllumination(clr.r, clr.g, clr.b);
519 else if (propKey ==
"$clr.opacity")
522 amat->Get(AI_MATKEY_OPACITY, o);
525 else if (propKey ==
"$mat.shininess")
528 amat->Get(AI_MATKEY_SHININESS, s);
529 mat->setShininess(s);
531 else if (propKey ==
"$mat.shadingm")
534 amat->Get(AI_MATKEY_SHADING_MODEL, model);
537 case aiShadingMode_Flat:
538 mat->setShadingMode(Ogre::SO_FLAT);
540 case aiShadingMode_Phong:
541 mat->setShadingMode(Ogre::SO_PHONG);
543 case aiShadingMode_Gouraud:
545 mat->setShadingMode(Ogre::SO_GOURAUD);
551 int mode = aiBlendMode_Default;
552 amat->Get(AI_MATKEY_BLEND_FUNC, mode);
555 case aiBlendMode_Additive:
556 mat->setSceneBlending(Ogre::SBT_ADD);
558 case aiBlendMode_Default:
561 if (diffuse.a < 0.99)
563 pass->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA);
567 pass->setSceneBlending(Ogre::SBT_REPLACE);
573 mat->setAmbient(ambient * 0.5);
574 mat->setDiffuse(diffuse);
575 specular.a = diffuse.a;
576 mat->setSpecular(specular);
582 if (!scene->HasMeshes())
584 ROS_ERROR(
"No meshes found in file [%s]", name.c_str());
585 return Ogre::MeshPtr();
588 std::vector<Ogre::MaterialPtr> material_table;
591 Ogre::MeshPtr mesh = Ogre::MeshManager::getSingleton().createManual(name,
ROS_PACKAGE_NAME);
593 Ogre::AxisAlignedBox aabb(Ogre::AxisAlignedBox::EXTENT_NULL);
595 buildMesh(scene, scene->mRootNode, mesh, aabb, radius, material_table);
597 mesh->_setBounds(aabb);
598 mesh->_setBoundingSphereRadius(radius);
599 mesh->buildEdgeList();
608 if (Ogre::MeshManager::getSingleton().resourceExists(resource_path))
610 return Ogre::MeshManager::getSingleton().getByName(resource_path);
614 fs::path model_path(resource_path);
615 #if BOOST_FILESYSTEM_VERSION == 3 616 std::string ext = model_path.extension().string();
618 std::string ext = model_path.extension();
620 boost::algorithm::to_lower(ext);
627 res = retriever.
get(resource_path);
632 return Ogre::MeshPtr();
637 return Ogre::MeshPtr();
640 Ogre::MeshSerializer ser;
641 Ogre::DataStreamPtr stream(
new Ogre::MemoryDataStream(res.
data.get(), res.
size));
643 Ogre::MeshManager::getSingleton().createManual(resource_path,
ROS_PACKAGE_NAME);
644 ser.importMesh(stream, mesh.get());
650 Assimp::Importer importer;
652 const aiScene* scene =
653 importer.ReadFile(resource_path, aiProcess_SortByPType | aiProcess_FindInvalidData |
654 aiProcess_GenNormals | aiProcess_Triangulate |
655 aiProcess_GenUVCoords | aiProcess_FlipUVs);
658 ROS_ERROR(
"Could not load resource [%s]: %s", resource_path.c_str(), importer.GetErrorString());
659 return Ogre::MeshPtr();
666 return Ogre::MeshPtr();
size_t Write(const void *, size_t, size_t) override
char getOsSeparator() const override
ResourceIOStream(const resource_retriever::MemoryResource &res)
Assimp::IOStream * Open(const char *file, const char *mode="rb") override
Ogre::MeshPtr loadMeshFromResource(const std::string &resource_path)
void Close(Assimp::IOStream *stream) override
TFSIMD_FORCE_INLINE tfScalar angle(const Quaternion &q1, const Quaternion &q2)
void loadTexture(const std::string &resource_path)
size_t FileSize() const override
void loadMaterials(const std::string &resource_path, const aiScene *scene, std::vector< Ogre::MaterialPtr > &material_table_out)
Load all materials needed by the given scene.
boost::shared_array< uint8_t > data
resource_retriever::Retriever retriever_
~ResourceIOStream() override
aiReturn Seek(size_t offset, aiOrigin origin) override
size_t Tell() const override
~ResourceIOSystem() override
MemoryResource get(const std::string &url)
void buildMesh(const aiScene *scene, const aiNode *node, const Ogre::MeshPtr &mesh, Ogre::AxisAlignedBox &aabb, float &radius, std::vector< Ogre::MaterialPtr > &material_table, aiMatrix4x4 transform=aiMatrix4x4())
Recursive mesh-building function.
size_t Read(void *buffer, size_t size, size_t count) override
bool Exists(const char *file) const override
resource_retriever::MemoryResource res_
Ogre::MeshPtr meshFromAssimpScene(const std::string &name, const aiScene *scene)