00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "vertexData.h"
00025 #include "ply.h"
00026 #include <cstdlib>
00027 #include <algorithm>
00028
00029
00030 using namespace std;
00031 using namespace mesh;
00032
00033
00034
00035 VertexData::VertexData()
00036 : _invertFaces( false )
00037 {
00038 _boundingBox[0] = Vertex( 0.0f );
00039 _boundingBox[1] = Vertex( 0.0f );
00040 }
00041
00042
00043
00044 void VertexData::readVertices( PlyFile* file, const int nVertices,
00045 const bool readColors )
00046 {
00047
00048 struct _Vertex
00049 {
00050 float x;
00051 float y;
00052 float z;
00053 unsigned char r;
00054 unsigned char g;
00055 unsigned char b;
00056 } vertex;
00057
00058 PlyProperty vertexProps[] =
00059 {
00060 { "x", PLY_FLOAT, PLY_FLOAT, offsetof( _Vertex, x ), 0, 0, 0, 0 },
00061 { "y", PLY_FLOAT, PLY_FLOAT, offsetof( _Vertex, y ), 0, 0, 0, 0 },
00062 { "z", PLY_FLOAT, PLY_FLOAT, offsetof( _Vertex, z ), 0, 0, 0, 0 },
00063 { "red", PLY_UCHAR, PLY_UCHAR, offsetof( _Vertex, r ), 0, 0, 0, 0 },
00064 { "green", PLY_UCHAR, PLY_UCHAR, offsetof( _Vertex, g ), 0, 0, 0, 0 },
00065 { "blue", PLY_UCHAR, PLY_UCHAR, offsetof( _Vertex, b ), 0, 0, 0, 0 }
00066 };
00067
00068
00069 int limit = readColors ? 6 : 3;
00070 for( int i = 0; i < limit; ++i )
00071 ply_get_property( file, "vertex", &vertexProps[i] );
00072
00073 vertices.clear();
00074 vertices.reserve( nVertices );
00075
00076 if( readColors )
00077 {
00078 colors.clear();
00079 colors.reserve( nVertices );
00080 }
00081
00082
00083 for( int i = 0; i < nVertices; ++i )
00084 {
00085 ply_get_element( file, static_cast< void* >( &vertex ) );
00086 vertices.push_back( Vertex( vertex.x, vertex.y, vertex.z ) );
00087 if( readColors )
00088 colors.push_back( Color( vertex.r, vertex.g, vertex.b, 0 ) );
00089 }
00090 }
00091
00092
00093
00094 void VertexData::readTriangles( PlyFile* file, const int nFaces )
00095 {
00096
00097 struct _Face
00098 {
00099 unsigned char nVertices;
00100 int* vertices;
00101 } face;
00102
00103 PlyProperty faceProps[] =
00104 {
00105 { "vertex_indices", PLY_INT, PLY_INT, offsetof( _Face, vertices ),
00106 1, PLY_UCHAR, PLY_UCHAR, offsetof( _Face, nVertices ) }
00107 };
00108
00109 ply_get_property( file, "face", &faceProps[0] );
00110
00111 triangles.clear();
00112 triangles.reserve( nFaces );
00113
00114
00115 uint8_t ind1 = _invertFaces ? 2 : 0;
00116 uint8_t ind3 = _invertFaces ? 0 : 2;
00117 for( int i = 0; i < nFaces; ++i )
00118 {
00119 ply_get_element( file, static_cast< void* >( &face ) );
00120 MESHASSERT( face.vertices != 0 );
00121 if( face.nVertices != 3 )
00122 {
00123 free( face.vertices );
00124 throw MeshException( "Error reading PLY file. Encountered a "
00125 "face which does not have three vertices." );
00126 }
00127 triangles.push_back( Triangle( face.vertices[ind1],
00128 face.vertices[1],
00129 face.vertices[ind3] ) );
00130
00131
00132 free( face.vertices );
00133 }
00134 }
00135
00136
00137
00138 bool VertexData::readPlyFile( const std::string& filename )
00139 {
00140 int nPlyElems;
00141 char** elemNames;
00142 int fileType;
00143 float version;
00144 bool result = false;
00145
00146 PlyFile* file = ply_open_for_reading( const_cast<char*>( filename.c_str( )),
00147 &nPlyElems, &elemNames,
00148 &fileType, &version );
00149 if( !file )
00150 {
00151 MESHERROR << "Unable to open PLY file " << filename
00152 << " for reading." << endl;
00153 return result;
00154 }
00155 MESHASSERT( elemNames != 0 );
00156
00157 #ifndef NDEBUG
00158 MESHINFO << filename << ": " << nPlyElems << " elements, file type = "
00159 << fileType << ", version = " << version << endl;
00160 #endif
00161
00162 for( int i = 0; i < nPlyElems; ++i )
00163 {
00164 int nElems;
00165 int nProps;
00166
00167 PlyProperty** props = ply_get_element_description( file, elemNames[i],
00168 &nElems, &nProps );
00169 MESHASSERT( props != 0 );
00170
00171 #ifndef NDEBUG
00172 MESHINFO << "element " << i << ": name = " << elemNames[i] << ", "
00173 << nProps << " properties, " << nElems << " elements" << endl;
00174 for( int j = 0; j < nProps; ++j )
00175 {
00176 MESHINFO << "element " << i << ", property " << j << ": "
00177 << "name = " << props[j]->name << endl;
00178 }
00179 #endif
00180
00181 if( equal_strings( elemNames[i], "vertex" ) )
00182 {
00183 bool hasColors = false;
00184
00185 for( int j = 0; j < nProps; ++j )
00186 if( equal_strings( props[j]->name, "red" ) )
00187 hasColors = true;
00188
00189 readVertices( file, nElems, hasColors );
00190 MESHASSERT( vertices.size() == static_cast< size_t >( nElems ) );
00191 if( hasColors )
00192 {
00193 MESHASSERT( colors.size() == static_cast< size_t >( nElems ));
00194 }
00195 }
00196 else if( equal_strings( elemNames[i], "face" ) )
00197 try
00198 {
00199 readTriangles( file, nElems );
00200 MESHASSERT( triangles.size() == static_cast< size_t >( nElems ) );
00201 result = true;
00202 }
00203 catch( exception& e )
00204 {
00205 MESHERROR << "Unable to read PLY file, an exception occured: "
00206 << e.what() << endl;
00207
00208
00209 i = nPlyElems;
00210 }
00211
00212
00213 for( int j = 0; j < nProps; ++j )
00214 free( props[j] );
00215 free( props );
00216 }
00217
00218 ply_close( file );
00219
00220
00221 for( int i = 0; i < nPlyElems; ++i )
00222 free( elemNames[i] );
00223 free( elemNames );
00224
00225 return result;
00226 }
00227
00228
00229
00230 void VertexData::calculateNormals( const bool vertexNormals )
00231 {
00232 #ifndef NDEBUG
00233 int wrongNormals = 0;
00234 #endif
00235
00236 normals.clear();
00237 if( vertexNormals )
00238 {
00239 normals.reserve( vertices.size() );
00240
00241
00242 for( size_t i = 0; i < vertices.size(); ++i )
00243 normals.push_back( Normal( 0, 0, 0 ) );
00244 }
00245 else
00246 normals.reserve( triangles.size() );
00247
00248
00249 Normal triangleNormal;
00250 Index i0, i1, i2;
00251 for( size_t i = 0; i < triangles.size(); ++i )
00252 {
00253 i0 = triangles[i].at(0);
00254 i1 = triangles[i].at(1);
00255 i2 = triangles[i].at(2);
00256 triangleNormal.compute_normal( vertices[i0], vertices[i1], vertices[i2] );
00257
00258
00259 #ifndef NDEBUG
00260 if( triangleNormal.length() == 0.0f )
00261 ++wrongNormals;
00262 #endif
00263
00264 if( vertexNormals )
00265 {
00266 normals[i0] += triangleNormal;
00267 normals[i1] += triangleNormal;
00268 normals[i2] += triangleNormal;
00269 }
00270 else
00271 normals.push_back( triangleNormal );
00272 }
00273
00274
00275 if( vertexNormals )
00276 for( size_t i = 0; i < vertices.size(); ++i )
00277 normals[i].normalize();
00278
00279 #ifndef NDEBUG
00280 if( wrongNormals > 0 )
00281 MESHINFO << wrongNormals << " faces had no valid normal." << endl;
00282 #endif
00283 }
00284
00285
00286
00287 void VertexData::calculateBoundingBox()
00288 {
00289 _boundingBox[0] = vertices[0];
00290 _boundingBox[1] = vertices[0];
00291 for( size_t v = 1; v < vertices.size(); ++v )
00292 for( size_t i = 0; i < 3; ++i )
00293 {
00294 _boundingBox[0][i] = min( _boundingBox[0][i], vertices[v][i] );
00295 _boundingBox[1][i] = max( _boundingBox[1][i], vertices[v][i] );
00296 }
00297 }
00298
00299
00300
00301 Axis VertexData::getLongestAxis( const size_t start,
00302 const size_t elements ) const
00303 {
00304 if( start + elements > triangles.size() )
00305 {
00306 EQERROR << "incorrect request to getLongestAxis" << endl
00307 << "start: " << start << endl
00308 << "elements: " << elements << endl
00309 << "sum: " << start+elements << endl
00310 << "data size: " << triangles.size() << endl;
00311 return AXIS_X;
00312 }
00313
00314 BoundingBox bb;
00315 bb[0] = vertices[ triangles[start][0] ];
00316 bb[1] = vertices[ triangles[start][0] ];
00317
00318 for( size_t t = start; t < start+elements; ++t )
00319 for( size_t v = 0; v < 3; ++v )
00320 for( size_t i = 0; i < 3; ++i )
00321 {
00322 bb[0][i] = min( bb[0][i], vertices[ triangles[t][v] ][i] );
00323 bb[1][i] = max( bb[1][i], vertices[ triangles[t][v] ][i] );
00324 }
00325
00326 const GLfloat bbX = bb[1][0] - bb[0][0];
00327 const GLfloat bbY = bb[1][1] - bb[0][1];
00328 const GLfloat bbZ = bb[1][2] - bb[0][2];
00329
00330 if( bbX >= bbY && bbX >= bbZ )
00331 return AXIS_X;
00332
00333 if( bbY >= bbX && bbY >= bbZ )
00334 return AXIS_Y;
00335
00336 return AXIS_Z;
00337 }
00338
00339
00340
00341 void VertexData::scale( const float baseSize )
00342 {
00343
00344 if( _boundingBox[0].length() == 0.0f && _boundingBox[1].length() == 0.0f )
00345 calculateBoundingBox();
00346
00347
00348 float factor = 0.0f;
00349 for( size_t i = 0; i < 3; ++i )
00350 factor = max( factor, _boundingBox[1][i] - _boundingBox[0][i] );
00351 factor = baseSize / factor;
00352
00353
00354 Vertex offset;
00355 for( size_t i = 0; i < 3; ++i )
00356 offset[i] = ( _boundingBox[0][i] + _boundingBox[1][i] ) * 0.5f;
00357
00358
00359 for( size_t v = 0; v < vertices.size(); ++v )
00360 for( size_t i = 0; i < 3; ++i )
00361 {
00362 vertices[v][i] -= offset[i];
00363 vertices[v][i] *= factor;
00364 }
00365
00366
00367 for( size_t v = 0; v < 2; ++v )
00368 for( size_t i = 0; i < 3; ++i )
00369 {
00370 _boundingBox[v][i] -= offset[i];
00371 _boundingBox[v][i] *= factor;
00372 }
00373 }
00374
00375
00376
00377 struct _TriangleSort
00378 {
00379 _TriangleSort( const VertexData& data, const Axis axis ) : _data( data ),
00380 _axis( axis ) {}
00381
00382 bool operator() ( const Triangle& t1, const Triangle& t2 )
00383 {
00384
00385 const Vertex& v11 = _data.vertices[ t1[0] ];
00386 const Vertex& v12 = _data.vertices[ t1[1] ];
00387 const Vertex& v13 = _data.vertices[ t1[2] ];
00388 const Vertex& v21 = _data.vertices[ t2[0] ];
00389 const Vertex& v22 = _data.vertices[ t2[1] ];
00390 const Vertex& v23 = _data.vertices[ t2[2] ];
00391
00392
00393 int axis = _axis;
00394 do
00395 {
00396
00397 const float median1 = (v11[axis] + v12[axis] + v13[axis] ) / 3.0f;
00398 const float median2 = (v21[axis] + v22[axis] + v23[axis] ) / 3.0f;
00399 if( median1 != median2 )
00400 return ( median1 < median2 );
00401
00402
00403 axis = ( axis + 1 ) % 3;
00404 }
00405 while( axis != _axis );
00406
00407 return false;
00408 }
00409
00410 const VertexData& _data;
00411 const Axis _axis;
00412 };
00413
00414
00415
00416 void VertexData::sort( const Index start, const Index length, const Axis axis )
00417 {
00418 MESHASSERT( length > 0 );
00419 MESHASSERT( start + length <= triangles.size() );
00420
00421 std::sort( triangles.begin() + start,
00422 triangles.begin() + start + length,
00423 _TriangleSort( *this, axis ) );
00424 }