Extension to the PLY plugin to read files with textures.
This commit is contained in:
parent
e5cccefafe
commit
edee9d0946
@ -18,6 +18,10 @@
|
|||||||
#include <osg/Geode>
|
#include <osg/Geode>
|
||||||
#include <osg/io_utils>
|
#include <osg/io_utils>
|
||||||
#include <osgUtil/SmoothingVisitor>
|
#include <osgUtil/SmoothingVisitor>
|
||||||
|
#include <osg/TexEnv>
|
||||||
|
#include <osgDB/ReaderWriter>
|
||||||
|
#include <osgDB/ReadFile>
|
||||||
|
#include <osg/Texture2D>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace ply;
|
using namespace ply;
|
||||||
@ -35,6 +39,7 @@ VertexData::VertexData()
|
|||||||
_diffuse = NULL;
|
_diffuse = NULL;
|
||||||
_ambient = NULL;
|
_ambient = NULL;
|
||||||
_specular = NULL;
|
_specular = NULL;
|
||||||
|
_texcoord = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -66,6 +71,8 @@ void VertexData::readVertices( PlyFile* file, const int nVertices,
|
|||||||
unsigned char specular_blue;
|
unsigned char specular_blue;
|
||||||
float specular_coeff;
|
float specular_coeff;
|
||||||
float specular_power;
|
float specular_power;
|
||||||
|
float texture_u;
|
||||||
|
float texture_v;
|
||||||
} vertex;
|
} vertex;
|
||||||
|
|
||||||
PlyProperty vertexProps[] =
|
PlyProperty vertexProps[] =
|
||||||
@ -74,8 +81,8 @@ void VertexData::readVertices( PlyFile* file, const int nVertices,
|
|||||||
{ "y", PLY_FLOAT, PLY_FLOAT, offsetof( _Vertex, y ), 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 },
|
{ "z", PLY_FLOAT, PLY_FLOAT, offsetof( _Vertex, z ), 0, 0, 0, 0 },
|
||||||
{ "nx", PLY_FLOAT, PLY_FLOAT, offsetof( _Vertex, nx ), 0, 0, 0, 0 },
|
{ "nx", PLY_FLOAT, PLY_FLOAT, offsetof( _Vertex, nx ), 0, 0, 0, 0 },
|
||||||
{ "ny", PLY_FLOAT, PLY_FLOAT, offsetof( _Vertex, ny ), 0, 0, 0, 0 },
|
{ "ny", PLY_FLOAT, PLY_FLOAT, offsetof(_Vertex, ny), 0, 0, 0, 0 },
|
||||||
{ "nz", PLY_FLOAT, PLY_FLOAT, offsetof( _Vertex, nz ), 0, 0, 0, 0 },
|
{ "nz", PLY_FLOAT, PLY_FLOAT, offsetof(_Vertex, nz), 0, 0, 0, 0 },
|
||||||
{ "red", PLY_UCHAR, PLY_UCHAR, offsetof( _Vertex, red ), 0, 0, 0, 0 },
|
{ "red", PLY_UCHAR, PLY_UCHAR, offsetof( _Vertex, red ), 0, 0, 0, 0 },
|
||||||
{ "green", PLY_UCHAR, PLY_UCHAR, offsetof( _Vertex, green ), 0, 0, 0, 0 },
|
{ "green", PLY_UCHAR, PLY_UCHAR, offsetof( _Vertex, green ), 0, 0, 0, 0 },
|
||||||
{ "blue", PLY_UCHAR, PLY_UCHAR, offsetof( _Vertex, blue ), 0, 0, 0, 0 },
|
{ "blue", PLY_UCHAR, PLY_UCHAR, offsetof( _Vertex, blue ), 0, 0, 0, 0 },
|
||||||
@ -91,6 +98,8 @@ void VertexData::readVertices( PlyFile* file, const int nVertices,
|
|||||||
{ "specular_blue", PLY_UCHAR, PLY_UCHAR, offsetof( _Vertex, specular_blue ), 0, 0, 0, 0 },
|
{ "specular_blue", PLY_UCHAR, PLY_UCHAR, offsetof( _Vertex, specular_blue ), 0, 0, 0, 0 },
|
||||||
{ "specular_coeff", PLY_FLOAT, PLY_FLOAT, offsetof( _Vertex, specular_coeff ), 0, 0, 0, 0 },
|
{ "specular_coeff", PLY_FLOAT, PLY_FLOAT, offsetof( _Vertex, specular_coeff ), 0, 0, 0, 0 },
|
||||||
{ "specular_power", PLY_FLOAT, PLY_FLOAT, offsetof( _Vertex, specular_power ), 0, 0, 0, 0 },
|
{ "specular_power", PLY_FLOAT, PLY_FLOAT, offsetof( _Vertex, specular_power ), 0, 0, 0, 0 },
|
||||||
|
{ "texture_u", PLY_FLOAT, PLY_FLOAT, offsetof(_Vertex, texture_u), 0, 0, 0, 0 },
|
||||||
|
{ "texture_v", PLY_FLOAT, PLY_FLOAT, offsetof(_Vertex, texture_v), 0, 0, 0, 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
// use all 6 properties when reading colors, only the first 3 otherwise
|
// use all 6 properties when reading colors, only the first 3 otherwise
|
||||||
@ -120,6 +129,10 @@ void VertexData::readVertices( PlyFile* file, const int nVertices,
|
|||||||
for( int i = 16; i < 21; ++i )
|
for( int i = 16; i < 21; ++i )
|
||||||
ply_get_property( file, "vertex", &vertexProps[i] );
|
ply_get_property( file, "vertex", &vertexProps[i] );
|
||||||
|
|
||||||
|
if (fields & TEXCOORD)
|
||||||
|
for (int i = 21; i < 23; ++i)
|
||||||
|
ply_get_property(file, "vertex", &vertexProps[i]);
|
||||||
|
|
||||||
// check whether array is valid otherwise allocate the space
|
// check whether array is valid otherwise allocate the space
|
||||||
if(!_vertices.valid())
|
if(!_vertices.valid())
|
||||||
_vertices = new osg::Vec3Array;
|
_vertices = new osg::Vec3Array;
|
||||||
@ -154,6 +167,11 @@ void VertexData::readVertices( PlyFile* file, const int nVertices,
|
|||||||
if(!_specular.valid())
|
if(!_specular.valid())
|
||||||
_specular = new osg::Vec4Array;
|
_specular = new osg::Vec4Array;
|
||||||
}
|
}
|
||||||
|
if (fields & TEXCOORD)
|
||||||
|
{
|
||||||
|
if (!_texcoord.valid())
|
||||||
|
_texcoord = new osg::Vec2Array;
|
||||||
|
}
|
||||||
|
|
||||||
// read in the vertices
|
// read in the vertices
|
||||||
for( int i = 0; i < nVertices; ++i )
|
for( int i = 0; i < nVertices; ++i )
|
||||||
@ -186,6 +204,8 @@ void VertexData::readVertices( PlyFile* file, const int nVertices,
|
|||||||
_specular->push_back( osg::Vec4( (unsigned int) vertex.specular_red / 255.0,
|
_specular->push_back( osg::Vec4( (unsigned int) vertex.specular_red / 255.0,
|
||||||
(unsigned int) vertex.specular_green / 255.0 ,
|
(unsigned int) vertex.specular_green / 255.0 ,
|
||||||
(unsigned int) vertex.specular_blue / 255.0, 1.0 ) );
|
(unsigned int) vertex.specular_blue / 255.0, 1.0 ) );
|
||||||
|
if (fields & TEXCOORD)
|
||||||
|
_texcoord->push_back(osg::Vec2(vertex.texture_u,vertex.texture_v));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,38 +228,41 @@ void VertexData::readTriangles( PlyFile* file, const int nFaces )
|
|||||||
|
|
||||||
ply_get_property( file, "face", &faceProps[0] );
|
ply_get_property( file, "face", &faceProps[0] );
|
||||||
|
|
||||||
//triangles.clear();
|
|
||||||
//triangles.reserve( nFaces );
|
|
||||||
if(!_triangles.valid())
|
if(!_triangles.valid())
|
||||||
_triangles = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 0);
|
_triangles = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES);
|
||||||
if(!_quads.valid())
|
|
||||||
_quads = new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0);
|
|
||||||
|
|
||||||
|
if(!_quads.valid())
|
||||||
|
_quads = new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS);
|
||||||
|
|
||||||
|
|
||||||
|
const char NUM_VERTICES_TRIANGLE(3);
|
||||||
|
const char NUM_VERTICES_QUAD(4);
|
||||||
|
|
||||||
// read the faces, reversing the reading direction if _invertFaces is true
|
// read the faces, reversing the reading direction if _invertFaces is true
|
||||||
for( int i = 0 ; i < nFaces; i++ )
|
for( int i = 0 ; i < nFaces; i++ )
|
||||||
{
|
{
|
||||||
|
// initialize face values
|
||||||
|
face.nVertices = 0;
|
||||||
|
face.vertices = 0;
|
||||||
|
|
||||||
ply_get_element( file, static_cast< void* >( &face ) );
|
ply_get_element( file, static_cast< void* >( &face ) );
|
||||||
MESHASSERT( face.vertices != 0 );
|
if (face.vertices)
|
||||||
if( (unsigned int)(face.nVertices) > 4 )
|
|
||||||
{
|
{
|
||||||
|
if (face.nVertices == NUM_VERTICES_TRIANGLE || face.nVertices == NUM_VERTICES_QUAD)
|
||||||
|
{
|
||||||
|
unsigned short index;
|
||||||
|
for(int j = 0 ; j < face.nVertices ; j++)
|
||||||
|
{
|
||||||
|
index = ( _invertFaces ? face.nVertices - 1 - j : j );
|
||||||
|
if(face.nVertices == 4)
|
||||||
|
_quads->push_back(face.vertices[index]);
|
||||||
|
else
|
||||||
|
_triangles->push_back(face.vertices[index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// free the memory that was allocated by ply_get_element
|
||||||
free( face.vertices );
|
free( face.vertices );
|
||||||
throw MeshException( "Error reading PLY file. Encountered a "
|
|
||||||
"face which does not have three or four vertices." );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned short index;
|
|
||||||
for(int j = 0 ; j < face.nVertices ; j++)
|
|
||||||
{
|
|
||||||
index = ( _invertFaces ? face.nVertices - 1 - j : j );
|
|
||||||
if(face.nVertices == 4)
|
|
||||||
_quads->push_back(face.vertices[index]);
|
|
||||||
else
|
|
||||||
_triangles->push_back(face.vertices[index]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// free the memory that was allocated by ply_get_element
|
|
||||||
free( face.vertices );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -288,13 +311,47 @@ osg::Node* VertexData::readPlyFile( const char* filename, const bool ignoreColor
|
|||||||
MESHINFO << filename << ": " << nPlyElems << " elements, file type = "
|
MESHINFO << filename << ": " << nPlyElems << " elements, file type = "
|
||||||
<< fileType << ", version = " << version << endl;
|
<< fileType << ", version = " << version << endl;
|
||||||
#endif
|
#endif
|
||||||
|
char *textureFile = NULL;
|
||||||
for( int i = 0; i < nComments; i++ )
|
for( int i = 0; i < nComments; i++ )
|
||||||
{
|
{
|
||||||
if( equal_strings( comments[i], "modified by flipply" ) )
|
if( equal_strings( comments[i], "modified by flipply" ) )
|
||||||
{
|
{
|
||||||
_invertFaces = true;
|
_invertFaces = true;
|
||||||
}
|
}
|
||||||
|
if (strncmp(comments[i], "TextureFile",11)==0)
|
||||||
|
{
|
||||||
|
textureFile = comments[i]+12;
|
||||||
|
char * path = new char[strlen(const_cast<char*>(filename)) + 1 + strlen(comments[i])];
|
||||||
|
if (textureFile[0] == '\\' || textureFile[0] == '/' || textureFile[1] == ':')
|
||||||
|
{
|
||||||
|
// texture filename is absolute
|
||||||
|
strcpy(path, textureFile);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// texture filename is relative
|
||||||
|
// add directory of ply file
|
||||||
|
strcpy(path, const_cast<char*>(filename));
|
||||||
|
char *pp = path + strlen(path);
|
||||||
|
while (pp >= path)
|
||||||
|
{
|
||||||
|
if (*pp == '\\' || *pp == '/')
|
||||||
|
{
|
||||||
|
pp++;
|
||||||
|
*pp = '\0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pp--;
|
||||||
|
}
|
||||||
|
if (pp == path - 1)
|
||||||
|
{
|
||||||
|
pp++;
|
||||||
|
*pp = '\0';
|
||||||
|
}
|
||||||
|
strcat(path, textureFile);
|
||||||
|
}
|
||||||
|
textureFile = path;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
for( int i = 0; i < nPlyElems; ++i )
|
for( int i = 0; i < nPlyElems; ++i )
|
||||||
@ -327,10 +384,10 @@ osg::Node* VertexData::readPlyFile( const char* filename, const bool ignoreColor
|
|||||||
// if the string is vertex means vertex data is started
|
// if the string is vertex means vertex data is started
|
||||||
if( equal_strings( elemNames[i], "vertex" ) )
|
if( equal_strings( elemNames[i], "vertex" ) )
|
||||||
{
|
{
|
||||||
int fields = NONE;
|
int fields = NONE;
|
||||||
// determine if the file stores vertex colors
|
// determine if the file stores vertex colors
|
||||||
for( int j = 0; j < nProps; ++j )
|
for( int j = 0; j < nProps; ++j )
|
||||||
{
|
{
|
||||||
// if the string have the red means color info is there
|
// if the string have the red means color info is there
|
||||||
if( equal_strings( props[j]->name, "x" ) )
|
if( equal_strings( props[j]->name, "x" ) )
|
||||||
fields |= XYZ;
|
fields |= XYZ;
|
||||||
@ -344,15 +401,19 @@ osg::Node* VertexData::readPlyFile( const char* filename, const bool ignoreColor
|
|||||||
fields |= AMBIENT;
|
fields |= AMBIENT;
|
||||||
if( equal_strings( props[j]->name, "diffuse_red" ) )
|
if( equal_strings( props[j]->name, "diffuse_red" ) )
|
||||||
fields |= DIFFUSE;
|
fields |= DIFFUSE;
|
||||||
if( equal_strings( props[j]->name, "specular_red" ) )
|
if (equal_strings(props[j]->name, "specular_red"))
|
||||||
fields |= SPECULAR;
|
fields |= SPECULAR;
|
||||||
}
|
if (equal_strings(props[j]->name, "texture_u"))
|
||||||
|
fields |= TEXCOORD;
|
||||||
|
if (equal_strings(props[j]->name, "texture_v"))
|
||||||
|
fields |= TEXCOORD;
|
||||||
|
}
|
||||||
|
|
||||||
if( ignoreColors )
|
if( ignoreColors )
|
||||||
{
|
{
|
||||||
fields &= ~(XYZ | NORMALS);
|
fields &= ~(XYZ | NORMALS);
|
||||||
MESHINFO << "Colors in PLY file ignored per request." << endl;
|
MESHINFO << "Colors in PLY file ignored per request." << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Read vertices and store in a std::vector array
|
// Read vertices and store in a std::vector array
|
||||||
@ -360,7 +421,7 @@ osg::Node* VertexData::readPlyFile( const char* filename, const bool ignoreColor
|
|||||||
// Check whether all vertices are loaded or not
|
// Check whether all vertices are loaded or not
|
||||||
MESHASSERT( _vertices->size() == static_cast< size_t >( nElems ) );
|
MESHASSERT( _vertices->size() == static_cast< size_t >( nElems ) );
|
||||||
|
|
||||||
// Check if all the optional elements were read or not
|
// Check if all the optional elements were read or not
|
||||||
if( fields & NORMALS )
|
if( fields & NORMALS )
|
||||||
{
|
{
|
||||||
MESHASSERT( _normals->size() == static_cast< size_t >( nElems ) );
|
MESHASSERT( _normals->size() == static_cast< size_t >( nElems ) );
|
||||||
@ -377,9 +438,13 @@ osg::Node* VertexData::readPlyFile( const char* filename, const bool ignoreColor
|
|||||||
{
|
{
|
||||||
MESHASSERT( _diffuse->size() == static_cast< size_t >( nElems ) );
|
MESHASSERT( _diffuse->size() == static_cast< size_t >( nElems ) );
|
||||||
}
|
}
|
||||||
if( fields & SPECULAR )
|
if (fields & SPECULAR)
|
||||||
{
|
{
|
||||||
MESHASSERT( _specular->size() == static_cast< size_t >( nElems ) );
|
MESHASSERT(_specular->size() == static_cast< size_t >(nElems));
|
||||||
|
}
|
||||||
|
if (fields & TEXCOORD)
|
||||||
|
{
|
||||||
|
MESHASSERT(_texcoord->size() == static_cast< size_t >(nElems));
|
||||||
}
|
}
|
||||||
|
|
||||||
result = true;
|
result = true;
|
||||||
@ -459,9 +524,9 @@ osg::Node* VertexData::readPlyFile( const char* filename, const bool ignoreColor
|
|||||||
geom->addPrimitiveSet(new osg::DrawArrays(GL_POINTS, 0, _vertices->size()));
|
geom->addPrimitiveSet(new osg::DrawArrays(GL_POINTS, 0, _vertices->size()));
|
||||||
|
|
||||||
|
|
||||||
// Apply the colours to the model; at the moment this is a
|
// Apply the colours to the model; at the moment this is a
|
||||||
// kludge because we only use one kind and apply them all the
|
// kludge because we only use one kind and apply them all the
|
||||||
// same way. Also, the priority order is completely arbitrary
|
// same way. Also, the priority order is completely arbitrary
|
||||||
|
|
||||||
if(_colors.valid())
|
if(_colors.valid())
|
||||||
{
|
{
|
||||||
@ -475,10 +540,14 @@ osg::Node* VertexData::readPlyFile( const char* filename, const bool ignoreColor
|
|||||||
{
|
{
|
||||||
geom->setColorArray(_diffuse.get(), osg::Array::BIND_PER_VERTEX );
|
geom->setColorArray(_diffuse.get(), osg::Array::BIND_PER_VERTEX );
|
||||||
}
|
}
|
||||||
else if(_specular.valid())
|
else if(_specular.valid())
|
||||||
{
|
{
|
||||||
geom->setColorArray(_specular.get(), osg::Array::BIND_PER_VERTEX );
|
geom->setColorArray(_specular.get(), osg::Array::BIND_PER_VERTEX );
|
||||||
}
|
}
|
||||||
|
else if (_texcoord.valid())
|
||||||
|
{
|
||||||
|
geom->setTexCoordArray(0, _texcoord);
|
||||||
|
}
|
||||||
|
|
||||||
// If the model has normals, add them to the geometry
|
// If the model has normals, add them to the geometry
|
||||||
if(_normals.valid())
|
if(_normals.valid())
|
||||||
@ -494,11 +563,26 @@ osg::Node* VertexData::readPlyFile( const char* filename, const bool ignoreColor
|
|||||||
// set flage true to activate the vertex buffer object of drawable
|
// set flage true to activate the vertex buffer object of drawable
|
||||||
geom->setUseVertexBufferObjects(true);
|
geom->setUseVertexBufferObjects(true);
|
||||||
|
|
||||||
|
osg::Image *image = NULL;
|
||||||
|
if (textureFile && (image = osgDB::readImageFile(textureFile)) != NULL)
|
||||||
|
{
|
||||||
|
osg::Texture2D *texture = new osg::Texture2D;
|
||||||
|
texture->setImage(image);
|
||||||
|
texture->setResizeNonPowerOfTwoHint(false);
|
||||||
|
|
||||||
|
osg::TexEnv *texenv = new osg::TexEnv;
|
||||||
|
texenv->setMode(osg::TexEnv::REPLACE);
|
||||||
|
|
||||||
|
osg::StateSet *stateset = geom->getOrCreateStateSet();
|
||||||
|
stateset->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
|
||||||
|
stateset->setTextureAttribute(0, texenv);
|
||||||
|
delete[] textureFile;
|
||||||
|
}
|
||||||
|
|
||||||
osg::Geode* geode = new osg::Geode;
|
osg::Geode* geode = new osg::Geode;
|
||||||
geode->addDrawable(geom);
|
geode->addDrawable(geom);
|
||||||
return geode;
|
return geode;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,8 @@ namespace ply
|
|||||||
AMBIENT = 8,
|
AMBIENT = 8,
|
||||||
DIFFUSE = 16,
|
DIFFUSE = 16,
|
||||||
SPECULAR = 32,
|
SPECULAR = 32,
|
||||||
RGBA = 64
|
RGBA = 64,
|
||||||
|
TEXCOORD = 128
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function which reads all the vertices and colors if color info is
|
// Function which reads all the vertices and colors if color info is
|
||||||
@ -75,6 +76,7 @@ namespace ply
|
|||||||
osg::ref_ptr<osg::Vec4Array> _ambient;
|
osg::ref_ptr<osg::Vec4Array> _ambient;
|
||||||
osg::ref_ptr<osg::Vec4Array> _diffuse;
|
osg::ref_ptr<osg::Vec4Array> _diffuse;
|
||||||
osg::ref_ptr<osg::Vec4Array> _specular;
|
osg::ref_ptr<osg::Vec4Array> _specular;
|
||||||
|
osg::ref_ptr<osg::Vec2Array> _texcoord;
|
||||||
|
|
||||||
// Normals in osg format
|
// Normals in osg format
|
||||||
osg::ref_ptr<osg::Vec3Array> _normals;
|
osg::ref_ptr<osg::Vec3Array> _normals;
|
||||||
|
Loading…
Reference in New Issue
Block a user