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 "stl_loader.h"
00031 #include <ros/console.h>
00032
00033 #include <OgreManualObject.h>
00034
00035 namespace ogre_tools
00036 {
00037
00038 STLLoader::STLLoader()
00039 {
00040
00041 }
00042
00043 STLLoader::~STLLoader()
00044 {
00045
00046 }
00047
00048 bool STLLoader::load(const std::string& path)
00049 {
00050 FILE* input = fopen( path.c_str(), "r" );
00051 if ( !input )
00052 {
00053 ROS_ERROR( "Could not open '%s' for read", path.c_str() );
00054 return false;
00055 }
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 fseek( input, 0, SEEK_END );
00073 long fileSize = ftell( input );
00074 rewind( input );
00075
00076 std::vector<uint8_t> buffer_vec(fileSize);
00077 uint8_t* buffer = &buffer_vec[0];
00078
00079 long num_bytes_read = fread( buffer, 1, fileSize, input );
00080 if ( num_bytes_read != fileSize )
00081 {
00082 ROS_ERROR("STLLoader::load( \"%s\" ) only read %ld bytes out of total %ld.",
00083 path.c_str(), num_bytes_read, fileSize);
00084 fclose( input );
00085 return false;
00086 }
00087 fclose( input );
00088
00089 return this->load(buffer, num_bytes_read, path);
00090 }
00091
00092 bool STLLoader::load(uint8_t* buffer, const size_t num_bytes, const std::string& origin)
00093 {
00094
00095 std::string buffer_str = std::string(reinterpret_cast<char *>(buffer), num_bytes);
00096
00097 if (buffer_str.substr(0, 5) == std::string("solid"))
00098 {
00099
00100
00101
00102 if (buffer_str.find("endsolid", 5) != std::string::npos)
00103 {
00104 ROS_ERROR_STREAM("The STL file '" << origin << "' is malformed. It "
00105 "starts with the word 'solid' and also contains the "
00106 "word 'endsolid', indicating that it's an ASCII STL "
00107 "file, but rviz can only load binary STL files so it "
00108 "will not be loaded. Please convert it to a "
00109 "binary STL file.");
00110 return false;
00111 }
00112
00113
00114 ROS_WARN_STREAM("The STL file '" << origin << "' is malformed. It starts"
00115 " with the word 'solid', indicating that it's an ASCII "
00116 "STL file, but it does not contain the word 'endsolid' so"
00117 "it is either a malformed ASCII STL file or it is actually "
00118 "a binary STL file. Trying to interpret it as a binary "
00119 "STL file instead.");
00120 }
00121
00122
00123 static const size_t binary_stl_header_len = 84;
00124 if (num_bytes <= binary_stl_header_len)
00125 {
00126 ROS_ERROR_STREAM("The STL file '" << origin <<"' is malformed. It "
00127 "appears to be a binary STL file but does not contain "
00128 "enough data for the 80 byte header and 16-bit integer "
00129 "triangle count.");
00130 return false;
00131 }
00132
00133
00134 unsigned int num_triangles = *(reinterpret_cast<uint16_t *>(buffer + 80));
00135 static const size_t number_of_bytes_per_triangle = 50;
00136 size_t expected_size = binary_stl_header_len + num_triangles * number_of_bytes_per_triangle;
00137 if (num_bytes != expected_size)
00138 {
00139 ROS_ERROR_STREAM("The STL file '" << origin << "' is malformed. According "
00140 "to the binary STL header it should have '" <<
00141 num_triangles << "' triangles, but it has too " <<
00142 (num_bytes > expected_size ? "much" : "little") <<
00143 " data for that to be the case.");
00144 return false;
00145 }
00146
00147
00148 return this->load_binary(buffer);
00149 }
00150
00151 bool STLLoader::load_binary(uint8_t* buffer)
00152 {
00153 uint8_t* pos = buffer;
00154
00155 pos += 80;
00156
00157 unsigned int numTriangles = *(unsigned int*)pos;
00158 pos += 4;
00159
00160 for ( unsigned int currentTriangle = 0; currentTriangle < numTriangles; ++currentTriangle )
00161 {
00162 Triangle tri;
00163
00164 tri.normal_.x = *(float*)pos;
00165 pos += 4;
00166 tri.normal_.y = *(float*)pos;
00167 pos += 4;
00168 tri.normal_.z = *(float*)pos;
00169 pos += 4;
00170
00171 tri.vertices_[0].x = *(float*)pos;
00172 pos += 4;
00173 tri.vertices_[0].y = *(float*)pos;
00174 pos += 4;
00175 tri.vertices_[0].z = *(float*)pos;
00176 pos += 4;
00177
00178 tri.vertices_[1].x = *(float*)pos;
00179 pos += 4;
00180 tri.vertices_[1].y = *(float*)pos;
00181 pos += 4;
00182 tri.vertices_[1].z = *(float*)pos;
00183 pos += 4;
00184
00185 tri.vertices_[2].x = *(float*)pos;
00186 pos += 4;
00187 tri.vertices_[2].y = *(float*)pos;
00188 pos += 4;
00189 tri.vertices_[2].z = *(float*)pos;
00190 pos += 4;
00191
00192
00193
00194 pos += 2;
00195
00196
00197
00198 if (tri.normal_.squaredLength() < 0.001)
00199 {
00200 Ogre::Vector3 side1 = tri.vertices_[0] - tri.vertices_[1];
00201 Ogre::Vector3 side2 = tri.vertices_[1] - tri.vertices_[2];
00202 tri.normal_ = side1.crossProduct(side2);
00203 }
00204 tri.normal_.normalise();
00205
00206 triangles_.push_back(tri);
00207 }
00208
00209 return true;
00210 }
00211
00212 void calculateUV(const Ogre::Vector3& vec, float& u, float& v)
00213 {
00214 Ogre::Vector3 pos(vec);
00215 pos.normalise();
00216 u = acos( pos.y / pos.length() );
00217
00218 float val = pos.x / ( sin( u ) );
00219 v = acos( val );
00220
00221 u /= Ogre::Math::PI;
00222 v /= Ogre::Math::PI;
00223 }
00224
00225
00226 Ogre::MeshPtr STLLoader::toMesh(const std::string& name)
00227 {
00228 Ogre::ManualObject* object = new Ogre::ManualObject( "the one and only" );
00229 object->begin( "BaseWhiteNoLighting", Ogre::RenderOperation::OT_TRIANGLE_LIST );
00230
00231 unsigned int vertexCount = 0;
00232 V_Triangle::const_iterator it = triangles_.begin();
00233 V_Triangle::const_iterator end = triangles_.end();
00234 for (; it != end; ++it )
00235 {
00236 if( vertexCount >= 2004 )
00237 {
00238
00239
00240 object->end();
00241 object->begin( "BaseWhiteNoLighting", Ogre::RenderOperation::OT_TRIANGLE_LIST );
00242 vertexCount = 0;
00243 }
00244
00245 const STLLoader::Triangle& tri = *it;
00246
00247 float u, v;
00248 u = v = 0.0f;
00249 object->position( tri.vertices_[0] );
00250 object->normal( tri.normal_);
00251 calculateUV( tri.vertices_[0], u, v );
00252 object->textureCoord( u, v );
00253
00254 object->position( tri.vertices_[1] );
00255 object->normal( tri.normal_);
00256 calculateUV( tri.vertices_[1], u, v );
00257 object->textureCoord( u, v );
00258
00259 object->position( tri.vertices_[2] );
00260 object->normal( tri.normal_);
00261 calculateUV( tri.vertices_[2], u, v );
00262 object->textureCoord( u, v );
00263
00264 object->triangle( vertexCount + 0, vertexCount + 1, vertexCount + 2 );
00265
00266 vertexCount += 3;
00267 }
00268
00269 object->end();
00270
00271 Ogre::MeshPtr mesh = object->convertToMesh( name, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME );
00272 mesh->buildEdgeList();
00273
00274 delete object;
00275
00276 return mesh;
00277 }
00278
00279 }