31 #include <OgrePrerequisites.h> 
   34 #include <boost/filesystem.hpp> 
   35 #include <boost/algorithm/string.hpp> 
   37 #include <OgreSkeleton.h> 
   38 #include <OgreSkeletonManager.h> 
   39 #include <OgreSkeletonSerializer.h> 
   40 #include <OgreMeshManager.h> 
   41 #include <OgreTextureManager.h> 
   42 #include <OgreMaterialManager.h> 
   43 #include <OgreTexture.h> 
   45 #include <OgreTechnique.h> 
   46 #include <OgreMaterial.h> 
   47 #include <OgreTextureUnitState.h> 
   48 #include <OgreMeshSerializer.h> 
   49 #include <OgreSubMesh.h> 
   50 #include <OgreHardwareBufferManager.h> 
   51 #include <OgreSharedPtr.h> 
   52 #include <OgreTechnique.h> 
   58 #include <assimp/Importer.hpp> 
   59 #include <assimp/scene.h> 
   60 #include <assimp/postprocess.h> 
   61 #include <assimp/IOStream.hpp> 
   62 #include <assimp/IOSystem.hpp> 
   63 #include <boost/filesystem/operations.hpp> 
   65 namespace fs = boost::filesystem;
 
   80   size_t Read(
void* buffer, 
size_t size, 
size_t count)
 override 
   82     size_t to_read = size * count;
 
   88     memcpy(buffer, 
pos_, to_read);
 
   94   size_t Write(
const void* , 
size_t , 
size_t )
 override 
  100   aiReturn 
Seek(
size_t offset, aiOrigin origin)
 override 
  102     uint8_t* new_pos = 
nullptr;
 
  109       new_pos = 
pos_ + offset; 
 
  120       return aiReturn_FAILURE;
 
  124     return aiReturn_SUCCESS;
 
  158   bool Exists(
const char* file)
 const override 
  183   Assimp::IOStream* 
Open(
const char* file, 
const char* mode = 
"rb")
 override 
  185     ROS_ASSERT(mode == std::string(
"r") || mode == std::string(
"rb"));
 
  203   void Close(Assimp::IOStream* stream) 
override;
 
  222                const Ogre::MeshPtr& mesh,
 
  223                Ogre::AxisAlignedBox& aabb,
 
  225                std::vector<Ogre::MaterialPtr>& material_table,
 
  226                aiMatrix4x4 transform = aiMatrix4x4())
 
  231   if (node->mParent == 
nullptr)
 
  234     transform = node->mTransformation;
 
  236     aiVector3D scaling, axis, pos;
 
  238     transform.Decompose(scaling, axis, 
angle, pos);
 
  240     transform = aiMatrix4x4(scaling, aiQuaternion(), pos);
 
  243     transform *= node->mTransformation;
 
  246   aiMatrix3x3 rotation(transform);
 
  248   for (uint32_t i = 0; i < node->mNumMeshes; i++)
 
  250     aiMesh* input_mesh = scene->mMeshes[node->mMeshes[i]];
 
  252     Ogre::SubMesh* submesh = mesh->createSubMesh();
 
  253     submesh->useSharedVertices = 
false;
 
  254     submesh->vertexData = 
new Ogre::VertexData();
 
  255     Ogre::VertexData* vertex_data = submesh->vertexData;
 
  256     Ogre::VertexDeclaration* vertex_decl = vertex_data->vertexDeclaration;
 
  260     vertex_decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
 
  261     offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
 
  264     if (input_mesh->HasNormals())
 
  266       vertex_decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL);
 
  267       offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
 
  271     if (input_mesh->HasTextureCoords(0))
 
  273       vertex_decl->addElement(0, offset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, 0);
 
  280     vertex_data->vertexCount = input_mesh->mNumVertices;
 
  281     Ogre::HardwareVertexBufferSharedPtr vbuf =
 
  282         Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(
 
  283             vertex_decl->getVertexSize(0), vertex_data->vertexCount,
 
  284             Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY, 
false);
 
  286     vertex_data->vertexBufferBinding->setBinding(0, vbuf);
 
  287     float* vertices = 
static_cast<float*
>(vbuf->lock(Ogre::HardwareBuffer::HBL_DISCARD));
 
  290     for (uint32_t j = 0; j < input_mesh->mNumVertices; j++)
 
  292       aiVector3D p = input_mesh->mVertices[j];
 
  298       Ogre::Vector3 v(p.x, p.y, p.z);
 
  300       float dist = v.length();
 
  306       if (input_mesh->HasNormals())
 
  308         aiVector3D n = input_mesh->mNormals[j];
 
  316       if (input_mesh->HasTextureCoords(0))
 
  318         *vertices++ = input_mesh->mTextureCoords[0][j].x;
 
  319         *vertices++ = input_mesh->mTextureCoords[0][j].y;
 
  324     submesh->indexData->indexCount = 0;
 
  325     for (uint32_t j = 0; j < input_mesh->mNumFaces; j++)
 
  327       aiFace& face = input_mesh->mFaces[j];
 
  328       submesh->indexData->indexCount += face.mNumIndices;
 
  332     if (vertex_data->vertexCount < (1 << 16))
 
  335       submesh->indexData->indexBuffer = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(
 
  336           Ogre::HardwareIndexBuffer::IT_16BIT, submesh->indexData->indexCount,
 
  337           Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY, 
false);
 
  339       Ogre::HardwareIndexBufferSharedPtr ibuf = submesh->indexData->indexBuffer;
 
  340       uint16_t* indices = 
static_cast<uint16_t*
>(ibuf->lock(Ogre::HardwareBuffer::HBL_DISCARD));
 
  343       for (uint32_t j = 0; j < input_mesh->mNumFaces; j++)
 
  345         aiFace& face = input_mesh->mFaces[j];
 
  346         for (uint32_t k = 0; k < face.mNumIndices; ++k)
 
  348           *indices++ = face.mIndices[k];
 
  361       submesh->indexData->indexBuffer = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(
 
  362           Ogre::HardwareIndexBuffer::IT_32BIT, submesh->indexData->indexCount,
 
  363           Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY, 
false);
 
  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     Ogre::MaterialPtr 
const& material = material_table[input_mesh->mMaterialIndex];
 
  383     submesh->setMaterialName(material->getName(), material->getGroup());
 
  386   for (uint32_t i = 0; i < node->mNumChildren; ++i)
 
  388     buildMesh(scene, node->mChildren[i], mesh, aabb, radius, material_table, transform);
 
  394   if (!Ogre::TextureManager::getSingleton().resourceExists(resource_path))
 
  400       res = retriever.
get(resource_path);
 
  409       Ogre::DataStreamPtr stream(
new Ogre::MemoryDataStream(res.
data.get(), res.
size));
 
  411       std::string extension = fs::path(resource_path).extension().string();
 
  413       if (extension[0] == 
'.')
 
  415         extension = extension.substr(1, extension.size() - 1);
 
  420         image.load(stream, extension);
 
  421         Ogre::TextureManager::getSingleton().loadImage(
 
  422             resource_path, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, image);
 
  424       catch (Ogre::Exception& e)
 
  426         ROS_ERROR(
"Could not load texture [%s]: %s", resource_path.c_str(), e.what());
 
  442                    const aiScene* scene,
 
  443                    std::vector<Ogre::MaterialPtr>& material_table_out)
 
  445 #if BOOST_FILESYSTEM_VERSION == 3 
  446   std::string ext = fs::path(resource_path).extension().string();
 
  448   std::string ext = fs::path(resource_path).extension();
 
  450   boost::algorithm::to_lower(ext);
 
  454     material_table_out.push_back(Ogre::MaterialManager::getSingleton().getByName(
"BaseWhiteNoLighting"));
 
  458   for (uint32_t i = 0; i < scene->mNumMaterials; i++)
 
  460     std::stringstream ss;
 
  461     ss << resource_path << 
"Material" << i;
 
  462     Ogre::MaterialPtr mat = Ogre::MaterialManager::getSingleton().create(
 
  463         ss.str(), Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, 
true);
 
  464     material_table_out.push_back(mat);
 
  466     Ogre::Technique* tech = mat->getTechnique(0);
 
  467     Ogre::Pass* pass = tech->getPass(0);
 
  469     aiMaterial* amat = scene->mMaterials[i];
 
  471     Ogre::ColourValue diffuse(1.0, 1.0, 1.0, 1.0);
 
  472     Ogre::ColourValue specular(1.0, 1.0, 1.0, 1.0);
 
  473     Ogre::ColourValue ambient(0, 0, 0, 1.0);
 
  475     for (uint32_t j = 0; j < amat->mNumProperties; j++)
 
  477       aiMaterialProperty* prop = amat->mProperties[j];
 
  478       std::string propKey = prop->mKey.data;
 
  480       if (propKey == 
"$tex.file")
 
  483         aiTextureMapping mapping;
 
  485         amat->GetTexture(aiTextureType_DIFFUSE, 0, &texName, &mapping, &uvIndex);
 
  488         std::string texture_path = fs::path(resource_path).parent_path().string() + 
"/" + texName.data;
 
  490         Ogre::TextureUnitState* tu = pass->createTextureUnitState();
 
  491         tu->setTextureName(texture_path);
 
  493       else if (propKey == 
"$clr.diffuse")
 
  496         amat->Get(AI_MATKEY_COLOR_DIFFUSE, clr);
 
  497         diffuse = Ogre::ColourValue(clr.r, clr.g, clr.b);
 
  499       else if (propKey == 
"$clr.ambient")
 
  502         amat->Get(AI_MATKEY_COLOR_AMBIENT, clr);
 
  503         ambient = Ogre::ColourValue(clr.r, clr.g, clr.b);
 
  505       else if (propKey == 
"$clr.specular")
 
  508         amat->Get(AI_MATKEY_COLOR_SPECULAR, clr);
 
  509         specular = Ogre::ColourValue(clr.r, clr.g, clr.b);
 
  511       else if (propKey == 
"$clr.emissive")
 
  514         amat->Get(AI_MATKEY_COLOR_EMISSIVE, clr);
 
  515         mat->setSelfIllumination(clr.r, clr.g, clr.b);
 
  517       else if (propKey == 
"$clr.opacity")
 
  520         amat->Get(AI_MATKEY_OPACITY, o);
 
  523       else if (propKey == 
"$mat.shininess")
 
  526         amat->Get(AI_MATKEY_SHININESS, 
s);
 
  527         mat->setShininess(
s);
 
  529       else if (propKey == 
"$mat.shadingm")
 
  532         amat->Get(AI_MATKEY_SHADING_MODEL, model);
 
  535         case aiShadingMode_Flat:
 
  536           mat->setShadingMode(Ogre::SO_FLAT);
 
  538         case aiShadingMode_Phong:
 
  539           mat->setShadingMode(Ogre::SO_PHONG);
 
  541         case aiShadingMode_Gouraud:
 
  543           mat->setShadingMode(Ogre::SO_GOURAUD);
 
  549     int mode = aiBlendMode_Default;
 
  550     amat->Get(AI_MATKEY_BLEND_FUNC, mode);
 
  553     case aiBlendMode_Additive:
 
  554       mat->setSceneBlending(Ogre::SBT_ADD);
 
  556     case aiBlendMode_Default:
 
  559       if (diffuse.a < 0.99)
 
  561         pass->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA);
 
  565         pass->setSceneBlending(Ogre::SBT_REPLACE);
 
  571     mat->setAmbient(ambient * 0.5);
 
  572     mat->setDiffuse(diffuse);
 
  573     specular.a = diffuse.a;
 
  574     mat->setSpecular(specular);
 
  580   if (!scene->HasMeshes())
 
  582     ROS_ERROR(
"No meshes found in file [%s]", name.c_str());
 
  583     return Ogre::MeshPtr();
 
  586   std::vector<Ogre::MaterialPtr> material_table;
 
  589   Ogre::MeshPtr mesh = Ogre::MeshManager::getSingleton().createManual(
 
  590       name, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
 
  592   Ogre::AxisAlignedBox aabb(Ogre::AxisAlignedBox::EXTENT_NULL);
 
  594   buildMesh(scene, scene->mRootNode, mesh, aabb, radius, material_table);
 
  596   mesh->_setBounds(aabb);
 
  597   mesh->_setBoundingSphereRadius(radius);
 
  598   mesh->buildEdgeList();
 
  607   if (Ogre::MeshManager::getSingleton().resourceExists(resource_path))
 
  609     return Ogre::MeshManager::getSingleton().getByName(resource_path);
 
  613     fs::path model_path(resource_path);
 
  614 #if BOOST_FILESYSTEM_VERSION == 3 
  615     std::string ext = model_path.extension().string();
 
  617     std::string ext = model_path.extension();
 
  619     boost::algorithm::to_lower(ext);
 
  626         res = retriever.
get(resource_path);
 
  631         return Ogre::MeshPtr();
 
  636         return Ogre::MeshPtr();
 
  640       Ogre::MeshSerializer ser;
 
  641       Ogre::DataStreamPtr stream(
new Ogre::MemoryDataStream(res.
data.get(), res.
size));
 
  642       Ogre::MeshPtr mesh = Ogre::MeshManager::getSingleton().createManual(
 
  643           resource_path, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_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();
 
  672   std::string skeleton_resource_path = resource_path.substr(0, resource_path.length() - 4);
 
  673   skeleton_resource_path.append(
"skeleton");
 
  675   if (Ogre::SkeletonManager::getSingleton().resourceExists(skeleton_resource_path))
 
  677     return Ogre::SkeletonManager::getSingleton().getByName(skeleton_resource_path);
 
  685       res = retriever.
get(skeleton_resource_path);
 
  690       return Ogre::SkeletonPtr();
 
  695       return Ogre::SkeletonPtr();
 
  698     fs::path skeleton_path(skeleton_resource_path);
 
  700     Ogre::SkeletonSerializer ser;
 
  701     Ogre::DataStreamPtr stream(
new Ogre::MemoryDataStream(res.
data.get(), res.
size));
 
  702     Ogre::SkeletonPtr skeleton = Ogre::SkeletonManager::getSingleton().create(
 
  703         skeleton_path.filename().string(), Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, 
true);
 
  704     ser.importSkeleton(stream, skeleton.get());
 
  709   return Ogre::SkeletonPtr();