2004-11-17 11:13:48 +01:00
/****************************************************************************
* VCGLib o o *
* Visual and Computer Graphics Library o o *
* _ O _ *
* Copyright ( C ) 2004 \ / ) \ / *
* Visual Computing Lab / \ / | *
* ISTI - Italian National Research Council | *
* \ *
* All rights reserved . *
* *
* This program is free software ; you can redistribute it and / or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation ; either version 2 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 General Public License ( http : //www.gnu.org/licenses/gpl.txt) *
* for more details . *
* *
2004-11-23 12:56:50 +01:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-11-17 11:13:48 +01:00
# ifndef __VCGLIB_IMPORT_OFF
# define __VCGLIB_IMPORT_OFF
# include <fstream>
2011-04-03 22:55:22 +02:00
# include <vcg/complex/algorithms/bitquad_support.h>
2008-03-13 09:48:10 +01:00
# include <wrap/callback.h>
# include <wrap/io_trimesh/io_mask.h>
2004-11-17 11:13:48 +01:00
namespace vcg
{
namespace tri
{
namespace io
{
// /** \addtogroup */
// /* @{ */
2004-11-18 16:13:03 +01:00
/**
This class encapsulate a filter for importing OFF meshes .
A basic description of the OFF file format can be found at http : //www.geomview.org/docs/html/geomview_41.html
*/
2004-11-17 11:13:48 +01:00
template < class MESH_TYPE >
class ImporterOFF
{
public :
2006-02-09 16:15:56 +01:00
2004-11-17 11:13:48 +01:00
typedef typename MESH_TYPE : : VertexType VertexType ;
typedef typename MESH_TYPE : : VertexIterator VertexIterator ;
typedef typename MESH_TYPE : : VertexPointer VertexPointer ;
typedef typename MESH_TYPE : : FaceType FaceType ;
typedef typename MESH_TYPE : : FaceIterator FaceIterator ;
typedef typename MESH_TYPE : : FacePointer FacePointer ;
typedef typename MESH_TYPE : : CoordType CoordType ;
typedef typename MESH_TYPE : : ScalarType ScalarType ;
2006-02-09 16:15:56 +01:00
// OFF codes
enum OFFCodes { NoError = 0 , CantOpen , InvalidFile ,
2008-10-16 16:32:37 +02:00
InvalidFile_MissingOFF ,
2010-04-19 14:20:56 +02:00
UnsupportedFormat , ErrorNotTriangularFace , ErrorHighDimension , ErrorDegenerateFace } ;
2006-02-09 16:15:56 +01:00
2004-11-17 11:13:48 +01:00
/*!
* Standard call for knowing the meaning of an error code
* \ param message_code The code returned by < CODE > Open < / CODE >
2006-02-06 14:11:01 +01:00
* \ return The string describing the error code
2004-11-17 11:13:48 +01:00
*/
static const char * ErrorMsg ( int message_code )
{
2006-02-06 14:11:01 +01:00
static const char * error_msg [ ] =
2004-11-17 11:13:48 +01:00
{
2006-02-06 14:11:01 +01:00
" No errors " , " Can't open file " , " Invalid file " ,
2008-10-16 16:32:37 +02:00
" Invalid file: OFF file should have in the first line the OFF keyword as a first token " ,
2010-04-19 14:20:56 +02:00
" Unsupported format " , " Face with more than 3 vertices " , " File with high dimensional vertexes are not supported " , " Error Degenerate Face with less than 3 vertices " } ;
2004-11-17 11:13:48 +01:00
2010-04-19 14:20:56 +02:00
if ( message_code > 6 | | message_code < 0 )
2004-11-17 11:13:48 +01:00
return " Unknown error " ;
2006-02-06 14:11:01 +01:00
else
2004-11-17 11:13:48 +01:00
return error_msg [ message_code ] ;
} ;
2006-03-29 10:15:46 +02:00
/**
* Load only the properties of the 3 D objects .
*
* \ param filename the name of the file to read from
* \ param loadmask the mask which encodes the properties
* \ return the operation result
*/
static bool LoadMask ( const char * filename , int & loadmask )
{
// To obtain the loading mask all the file must be parsed
// to distinguish between per-vertex and per-face color attribute.
2008-04-15 12:38:12 +02:00
loadmask = 0 ;
2006-03-29 10:15:46 +02:00
MESH_TYPE dummyMesh ;
2010-12-21 16:04:14 +01:00
return ( Open ( dummyMesh , filename , loadmask ) = = NoError ) ;
2006-03-29 10:15:46 +02:00
}
2008-03-13 09:48:10 +01:00
static int Open ( MESH_TYPE & mesh , const char * filename , CallBackPos * cb = 0 )
2006-03-29 10:15:46 +02:00
{
int loadmask ;
return Open ( mesh , filename , loadmask , cb ) ;
}
2006-01-10 14:20:42 +01:00
2004-11-17 11:13:48 +01:00
/*!
2006-03-29 10:15:46 +02:00
* Standard call for reading a mesh .
*
* \ param mesh the destination mesh
* \ param filename the name of the file to read from
* \ return the operation result
*/
2006-02-09 16:15:56 +01:00
static int Open ( MESH_TYPE & mesh , const char * filename , int & loadmask ,
2010-12-21 16:04:14 +01:00
CallBackPos * cb = 0 )
2004-11-17 11:13:48 +01:00
{
std : : ifstream stream ( filename ) ;
if ( stream . fail ( ) )
2005-01-26 23:44:51 +01:00
return CantOpen ;
2004-11-17 11:13:48 +01:00
std : : vector < std : : string > tokens ;
TokenizeNextLine ( stream , tokens ) ;
2006-02-09 16:15:56 +01:00
2006-03-29 10:15:46 +02:00
bool isNormalDefined = false ;
bool isColorDefined = false ;
bool isTexCoordDefined = false ;
int dimension = 3 ;
bool homogeneousComponents = false ;
2008-10-16 16:32:37 +02:00
/*
[ ST ] [ C ] [ N ] [ 4 ] [ n ] OFF # Header keyword
[ Ndim ] # Space dimension of vertices , present only if nOFF
NVertices NFaces NEdges # NEdges not used or checked
x [ 0 ] y [ 0 ] z [ 0 ] # Vertices , possibly with normals , colors , and / or texture coordinates , in that order , if the prefixes N , C , ST are present .
# If 4OFF, each vertex has 4 components including a final homogeneous component.
# If nOFF, each vertex has Ndim components.
# If 4nOFF, each vertex has Ndim+1 components.
. . .
x [ NVertices - 1 ] y [ NVertices - 1 ] z [ NVertices - 1 ]
# Faces
# Nv = # vertices on this face
# v[0] ... v[Nv-1]: vertex indices
# in range 0..NVertices-1
Nv v [ 0 ] v [ 1 ] . . . v [ Nv - 1 ] colorspec
. . .
# colorspec continues past v[Nv-1] to end-of-line; may be 0 to 4 numbers
# nothing: default
# integer: colormap index
# 3 or 4 integers: RGB[A] values 0..255
# 3 or 4 floats: RGB[A] values 0..1
*/
std : : string header = tokens [ 0 ] ;
2006-02-09 16:15:56 +01:00
if ( header . rfind ( " OFF " ) ! = std : : basic_string < char > : : npos )
2008-10-16 16:32:37 +02:00
{ // the OFF string is in the header go on parsing it.
2006-02-09 16:15:56 +01:00
for ( int u = static_cast < int > ( header . rfind ( " OFF " ) - 1 ) ; u > = 0 ; u - - )
2004-11-17 11:13:48 +01:00
{
2008-04-15 12:38:12 +02:00
if ( header [ u ] = = ' C ' ) isColorDefined = true ;
else if ( header [ u ] = = ' N ' ) isNormalDefined = true ;
else if ( u > 0 & & header [ u - 1 ] = = ' S ' & & header [ u ] = = ' T ' ) isTexCoordDefined = true ;
else if ( header [ u ] = = ' 4 ' ) homogeneousComponents = true ;
2008-10-16 16:32:37 +02:00
else if ( header [ u ] = = ' n ' ) return ErrorHighDimension ;
2004-11-17 11:13:48 +01:00
}
}
2008-10-16 16:32:37 +02:00
else return InvalidFile_MissingOFF ;
2004-11-17 11:13:48 +01:00
2008-10-16 16:32:37 +02:00
// If the file is slightly malformed and it has nvert and nface AFTER the OFF string instead of in the next line
// we manage it here...
if ( tokens . size ( ) = = 1 ) TokenizeNextLine ( stream , tokens ) ;
else tokens . erase ( tokens . begin ( ) , tokens . begin ( ) + 1 ) ;
2006-03-29 10:15:46 +02:00
// Update loading mask
///////////////////////////////////////
loadmask = Mask : : IOM_VERTCOORD | Mask : : IOM_FACEINDEX ;
2008-04-15 12:38:12 +02:00
if ( isNormalDefined ) loadmask | = Mask : : IOM_VERTNORMAL ;
if ( isTexCoordDefined ) loadmask | = Mask : : IOM_VERTTEXCOORD ;
if ( isColorDefined ) { loadmask | = Mask : : IOM_VERTCOLOR ; loadmask | = Mask : : IOM_FACECOLOR ; }
2006-03-29 10:15:46 +02:00
2010-10-21 19:45:14 +02:00
//if(onlyMaskFlag) return NoError;
2008-04-15 12:38:12 +02:00
mesh . Clear ( ) ;
2006-02-09 16:15:56 +01:00
// check on next 2 lines to detect corrupted files
if ( tokens . size ( ) < 3 )
return InvalidFile ;
2004-11-17 11:13:48 +01:00
unsigned int nVertices , nFaces , nEdges ;
nVertices = atoi ( tokens [ 0 ] . c_str ( ) ) ;
2006-02-09 16:15:56 +01:00
nFaces = atoi ( tokens [ 1 ] . c_str ( ) ) ;
nEdges = atoi ( tokens [ 2 ] . c_str ( ) ) ;
// dimension is the space dimension of vertices => it must be three(!)
if ( dimension ! = 3 )
return UnsupportedFormat ;
if ( homogeneousComponents )
return UnsupportedFormat ;
2004-11-17 11:13:48 +01:00
2006-03-29 10:15:46 +02:00
// READ VERTICES
//////////////////////////////////////////////////////
2004-11-17 11:13:48 +01:00
VertexIterator v_iter = Allocator < MESH_TYPE > : : AddVertices ( mesh , nVertices ) ;
2006-02-09 16:15:56 +01:00
TokenizeNextLine ( stream , tokens ) ;
size_t k = 0 ; // next token to read
2004-11-17 11:13:48 +01:00
for ( unsigned int i = 0 ; i < nVertices ; i + + , v_iter + + )
{
2006-03-29 10:15:46 +02:00
if ( cb & & ( i % 1000 ) = = 0 )
cb ( i * 50 / nVertices , " Vertex Loading " ) ;
2004-11-17 11:13:48 +01:00
2006-02-09 16:15:56 +01:00
// Read 3 vertex coordinates
for ( unsigned int j = 0 ; j < 3 ; j + + )
2005-09-28 12:30:14 +02:00
{
2006-02-09 16:15:56 +01:00
// Go to next line when needed
if ( k = = tokens . size ( ) ) // if EOL
{
TokenizeNextLine ( stream , tokens ) ;
if ( tokens . size ( ) = = 0 ) // if EOF
return InvalidFile ;
k = 0 ;
}
2006-03-29 10:15:46 +02:00
2006-02-09 16:15:56 +01:00
// Read vertex coordinate
( * v_iter ) . P ( ) [ j ] = ( ScalarType ) atof ( tokens [ k ] . c_str ( ) ) ;
k + + ;
2005-09-28 12:30:14 +02:00
}
2006-02-09 16:15:56 +01:00
if ( isNormalDefined )
2005-09-28 12:30:14 +02:00
{
2006-02-09 16:15:56 +01:00
// Read 3 normal coordinates
2005-09-28 12:30:14 +02:00
for ( unsigned int j = 0 ; j < 3 ; j + + )
{
2006-02-09 16:15:56 +01:00
// Go to next line when needed
if ( k = = tokens . size ( ) ) // if EOL
2005-09-28 12:30:14 +02:00
{
TokenizeNextLine ( stream , tokens ) ;
2006-02-09 16:15:56 +01:00
if ( tokens . size ( ) = = 0 ) // if EOF
return InvalidFile ;
k = 0 ;
2005-09-28 12:30:14 +02:00
}
2006-03-29 10:15:46 +02:00
2006-02-09 16:15:56 +01:00
// Read normal coordinate
( * v_iter ) . N ( ) [ j ] = ( ScalarType ) atof ( tokens [ k ] . c_str ( ) ) ;
k + + ;
2005-09-28 12:30:14 +02:00
}
}
2004-11-17 11:13:48 +01:00
2006-03-29 10:15:46 +02:00
// NOTE: It is assumed that colored vertex takes exactly one text line
// (otherwise it is impossible to parse color information since
// color components can vary)
2006-02-09 16:15:56 +01:00
if ( isColorDefined )
{
// The number of color components varies from 0 to 4.
// The OFF format guaranties that there is 1 vertex per line.
int nb_color_components = static_cast < int > ( tokens . size ( ) )
- static_cast < int > ( k ) /* tokens already parsed */
- 2 * ( isTexCoordDefined ? 1 : 0 ) ;
2006-03-29 10:15:46 +02:00
2006-02-09 16:15:56 +01:00
if ( nb_color_components < 0 | | nb_color_components > 4 )
return InvalidFile ;
2006-03-29 10:15:46 +02:00
// set per-vertex color attribute
if ( nb_color_components > 0 )
loadmask | = Mask : : IOM_VERTCOLOR ;
2006-02-09 16:15:56 +01:00
// Store color components
2008-04-15 12:38:12 +02:00
if ( tri : : HasPerVertexColor ( mesh ) )
2006-02-09 16:15:56 +01:00
{
// Read color components
2004-11-17 11:13:48 +01:00
2006-02-09 16:15:56 +01:00
if ( nb_color_components = = 1 )
{
// read color index
( * v_iter ) . C ( ) . Import ( ColorMap ( atoi ( tokens [ k ] . c_str ( ) ) ) ) ;
}
else if ( nb_color_components = = 3 )
{
// read RGB color
2007-12-13 18:57:33 +01:00
if ( tokens [ k ] . find ( " . " ) = = size_t ( - 1 ) ) // if it is a float there is a dot
2006-02-09 16:15:56 +01:00
{
// integers
unsigned char r =
static_cast < unsigned char > ( atoi ( tokens [ k ] . c_str ( ) ) ) ;
unsigned char g =
static_cast < unsigned char > ( atoi ( tokens [ k + 1 ] . c_str ( ) ) ) ;
unsigned char b =
static_cast < unsigned char > ( atoi ( tokens [ k + 2 ] . c_str ( ) ) ) ;
vcg : : Color4b color ( r , g , b , 255 ) ;
( * v_iter ) . C ( ) . Import ( color ) ;
}
else
{
// floats
float r = static_cast < float > ( atof ( tokens [ k ] . c_str ( ) ) ) ;
float g = static_cast < float > ( atof ( tokens [ k + 1 ] . c_str ( ) ) ) ;
float b = static_cast < float > ( atof ( tokens [ k + 2 ] . c_str ( ) ) ) ;
vcg : : Color4f color ( r , g , b , 1.0 ) ;
( * v_iter ) . C ( ) . Import ( color ) ;
}
}
else if ( nb_color_components = = 4 )
{
// read RGBA color
2007-12-13 18:57:33 +01:00
if ( tokens [ k ] . find ( " . " ) = = size_t ( - 1 ) )
2006-02-09 16:15:56 +01:00
{
// integers
unsigned char r =
static_cast < unsigned char > ( atoi ( tokens [ k ] . c_str ( ) ) ) ;
unsigned char g =
static_cast < unsigned char > ( atoi ( tokens [ k + 1 ] . c_str ( ) ) ) ;
unsigned char b =
static_cast < unsigned char > ( atoi ( tokens [ k + 2 ] . c_str ( ) ) ) ;
unsigned char a =
static_cast < unsigned char > ( atoi ( tokens [ k + 3 ] . c_str ( ) ) ) ;
Color4b color ( r , g , b , a ) ;
( * v_iter ) . C ( ) . Import ( color ) ;
}
else
{
// floats
float r = static_cast < float > ( atof ( tokens [ k ] . c_str ( ) ) ) ;
float g = static_cast < float > ( atof ( tokens [ k + 1 ] . c_str ( ) ) ) ;
float b = static_cast < float > ( atof ( tokens [ k + 2 ] . c_str ( ) ) ) ;
float a = static_cast < float > ( atof ( tokens [ k + 3 ] . c_str ( ) ) ) ;
vcg : : Color4f color ( r , g , b , a ) ;
( * v_iter ) . C ( ) . Import ( color ) ;
}
}
}
2006-03-29 10:15:46 +02:00
k + = nb_color_components ;
2006-02-09 16:15:56 +01:00
}
if ( isTexCoordDefined )
{
for ( unsigned int j = 0 ; j < 2 ; j + + )
{
// Go to next line when needed
if ( k = = tokens . size ( ) ) // if EOL
{
TokenizeNextLine ( stream , tokens ) ;
if ( tokens . size ( ) = = 0 ) // if EOF
return InvalidFile ;
k = 0 ;
}
2006-03-29 10:50:10 +02:00
std : : string str = tokens [ k ] ;
k + + ;
2006-02-09 16:15:56 +01:00
// Store texture coordinates
2008-04-15 12:38:12 +02:00
if ( tri : : HasPerWedgeTexCoord ( mesh ) )
2006-02-09 16:15:56 +01:00
{
//...TODO...
}
}
}
} // for i=...
2004-11-17 11:13:48 +01:00
2006-03-29 10:15:46 +02:00
// READ FACES
//////////////////////////////////////////////////////
2004-11-17 11:13:48 +01:00
Allocator < MESH_TYPE > : : AddFaces ( mesh , nFaces ) ;
unsigned int f0 = 0 ;
2011-01-27 16:49:21 +01:00
// Initial call to the QuadTriangulate with an empty vector to just reset the static set of existing diagonals
std : : vector < VertexPointer > qtmp ;
BitQuad < MESH_TYPE > : : QuadTriangulate ( qtmp ) ;
2006-03-29 10:15:46 +02:00
for ( unsigned int f = 0 ; f < nFaces ; f + + )
2004-11-17 11:13:48 +01:00
{
f0 = f ;
if ( stream . fail ( ) )
2006-02-09 16:15:56 +01:00
return InvalidFile ;
2004-11-17 11:13:48 +01:00
2006-03-29 10:15:46 +02:00
if ( cb & & ( f % 1000 ) = = 0 )
cb ( 50 + f * 50 / nFaces , " Face Loading " ) ;
2006-01-10 14:20:42 +01:00
2004-11-17 11:13:48 +01:00
TokenizeNextLine ( stream , tokens ) ;
int vert_per_face = atoi ( tokens [ 0 ] . c_str ( ) ) ;
2010-04-19 14:20:56 +02:00
if ( vert_per_face < 3 )
return ErrorDegenerateFace ;
2006-03-29 10:15:46 +02:00
k = 1 ;
2004-11-17 11:13:48 +01:00
if ( vert_per_face = = 3 )
{
2006-03-29 10:15:46 +02:00
for ( int j = 0 ; j < 3 ; j + + )
2005-09-28 12:30:14 +02:00
{
2010-01-16 15:59:40 +01:00
if ( k = = tokens . size ( ) ) // if EOL // Go to next line when needed
2006-03-29 10:15:46 +02:00
{
TokenizeNextLine ( stream , tokens ) ;
2010-01-16 15:59:40 +01:00
if ( tokens . size ( ) = = 0 ) return InvalidFile ; // if EOF
2006-03-29 10:15:46 +02:00
k = 0 ;
}
mesh . face [ f ] . V ( j ) = & ( mesh . vert [ atoi ( tokens [ k ] . c_str ( ) ) ] ) ;
k + + ;
2005-09-28 12:30:14 +02:00
}
2004-11-17 11:13:48 +01:00
}
else
{
2006-02-09 16:15:56 +01:00
// The face must be triangulate
unsigned int trigs = vert_per_face - 3 ; // number of extra faces to add
2004-11-17 11:13:48 +01:00
nFaces + = trigs ;
Allocator < MESH_TYPE > : : AddFaces ( mesh , trigs ) ;
2010-01-16 15:59:40 +01:00
std : : vector < int > vertIndices ( vert_per_face ) ;
2006-03-29 10:15:46 +02:00
for ( int j = 0 ; j < vert_per_face ; j + + )
{
2010-01-16 15:59:40 +01:00
if ( k = = tokens . size ( ) ) // if EOL // Go to next line when needed
2006-03-29 10:15:46 +02:00
{
TokenizeNextLine ( stream , tokens ) ;
2010-01-16 15:59:40 +01:00
if ( tokens . size ( ) = = 0 ) return InvalidFile ; // if EOF
k = 0 ;
2006-03-29 10:15:46 +02:00
}
vertIndices [ j ] = atoi ( tokens [ k ] . c_str ( ) ) ;
k + + ;
}
2010-01-16 15:59:40 +01:00
if ( vert_per_face = = 4 )
2011-01-27 16:49:21 +01:00
{ // To well triangulate use the bitquad support function that reorders vertex for a simple fan
std : : vector < VertexPointer > q ( 4 ) ;
for ( int qqi = 0 ; qqi < 4 ; + + qqi )
q [ qqi ] = & mesh . vert [ vertIndices [ qqi ] ] ;
BitQuad < MESH_TYPE > : : QuadTriangulate ( q ) ;
for ( int qqi = 0 ; qqi < 4 ; + + qqi )
vertIndices [ qqi ] = q [ qqi ] - & mesh . vert [ 0 ] ;
2010-01-16 15:59:40 +01:00
}
// standard fan triangulation (we hope the polygon is convex...)
for ( int j = 0 ; j < = vert_per_face - 3 ; j + + )
{
mesh . face [ f + j ] . V ( 0 ) = & ( mesh . vert [ vertIndices [ 0 ] ] ) ;
mesh . face [ f + j ] . V ( 1 ) = & ( mesh . vert [ vertIndices [ 1 + j ] ] ) ;
mesh . face [ f + j ] . V ( 2 ) = & ( mesh . vert [ vertIndices [ 2 + j ] ] ) ;
if ( tri : : HasPerFaceFlags ( mesh ) ) {
// tag internal polygonal edges as "faux"
if ( j > 0 ) mesh . face [ f + j ] . SetF ( 0 ) ;
if ( j < vert_per_face - 3 ) mesh . face [ f + j ] . SetF ( 2 ) ;
loadmask | = Mask : : IOM_BITPOLYGONAL ;
}
}
f + = trigs ;
2004-11-17 11:13:48 +01:00
}
2006-03-29 10:15:46 +02:00
// NOTE: It is assumed that colored face takes exactly one text line
// (otherwise it is impossible to parse color information since
// color components can vary)
2010-10-21 19:45:14 +02:00
size_t color_elements = tokens . size ( ) - vert_per_face - 1 ;
isColorDefined | = ( color_elements > 0 ) ;
if ( isColorDefined ) loadmask | = Mask : : IOM_FACECOLOR ;
if ( ( color_elements > 0 ) & & tri : : HasPerFaceColor ( mesh ) )
2004-11-17 11:13:48 +01:00
{
2010-10-21 19:45:14 +02:00
2006-03-29 10:15:46 +02:00
// set per-face color attribute
if ( color_elements > 0 )
loadmask | = Mask : : IOM_FACECOLOR ;
2004-11-17 11:13:48 +01:00
switch ( color_elements )
{
case 0 :
{
for ( ; f0 < = f ; f0 + + )
mesh . face [ f0 ] . C ( ) . Import ( vcg : : Color4f ( .666f , .666f , .666f , .666f ) ) ;
break ;
}
case 1 :
{
for ( ; f0 < = f ; f0 + + )
2006-02-09 16:15:56 +01:00
mesh . face [ f0 ] . C ( ) . Import ( ColorMap ( atoi ( tokens [ vert_per_face + 1 ] . c_str ( ) ) ) ) ;
2004-11-17 11:13:48 +01:00
break ;
}
case 3 :
{
2007-12-13 18:57:33 +01:00
if ( tokens [ vert_per_face + 1 ] . find ( ' . ' ) = = size_t ( - 1 ) )
2004-11-17 11:13:48 +01:00
{
int rgb [ 3 ] ;
rgb [ 0 ] = atoi ( tokens [ vert_per_face + 1 ] . c_str ( ) ) ;
rgb [ 1 ] = atoi ( tokens [ vert_per_face + 2 ] . c_str ( ) ) ;
rgb [ 2 ] = atoi ( tokens [ vert_per_face + 3 ] . c_str ( ) ) ;
for ( ; f0 < = f ; f0 + + )
mesh . face [ f0 ] . C ( ) . SetRGB ( rgb [ 0 ] , rgb [ 1 ] , rgb [ 2 ] ) ;
}
else
{
float color [ 3 ] ;
color [ 0 ] = ( float ) atof ( tokens [ vert_per_face + 1 ] . c_str ( ) ) ;
color [ 1 ] = ( float ) atof ( tokens [ vert_per_face + 2 ] . c_str ( ) ) ;
color [ 2 ] = ( float ) atof ( tokens [ vert_per_face + 3 ] . c_str ( ) ) ;
for ( ; f0 < = f ; f0 + + )
mesh . face [ f0 ] . C ( ) . Import ( vcg : : Color4f ( color [ 0 ] , color [ 1 ] , color [ 2 ] , 1.0f ) ) ;
}
break ;
}
case 4 :
{
2007-12-13 18:57:33 +01:00
if ( tokens [ vert_per_face + 1 ] . find ( ' . ' ) = = 0 ) // if it is a float there is a dot
2004-11-17 11:13:48 +01:00
{
unsigned char color [ 4 ] ;
color [ 0 ] = ( unsigned char ) atoi ( tokens [ vert_per_face + 1 ] . c_str ( ) ) ;
color [ 1 ] = ( unsigned char ) atoi ( tokens [ vert_per_face + 2 ] . c_str ( ) ) ;
color [ 2 ] = ( unsigned char ) atoi ( tokens [ vert_per_face + 3 ] . c_str ( ) ) ;
color [ 3 ] = ( unsigned char ) atoi ( tokens [ vert_per_face + 4 ] . c_str ( ) ) ;
for ( ; f0 < = f ; f0 + + )
mesh . face [ f0 ] . C ( ) . Import ( vcg : : Color4f ( color [ 0 ] , color [ 1 ] , color [ 2 ] , color [ 3 ] ) ) ;
}
else
{
float color [ 4 ] ;
2005-01-03 12:18:24 +01:00
color [ 0 ] = float ( atof ( tokens [ vert_per_face + 1 ] . c_str ( ) ) ) ;
color [ 1 ] = float ( atof ( tokens [ vert_per_face + 2 ] . c_str ( ) ) ) ;
color [ 2 ] = float ( atof ( tokens [ vert_per_face + 3 ] . c_str ( ) ) ) ;
color [ 3 ] = float ( atof ( tokens [ vert_per_face + 4 ] . c_str ( ) ) ) ;
2004-11-17 11:13:48 +01:00
for ( ; f0 < = f ; f0 + + )
mesh . face [ f0 ] . C ( ) . Import ( vcg : : Color4f ( color [ 0 ] , color [ 1 ] , color [ 2 ] , color [ 3 ] ) ) ;
}
break ;
}
} //end switch
} // end if (isColorDefined)
2006-02-09 16:15:56 +01:00
} // end of for f=...
2005-01-26 23:44:51 +01:00
return NoError ;
2004-11-17 11:13:48 +01:00
2006-02-09 16:15:56 +01:00
} // end Open
2004-11-17 11:13:48 +01:00
2006-01-10 14:20:42 +01:00
protected :
2004-11-17 11:13:48 +01:00
/*!
* Read the next valid line and parses it into " tokens " , allowing the tokens to be read one at a time .
* \ param stream The object providing the input stream
* \ param tokens The " tokens " in the next line
*/
2011-02-17 12:38:01 +01:00
inline static void TokenizeNextLine ( std : : ifstream & stream , std : : vector < std : : string > & tokens )
2004-11-17 11:13:48 +01:00
{
std : : string line ;
do
std : : getline ( stream , line , ' \n ' ) ;
while ( line [ 0 ] = = ' # ' | | line . length ( ) = = 0 ) ;
2006-03-29 10:15:46 +02:00
size_t from = 0 ;
size_t to = 0 ;
2004-11-17 11:13:48 +01:00
size_t length = line . size ( ) ;
tokens . clear ( ) ;
do
{
2009-09-28 02:01:12 +02:00
while ( ( line [ from ] = = ' ' | | line [ from ] = = ' \t ' | | line [ from ] = = ' \r ' ) & & from ! = length )
2004-11-17 11:13:48 +01:00
from + + ;
2006-03-29 10:15:46 +02:00
if ( from ! = length )
{
to = from + 1 ;
2011-02-17 12:38:01 +01:00
while ( ( ( ( line [ to ] ! = ' ' ) & & ( line [ to ] ! = ' \t ' ) ) | | ( line [ to ] = = ' \r ' ) ) & & to ! = length )
2006-03-29 10:15:46 +02:00
to + + ;
tokens . push_back ( line . substr ( from , to - from ) . c_str ( ) ) ;
from = to ;
}
2004-11-17 11:13:48 +01:00
}
while ( from < length ) ;
} // end Tokenize
/*!
* Provide the int - > color mapping , according to the Geomview ' s ` cmap . fmap ' file .
* \ param i the color index
* \ return the corresponding < CODE > vcg : : Color4f < / CODE > color
*/
static const vcg : : Color4f ColorMap ( int i )
{
static const float colorMap [ 148 ] [ 4 ] =
{
{ 1.0f , 1.0f , 1.0f , 1.0f } ,
{ 1.0f , 1.0f , 1.0f , 1.0f } ,
{ 1.0f , 1.0f , 1.0f , 1.0f } ,
{ 1.0f , 1.0f , 1.0f , 1.0f } ,
{ 1.0f , 1.0f , 1.0f , 1.0f } ,
{ 1.0f , 1.0f , 1.0f , 1.0f } ,
{ 0.7f , 0.7f , 0.7f , 0.7f } ,
{ 0.2f , 0.2f , 0.2f , 0.2f } ,
{ 0.9f , 0.9f , 0.9f , 0.9f } ,
{ 0.1f , 0.1f , 0.1f , 0.1f } ,
{ 0.1f , 0.1f , 0.1f , 0.1f } ,
{ 0.8f , 0.8f , 0.8f , 0.8f } ,
{ 0.7f , 0.7f , 0.7f , 0.7f } ,
{ 0.7f , 0.7f , 0.7f , 0.7f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.9f , 0.9f , 0.9f , 0.9f } ,
{ 0.2f , 0.2f , 0.2f , 0.2f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.75f , 0.75f , 0.75f , 0.75f } ,
{ 0.8f , 0.8f , 0.8f , 0.8f } ,
{ 0.8f , 0.8f , 0.8f , 0.8f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.4f , 0.4f , 0.4f , 0.4f } ,
{ 0.4f , 0.4f , 0.4f , 0.4f } ,
{ 0.8f , 0.8f , 0.8f , 0.8f } ,
{ 0.8f , 0.8f , 0.8f , 0.8f } ,
{ 0.7f , 0.7f , 0.7f , 0.7f } ,
{ 0.7f , 0.7f , 0.7f , 0.7f } ,
{ 0.7f , 0.7f , 0.7f , 0.7f } ,
{ 0.7f , 0.7f , 0.7f , 0.7f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.9f , 0.9f , 0.9f , 0.9f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.75f , 0.75f , 0.75f , 0.75f } ,
{ 0.8f , 0.8f , 0.8f , 0.8f } ,
{ 0.4f , 0.4f , 0.4f , 0.4f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.4f , 0.4f , 0.4f , 0.4f } ,
{ 0.8f , 0.8f , 0.8f , 0.8f } ,
{ 0.7f , 0.7f , 0.7f , 0.7f } ,
{ 0.7f , 0.7f , 0.7f , 0.7f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.9f , 0.9f , 0.9f , 0.9f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.75f , 0.75f , 0.75f , 0.75f } ,
{ 0.8f , 0.8f , 0.8f , 0.8f } ,
{ 0.4f , 0.4f , 0.4f , 0.4f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.4f , 0.4f , 0.4f , 0.4f } ,
{ 0.8f , 0.8f , 0.8f , 0.8f } ,
{ 0.7f , 0.7f , 0.7f , 0.7f } ,
{ 0.7f , 0.7f , 0.7f , 0.7f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.9f , 0.9f , 0.9f , 0.9f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.75f , 0.75f , 0.75f , 0.75f } ,
{ 0.8f , 0.8f , 0.8f , 0.8f } ,
{ 0.4f , 0.4f , 0.4f , 0.4f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.4f , 0.4f , 0.4f , 0.4f } ,
{ 0.8f , 0.8f , 0.8f , 0.8f } ,
{ 1.0f , 1.0f , 1.0f , 1.0f } ,
{ 1.0f , 1.0f , 1.0f , 1.0f } ,
{ 1.0f , 1.0f , 1.0f , 1.0f } ,
{ 1.0f , 1.0f , 1.0f , 1.0f } ,
{ 1.0f , 1.0f , 1.0f , 1.0f } ,
{ 1.0f , 1.0f , 1.0f , 1.0f } ,
{ 0.05f , 0.05f , 0.05f , 0.05f } ,
{ 0.7f , 0.7f , 0.7f , 0.7f } ,
{ 0.2f , 0.2f , 0.2f , 0.2f } ,
{ 0.9f , 0.9f , 0.9f , 0.9f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.1f , 0.1f , 0.1f , 0.1f } ,
{ 0.8f , 0.8f , 0.8f , 0.8f } ,
{ 0.7f , 0.7f , 0.7f , 0.7f } ,
{ 0.7f , 0.7f , 0.7f , 0.7f } ,
{ 0.7f , 0.7f , 0.7f , 0.7f } ,
{ 0.7f , 0.7f , 0.7f , 0.7f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.9f , 0.9f , 0.9f , 0.9f } ,
{ 0.9f , 0.9f , 0.9f , 0.9f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.75f , 0.75f , 0.75f , 0.75f } ,
{ 0.75f , 0.75f , 0.75f , 0.75f } ,
{ 0.8f , 0.8f , 0.8f , 0.8f } ,
{ 0.8f , 0.8f , 0.8f , 0.8f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.4f , 0.4f , 0.4f , 0.4f } ,
{ 0.4f , 0.4f , 0.4f , 0.4f } ,
{ 0.8f , 0.8f , 0.8f , 0.8f } ,
{ 0.8f , 0.8f , 0.8f , 0.8f } ,
{ 0.7f , 0.7f , 0.7f , 0.7f } ,
{ 0.7f , 0.7f , 0.7f , 0.7f } ,
{ 0.7f , 0.7f , 0.7f , 0.7f } ,
{ 0.7f , 0.7f , 0.7f , 0.7f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.9f , 0.9f , 0.9f , 0.9f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.75f , 0.75f , 0.75f , 0.75f } ,
{ 0.8f , 0.8f , 0.8f , 0.8f } ,
{ 0.4f , 0.4f , 0.4f , 0.4f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.4f , 0.4f , 0.4f , 0.4f } ,
{ 0.8f , 0.8f , 0.8f , 0.8f } ,
{ 0.7f , 0.7f , 0.7f , 0.7f } ,
{ 0.7f , 0.7f , 0.7f , 0.7f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.9f , 0.9f , 0.9f , 0.9f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.75f , 0.75f , 0.75f , 0.75f } ,
{ 0.8f , 0.8f , 0.8f , 0.8f } ,
{ 0.4f , 0.4f , 0.4f , 0.4f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.4f , 0.4f , 0.4f , 0.4f } ,
{ 0.8f , 0.8f , 0.8f , 0.8f } ,
{ 0.7f , 0.7f , 0.7f , 0.7f } ,
{ 0.7f , 0.7f , 0.7f , 0.7f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.9f , 0.9f , 0.9f , 0.9f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.75f , 0.75f , 0.75f , 0.75f } ,
{ 0.8f , 0.8f , 0.8f , 0.8f } ,
{ 0.4f , 0.4f , 0.4f , 0.4f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.0f , 0.0f , 0.0f , 0.0f } ,
{ 0.4f , 0.4f , 0.4f , 0.4f } ,
{ 0.8f , 0.8f , 0.8f , 0.8f }
} ;
return Color4f ( colorMap [ i ] [ 0 ] , colorMap [ i ] [ 1 ] , colorMap [ i ] [ 2 ] , colorMap [ i ] [ 3 ] ) ;
}
} ;
// /*! @} */
2005-12-01 01:58:56 +01:00
} //namespace io
} //namespace tri
} // namespace vcg
2004-11-17 11:13:48 +01:00
2005-01-26 23:44:51 +01:00
# endif //__VCGLIB_IMPORT_OFF