Extension to the PLY plugin to read files with textures.

This commit is contained in:
Uwe Woessner 2017-08-15 15:42:22 +01:00 committed by Robert Osfield
parent e5cccefafe
commit edee9d0946
2 changed files with 128 additions and 42 deletions

View File

@ -18,6 +18,10 @@
#include <osg/Geode>
#include <osg/io_utils>
#include <osgUtil/SmoothingVisitor>
#include <osg/TexEnv>
#include <osgDB/ReaderWriter>
#include <osgDB/ReadFile>
#include <osg/Texture2D>
using namespace std;
using namespace ply;
@ -35,6 +39,7 @@ VertexData::VertexData()
_diffuse = NULL;
_ambient = NULL;
_specular = NULL;
_texcoord = NULL;
}
@ -66,6 +71,8 @@ void VertexData::readVertices( PlyFile* file, const int nVertices,
unsigned char specular_blue;
float specular_coeff;
float specular_power;
float texture_u;
float texture_v;
} vertex;
PlyProperty vertexProps[] =
@ -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_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 },
{ "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
@ -120,6 +129,10 @@ void VertexData::readVertices( PlyFile* file, const int nVertices,
for( int i = 16; i < 21; ++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
if(!_vertices.valid())
_vertices = new osg::Vec3Array;
@ -154,6 +167,11 @@ void VertexData::readVertices( PlyFile* file, const int nVertices,
if(!_specular.valid())
_specular = new osg::Vec4Array;
}
if (fields & TEXCOORD)
{
if (!_texcoord.valid())
_texcoord = new osg::Vec2Array;
}
// read in the vertices
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,
(unsigned int) vertex.specular_green / 255.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,26 +228,28 @@ void VertexData::readTriangles( PlyFile* file, const int nFaces )
ply_get_property( file, "face", &faceProps[0] );
//triangles.clear();
//triangles.reserve( nFaces );
if(!_triangles.valid())
_triangles = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 0);
if(!_quads.valid())
_quads = new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0);
_triangles = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES);
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
for( int i = 0 ; i < nFaces; i++ )
{
ply_get_element( file, static_cast< void* >( &face ) );
MESHASSERT( face.vertices != 0 );
if( (unsigned int)(face.nVertices) > 4 )
{
free( face.vertices );
throw MeshException( "Error reading PLY file. Encountered a "
"face which does not have three or four vertices." );
}
// initialize face values
face.nVertices = 0;
face.vertices = 0;
ply_get_element( file, static_cast< void* >( &face ) );
if (face.vertices)
{
if (face.nVertices == NUM_VERTICES_TRIANGLE || face.nVertices == NUM_VERTICES_QUAD)
{
unsigned short index;
for(int j = 0 ; j < face.nVertices ; j++)
{
@ -237,11 +259,12 @@ void VertexData::readTriangles( PlyFile* file, const int nFaces )
else
_triangles->push_back(face.vertices[index]);
}
}
// 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 */
@ -288,13 +311,47 @@ osg::Node* VertexData::readPlyFile( const char* filename, const bool ignoreColor
MESHINFO << filename << ": " << nPlyElems << " elements, file type = "
<< fileType << ", version = " << version << endl;
#endif
char *textureFile = NULL;
for( int i = 0; i < nComments; i++ )
{
if( equal_strings( comments[i], "modified by flipply" ) )
{
_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 )
@ -346,6 +403,10 @@ osg::Node* VertexData::readPlyFile( const char* filename, const bool ignoreColor
fields |= DIFFUSE;
if (equal_strings(props[j]->name, "specular_red"))
fields |= SPECULAR;
if (equal_strings(props[j]->name, "texture_u"))
fields |= TEXCOORD;
if (equal_strings(props[j]->name, "texture_v"))
fields |= TEXCOORD;
}
if( ignoreColors )
@ -381,6 +442,10 @@ osg::Node* VertexData::readPlyFile( const char* filename, const bool ignoreColor
{
MESHASSERT(_specular->size() == static_cast< size_t >(nElems));
}
if (fields & TEXCOORD)
{
MESHASSERT(_texcoord->size() == static_cast< size_t >(nElems));
}
result = true;
}
@ -479,6 +544,10 @@ osg::Node* VertexData::readPlyFile( const char* filename, const bool ignoreColor
{
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(_normals.valid())
@ -494,6 +563,21 @@ osg::Node* VertexData::readPlyFile( const char* filename, const bool ignoreColor
// set flage true to activate the vertex buffer object of drawable
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;
geode->addDrawable(geom);

View File

@ -55,7 +55,8 @@ namespace ply
AMBIENT = 8,
DIFFUSE = 16,
SPECULAR = 32,
RGBA = 64
RGBA = 64,
TEXCOORD = 128
};
// 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> _diffuse;
osg::ref_ptr<osg::Vec4Array> _specular;
osg::ref_ptr<osg::Vec2Array> _texcoord;
// Normals in osg format
osg::ref_ptr<osg::Vec3Array> _normals;