30 #include "vertexData.h"
36 #if (( __GNUC__ > 4 ) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) )
37 # include <parallel/algorithm>
38 using __gnu_parallel::sort;
46 VertexData::VertexData()
47 : _invertFaces( false )
49 _boundingBox[0] = Vertex( 0.0f );
50 _boundingBox[1] = Vertex( 0.0f );
55 void VertexData::readVertices(
PlyFile* file,
const int nVertices,
56 const bool readColors )
71 {
"x", PLY_FLOAT, PLY_FLOAT, offsetof( _Vertex, x ), 0, 0, 0, 0 },
72 {
"y", PLY_FLOAT, PLY_FLOAT, offsetof( _Vertex, y ), 0, 0, 0, 0 },
73 {
"z", PLY_FLOAT, PLY_FLOAT, offsetof( _Vertex, z ), 0, 0, 0, 0 },
74 {
"red", PLY_UCHAR, PLY_UCHAR, offsetof( _Vertex, r ), 0, 0, 0, 0 },
75 {
"green", PLY_UCHAR, PLY_UCHAR, offsetof( _Vertex, g ), 0, 0, 0, 0 },
76 {
"blue", PLY_UCHAR, PLY_UCHAR, offsetof( _Vertex, b ), 0, 0, 0, 0 }
80 int limit = readColors ? 6 : 3;
81 for(
int i = 0; i < limit; ++i )
82 ply_get_property( file,
"vertex", &vertexProps[i] );
85 vertices.reserve( nVertices );
90 colors.reserve( nVertices );
94 for(
int i = 0; i < nVertices; ++i )
96 ply_get_element( file, static_cast< void* >( &vertex ) );
97 vertices.push_back( Vertex( vertex.x, vertex.y, vertex.z ) );
99 colors.push_back( Color( vertex.r, vertex.g, vertex.b ) );
105 void VertexData::readTriangles(
PlyFile* file,
const int nFaces )
110 unsigned char nVertices;
116 {
"vertex_indices", PLY_INT, PLY_INT, offsetof( _Face, vertices ),
117 1, PLY_UCHAR, PLY_UCHAR, offsetof( _Face, nVertices ) }
120 ply_get_property( file,
"face", &faceProps[0] );
123 triangles.reserve( nFaces );
126 uint8_t ind1 = _invertFaces ? 2 : 0;
127 uint8_t ind3 = _invertFaces ? 0 : 2;
128 for(
int i = 0; i < nFaces; ++i )
130 ply_get_element( file, static_cast< void* >( &face ) );
131 MESHASSERT( face.vertices != 0 );
132 if( face.nVertices != 3 )
134 free( face.vertices );
135 throw MeshException(
"Error reading PLY file. Encountered a "
136 "face which does not have three vertices." );
138 triangles.push_back( Triangle( face.vertices[ind1],
140 face.vertices[ind3] ) );
143 free( face.vertices );
149 bool VertexData::readPlyFile(
const std::string& filename )
157 PlyFile* file = ply_open_for_reading( const_cast<char*>( filename.c_str( )),
158 &nPlyElems, &elemNames,
159 &fileType, &version );
162 MESHERROR <<
"Unable to open PLY file " << filename
163 <<
" for reading." << std::endl;
166 MESHASSERT( elemNames != 0 );
169 MESHINFO << filename <<
": " << nPlyElems <<
" elements, file type = "
170 << fileType <<
", version = " << version << std::endl;
173 for(
int i = 0; i < nPlyElems; ++i )
178 PlyProperty** props = ply_get_element_description( file, elemNames[i],
180 MESHASSERT( props != 0 );
183 MESHINFO <<
"element " << i <<
": name = " << elemNames[i] <<
", "
184 << nProps <<
" properties, " << nElems <<
" elements"
186 for(
int j = 0; j < nProps; ++j )
188 MESHINFO <<
"element " << i <<
", property " << j <<
": "
189 <<
"name = " << props[j]->name << std::endl;
193 if( equal_strings( elemNames[i],
"vertex" ) )
195 bool hasColors =
false;
197 for(
int j = 0; j < nProps; ++j )
198 if( equal_strings( props[j]->name,
"red" ) )
201 readVertices( file, nElems, hasColors );
202 MESHASSERT( vertices.size() ==
static_cast< size_t >( nElems ) );
205 MESHASSERT( colors.size() ==
static_cast< size_t >( nElems ));
208 else if( equal_strings( elemNames[i],
"face" ) )
211 readTriangles( file, nElems );
212 MESHASSERT( triangles.size() ==
static_cast< size_t >( nElems ) );
215 catch(
const std::exception& e )
217 MESHERROR <<
"Unable to read PLY file, an exception occured: "
218 << e.what() << std::endl;
225 for(
int j = 0; j < nProps; ++j )
233 for(
int i = 0; i < nPlyElems; ++i )
234 free( elemNames[i] );
242 void VertexData::calculateNormals()
245 int wrongNormals = 0;
249 normals.reserve( vertices.size() );
252 for(
size_t i = 0; i < vertices.size(); ++i )
253 normals.push_back( Normal( 0, 0, 0 ) );
256 #pragma omp parallel for
257 for( ssize_t i = 0; i < ssize_t( triangles.size( )); ++i )
259 const Index i0 = triangles[i][0];
260 const Index i1 = triangles[i][1];
261 const Index i2 = triangles[i][2];
262 const Normal normal = vertices[i0].compute_normal( vertices[i1],
266 if( normal.length() == 0.0f )
270 normals[i0] += normal;
271 normals[i1] += normal;
272 normals[i2] += normal;
276 #pragma omp parallel for
277 for( ssize_t i = 0; i < ssize_t( vertices.size( )); ++i )
278 normals[i].normalize();
281 if( wrongNormals > 0 )
282 MESHINFO << wrongNormals <<
" faces have no valid normal." << std::endl;
288 void VertexData::calculateBoundingBox()
290 _boundingBox[0] = vertices[0];
291 _boundingBox[1] = vertices[0];
292 for(
size_t v = 1; v < vertices.size(); ++v )
293 for(
size_t i = 0; i < 3; ++i )
295 _boundingBox[0][i] = std::min( _boundingBox[0][i], vertices[v][i] );
296 _boundingBox[1][i] = std::max( _boundingBox[1][i], vertices[v][i] );
302 Axis VertexData::getLongestAxis(
const size_t start,
303 const size_t elements )
const
305 if( start + elements > triangles.size() )
307 LBERROR <<
"incorrect request to getLongestAxis" << std::endl
308 <<
"start: " << start << std::endl
309 <<
"elements: " << elements << std::endl
310 <<
"sum: " << start+elements << std::endl
311 <<
"data size: " << triangles.size() << std::endl;
316 bb[0] = vertices[ triangles[start][0] ];
317 bb[1] = vertices[ triangles[start][0] ];
319 for(
size_t t = start; t < start+elements; ++t )
320 for(
size_t v = 0; v < 3; ++v )
321 for(
size_t i = 0; i < 3; ++i )
323 bb[0][i] = std::min( bb[0][i], vertices[ triangles[t][v] ][i] );
324 bb[1][i] = std::max( bb[1][i], vertices[ triangles[t][v] ][i] );
327 const GLfloat bbX = bb[1][0] - bb[0][0];
328 const GLfloat bbY = bb[1][1] - bb[0][1];
329 const GLfloat bbZ = bb[1][2] - bb[0][2];
331 if( bbX >= bbY && bbX >= bbZ )
334 if( bbY >= bbX && bbY >= bbZ )
342 void VertexData::scale(
const float baseSize )
345 if( _boundingBox[0].length() == 0.0f && _boundingBox[1].length() == 0.0f )
346 calculateBoundingBox();
350 for(
size_t i = 0; i < 3; ++i )
351 factor = std::max( factor, _boundingBox[1][i] - _boundingBox[0][i] );
352 factor = baseSize / factor;
356 for(
size_t i = 0; i < 3; ++i )
357 offset[i] = ( _boundingBox[0][i] + _boundingBox[1][i] ) * 0.5f;
360 #pragma omp parallel for
361 for( ssize_t v = 0; v < ssize_t( vertices.size( )); ++v )
362 for(
size_t i = 0; i < 3; ++i )
364 vertices[v][i] -= offset[i];
365 vertices[v][i] *= factor;
369 for(
size_t v = 0; v < 2; ++v )
370 for(
size_t i = 0; i < 3; ++i )
372 _boundingBox[v][i] -= offset[i];
373 _boundingBox[v][i] *= factor;
382 _TriangleSort(
const VertexData& data,
const Axis axis ) : _data( data ),
385 bool operator() (
const Triangle& t1,
const Triangle& t2 )
388 const Vertex& v11 = _data.vertices[ t1[0] ];
389 const Vertex& v12 = _data.vertices[ t1[1] ];
390 const Vertex& v13 = _data.vertices[ t1[2] ];
391 const Vertex& v21 = _data.vertices[ t2[0] ];
392 const Vertex& v22 = _data.vertices[ t2[1] ];
393 const Vertex& v23 = _data.vertices[ t2[2] ];
400 const float median1 = (v11[axis] + v12[axis] + v13[axis] ) / 3.0f;
401 const float median2 = (v21[axis] + v22[axis] + v23[axis] ) / 3.0f;
402 if( median1 != median2 )
403 return ( median1 < median2 );
406 axis = ( axis + 1 ) % 3;
408 while( axis != _axis );
419 void VertexData::sort(
const Index start,
const Index length,
const Axis axis )
421 MESHASSERT( length > 0 );
422 MESHASSERT( start + length <= triangles.size() );
424 ::sort( triangles.begin() + start, triangles.begin() + start + length,
425 _TriangleSort( *
this, axis ) );