root/OpenSceneGraph/trunk/src/osgPlugins/ply/vertexData.cpp @ 10149

Revision 10149, 12.0 kB (checked in by robert, 6 years ago)

From MAthias Froehlich, "Attached is a compile fix I need on Suse 11.1 for a successful compile.
Just avoid uint8_t typed values in src/osgPlugins/ply/vertexData.cpp
if they are not needed for a particular reason ..."

RevLine 
[10012]1/* 
2    vertexData.cpp
3    Copyright (c) 2007, Tobias Wolf <twolf@access.unizh.ch>
4    All rights reserved. 
5   
6    Implementation of the VertexData class.
7*/
8
9/** note, derived from Equalizer LGPL source.*/
10
11#include "typedefs.h"
12#include "vertexData.h"
13#include "ply.h"
[10079]14
[10012]15#include <cstdlib>
16#include <algorithm>
17#include <osg/Geometry>
18#include <osg/Geode>
19#include <osg/io_utils>
20
21using namespace std;
22using namespace ply;
23
24
25struct Normal{
26    osg::Vec3 triNormal;
27    void normal(osg::Vec3 v1, osg::Vec3 v2, osg::Vec3 v3)
28    {
29        osg::Vec3 u,v;
30
31        // right hand system, CCW triangle
32        u = v2 - v1;
33        v = v3 - v1;
34        triNormal = u^v;
35        triNormal.normalize();
36    }
37};
38
39/*  Contructor.  */
40VertexData::VertexData()
41    : _invertFaces( false )
42{
43    // Initialize the members
44    _vertices = NULL;
45    _colors = NULL;
46    _normals = NULL;
47    _triangles = NULL;
48   
49}
50
51
52/*  Read the vertex and (if available/wanted) color data from the open file.  */
53void VertexData::readVertices( PlyFile* file, const int nVertices,
54                               const bool readColors )
55{
56    // temporary vertex structure for ply loading
57    struct _Vertex
58    {
59        float           x;
60        float           y;
61        float           z;
62        unsigned char   r;
63        unsigned char   g;
64        unsigned char   b;
65    } vertex;
66
67    PlyProperty vertexProps[] =
68    {
69        { "x", PLY_FLOAT, PLY_FLOAT, offsetof( _Vertex, x ), 0, 0, 0, 0 },
70        { "y", PLY_FLOAT, PLY_FLOAT, offsetof( _Vertex, y ), 0, 0, 0, 0 },
71        { "z", PLY_FLOAT, PLY_FLOAT, offsetof( _Vertex, z ), 0, 0, 0, 0 },
72        { "red", PLY_UCHAR, PLY_UCHAR, offsetof( _Vertex, r ), 0, 0, 0, 0 },
73        { "green", PLY_UCHAR, PLY_UCHAR, offsetof( _Vertex, g ), 0, 0, 0, 0 },
74        { "blue", PLY_UCHAR, PLY_UCHAR, offsetof( _Vertex, b ), 0, 0, 0, 0 }
75    };
76   
77    // use all 6 properties when reading colors, only the first 3 otherwise
78    int limit = readColors ? 6 : 3;
79    for( int i = 0; i < limit; ++i )
80        ply_get_property( file, "vertex", &vertexProps[i] );
81   
82    // check whether array is valid otherwise allocate the space
83    if(!_vertices.valid())
84        _vertices = new osg::Vec3Array;
85   
86    // If read colors allocate space for color array
87    if( readColors )
88    {
89        if(!_colors.valid())
90            _colors = new osg::Vec4Array;
91    }
92   
93    // read in the vertices
94    for( int i = 0; i < nVertices; ++i )
95    {
96        ply_get_element( file, static_cast< void* >( &vertex ) );
97        _vertices->push_back( osg::Vec3( vertex.x, vertex.y, vertex.z ) );
98        if( readColors )
99            _colors->push_back( osg::Vec4( (unsigned int) vertex.r / 256.0, (unsigned int) vertex.g / 256.0 , (unsigned int) vertex.b/ 256.0, 0.0 ) );
100    }
101}
102
103
104/*  Read the index data from the open file.  */
105void VertexData::readTriangles( PlyFile* file, const int nFaces )
106{
107    // temporary face structure for ply loading
108    struct _Face
109    {
110        unsigned char   nVertices;
111        int*            vertices;
112    } face;
113
114    PlyProperty faceProps[] =
115    {
116        { "vertex_indices", PLY_INT, PLY_INT, offsetof( _Face, vertices ),
117          1, PLY_UCHAR, PLY_UCHAR, offsetof( _Face, nVertices ) }
118    };
119   
120    ply_get_property( file, "face", &faceProps[0] );
121   
122    //triangles.clear();
123    //triangles.reserve( nFaces );
124    if(!_triangles.valid())
125        _triangles = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 0);
126
127   
128    // read in the faces, asserting that they are only triangles
[10149]129    int ind1 = _invertFaces ? 2 : 0;
130    int ind3 = _invertFaces ? 0 : 2;
[10012]131    for( int i = 0; i < nFaces; ++i )
132    {
133        ply_get_element( file, static_cast< void* >( &face ) );
134        MESHASSERT( face.vertices != 0 );
135        if( (unsigned int)(face.nVertices) != 3 )
136        {
137            free( face.vertices );
138            throw MeshException( "Error reading PLY file. Encountered a "
139                                 "face which does not have three vertices." );
140        }
141        // Add the face indices in the premitive set
142        _triangles->push_back( face.vertices[ind1]);
143        _triangles->push_back( face.vertices[1]);
144        _triangles->push_back( face.vertices[ind3] );
145       
146        // free the memory that was allocated by ply_get_element
147        free( face.vertices );
148    }
149}
150
151
152/*  Open a PLY file and read vertex, color and index data. and returns the node  */
153osg::Node* VertexData::readPlyFile( const char* filename, const bool ignoreColors )
154{
155    int     nPlyElems;
156    char**  elemNames;
157    int     fileType;
158    float   version;
159    bool    result = false;
[10040]160    int     nComments;
161    char**  comments;
[10012]162   
[10040]163    PlyFile* file = NULL;
164
165    // Try to open ply file as for reading
166    try{
167            file  = ply_open_for_reading( const_cast< char* >( filename ),
[10012]168                                          &nPlyElems, &elemNames,
169                                          &fileType, &version );
[10040]170    }
171    // Catch the if any exception thrown
172    catch( exception& e )
173    {
174        MESHERROR << "Unable to read PLY file, an exception occured:  " 
175                    << e.what() << endl;
176    }
[10012]177
178    if( !file )
179    {
180        MESHERROR << "Unable to open PLY file " << filename
181                  << " for reading." << endl;
182        return NULL;
183    }
184
185    MESHASSERT( elemNames != 0 );
[10040]186   
[10012]187
188    nComments = file->num_comments;
189    comments = file->comments;
190   
191   
192    #ifndef NDEBUG
193    MESHINFO << filename << ": " << nPlyElems << " elements, file type = " 
194             << fileType << ", version = " << version << endl;
195    #endif
196
197    for( int i = 0; i < nComments; i++ )
198    {
199        if( equal_strings( comments[i], "modified by flipply" ) )
200        {
201            _invertFaces = true;
202        }
203
204    }
205    for( int i = 0; i < nPlyElems; ++i )
206    {
207        int nElems;
208        int nProps;
209       
[10040]210        PlyProperty** props = NULL;
211        try{
212                props = ply_get_element_description( file, elemNames[i],
213                                                     &nElems, &nProps );
214        }
215        catch( exception& e )
216        {
217            MESHERROR << "Unable to get PLY file description, an exception occured:  " 
218                        << e.what() << endl;
219        }
[10012]220        MESHASSERT( props != 0 );
221       
222        #ifndef NDEBUG
223        MESHINFO << "element " << i << ": name = " << elemNames[i] << ", "
224                 << nProps << " properties, " << nElems << " elements" << endl;
225        for( int j = 0; j < nProps; ++j )
226        {
227            MESHINFO << "element " << i << ", property " << j << ": "
228                     << "name = " << props[j]->name << endl;
229        }
230        #endif
231       
232        // if the string is vertex means vertex data is started
233        if( equal_strings( elemNames[i], "vertex" ) )
234        {
235            bool hasColors = false;
236            // determine if the file stores vertex colors
237            for( int j = 0; j < nProps; ++j )
238                // if the string have the red means color info is there
239                if( equal_strings( props[j]->name, "red" ) )
240                    hasColors = true;
241           
242            if( ignoreColors )
243                MESHINFO << "Colors in PLY file ignored per request." << endl;
[10040]244         
245            try {   
246                // Read vertices and store in a std::vector array
247                readVertices( file, nElems, hasColors && !ignoreColors );
248                // Check whether all vertices are loaded or not
249                MESHASSERT( _vertices->size() == static_cast< size_t >( nElems ) );
250                // Check all color elements read or not
251                if( hasColors && !ignoreColors )
[10079]252                {
[10040]253                    MESHASSERT( _colors->size() == static_cast< size_t >( nElems ) );
[10079]254                }
[10040]255            }
256            catch( exception& e )
257            {
258                MESHERROR << "Unable to read vertex in PLY file, an exception occured:  " 
259                            << e.what() << endl;
260                // stop for loop by setting the loop variable to break condition
261                // this way resources still get released even on error cases
262                i = nPlyElems;
263               
264            }
[10012]265        }
266        // If the string is face means triangle info started
267        else if( equal_strings( elemNames[i], "face" ) )
268        try
269        {
270            // Read Triangles
271            readTriangles( file, nElems );
272            // Check whether all face elements read or not
273            MESHASSERT( _triangles->size()/3  == static_cast< size_t >( nElems ) );
274            result = true;
275        }
276        catch( exception& e )
277        {
278            MESHERROR << "Unable to read PLY file, an exception occured:  " 
279                      << e.what() << endl;
280            // stop for loop by setting the loop variable to break condition
281            // this way resources still get released even on error cases
282            i = nPlyElems;
283        }
284       
285        // free the memory that was allocated by ply_get_element_description
286        for( int j = 0; j < nProps; ++j )
287            free( props[j] );
288        free( props );
289    }
290   
291    ply_close( file );
292   
293    // free the memory that was allocated by ply_open_for_reading
294    for( int i = 0; i < nPlyElems; ++i )
295        free( elemNames[i] );
296    free( elemNames );
297
298   // If the result is true means the ply file is successfully read
299   if(result)
300   {
301        // Create geometry node
302        osg::Geometry* geom  =  new osg::Geometry;
303
304        // set the vertex array
305        geom->setVertexArray(_vertices.get());
306
307        // If the normals are not calculated calculate the normals for faces
308        if(!_normals.valid())
309            _calculateNormals();
310
311       
312        // set the normals
313        geom->setNormalArray(_normals.get());
314        geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
315       
316        // Add the premetive set
317        geom->addPrimitiveSet(_triangles.get());
318
319        // if color info is given set the color array
320        if(_colors.valid())
321        {
322            geom->setColorArray(_colors.get());
323            geom->setColorBinding( osg::Geometry::BIND_PER_VERTEX );
324           
325        }
326
327       
328        // set flage true to activate the vertex buffer object of drawable
329        geom->setUseVertexBufferObjects(true);
330       
331
332        osg::Geode* geode = new osg::Geode;
333        geode->addDrawable(geom);
334        return geode;
335   }
336   
337    return NULL;
338}
339
340
341/*  Calculate the face or vertex normals of the current vertex data.  */
342void VertexData::_calculateNormals( const bool vertexNormals )
343{
344
345    if(_normals.valid())
346        return;
347
348    #ifndef NDEBUG
349    int wrongNormals = 0;
350    #endif
351
352    if(!_normals.valid())
353    {
354        _normals = new osg::Vec3Array;
355    }
356   
357    //normals.clear();
358    if( vertexNormals )
359    {
360        // initialize all normals to zero
361        for( size_t i = 0; i < _vertices->size(); ++i )
362        {
363            _normals->push_back( osg::Vec3( 0, 0, 0 ) );
364        }
365    }
366
367   
368    for( size_t i = 0; i < ((_triangles->size()));  i += 3 )
369    {
370        // iterate over all triangles and add their normals to adjacent vertices
371        Normal  triangleNormal;
372        unsigned int i0, i1, i2;
373        i0 = (*_triangles)[i+0];
374        i1 = (*_triangles)[i+1];
375        i2 = (*_triangles)[i+2];
376        triangleNormal.normal((*_vertices)[i0],
377                               (*_vertices)[i1],
378                               (*_vertices)[i2] );
379       
380        // count emtpy normals in debug mode
381        #ifndef NDEBUG
382        if( triangleNormal.triNormal.length() == 0.0f )
383            ++wrongNormals;
384        #endif
385         
386        if( vertexNormals )
387        {
388            (*_normals)[i0] += triangleNormal.triNormal;
389            (*_normals)[i1] += triangleNormal.triNormal;
390            (*_normals)[i2] += triangleNormal.triNormal;
391        }
392        else
393            _normals->push_back( triangleNormal.triNormal );
394    }
395   
396    // normalize all the normals
397    if( vertexNormals )
398        for( size_t i = 0; i < _normals->size(); ++i )
399            (*_normals)[i].normalize();
400   
401    #ifndef NDEBUG
402    if( wrongNormals > 0 )
403        MESHINFO << wrongNormals << " faces had no valid normal." << endl;
404    #endif
405}
Note: See TracBrowser for help on using the browser.