fixed bugs in OBJ importer that caused crashes when the v/vt/vn vertex pattern was not the same for all vertices in the file.

This commit is contained in:
Marco Di Benedetto 2012-12-05 17:38:16 +00:00
parent 357ef4e8f9
commit b70569feb8
1 changed files with 1109 additions and 1055 deletions

View File

@ -461,8 +461,15 @@ public:
if ( oi.mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD ) if ( oi.mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD )
{ // verifying validity of texture coords indices { // verifying validity of texture coords indices
bool invalid = false;
for(int i=0;i<3;i++) for(int i=0;i<3;i++)
if(!GoodObjIndex(ff.t[i],oi.numTexCoords)) return E_BAD_VERT_TEX_INDEX; if(!GoodObjIndex(ff.t[i],oi.numTexCoords))
{
//return E_BAD_VERT_TEX_INDEX;
invalid = true;
break;
}
if (invalid) continue;
ff.tInd=materials[currentMaterialIdx].index; ff.tInd=materials[currentMaterialIdx].index;
} }
@ -470,14 +477,30 @@ public:
if ((ff.v[0] == ff.v[1]) || (ff.v[0] == ff.v[2]) || (ff.v[1] == ff.v[2])) if ((ff.v[0] == ff.v[1]) || (ff.v[0] == ff.v[2]) || (ff.v[1] == ff.v[2]))
result = E_VERTICES_WITH_SAME_IDX_IN_FACE; result = E_VERTICES_WITH_SAME_IDX_IN_FACE;
{
bool invalid = false;
for(int i=0;i<3;i++) for(int i=0;i<3;i++)
if(!GoodObjIndex(ff.v[i],numVertices)) return E_BAD_VERT_INDEX; if(!GoodObjIndex(ff.v[i],numVertices))
{
//return E_BAD_VERT_INDEX;
invalid = true;
break;
}
if (invalid) continue;
}
// assigning face normal // assigning face normal
if ( oi.mask & vcg::tri::io::Mask::IOM_WEDGNORMAL ) if ( oi.mask & vcg::tri::io::Mask::IOM_WEDGNORMAL )
{ // verifying validity of vertex normal indices { // verifying validity of vertex normal indices
bool invalid = false;
for(int i=0;i<3;i++) for(int i=0;i<3;i++)
if(!GoodObjIndex(ff.n[i],numVNormals)) return E_BAD_VERT_NORMAL_INDEX; if(!GoodObjIndex(ff.n[i],numVNormals))
{
//return E_BAD_VERT_NORMAL_INDEX;
invalid = true;
break;
}
if (invalid) continue;
} }
// assigning face color // assigning face color
@ -529,7 +552,6 @@ public:
} // end for each line... } // end for each line...
} // end while stream not eof } // end while stream not eof
assert((numTriangles +numVertices) == numVerticesPlusFaces+extraTriangles); assert((numTriangles +numVertices) == numVerticesPlusFaces+extraTriangles);
vcg::tri::Allocator<OpenMeshType>::AddFaces(m,numTriangles); vcg::tri::Allocator<OpenMeshType>::AddFaces(m,numTriangles);
//------------------------------------------------------------------------------- //-------------------------------------------------------------------------------
@ -558,16 +580,22 @@ public:
m.face[i].V(j)->T().n() = indexedFaces[i].tInd; m.face[i].V(j)->T().n() = indexedFaces[i].tInd;
} }
if ( oi.mask & vcg::tri::io::Mask::IOM_WEDGNORMAL ) if ( oi.mask & vcg::tri::io::Mask::IOM_WEDGNORMAL )
{
m.face[i].WN(j).Import(normals[indexedFaces[i].n[j]]); m.face[i].WN(j).Import(normals[indexedFaces[i].n[j]]);
}
if ( oi.mask & vcg::tri::io::Mask::IOM_VERTNORMAL ) if ( oi.mask & vcg::tri::io::Mask::IOM_VERTNORMAL )
{
m.face[i].V(j)->N().Import(normals[indexedFaces[i].n[j]]); m.face[i].V(j)->N().Import(normals[indexedFaces[i].n[j]]);
}
// set faux edge flags according to internals faces // set faux edge flags according to internals faces
if (indexedFaces[i].edge[j]) m.face[i].SetF(j); if (indexedFaces[i].edge[j]) m.face[i].SetF(j);
else m.face[i].ClearF(j); else m.face[i].ClearF(j);
} }
if (HasPerFaceNormal(m))
{
if (((oi.mask & vcg::tri::io::Mask::IOM_FACECOLOR) != 0) && (HasPerFaceColor(m))) if (((oi.mask & vcg::tri::io::Mask::IOM_FACECOLOR) != 0) && (HasPerFaceColor(m)))
{ {
m.face[i].C() = indexedFaces[i].c; m.face[i].C() = indexedFaces[i].c;
@ -579,9 +607,6 @@ public:
m.face[i].N().Import(m.face[i].WN(0)+m.face[i].WN(1)+m.face[i].WN(2)); m.face[i].N().Import(m.face[i].WN(0)+m.face[i].WN(1)+m.face[i].WN(2));
} }
else else
{
// computing face normal from position of face vertices
if (HasPerFaceNormal(m))
{ {
face::ComputeNormalizedNormal(m.face[i]); face::ComputeNormalizedNormal(m.face[i]);
} }
@ -617,14 +642,14 @@ public:
do do
{ {
std::getline(stream, line); std::getline(stream, line);
if(colVec && line[0] == '#') const size_t len = line.length();
if((len > 0) && colVec && line[0] == '#')
{ {
// The following MRGB block contains ZBrush Vertex Color (Polypaint) // The following MRGB block contains ZBrush Vertex Color (Polypaint)
// and masking output as 4 hexadecimal values per vertex. The vertex color format is MMRRGGBB with up to 64 entries per MRGB line. // and masking output as 4 hexadecimal values per vertex. The vertex color format is MMRRGGBB with up to 64 entries per MRGB line.
if(line[1] == 'M' && line[2] == 'R' && line[3] == 'G' && line[4] == 'B') if((len >= 5) && line[1] == 'M' && line[2] == 'R' && line[3] == 'G' && line[4] == 'B')
{ // Parsing the polycolor of ZBrush { // Parsing the polycolor of ZBrush
MRGBLineCount()++; MRGBLineCount()++;
size_t len = line.length();
char buf[3]="00"; char buf[3]="00";
Color4b cc(Color4b::Black); Color4b cc(Color4b::Black);
for(size_t i=6;(i+7)<len;i+=8) for(size_t i=6;(i+7)<len;i+=8)
@ -643,9 +668,9 @@ public:
} }
} }
} }
while (( line.empty() || (!line.empty() && line[0] == '#')) && !stream.eof()); // skip comments and empty lines while (( line.length()==0 || line[0] == '#') && !stream.eof()); // skip comments and empty lines
if ( (line.length() == 0)||(!line.empty() && line[0] == '#') ) // can be true only on last line of file if ( (line.length() == 0)||(line[0] == '#') ) // can be true only on last line of file
return; return;
size_t from = 0; size_t from = 0;
@ -669,8 +694,36 @@ public:
while (from<length); while (from<length);
} // end TokenizeNextLine } // end TokenizeNextLine
inline static void SplitToken(const std::string & token, int & vId, int & nId, int & tId, int mask)
{
static const char delimiter = '/';
(void)mask;
vId = nId = tId = 0;
if (token.empty()) return;
size_t firstSep = token.find_first_of(delimiter);
size_t secondSep = (firstSep == std::string::npos) ? (std::string::npos) : (token.find_first_of(delimiter, firstSep + 1));
const bool hasPosition = true;
const bool hasTexcoord = (firstSep != std::string::npos) && ((firstSep + 1) < secondSep);
const bool hasNormal = (secondSep != std::string::npos);
if (hasPosition) vId = atoi(token.substr(0, firstSep).c_str()) - 1;
if (hasTexcoord) tId = atoi(token.substr(firstSep + 1, secondSep - firstSep - 1).c_str()) - 1;
if (hasNormal ) nId = atoi(token.substr(secondSep + 1).c_str()) - 1;
/*
const std::string vStr = (hasPosition) ? (token.substr(0, firstSep)) : ("0");
const std::string tStr = (hasTexcoord) ? (token.substr(firstSep + 1, secondSep - firstSep - 1)) : ("0");
const std::string nStr = (hasNormal) ? (token.substr(secondSep + 1)) : ("0");
if (!vStr.empty()) vId = atoi(vStr.c_str()) - 1;
if (!tStr.empty()) tId = atoi(tStr.c_str()) - 1;
if (!nStr.empty()) nId = atoi(nStr.c_str()) - 1;
*/
}
#if 0
// This function takes a token and, according to the mask, it returns the indexes of the involved vertex, normal and texcoord indexes. // This function takes a token and, according to the mask, it returns the indexes of the involved vertex, normal and texcoord indexes.
// Example. if the obj file has vertex texcoord (e.g. lines 'vt 0.444 0.5555') // Example. if the obj file has vertex texcoord (e.g. lines 'vt 0.444 0.5555')
// when parsing a line like // when parsing a line like
@ -792,6 +845,7 @@ public:
} }
} }
} // end of SplitVVTVNToken } // end of SplitVVTVNToken
#endif
/*! /*!
* Retrieves infos about kind of data stored into the file and fills a mask appropriately * Retrieves infos about kind of data stored into the file and fills a mask appropriately