Insert Laurent Saboret modifications

Add color components handling
This commit is contained in:
Massimiliano Corsini 2006-02-09 15:15:56 +00:00
parent 287fd21a07
commit e12695f3ea
1 changed files with 205 additions and 74 deletions

View File

@ -24,6 +24,10 @@
History History
$Log: not supported by cvs2svn $ $Log: not supported by cvs2svn $
Revision 1.12 2006/02/06 13:11:01 corsini
Renamed UnexpectedEOF as InvalidFile and
added UnsupportedFormat and ErrorNotTriangularFace (by Laurent Saboret)
Revision 1.11 2006/01/30 15:02:50 cignoni Revision 1.11 2006/01/30 15:02:50 cignoni
Added mask filling in open Added mask filling in open
@ -81,6 +85,7 @@ namespace vcg
class ImporterOFF class ImporterOFF
{ {
public: public:
typedef typename MESH_TYPE::VertexType VertexType; typedef typename MESH_TYPE::VertexType VertexType;
typedef typename MESH_TYPE::VertexIterator VertexIterator; typedef typename MESH_TYPE::VertexIterator VertexIterator;
typedef typename MESH_TYPE::VertexPointer VertexPointer; typedef typename MESH_TYPE::VertexPointer VertexPointer;
@ -90,6 +95,10 @@ namespace vcg
typedef typename MESH_TYPE::CoordType CoordType; typedef typename MESH_TYPE::CoordType CoordType;
typedef typename MESH_TYPE::ScalarType ScalarType; typedef typename MESH_TYPE::ScalarType ScalarType;
// OFF codes
enum OFFCodes {NoError=0, CantOpen, InvalidFile,
UnsupportedFormat, ErrorNotTriangularFace};
/*! /*!
* Standard call for knowing the meaning of an error code * Standard call for knowing the meaning of an error code
* \param message_code The code returned by <CODE>Open</CODE> * \param message_code The code returned by <CODE>Open</CODE>
@ -121,14 +130,18 @@ namespace vcg
* \param filename the name of the file to read from * \param filename the name of the file to read from
* \return the operation result * \return the operation result
*/ */
static int Open(MESH_TYPE &mesh, const char *filename, int &loadmask, CallBackPos *cb=0) static int Open(MESH_TYPE &mesh, const char *filename, int &loadmask,
CallBackPos *cb=0)
{ {
mesh.Clear(); mesh.Clear();
// The "[ST][C][N][4][n]OFF" keyword is optional. Default is "OFF".
bool isNormalDefined = false; bool isNormalDefined = false;
bool isColorDefined = false; bool isColorDefined = false;
bool isTexCoordDefined = false; bool isTexCoordDefined = false;
int dimension = 3; int dimension = 3;
bool homogeneousComponents = false;
std::ifstream stream(filename); std::ifstream stream(filename);
if (stream.fail()) if (stream.fail())
@ -136,121 +149,222 @@ namespace vcg
std::vector< std::string > tokens; std::vector< std::string > tokens;
TokenizeNextLine(stream, tokens); TokenizeNextLine(stream, tokens);
if (tokens[tokens.size()-1].rfind("OFF")!= std::basic_string<char>::npos)
std::string header = tokens[tokens.size()-1];
if (header.rfind("OFF") != std::basic_string<char>::npos)
{ {
for (int u=int(tokens.size())-2; u>=0; u--) for (int u = static_cast<int>(header.rfind("OFF")-1); u>=0; u--)
{
std::string header = tokens[u];
if (header.compare("C")==0)
{ {
if (header[u] == 'C')
isColorDefined = true; isColorDefined = true;
continue; else if (header[u] == 'N')
}
if (header.compare("N")==0)
{
isNormalDefined = true; isNormalDefined = true;
continue; else if (u>0 && header[u-1] == 'S' && header[u] == 'T')
}
if (header.compare("ST")==0)
{
isTexCoordDefined = true; isTexCoordDefined = true;
continue; else if (header[u] == '4')
} homogeneousComponents = true;
} else if (header[u] == 'n')
if (tokens[tokens.size()-1].compare("4OFF")==0)
dimension = 4;
else if (tokens[tokens.size()-1].compare("nOFF")==0)
{ {
TokenizeNextLine(stream, tokens); TokenizeNextLine(stream, tokens);
dimension = atoi(tokens[0].c_str()); dimension = atoi(tokens[0].c_str());
} }
else }
dimension = 3;
TokenizeNextLine(stream, tokens); TokenizeNextLine(stream, tokens);
} }
// check on next 2 lines to detect corrupted files
if(tokens.size() < 3)
return InvalidFile;
unsigned int nVertices, nFaces, nEdges; unsigned int nVertices, nFaces, nEdges;
nVertices = atoi(tokens[0].c_str()); nVertices = atoi(tokens[0].c_str());
nFaces = atoi(tokens[1].c_str()); nFaces = atoi(tokens[1].c_str());
nEdges = atoi(tokens[2].c_str()); nEdges = atoi(tokens[2].c_str());
assert(dimension = 3); // dimension is the space dimension of vertices => it must be three(!)
if (dimension != 3)
return UnsupportedFormat;
if (homogeneousComponents)
return UnsupportedFormat;
VertexIterator v_iter = Allocator<MESH_TYPE>::AddVertices(mesh, nVertices); VertexIterator v_iter = Allocator<MESH_TYPE>::AddVertices(mesh, nVertices);
TokenizeNextLine(stream, tokens);
size_t k = 0; // next token to read
for (unsigned int i=0; i<nVertices; i++, v_iter++) for (unsigned int i=0; i<nVertices; i++, v_iter++)
{ {
if (stream.fail())
return UnexpectedEOF;
if (cb && (i%1000)==0) cb(i*50/nVertices,"Vertex Loading"); if (cb && (i%1000)==0) cb(i*50/nVertices,"Vertex Loading");
TokenizeNextLine(stream, tokens); // Read 3 vertex coordinates
if(tokens.size() ==3)
{
for (unsigned int j=0; j<3; j++) for (unsigned int j=0; j<3; j++)
(*v_iter).P()[j] = (ScalarType) atof(tokens[j].c_str()); {
// 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;
}
// Read vertex coordinate
(*v_iter).P()[j] = (ScalarType) atof(tokens[k].c_str());
k++;
}
if (isNormalDefined)
{
// Read 3 normal coordinates
for (unsigned int j=0; j<3; 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;
}
// Read normal coordinate
(*v_iter).N()[j] = (ScalarType) atof(tokens[k].c_str());
k++;
}
}
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);
if (nb_color_components < 0 || nb_color_components > 4)
return InvalidFile;
// Store color components
if (VertexType::HasColor())
{
// Read color components
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
if (tokens[k].find(".") == -1)
{
// 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 else
{ {
size_t k = tokens.size(); // floats
for (unsigned int j=0; j<3; j++) 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)
{ {
(*v_iter).P()[j] = (ScalarType) atof(tokens[k].c_str()); // read RGBA color
k--; if (tokens[k].find(".") == -1)
if(k==0) {
// 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);
}
}
}
else // Skip color components
k += nb_color_components;
}
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); TokenizeNextLine(stream, tokens);
k = tokens.size(); if (tokens.size() == 0) // if EOF
} return InvalidFile;
} k = 0;
}
if (isNormalDefined)
for (unsigned int j=3; j<6; j++)
(*v_iter).N()[j] = (ScalarType) atof(tokens[j].c_str());
if (isColorDefined) {}
if (isTexCoordDefined) {}
} }
// Store texture coordinates
if (VertexType::HasTexture())
{
//...TODO...
}
}
}
} // for i=...
// Read faces
Allocator<MESH_TYPE>::AddFaces(mesh, nFaces); Allocator<MESH_TYPE>::AddFaces(mesh, nFaces);
unsigned int f0=0; unsigned int f0=0;
for (unsigned int f=0; f<nFaces; f++) for (unsigned int f=0; f<nFaces; f++)
{ {
f0 = f; f0 = f;
if (stream.fail()) if (stream.fail())
return UnexpectedEOF; return InvalidFile;
if(cb && (f%1000)==0) cb(50+f*50/nFaces,"Vertex Loading"); if(cb && (f%1000)==0) cb(50+f*50/nFaces,"Face Loading");
TokenizeNextLine(stream, tokens); TokenizeNextLine(stream, tokens);
int vert_per_face = atoi(tokens[0].c_str()); int vert_per_face = atoi(tokens[0].c_str());
if (vert_per_face == 3) if (vert_per_face == 3)
{ {
if(tokens.size() ==4) // It is assumed that the vertex indexes are on 1 line
if(tokens.size() >= 4)
{ {
for(unsigned int j = 0; j<3; j++) for(unsigned int j = 0; j<3; j++)
mesh.face[f].V(j) = &(mesh.vert[ atoi(tokens[j+1].c_str()) ]); mesh.face[f].V(j) = &(mesh.vert[ atoi(tokens[j+1].c_str()) ]);
} }
else else
{ return InvalidFile;
TokenizeNextLine(stream, tokens);
size_t k = tokens.size();
for (unsigned int j=0; j<3; j++)
{
mesh.face[f].V(j) = &(mesh.vert[ atoi(tokens[j].c_str()) ]);
k--;
if(k==0)
{
TokenizeNextLine(stream, tokens);
k = tokens.size();
}
}
}
} }
else else
{ {
unsigned int trigs = vert_per_face-3; // The face must be triangulate
unsigned int trigs = vert_per_face-3; // number of extra faces to add
nFaces += trigs; nFaces += trigs;
Allocator<MESH_TYPE>::AddFaces(mesh, trigs); Allocator<MESH_TYPE>::AddFaces(mesh, trigs);
int *vertIndices = new int[vert_per_face]; int *vertIndices = new int[vert_per_face];
@ -264,6 +378,7 @@ namespace vcg
mesh.face[f+k].V(1) = &(mesh.vert[ vertIndices[1+k] ]); mesh.face[f+k].V(1) = &(mesh.vert[ vertIndices[1+k] ]);
mesh.face[f+k].V(2) = &(mesh.vert[ vertIndices[2+k] ]); mesh.face[f+k].V(2) = &(mesh.vert[ vertIndices[2+k] ]);
} }
f+=trigs; f+=trigs;
delete []vertIndices; delete []vertIndices;
} }
@ -334,14 +449,30 @@ namespace vcg
} }
} //end switch } //end switch
} // end if (isColorDefined) } // end if (isColorDefined)
} } // end of for f=...
// Update loading mask
///////////////////////////////////////
loadmask = Mask::IOM_VERTCOORD | Mask::IOM_FACEINDEX; loadmask = Mask::IOM_VERTCOORD | Mask::IOM_FACEINDEX;
if(isColorDefined) loadmask |= Mask::IOM_FACECOLOR;
if (isColorDefined)
{
if (VertexType::HasColor())
loadmask |= Mask::IOM_VERTCOLOR;
// FIXME: This can not be true in the general case.
if (FaceType::HasFaceColor())
loadmask |= Mask::IOM_FACECOLOR;
}
if (isTexCoordDefined && VertexType::HasTexture())
loadmask |= Mask::IOM_VERTTEXCOORD;
return NoError; return NoError;
} // end Open } // end Open
enum OFFCodes {NoError=0, CantOpen, UnexpectedEOF};
protected: protected:
/*! /*!