Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <rve_render_server/mesh_loader.h>
00031 #include <rve_render_server/mesh.h>
00032 #include <rve_render_server/submesh.h>
00033 #include <rve_render_server/material.h>
00034 #include <rve_render_server/init.h>
00035 #include <rve_render_server/renderer.h>
00036
00037 #include <rve_mesh_loader/loader.h>
00038 #include <rve_msgs/Mesh.h>
00039
00040 #include <rve_common/uuid.h>
00041
00042 #include <resource_retriever/retriever.h>
00043
00044 #include <OGRE/OgreMeshManager.h>
00045 #include <OGRE/OgreMeshSerializer.h>
00046 #include <OGRE/OgreSubMesh.h>
00047 #include <OGRE/OgreHardwareBufferManager.h>
00048 #include <OGRE/OgreRoot.h>
00049
00050 #include <boost/filesystem.hpp>
00051
00052 namespace fs = boost::filesystem;
00053
00054 namespace rve_render_server
00055 {
00056
00057 MaterialPtr createMaterial(const rve_msgs::Material& mat)
00058 {
00059 MaterialPtr out(new Material(mat.id));
00060 out->setMaterial(mat);
00061 getRenderer()->addMaterial(out->getID(), out);
00062 return out;
00063 }
00064
00065 void createMaterialsForMesh(const rve_msgs::Mesh& input_mesh)
00066 {
00067 for (uint32_t i = 0; i < input_mesh.materials.size(); i++)
00068 {
00069 const rve_msgs::Material& in_mat = input_mesh.materials[i];
00070 createMaterial(in_mat);
00071 }
00072 }
00073
00074
00075 MeshPtr convertMesh(const rve_common::UUID& id, const rve_msgs::Mesh& input_mesh)
00076 {
00077 createMaterialsForMesh(input_mesh);
00078
00079 Ogre::MeshPtr mesh = Ogre::MeshManager::getSingleton().createManual(id.toString(), ROS_PACKAGE_NAME);
00080
00081 Ogre::AxisAlignedBox aabb;
00082 float radius = 0.0;
00083 for (size_t i = 0; i < input_mesh.submeshes.size(); ++i)
00084 {
00085 const rve_msgs::SubMesh& input_submesh = input_mesh.submeshes[i];
00086
00087 bool has_normals = !input_submesh.normals.empty();
00088
00089 Ogre::SubMesh* submesh = mesh->createSubMesh();
00090 submesh->useSharedVertices = false;
00091 submesh->vertexData = new Ogre::VertexData();
00092 Ogre::VertexData* vertex_data = submesh->vertexData;
00093 Ogre::VertexDeclaration* vertex_decl = vertex_data->vertexDeclaration;
00094
00095 size_t offset = 0;
00096
00097 vertex_decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
00098 offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
00099
00100
00101 if (has_normals)
00102 {
00103 ROS_ASSERT(input_submesh.normals.size() == input_submesh.positions.size());
00104
00105 vertex_decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL);
00106 offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
00107 }
00108
00109
00110 for (size_t j = 0; j < input_submesh.colors.size(); ++j)
00111 {
00112 ROS_ASSERT(input_submesh.colors[j].array.size() == input_submesh.positions.size());
00113 vertex_decl->addElement(0, offset, Ogre::VET_COLOUR, Ogre::VES_DIFFUSE, j);
00114 offset += Ogre::VertexElement::getTypeSize(Ogre::VET_COLOUR);
00115 }
00116
00117
00118 uint32_t texcoord_index = 0;
00119 for (size_t j = 0; j < input_submesh.tex_coords.size(); ++j)
00120 {
00121 ROS_ASSERT(input_submesh.tex_coords[j].array.size() == input_submesh.positions.size());
00122 ROS_ASSERT(input_submesh.tex_coords[j].dims <= 3);
00123
00124 Ogre::VertexElementType type = Ogre::VET_FLOAT1;
00125 if (input_submesh.tex_coords[j].dims == 2)
00126 {
00127 type = Ogre::VET_FLOAT2;
00128 }
00129 else if (input_submesh.tex_coords[j].dims == 3)
00130 {
00131 type = Ogre::VET_FLOAT3;
00132 }
00133
00134 vertex_decl->addElement(0, offset, type, Ogre::VES_TEXTURE_COORDINATES, texcoord_index++);
00135 offset += Ogre::VertexElement::getTypeSize(type);
00136 }
00137
00138
00139 if (!input_submesh.tangents.empty())
00140 {
00141
00142 vertex_decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_TANGENT, 0);
00143 offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
00144 }
00145
00146
00147 vertex_data->vertexCount = input_submesh.positions.size();
00148 Ogre::HardwareVertexBufferSharedPtr vbuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(vertex_decl->getVertexSize(0),
00149 vertex_data->vertexCount,
00150 Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY,
00151 false);
00152
00153 vertex_data->vertexBufferBinding->setBinding(0, vbuf);
00154 float* vertices = static_cast<float*>(vbuf->lock(Ogre::HardwareBuffer::HBL_DISCARD));
00155
00156
00157 for (size_t j = 0; j < input_submesh.positions.size(); j++)
00158 {
00159 const rve_msgs::Vector3& p = input_submesh.positions[j];
00160 *vertices++ = p.x;
00161 *vertices++ = p.y;
00162 *vertices++ = p.z;
00163
00164 Ogre::Vector3 ogre_pos(p.x, p.y, p.z);
00165 aabb.merge(ogre_pos);
00166 float dist = ogre_pos.length();
00167 if (dist > radius)
00168 {
00169 radius = dist;
00170 }
00171
00172 if (has_normals)
00173 {
00174 const rve_msgs::Vector3& n = input_submesh.normals[j];
00175 *vertices++ = n.x;
00176 *vertices++ = n.y;
00177 *vertices++ = n.z;
00178 }
00179
00180 for (size_t k = 0; k < input_submesh.colors.size(); ++k)
00181 {
00182 const std_msgs::ColorRGBA& color = input_submesh.colors[k].array[j];
00183 Ogre::Root::getSingleton().convertColourValue(Ogre::ColourValue(color.r, color.g, color.b, color.a), reinterpret_cast<uint32_t*>(vertices));
00184 ++vertices;
00185 }
00186
00187 for (size_t k = 0; k < input_submesh.tex_coords.size(); ++k)
00188 {
00189 const rve_msgs::TexCoord& tex = input_submesh.tex_coords[k].array[j];
00190 for (uint32_t l = 0; l < input_submesh.tex_coords[k].dims; ++l)
00191 {
00192 *vertices++ = tex.uvw[l];
00193 }
00194 }
00195
00196 if (!input_submesh.tangents.empty())
00197 {
00198 const rve_msgs::Vector3& t = input_submesh.tangents[j];
00199 *vertices++ = t.x;
00200 *vertices++ = t.y;
00201 *vertices++ = t.z;
00202 }
00203 }
00204
00205 submesh->indexData->indexCount = input_submesh.indices.size();
00206
00207
00208 submesh->indexData->indexBuffer = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(
00209 Ogre::HardwareIndexBuffer::IT_16BIT,
00210 submesh->indexData->indexCount,
00211 Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY,
00212 false);
00213
00214 Ogre::HardwareIndexBufferSharedPtr ibuf = submesh->indexData->indexBuffer;
00215 uint16_t* indices = static_cast<uint16_t*>(ibuf->lock(Ogre::HardwareBuffer::HBL_DISCARD));
00216
00217
00218 for (uint32_t j = 0; j < input_submesh.indices.size(); j++)
00219 {
00220 *indices++ = input_submesh.indices[j];
00221 }
00222
00223
00224 vbuf->unlock();
00225 ibuf->unlock();
00226 }
00227
00228 mesh->_setBounds(aabb);
00229 mesh->_setBoundingSphereRadius(radius);
00230
00231 MeshPtr out_mesh(new Mesh(id, mesh));
00232
00233 for (size_t i = 0; i < input_mesh.submeshes.size(); ++i)
00234 {
00235 int8_t mat_index = input_mesh.submeshes[i].material_index;
00236 if (mat_index >= 0 && mat_index < (int8_t)input_mesh.materials.size())
00237 {
00238 out_mesh->getSubMesh(i)->setMaterialID(input_mesh.materials[mat_index].id);
00239 }
00240 }
00241
00242 getRenderer()->addMesh(id, out_mesh);
00243
00244 return out_mesh;
00245 }
00246
00247 MeshPtr loadMesh(const std::string& resource_path)
00248 {
00249 fs::path model_path(resource_path);
00250 std::string ext = model_path.extension();
00251
00252 if (ext == ".mesh" || ext == ".MESH")
00253 {
00254 resource_retriever::Retriever retriever;
00255 resource_retriever::MemoryResource res;
00256 try
00257 {
00258 res = retriever.get(resource_path);
00259 }
00260 catch (resource_retriever::Exception& e)
00261 {
00262 ROS_ERROR("%s", e.what());
00263 return MeshPtr();
00264 }
00265
00266 if (res.size == 0)
00267 {
00268 return MeshPtr();
00269 }
00270
00271 rve_common::UUID id = rve_common::UUID::generate();
00272
00273 Ogre::MeshSerializer ser;
00274 Ogre::DataStreamPtr stream(new Ogre::MemoryDataStream(res.data.get(), res.size));
00275 Ogre::MeshPtr mesh = Ogre::MeshManager::getSingleton().createManual(id.toString(), ROS_PACKAGE_NAME);
00276 ser.importMesh(stream, mesh.get());
00277
00278 MeshPtr out_mesh(new Mesh(id, mesh));
00279 getRenderer()->addMesh(id, out_mesh);
00280 return out_mesh;
00281 }
00282 else
00283 {
00284 rve_msgs::Mesh mesh_msg;
00285 rve_mesh_loader::load(resource_path, mesh_msg);
00286 return convertMesh(rve_common::UUID::generate(), mesh_msg);
00287 }
00288
00289 }
00290
00291 }