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:
parent
357ef4e8f9
commit
b70569feb8
|
@ -41,17 +41,17 @@
|
||||||
|
|
||||||
|
|
||||||
namespace vcg {
|
namespace vcg {
|
||||||
namespace tri {
|
namespace tri {
|
||||||
namespace io {
|
namespace io {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This class encapsulate a filter for importing obj (Alias Wavefront) meshes.
|
This class encapsulate a filter for importing obj (Alias Wavefront) meshes.
|
||||||
Warning: this code assume little endian (PC) architecture!!!
|
Warning: this code assume little endian (PC) architecture!!!
|
||||||
*/
|
*/
|
||||||
template <class OpenMeshType>
|
template <class OpenMeshType>
|
||||||
class ImporterOBJ
|
class ImporterOBJ
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static int &MRGBLineCount(){static int _MRGBLineCount=0; return _MRGBLineCount;}
|
static int &MRGBLineCount(){static int _MRGBLineCount=0; return _MRGBLineCount;}
|
||||||
|
|
||||||
typedef typename OpenMeshType::VertexPointer VertexPointer;
|
typedef typename OpenMeshType::VertexPointer VertexPointer;
|
||||||
|
@ -354,7 +354,7 @@ public:
|
||||||
|
|
||||||
if( (vertexesPerFace>3) && OpenMeshType::FaceType::HasPolyInfo() )
|
if( (vertexesPerFace>3) && OpenMeshType::FaceType::HasPolyInfo() )
|
||||||
{
|
{
|
||||||
//_BEGIN___ if you are loading a GENERIC POLYGON mesh
|
//_BEGIN___ if you are loading a GENERIC POLYGON mesh
|
||||||
ff.set(vertexesPerFace);
|
ff.set(vertexesPerFace);
|
||||||
for(int i=0;i<vertexesPerFace;++i) { // remember index starts from 1 instead of 0
|
for(int i=0;i<vertexesPerFace;++i) { // remember index starts from 1 instead of 0
|
||||||
SplitToken(tokens[i+1], ff.v[i], ff.n[i], ff.t[i], inputMask);
|
SplitToken(tokens[i+1], ff.v[i], ff.n[i], ff.t[i], inputMask);
|
||||||
|
@ -396,11 +396,11 @@ public:
|
||||||
++numTriangles;
|
++numTriangles;
|
||||||
indexedFaces.push_back(ff);
|
indexedFaces.push_back(ff);
|
||||||
|
|
||||||
//_END ___ if you are loading a GENERIC POLYGON mesh
|
//_END ___ if you are loading a GENERIC POLYGON mesh
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//_BEGIN___ if you are loading a TRIMESH mesh
|
//_BEGIN___ if you are loading a TRIMESH mesh
|
||||||
std::vector<std::vector<vcg::Point3f> > polygonVect(1); // it is a vector of polygon loops
|
std::vector<std::vector<vcg::Point3f> > polygonVect(1); // it is a vector of polygon loops
|
||||||
polygonVect[0].resize(vertexesPerFace);
|
polygonVect[0].resize(vertexesPerFace);
|
||||||
std::vector<int> indexVVect(vertexesPerFace);
|
std::vector<int> indexVVect(vertexesPerFace);
|
||||||
|
@ -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]);
|
||||||
}
|
}
|
||||||
|
@ -590,10 +615,10 @@ public:
|
||||||
// final pass to manage the ZBrush PerVertex Color that are managed into comments
|
// final pass to manage the ZBrush PerVertex Color that are managed into comments
|
||||||
if(vertexColorVector.size()>0)
|
if(vertexColorVector.size()>0)
|
||||||
{
|
{
|
||||||
// if(vertexColorVector.size()!=m.vn){
|
// if(vertexColorVector.size()!=m.vn){
|
||||||
// qDebug("Warning Read %i vertices and %i vertex colors",m.vn,vertexColorVector.size());
|
// qDebug("Warning Read %i vertices and %i vertex colors",m.vn,vertexColorVector.size());
|
||||||
// qDebug("line count %i x 64 = %i",MRGBLineCount(), MRGBLineCount()*64);
|
// qDebug("line count %i x 64 = %i",MRGBLineCount(), MRGBLineCount()*64);
|
||||||
// }
|
// }
|
||||||
for(int i=0;i<m.vn;++i)
|
for(int i=0;i<m.vn;++i)
|
||||||
{
|
{
|
||||||
m.vert[i].C()=vertexColorVector[i];
|
m.vert[i].C()=vertexColorVector[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
|
||||||
|
@ -1047,9 +1101,9 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}; // end class
|
}; // end class
|
||||||
} // end Namespace tri
|
} // end Namespace tri
|
||||||
} // end Namespace io
|
} // end Namespace io
|
||||||
} // end Namespace vcg
|
} // end Namespace vcg
|
||||||
|
|
||||||
#endif // ndef __VCGLIB_IMPORT_OBJ
|
#endif // ndef __VCGLIB_IMPORT_OBJ
|
||||||
|
|
Loading…
Reference in New Issue