33 #include <boost/filesystem.hpp> 37 #include <OgreMeshManager.h> 38 #include <OgreTextureManager.h> 39 #include <OgreMaterialManager.h> 40 #include <OgreTexture.h> 42 #include <OgreTechnique.h> 43 #include <OgreMaterial.h> 44 #include <OgreTextureUnitState.h> 45 #include <OgreMeshSerializer.h> 46 #include <OgreSubMesh.h> 47 #include <OgreHardwareBufferManager.h> 48 #include <OgreSharedPtr.h> 49 #include <OgreTechnique.h> 56 #if defined(ASSIMP_UNIFIED_HEADER_NAMES) 57 #include <assimp/Importer.hpp> 58 #include <assimp/scene.h> 59 #include <assimp/postprocess.h> 60 #include <assimp/IOStream.hpp> 61 #include <assimp/IOSystem.hpp> 63 #include <assimp/assimp.hpp> 64 #include <assimp/aiScene.h> 65 #include <assimp/aiPostProcess.h> 66 #include <assimp/IOStream.h> 67 #include <assimp/IOSystem.h> 70 namespace fs = boost::filesystem;
86 size_t Read(
void* buffer,
size_t size,
size_t count)
88 size_t to_read = size * count;
94 memcpy(buffer,
pos_, to_read);
100 size_t Write(
const void* buffer,
size_t size,
size_t count) {
ROS_BREAK();
return 0; }
102 aiReturn
Seek(
size_t offset, aiOrigin origin)
104 uint8_t* new_pos = 0;
111 new_pos =
pos_ + offset;
122 return aiReturn_FAILURE;
126 return aiReturn_SUCCESS;
166 res = retriever_.get(file);
183 Assimp::IOStream*
Open(
const char* file,
const char* mode =
"rb")
185 ROS_ASSERT(mode == std::string(
"r") || mode == std::string(
"rb"));
192 res = retriever_.get(file);
202 void Close(Assimp::IOStream* stream);
218 void buildMesh(
const aiScene* scene,
const aiNode* node,
219 const Ogre::MeshPtr& mesh,
220 Ogre::AxisAlignedBox& aabb,
float& radius,
const float scale,
221 std::vector<Ogre::MaterialPtr>& material_table )
228 aiMatrix4x4 transform = node->mTransformation;
229 aiNode *pnode = node->mParent;
234 if (pnode->mParent !=
NULL)
235 transform = pnode->mTransformation * transform;
236 pnode = pnode->mParent;
239 aiMatrix3x3 rotation(transform);
240 aiMatrix3x3 inverse_transpose_rotation(rotation);
241 inverse_transpose_rotation.Inverse();
242 inverse_transpose_rotation.Transpose();
244 for (uint32_t i = 0; i < node->mNumMeshes; i++)
246 aiMesh* input_mesh = scene->mMeshes[node->mMeshes[i]];
248 Ogre::SubMesh* submesh = mesh->createSubMesh();
249 submesh->useSharedVertices =
false;
250 submesh->vertexData =
new Ogre::VertexData();
251 Ogre::VertexData* vertex_data = submesh->vertexData;
252 Ogre::VertexDeclaration* vertex_decl = vertex_data->vertexDeclaration;
256 vertex_decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
257 offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
260 if (input_mesh->HasNormals())
262 vertex_decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL);
263 offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
267 if (input_mesh->HasTextureCoords(0))
269 vertex_decl->addElement(0, offset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, 0);
270 offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2);
276 vertex_data->vertexCount = input_mesh->mNumVertices;
277 Ogre::HardwareVertexBufferSharedPtr vbuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(vertex_decl->getVertexSize(0),
278 vertex_data->vertexCount,
279 Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY,
282 vertex_data->vertexBufferBinding->setBinding(0, vbuf);
283 float* vertices =
static_cast<float*
>(vbuf->lock(Ogre::HardwareBuffer::HBL_DISCARD));
286 for (uint32_t j = 0; j < input_mesh->mNumVertices; j++)
288 aiVector3D p = input_mesh->mVertices[j];
295 Ogre::Vector3 v(p.x, p.y, p.z);
297 float dist = v.length();
303 if (input_mesh->HasNormals())
305 aiVector3D n = inverse_transpose_rotation * input_mesh->mNormals[j];
312 if (input_mesh->HasTextureCoords(0))
314 *vertices++ = input_mesh->mTextureCoords[0][j].x;
315 *vertices++ = input_mesh->mTextureCoords[0][j].y;
320 submesh->indexData->indexCount = 0;
321 for (uint32_t j = 0; j < input_mesh->mNumFaces; j++)
323 aiFace& face = input_mesh->mFaces[j];
324 submesh->indexData->indexCount += face.mNumIndices;
328 if( vertex_data->vertexCount < (1<<16) )
331 submesh->indexData->indexBuffer = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(
332 Ogre::HardwareIndexBuffer::IT_16BIT,
333 submesh->indexData->indexCount,
334 Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY,
337 Ogre::HardwareIndexBufferSharedPtr ibuf = submesh->indexData->indexBuffer;
338 uint16_t* indices =
static_cast<uint16_t*
>(ibuf->lock(Ogre::HardwareBuffer::HBL_DISCARD));
341 for (uint32_t j = 0; j < input_mesh->mNumFaces; j++)
343 aiFace& face = input_mesh->mFaces[j];
344 for (uint32_t k = 0; k < face.mNumIndices; ++k)
346 *indices++ = face.mIndices[k];
359 submesh->indexData->indexBuffer = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(
360 Ogre::HardwareIndexBuffer::IT_32BIT,
361 submesh->indexData->indexCount,
362 Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY,
365 Ogre::HardwareIndexBufferSharedPtr ibuf = submesh->indexData->indexBuffer;
366 uint32_t* indices =
static_cast<uint32_t*
>(ibuf->lock(Ogre::HardwareBuffer::HBL_DISCARD));
369 for (uint32_t j = 0; j < input_mesh->mNumFaces; j++)
371 aiFace& face = input_mesh->mFaces[j];
372 for (uint32_t k = 0; k < face.mNumIndices; ++k)
374 *indices++ = face.mIndices[k];
382 submesh->setMaterialName(material_table[input_mesh->mMaterialIndex]->getName());
385 for (uint32_t i=0; i < node->mNumChildren; ++i)
387 buildMesh(scene, node->mChildren[i], mesh, aabb, radius, scale, material_table);
393 if (!Ogre::TextureManager::getSingleton().resourceExists(resource_path))
399 res = retriever.
get(resource_path);
408 Ogre::DataStreamPtr stream(
new Ogre::MemoryDataStream(res.
data.get(), res.
size));
410 std::string extension = fs::extension(fs::path(resource_path));
412 if (extension[0] ==
'.')
414 extension = extension.substr(1, extension.size() - 1);
419 image.load(stream, extension);
420 Ogre::TextureManager::getSingleton().loadImage(resource_path, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, image);
422 catch (Ogre::Exception& e)
424 ROS_ERROR(
"Could not load texture [%s]: %s", resource_path.c_str(), e.what());
438 const aiScene* scene,
439 std::vector<Ogre::MaterialPtr>& material_table_out )
441 for (uint32_t i = 0; i < scene->mNumMaterials; i++)
443 std::stringstream ss;
444 ss << resource_path <<
"Material" << i;
445 Ogre::MaterialPtr mat = Ogre::MaterialManager::getSingleton().create(ss.str(),
ROS_PACKAGE_NAME,
true);
446 material_table_out.push_back(mat);
448 Ogre::Technique* tech = mat->getTechnique(0);
449 Ogre::Pass* pass = tech->getPass(0);
451 aiMaterial *amat = scene->mMaterials[i];
453 Ogre::ColourValue diffuse(1.0, 1.0, 1.0, 1.0);
454 Ogre::ColourValue specular(1.0, 1.0, 1.0, 1.0);
455 Ogre::ColourValue ambient(0, 0, 0, 1.0);
457 for (uint32_t j=0; j < amat->mNumProperties; j++)
459 aiMaterialProperty *prop = amat->mProperties[j];
460 std::string propKey = prop->mKey.data;
462 if (propKey ==
"$tex.file")
465 aiTextureMapping mapping;
467 amat->GetTexture(aiTextureType_DIFFUSE,0, &texName, &mapping, &uvIndex);
470 std::string texture_path = fs::path(resource_path).parent_path().string() +
"/" + texName.data;
472 Ogre::TextureUnitState* tu = pass->createTextureUnitState();
473 tu->setTextureName(texture_path);
475 else if (propKey ==
"$clr.diffuse")
478 amat->Get(AI_MATKEY_COLOR_DIFFUSE, clr);
479 diffuse = Ogre::ColourValue(clr.r, clr.g, clr.b);
481 else if (propKey ==
"$clr.ambient")
484 amat->Get(AI_MATKEY_COLOR_AMBIENT, clr);
485 ambient = Ogre::ColourValue(clr.r, clr.g, clr.b);
487 else if (propKey ==
"$clr.specular")
490 amat->Get(AI_MATKEY_COLOR_SPECULAR, clr);
491 specular = Ogre::ColourValue(clr.r, clr.g, clr.b);
493 else if (propKey ==
"$clr.emissive")
496 amat->Get(AI_MATKEY_COLOR_EMISSIVE, clr);
497 mat->setSelfIllumination(clr.r, clr.g, clr.b);
499 else if (propKey ==
"$clr.opacity")
502 amat->Get(AI_MATKEY_OPACITY, o);
505 else if (propKey ==
"$mat.shininess")
508 amat->Get(AI_MATKEY_SHININESS, s);
509 mat->setShininess(s);
511 else if (propKey ==
"$mat.shadingm")
514 amat->Get(AI_MATKEY_SHADING_MODEL, model);
517 case aiShadingMode_Flat:
518 mat->setShadingMode(Ogre::SO_FLAT);
520 case aiShadingMode_Phong:
521 mat->setShadingMode(Ogre::SO_PHONG);
523 case aiShadingMode_Gouraud:
525 mat->setShadingMode(Ogre::SO_GOURAUD);
531 int mode = aiBlendMode_Default;
532 amat->Get(AI_MATKEY_BLEND_FUNC, mode);
535 case aiBlendMode_Additive:
536 mat->setSceneBlending(Ogre::SBT_ADD);
538 case aiBlendMode_Default:
541 if (diffuse.a < 0.99)
543 pass->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA);
547 pass->setSceneBlending(Ogre::SBT_REPLACE);
553 mat->setAmbient(ambient * 0.5);
554 mat->setDiffuse(diffuse);
555 specular.a = diffuse.a;
556 mat->setSpecular(specular);
575 static std::map<std::string, float> rescale_cache;
580 TiXmlDocument xmlDoc;
581 float unit_scale(1.0);
586 res = retriever.
get(resource_path);
601 const char * data =
reinterpret_cast<const char *
> (res.
data.get());
607 TiXmlElement * colladaXml = xmlDoc.FirstChildElement(
"COLLADA");
610 TiXmlElement *assetXml = colladaXml->FirstChildElement(
"asset");
613 TiXmlElement *unitXml = assetXml->FirstChildElement(
"unit");
614 if (unitXml && unitXml->Attribute(
"meter"))
617 if(unitXml->QueryFloatAttribute(
"meter", &unit_scale) != 0)
618 ROS_WARN_STREAM(
"getMeshUnitRescale::Failed to convert unit element meter attribute to determine scaling. unit element: " 631 if (!scene->HasMeshes())
633 ROS_ERROR(
"No meshes found in file [%s]", name.c_str());
634 return Ogre::MeshPtr();
637 std::vector<Ogre::MaterialPtr> material_table;
640 Ogre::MeshPtr mesh = Ogre::MeshManager::getSingleton().createManual(name,
ROS_PACKAGE_NAME);
642 Ogre::AxisAlignedBox aabb(Ogre::AxisAlignedBox::EXTENT_NULL);
645 buildMesh(scene, scene->mRootNode, mesh, aabb, radius, scale, material_table);
647 mesh->_setBounds(aabb);
648 mesh->_setBoundingSphereRadius(radius);
649 mesh->buildEdgeList();
658 if (Ogre::MeshManager::getSingleton().resourceExists(resource_path))
660 return Ogre::MeshManager::getSingleton().getByName(resource_path);
664 fs::path model_path(resource_path);
665 #if BOOST_FILESYSTEM_VERSION == 3 666 std::string ext = model_path.extension().string();
668 std::string ext = model_path.extension();
670 if (ext ==
".mesh" || ext ==
".MESH")
676 res = retriever.
get(resource_path);
681 return Ogre::MeshPtr();
686 return Ogre::MeshPtr();
689 Ogre::MeshSerializer ser;
690 Ogre::DataStreamPtr stream(
new Ogre::MemoryDataStream(res.
data.get(), res.
size));
691 Ogre::MeshPtr mesh = Ogre::MeshManager::getSingleton().createManual(resource_path,
"rviz");
692 ser.importMesh(stream, mesh.get());
696 else if (ext ==
".stl" || ext ==
".STL" || ext ==
".stlb" || ext ==
".STLB")
702 res = retriever.
get(resource_path);
707 return Ogre::MeshPtr();
712 return Ogre::MeshPtr();
716 if (!loader.
load(res.
data.get(), res.
size, resource_path))
718 ROS_ERROR(
"Failed to load file [%s]", resource_path.c_str());
719 return Ogre::MeshPtr();
722 return loader.
toMesh(resource_path);
726 Assimp::Importer importer;
728 const aiScene* scene = importer.ReadFile(resource_path, aiProcess_SortByPType|aiProcess_GenNormals|aiProcess_Triangulate|aiProcess_GenUVCoords|aiProcess_FlipUVs);
731 ROS_ERROR(
"Could not load resource [%s]: %s", resource_path.c_str(), importer.GetErrorString());
732 return Ogre::MeshPtr();
739 return Ogre::MeshPtr();
ResourceIOStream(const resource_retriever::MemoryResource &res)
float getMeshUnitRescale(const std::string &resource_path)
Ogre::MeshPtr loadMeshFromResource(const std::string &resource_path)
size_t Write(const void *buffer, size_t size, size_t count)
void loadTexture(const std::string &resource_path)
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_
#define ROS_WARN_STREAM(args)
MemoryResource get(const std::string &url)
void buildMesh(const aiScene *scene, const aiNode *node, const Ogre::MeshPtr &mesh, Ogre::AxisAlignedBox &aabb, float &radius, const float scale, std::vector< Ogre::MaterialPtr > &material_table)
Recursive mesh-building function.
size_t Read(void *buffer, size_t size, size_t count)
void Close(Assimp::IOStream *stream)
char getOsSeparator() const
bool Exists(const char *file) const
resource_retriever::MemoryResource res_
Assimp::IOStream * Open(const char *file, const char *mode="rb")
Ogre::MeshPtr meshFromAssimpScene(const std::string &name, const aiScene *scene)
aiReturn Seek(size_t offset, aiOrigin origin)