From Santosh Gaikwad, ply plugin, based on Equalizer and other LGPL compatible sources.
"Attached is the osg-plugin for reading ply ( Stanford Triangle Format ) file. I have written the plugin according to OSG standard and have also added cmake build system. The plugin is working fine on both Linux and Windows and should behave similarly on other OS as well." "I developed this plugin while working on a project based on Equalizer. So VertexData which I am using is taken from equalizer and modified to make them work as separate OSG plugin. Before contributing this plugin to OSG community, I asked project manager of Equalizer project Stefen regarding potential licensing issues and this is what he has said "The kd-Tree (VertexBuffer*) is LGPL-licensed, and the base ply loader (ply*) is BSD. As long as you leave the copyright notices intact, there is no issue." so I think using these files in OSG should not be a problem. As far as author of ReaderWriterPLY.cpp is concerned I am the author. I am working for Darshan3d which is a subsidiary of VizExperts thats why I have put VizExperts copyright."
This commit is contained in:
15
src/osgPlugins/ply/CMakeLists.txt
Normal file
15
src/osgPlugins/ply/CMakeLists.txt
Normal file
@@ -0,0 +1,15 @@
|
||||
#this file is automatically generated
|
||||
|
||||
|
||||
SET(TARGET_SRC ReaderWriterPLY.cpp
|
||||
vertexData.cpp
|
||||
plyfile.cpp
|
||||
)
|
||||
|
||||
SET(TARGET_H
|
||||
typedefs.h
|
||||
ply.h
|
||||
vertexData.h
|
||||
)
|
||||
#### end var setup ###
|
||||
SETUP_PLUGIN(ply)
|
||||
81
src/osgPlugins/ply/ReaderWriterPLY.cpp
Normal file
81
src/osgPlugins/ply/ReaderWriterPLY.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* PLY ( Stanford Triangle Format ) File Loader for OSG
|
||||
* Copyright (C) 2009 by VizExperts Limited
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/ReadFile>
|
||||
#include <osgDB/FileUtils>
|
||||
#include <osgDB/FileNameUtils>
|
||||
|
||||
|
||||
#include "vertexData.h"
|
||||
|
||||
using namespace osg;
|
||||
using namespace osgDB;
|
||||
using namespace std;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//!
|
||||
//! \class ReaderWriterPLY
|
||||
//! \brief This is the Reader for the ply file format
|
||||
//!
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
class ReaderWriterPLY : public osgDB::ReaderWriter
|
||||
{
|
||||
public:
|
||||
ReaderWriterPLY()
|
||||
{
|
||||
supportsExtension("ply","Stanford Triangle Format");
|
||||
}
|
||||
|
||||
virtual const char* className() { return "ReaderWriterPLY"; }
|
||||
virtual ReadResult readNode(const std::string& fileName, const osgDB::ReaderWriter::Options*) const;
|
||||
protected:
|
||||
};
|
||||
|
||||
// register with Registry to instantiate the above reader/writer.
|
||||
REGISTER_OSGPLUGIN(ply, ReaderWriterPLY)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//!
|
||||
//! \brief Function which is called when any ply file is requested to load in
|
||||
//! \osgDB. Load read ply file and if it successes return the osg::Node
|
||||
//!
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
osgDB::ReaderWriter::ReadResult ReaderWriterPLY::readNode(const std::string& filename, const osgDB::ReaderWriter::Options* options) const
|
||||
{
|
||||
// Get the file extension
|
||||
std::string ext = osgDB::getFileExtension(filename);
|
||||
|
||||
// If the file extension does not support then return that file is not handled
|
||||
if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;
|
||||
|
||||
// Check whether or not file exist or not
|
||||
std::string fileName = osgDB::findDataFile(filename, options);
|
||||
if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;
|
||||
|
||||
//Instance of vertex data which will read the ply file and convert in to osg::Node
|
||||
ply::VertexData vertexData;
|
||||
osg::Node* node = vertexData.readPlyFile(filename.c_str());
|
||||
|
||||
if (node)
|
||||
return node;
|
||||
|
||||
return ReadResult::FILE_NOT_HANDLED;
|
||||
}
|
||||
172
src/osgPlugins/ply/ply.h
Normal file
172
src/osgPlugins/ply/ply.h
Normal file
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
|
||||
Header for PLY polygon files.
|
||||
|
||||
- Greg Turk, March 1994
|
||||
|
||||
A PLY file contains a single polygonal _object_.
|
||||
|
||||
An object is composed of lists of _elements_. Typical elements are
|
||||
vertices, faces, edges and materials.
|
||||
|
||||
Each type of element for a given object has one or more _properties_
|
||||
associated with the element type. For instance, a vertex element may
|
||||
have as properties three floating-point values x,y,z and three unsigned
|
||||
chars for red, green and blue.
|
||||
|
||||
---------------------------------------------------------------
|
||||
|
||||
Copyright (c) 1994 The Board of Trustees of The Leland Stanford
|
||||
Junior University. All rights reserved.
|
||||
|
||||
Permission to use, copy, modify and distribute this software and its
|
||||
documentation for any purpose is hereby granted without fee, provided
|
||||
that the above copyright notice and this permission notice appear in
|
||||
all copies of this software and that you do not sell the software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
|
||||
WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __PLY_H__
|
||||
#define __PLY_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define PLY_ASCII 1 /* ascii PLY file */
|
||||
#define PLY_BINARY_BE 2 /* binary PLY file, big endian */
|
||||
#define PLY_BINARY_LE 3 /* binary PLY file, little endian */
|
||||
|
||||
#define PLY_OKAY 0 /* ply routine worked okay */
|
||||
#define PLY_ERROR -1 /* error in ply routine */
|
||||
|
||||
/* scalar data types supported by PLY format */
|
||||
|
||||
#define PLY_START_TYPE 0
|
||||
#define PLY_CHAR 1
|
||||
#define PLY_SHORT 2
|
||||
#define PLY_INT 3
|
||||
#define PLY_UCHAR 4
|
||||
#define PLY_USHORT 5
|
||||
#define PLY_UINT 6
|
||||
#define PLY_FLOAT 7
|
||||
#define PLY_DOUBLE 8
|
||||
#define PLY_FLOAT32 9
|
||||
#define PLY_UINT8 10
|
||||
#define PLY_INT32 11
|
||||
#define PLY_END_TYPE 12
|
||||
|
||||
#define PLY_SCALAR 0
|
||||
#define PLY_LIST 1
|
||||
|
||||
|
||||
typedef struct PlyProperty { /* description of a property */
|
||||
|
||||
char *name; /* property name */
|
||||
int external_type; /* file's data type */
|
||||
int internal_type; /* program's data type */
|
||||
int offset; /* offset bytes of prop in a struct */
|
||||
|
||||
int is_list; /* 1 = list, 0 = scalar */
|
||||
int count_external; /* file's count type */
|
||||
int count_internal; /* program's count type */
|
||||
int count_offset; /* offset byte for list count */
|
||||
|
||||
} PlyProperty;
|
||||
|
||||
typedef struct PlyElement { /* description of an element */
|
||||
char *name; /* element name */
|
||||
int num; /* number of elements in this object */
|
||||
int size; /* size of element (bytes) or -1 if variable */
|
||||
int nprops; /* number of properties for this element */
|
||||
PlyProperty **props; /* list of properties in the file */
|
||||
char *store_prop; /* flags: property wanted by user? */
|
||||
int other_offset; /* offset to un-asked-for props, or -1 if none*/
|
||||
int other_size; /* size of other_props structure */
|
||||
} PlyElement;
|
||||
|
||||
typedef struct PlyOtherProp { /* describes other properties in an element */
|
||||
char *name; /* element name */
|
||||
int size; /* size of other_props */
|
||||
int nprops; /* number of properties in other_props */
|
||||
PlyProperty **props; /* list of properties in other_props */
|
||||
} PlyOtherProp;
|
||||
|
||||
typedef struct OtherData { /* for storing other_props for an other element */
|
||||
void *other_props;
|
||||
} OtherData;
|
||||
|
||||
typedef struct OtherElem { /* data for one "other" element */
|
||||
char *elem_name; /* names of other elements */
|
||||
int elem_count; /* count of instances of each element */
|
||||
OtherData **other_data; /* actual property data for the elements */
|
||||
PlyOtherProp *other_props; /* description of the property data */
|
||||
} OtherElem;
|
||||
|
||||
typedef struct PlyOtherElems { /* "other" elements, not interpreted by user */
|
||||
int num_elems; /* number of other elements */
|
||||
OtherElem *other_list; /* list of data for other elements */
|
||||
} PlyOtherElems;
|
||||
|
||||
typedef struct PlyFile { /* description of PLY file */
|
||||
FILE *fp; /* file pointer */
|
||||
int file_type; /* ascii or binary */
|
||||
float version; /* version number of file */
|
||||
int nelems; /* number of elements of object */
|
||||
PlyElement **elems; /* list of elements */
|
||||
int num_comments; /* number of comments */
|
||||
char **comments; /* list of comments */
|
||||
int num_obj_info; /* number of items of object information */
|
||||
char **obj_info; /* list of object info items */
|
||||
PlyElement *which_elem; /* which element we're currently writing */
|
||||
PlyOtherElems *other_elems; /* "other" elements from a PLY file */
|
||||
} PlyFile;
|
||||
|
||||
/* memory allocation */
|
||||
extern char *my_alloc();
|
||||
#define myalloc(mem_size) my_alloc((mem_size), __LINE__, __FILE__)
|
||||
|
||||
|
||||
/*** delcaration of routines ***/
|
||||
|
||||
extern PlyFile *ply_write(FILE *, int, char **, int);
|
||||
extern PlyFile *ply_open_for_writing(char *, int, char **, int, float *);
|
||||
extern void ply_describe_element(PlyFile *, char *, int, int, PlyProperty *);
|
||||
extern void ply_describe_property(PlyFile *, char *, PlyProperty *);
|
||||
extern void ply_element_count(PlyFile *, const char *, int);
|
||||
extern void ply_header_complete(PlyFile *);
|
||||
extern void ply_put_element_setup(PlyFile *, const char *);
|
||||
extern void ply_put_element(PlyFile *, void *);
|
||||
extern void ply_put_comment(PlyFile *, const char *);
|
||||
extern void ply_put_obj_info(PlyFile *, const char *);
|
||||
extern PlyFile *ply_read(FILE *, int *, char ***);
|
||||
extern PlyFile *ply_open_for_reading( char *, int *, char ***, int *, float *);
|
||||
extern PlyProperty **ply_get_element_description(PlyFile *, char *, int*, int*);
|
||||
extern void ply_get_element_setup( PlyFile *, char *, int, PlyProperty *);
|
||||
extern void ply_get_property(PlyFile *, char *, PlyProperty *);
|
||||
extern PlyOtherProp *ply_get_other_properties(PlyFile *, char *, int);
|
||||
extern void ply_get_element(PlyFile *, void *);
|
||||
extern char **ply_get_comments(PlyFile *, int *);
|
||||
extern char **ply_get_obj_info(PlyFile *, int *);
|
||||
extern void ply_close(PlyFile *);
|
||||
extern void ply_get_info(PlyFile *, float *, int *);
|
||||
extern PlyOtherElems *ply_get_other_element (PlyFile *, char *, int);
|
||||
extern void ply_describe_other_elements ( PlyFile *, PlyOtherElems *);
|
||||
extern void ply_put_other_elements (PlyFile *);
|
||||
extern void ply_free_other_elements (PlyOtherElems *);
|
||||
|
||||
extern int equal_strings(const char *, const char *);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !__PLY_H__ */
|
||||
|
||||
2686
src/osgPlugins/ply/plyfile.cpp
Normal file
2686
src/osgPlugins/ply/plyfile.cpp
Normal file
File diff suppressed because it is too large
Load Diff
112
src/osgPlugins/ply/typedefs.h
Normal file
112
src/osgPlugins/ply/typedefs.h
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
typedefs.h
|
||||
Copyright (c) 2007, Tobias Wolf <twolf@access.unizh.ch>
|
||||
All rights reserved.
|
||||
|
||||
Type definitions for the mesh classes.
|
||||
*/
|
||||
|
||||
/** note, derived from Equalizer LGPL source.*/
|
||||
|
||||
|
||||
#ifndef MESH_TYPEDEFS_H
|
||||
#define MESH_TYPEDEFS_H
|
||||
|
||||
# ifdef WIN32
|
||||
# include <Winsock2.h>
|
||||
# include <Windows.h>
|
||||
# endif
|
||||
|
||||
# include <osg/Notify>
|
||||
# include <cassert>
|
||||
# define MESHASSERT assert
|
||||
# define MESHERROR osg::notify(osg::WARN)
|
||||
# define MESHWARN osg::notify(osg::WARN)
|
||||
# define MESHINFO osg::notify(osg::INFO)
|
||||
|
||||
#ifdef WIN32
|
||||
typedef int socklen_t;
|
||||
|
||||
typedef UINT64 uint64_t;
|
||||
typedef INT64 int64_t;
|
||||
typedef UINT32 uint32_t;
|
||||
typedef INT32 int32_t;
|
||||
typedef UINT16 uint16_t;
|
||||
typedef UINT8 uint8_t;
|
||||
# ifndef HAVE_SSIZE_T
|
||||
typedef SSIZE_T ssize_t;
|
||||
# endif
|
||||
|
||||
#endif // Win32
|
||||
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
namespace ply
|
||||
{
|
||||
|
||||
|
||||
|
||||
typedef size_t Index;
|
||||
// typedef unsigned short ShortIndex;
|
||||
|
||||
|
||||
// mesh exception
|
||||
struct MeshException : public std::exception
|
||||
{
|
||||
explicit MeshException( const std::string& msg ) : _message( msg ) {}
|
||||
virtual ~MeshException() throw() {}
|
||||
virtual const char* what() const throw() { return _message.c_str(); }
|
||||
private:
|
||||
std::string _message;
|
||||
};
|
||||
|
||||
// null output stream that discards everything written to it
|
||||
struct NullOStream : std::ostream
|
||||
{
|
||||
struct NullStreamBuf : std::streambuf
|
||||
{
|
||||
int overflow( int c ) { return traits_type::not_eof( c ); }
|
||||
} _nullBuf;
|
||||
|
||||
NullOStream() : std::ios( &_nullBuf ), std::ostream( &_nullBuf ) {}
|
||||
};
|
||||
|
||||
// wrapper to enable array use where arrays would not be allowed otherwise
|
||||
template< class T, size_t d >
|
||||
struct ArrayWrapper
|
||||
{
|
||||
T& operator[]( const size_t i )
|
||||
{
|
||||
MESHASSERT( i < d );
|
||||
return data[i];
|
||||
}
|
||||
|
||||
const T& operator[]( const size_t i ) const
|
||||
{
|
||||
MESHASSERT( i < d );
|
||||
return data[i];
|
||||
}
|
||||
|
||||
private:
|
||||
T data[d];
|
||||
};
|
||||
|
||||
|
||||
// binary mesh file version, increment if changing the file format
|
||||
const unsigned short FILE_VERSION ( 0x0114 );
|
||||
|
||||
|
||||
// enumeration for the sort axis
|
||||
enum Axis
|
||||
{
|
||||
AXIS_X,
|
||||
AXIS_Y,
|
||||
AXIS_Z
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // MESH_TYPEDEFS_H
|
||||
373
src/osgPlugins/ply/vertexData.cpp
Normal file
373
src/osgPlugins/ply/vertexData.cpp
Normal file
@@ -0,0 +1,373 @@
|
||||
/*
|
||||
vertexData.cpp
|
||||
Copyright (c) 2007, Tobias Wolf <twolf@access.unizh.ch>
|
||||
All rights reserved.
|
||||
|
||||
Implementation of the VertexData class.
|
||||
*/
|
||||
|
||||
/** note, derived from Equalizer LGPL source.*/
|
||||
|
||||
#include "typedefs.h"
|
||||
|
||||
#include "vertexData.h"
|
||||
#include "ply.h"
|
||||
#include <cstdlib>
|
||||
#include <algorithm>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Geode>
|
||||
#include <osg/io_utils>
|
||||
|
||||
using namespace std;
|
||||
using namespace ply;
|
||||
|
||||
|
||||
struct Normal{
|
||||
osg::Vec3 triNormal;
|
||||
void normal(osg::Vec3 v1, osg::Vec3 v2, osg::Vec3 v3)
|
||||
{
|
||||
osg::Vec3 u,v;
|
||||
|
||||
// right hand system, CCW triangle
|
||||
u = v2 - v1;
|
||||
v = v3 - v1;
|
||||
triNormal = u^v;
|
||||
triNormal.normalize();
|
||||
}
|
||||
};
|
||||
|
||||
/* Contructor. */
|
||||
VertexData::VertexData()
|
||||
: _invertFaces( false )
|
||||
{
|
||||
// Initialize the members
|
||||
_vertices = NULL;
|
||||
_colors = NULL;
|
||||
_normals = NULL;
|
||||
_triangles = NULL;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Read the vertex and (if available/wanted) color data from the open file. */
|
||||
void VertexData::readVertices( PlyFile* file, const int nVertices,
|
||||
const bool readColors )
|
||||
{
|
||||
// temporary vertex structure for ply loading
|
||||
struct _Vertex
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
unsigned char r;
|
||||
unsigned char g;
|
||||
unsigned char b;
|
||||
} vertex;
|
||||
|
||||
PlyProperty vertexProps[] =
|
||||
{
|
||||
{ "x", PLY_FLOAT, PLY_FLOAT, offsetof( _Vertex, x ), 0, 0, 0, 0 },
|
||||
{ "y", PLY_FLOAT, PLY_FLOAT, offsetof( _Vertex, y ), 0, 0, 0, 0 },
|
||||
{ "z", PLY_FLOAT, PLY_FLOAT, offsetof( _Vertex, z ), 0, 0, 0, 0 },
|
||||
{ "red", PLY_UCHAR, PLY_UCHAR, offsetof( _Vertex, r ), 0, 0, 0, 0 },
|
||||
{ "green", PLY_UCHAR, PLY_UCHAR, offsetof( _Vertex, g ), 0, 0, 0, 0 },
|
||||
{ "blue", PLY_UCHAR, PLY_UCHAR, offsetof( _Vertex, b ), 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
// use all 6 properties when reading colors, only the first 3 otherwise
|
||||
int limit = readColors ? 6 : 3;
|
||||
for( int i = 0; i < limit; ++i )
|
||||
ply_get_property( file, "vertex", &vertexProps[i] );
|
||||
|
||||
// check whether array is valid otherwise allocate the space
|
||||
if(!_vertices.valid())
|
||||
_vertices = new osg::Vec3Array;
|
||||
|
||||
// If read colors allocate space for color array
|
||||
if( readColors )
|
||||
{
|
||||
if(!_colors.valid())
|
||||
_colors = new osg::Vec4Array;
|
||||
}
|
||||
|
||||
// read in the vertices
|
||||
for( int i = 0; i < nVertices; ++i )
|
||||
{
|
||||
ply_get_element( file, static_cast< void* >( &vertex ) );
|
||||
_vertices->push_back( osg::Vec3( vertex.x, vertex.y, vertex.z ) );
|
||||
if( readColors )
|
||||
_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 ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Read the index data from the open file. */
|
||||
void VertexData::readTriangles( PlyFile* file, const int nFaces )
|
||||
{
|
||||
// temporary face structure for ply loading
|
||||
struct _Face
|
||||
{
|
||||
unsigned char nVertices;
|
||||
int* vertices;
|
||||
} face;
|
||||
|
||||
PlyProperty faceProps[] =
|
||||
{
|
||||
{ "vertex_indices", PLY_INT, PLY_INT, offsetof( _Face, vertices ),
|
||||
1, PLY_UCHAR, PLY_UCHAR, offsetof( _Face, nVertices ) }
|
||||
};
|
||||
|
||||
ply_get_property( file, "face", &faceProps[0] );
|
||||
|
||||
//triangles.clear();
|
||||
//triangles.reserve( nFaces );
|
||||
if(!_triangles.valid())
|
||||
_triangles = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 0);
|
||||
|
||||
|
||||
// read in the faces, asserting that they are only triangles
|
||||
uint8_t ind1 = _invertFaces ? 2 : 0;
|
||||
uint8_t ind3 = _invertFaces ? 0 : 2;
|
||||
for( int i = 0; i < nFaces; ++i )
|
||||
{
|
||||
ply_get_element( file, static_cast< void* >( &face ) );
|
||||
MESHASSERT( face.vertices != 0 );
|
||||
if( (unsigned int)(face.nVertices) != 3 )
|
||||
{
|
||||
free( face.vertices );
|
||||
throw MeshException( "Error reading PLY file. Encountered a "
|
||||
"face which does not have three vertices." );
|
||||
}
|
||||
// Add the face indices in the premitive set
|
||||
_triangles->push_back( face.vertices[ind1]);
|
||||
_triangles->push_back( face.vertices[1]);
|
||||
_triangles->push_back( face.vertices[ind3] );
|
||||
|
||||
// free the memory that was allocated by ply_get_element
|
||||
free( face.vertices );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Open a PLY file and read vertex, color and index data. and returns the node */
|
||||
osg::Node* VertexData::readPlyFile( const char* filename, const bool ignoreColors )
|
||||
{
|
||||
int nPlyElems;
|
||||
char** elemNames;
|
||||
int fileType;
|
||||
float version;
|
||||
bool result = false;
|
||||
int nComments;
|
||||
char** comments;
|
||||
|
||||
PlyFile* file = ply_open_for_reading( const_cast< char* >( filename ),
|
||||
&nPlyElems, &elemNames,
|
||||
&fileType, &version );
|
||||
|
||||
if( !file )
|
||||
{
|
||||
MESHERROR << "Unable to open PLY file " << filename
|
||||
<< " for reading." << endl;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MESHASSERT( elemNames != 0 );
|
||||
|
||||
nComments = file->num_comments;
|
||||
comments = file->comments;
|
||||
|
||||
|
||||
#ifndef NDEBUG
|
||||
MESHINFO << filename << ": " << nPlyElems << " elements, file type = "
|
||||
<< fileType << ", version = " << version << endl;
|
||||
#endif
|
||||
|
||||
for( int i = 0; i < nComments; i++ )
|
||||
{
|
||||
if( equal_strings( comments[i], "modified by flipply" ) )
|
||||
{
|
||||
_invertFaces = true;
|
||||
}
|
||||
|
||||
}
|
||||
for( int i = 0; i < nPlyElems; ++i )
|
||||
{
|
||||
int nElems;
|
||||
int nProps;
|
||||
|
||||
PlyProperty** props = ply_get_element_description( file, elemNames[i],
|
||||
&nElems, &nProps );
|
||||
MESHASSERT( props != 0 );
|
||||
|
||||
#ifndef NDEBUG
|
||||
MESHINFO << "element " << i << ": name = " << elemNames[i] << ", "
|
||||
<< nProps << " properties, " << nElems << " elements" << endl;
|
||||
for( int j = 0; j < nProps; ++j )
|
||||
{
|
||||
MESHINFO << "element " << i << ", property " << j << ": "
|
||||
<< "name = " << props[j]->name << endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
// if the string is vertex means vertex data is started
|
||||
if( equal_strings( elemNames[i], "vertex" ) )
|
||||
{
|
||||
bool hasColors = false;
|
||||
// determine if the file stores vertex colors
|
||||
for( int j = 0; j < nProps; ++j )
|
||||
// if the string have the red means color info is there
|
||||
if( equal_strings( props[j]->name, "red" ) )
|
||||
hasColors = true;
|
||||
|
||||
if( ignoreColors )
|
||||
MESHINFO << "Colors in PLY file ignored per request." << endl;
|
||||
|
||||
// Read vertices and store in a std::vector array
|
||||
readVertices( file, nElems, hasColors && !ignoreColors );
|
||||
// Check whether all vertices are loaded or not
|
||||
MESHASSERT( _vertices->size() == static_cast< size_t >( nElems ) );
|
||||
// Check all color elements read or not
|
||||
if( hasColors && !ignoreColors )
|
||||
MESHASSERT( _colors->size() == static_cast< size_t >( nElems ) );
|
||||
}
|
||||
// If the string is face means triangle info started
|
||||
else if( equal_strings( elemNames[i], "face" ) )
|
||||
try
|
||||
{
|
||||
// Read Triangles
|
||||
readTriangles( file, nElems );
|
||||
// Check whether all face elements read or not
|
||||
MESHASSERT( _triangles->size()/3 == static_cast< size_t >( nElems ) );
|
||||
result = true;
|
||||
}
|
||||
catch( exception& e )
|
||||
{
|
||||
MESHERROR << "Unable to read PLY file, an exception occured: "
|
||||
<< e.what() << endl;
|
||||
// stop for loop by setting the loop variable to break condition
|
||||
// this way resources still get released even on error cases
|
||||
i = nPlyElems;
|
||||
}
|
||||
|
||||
// free the memory that was allocated by ply_get_element_description
|
||||
for( int j = 0; j < nProps; ++j )
|
||||
free( props[j] );
|
||||
free( props );
|
||||
}
|
||||
|
||||
ply_close( file );
|
||||
|
||||
// free the memory that was allocated by ply_open_for_reading
|
||||
for( int i = 0; i < nPlyElems; ++i )
|
||||
free( elemNames[i] );
|
||||
free( elemNames );
|
||||
|
||||
// If the result is true means the ply file is successfully read
|
||||
if(result)
|
||||
{
|
||||
// Create geometry node
|
||||
osg::Geometry* geom = new osg::Geometry;
|
||||
|
||||
// set the vertex array
|
||||
geom->setVertexArray(_vertices.get());
|
||||
|
||||
// If the normals are not calculated calculate the normals for faces
|
||||
if(!_normals.valid())
|
||||
_calculateNormals();
|
||||
|
||||
|
||||
// set the normals
|
||||
geom->setNormalArray(_normals.get());
|
||||
geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
|
||||
|
||||
// Add the premetive set
|
||||
geom->addPrimitiveSet(_triangles.get());
|
||||
|
||||
// if color info is given set the color array
|
||||
if(_colors.valid())
|
||||
{
|
||||
geom->setColorArray(_colors.get());
|
||||
geom->setColorBinding( osg::Geometry::BIND_PER_VERTEX );
|
||||
|
||||
}
|
||||
|
||||
|
||||
// set flage true to activate the vertex buffer object of drawable
|
||||
geom->setUseVertexBufferObjects(true);
|
||||
|
||||
|
||||
osg::Geode* geode = new osg::Geode;
|
||||
geode->addDrawable(geom);
|
||||
return geode;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Calculate the face or vertex normals of the current vertex data. */
|
||||
void VertexData::_calculateNormals( const bool vertexNormals )
|
||||
{
|
||||
|
||||
if(_normals.valid())
|
||||
return;
|
||||
|
||||
#ifndef NDEBUG
|
||||
int wrongNormals = 0;
|
||||
#endif
|
||||
|
||||
if(!_normals.valid())
|
||||
{
|
||||
_normals = new osg::Vec3Array;
|
||||
}
|
||||
|
||||
//normals.clear();
|
||||
if( vertexNormals )
|
||||
{
|
||||
// initialize all normals to zero
|
||||
for( size_t i = 0; i < _vertices->size(); ++i )
|
||||
{
|
||||
_normals->push_back( osg::Vec3( 0, 0, 0 ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for( size_t i = 0; i < ((_triangles->size())); i += 3 )
|
||||
{
|
||||
// iterate over all triangles and add their normals to adjacent vertices
|
||||
Normal triangleNormal;
|
||||
unsigned int i0, i1, i2;
|
||||
i0 = (*_triangles)[i+0];
|
||||
i1 = (*_triangles)[i+1];
|
||||
i2 = (*_triangles)[i+2];
|
||||
triangleNormal.normal((*_vertices)[i0],
|
||||
(*_vertices)[i1],
|
||||
(*_vertices)[i2] );
|
||||
|
||||
// count emtpy normals in debug mode
|
||||
#ifndef NDEBUG
|
||||
if( triangleNormal.triNormal.length() == 0.0f )
|
||||
++wrongNormals;
|
||||
#endif
|
||||
|
||||
if( vertexNormals )
|
||||
{
|
||||
(*_normals)[i0] += triangleNormal.triNormal;
|
||||
(*_normals)[i1] += triangleNormal.triNormal;
|
||||
(*_normals)[i2] += triangleNormal.triNormal;
|
||||
}
|
||||
else
|
||||
_normals->push_back( triangleNormal.triNormal );
|
||||
}
|
||||
|
||||
// normalize all the normals
|
||||
if( vertexNormals )
|
||||
for( size_t i = 0; i < _normals->size(); ++i )
|
||||
(*_normals)[i].normalize();
|
||||
|
||||
#ifndef NDEBUG
|
||||
if( wrongNormals > 0 )
|
||||
MESHINFO << wrongNormals << " faces had no valid normal." << endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
74
src/osgPlugins/ply/vertexData.h
Normal file
74
src/osgPlugins/ply/vertexData.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
vertexData.h
|
||||
Copyright (c) 2007, Tobias Wolf <twolf@access.unizh.ch>
|
||||
All rights reserved.
|
||||
|
||||
Header file of the VertexData class.
|
||||
*/
|
||||
|
||||
/** note, derived from Equalizer LGPL source.*/
|
||||
|
||||
|
||||
#ifndef MESH_VERTEXDATA_H
|
||||
#define MESH_VERTEXDATA_H
|
||||
|
||||
|
||||
#include <osg/Node>
|
||||
#include <osg/PrimitiveSet>
|
||||
|
||||
#include <vector>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//!
|
||||
//! \class VertexData
|
||||
//! \brief helps to read ply file and converts in to osg::Node format
|
||||
//!
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// defined elsewhere
|
||||
class PlyFile;
|
||||
|
||||
namespace ply
|
||||
{
|
||||
/* Holds the flat data and offers routines to read, scale and sort it. */
|
||||
class VertexData
|
||||
{
|
||||
public:
|
||||
// Default constructor
|
||||
VertexData();
|
||||
|
||||
// Reads ply file and convert in to osg::Node and returns the same
|
||||
osg::Node* readPlyFile( const char* file, const bool ignoreColors = false );
|
||||
|
||||
// to set the flag for using inverted face
|
||||
void useInvertedFaces() { _invertFaces = true; }
|
||||
|
||||
private:
|
||||
// Function which reads all the vertices and colors if color info is
|
||||
// given and also if the user wants that information
|
||||
void readVertices( PlyFile* file, const int nVertices,
|
||||
const bool readColors );
|
||||
|
||||
// Reads the triangle indices from the ply file
|
||||
void readTriangles( PlyFile* file, const int nFaces );
|
||||
|
||||
// Calculates the normals according to passed flag
|
||||
// if vertexNormals is true then computes normal per vertices
|
||||
// otherwise per triangle means per face
|
||||
void _calculateNormals( const bool vertexNormals = true );
|
||||
|
||||
bool _invertFaces;
|
||||
|
||||
// Vertex array in osg format
|
||||
osg::ref_ptr<osg::Vec3Array> _vertices;
|
||||
// Color array in osg format
|
||||
osg::ref_ptr<osg::Vec4Array> _colors;
|
||||
// Normals in osg format
|
||||
osg::ref_ptr<osg::Vec3Array> _normals;
|
||||
// The indices of the faces in premitive set
|
||||
osg::ref_ptr<osg::DrawElementsUInt> _triangles;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif // MESH_VERTEXDATA_H
|
||||
Reference in New Issue
Block a user