stl ,functor and vertex duplicate

Started by
1 comment, last by Guthur 15 years, 5 months ago
hy. I'm try to import mesh from a collada file. I use a mesh class and in a file called import.cpp i'm import that mesh. so i declared a Vertex data vector and a index vector for store the data and at the end copy the vector data to the mesh vertex and index properties. i have create a vertex struct: struct Vertex { Vertex(){} Vertex(float x, float y, float z, float nx, float ny, float nz, float u, float v) { _x = x; _y = y; _z = z; _nx = nx; _ny = ny; _nz = nz; _u = u; _v = v; } float _x, _y, _z, _nx, _ny, _nz, _u, _v; bool operator ==(const Vertex& other) const; bool operator < (const Vertex& other) const; static const DWORD FVF; }; now i insert the points from the collada importation and i must check if a point exist , for this i use a member var set<Vertex*> m_PresentVertex declared as std::set<Vertex *, ig::SLessPointerFunctor <Vertex> > m_PresentVertex and a functor namespace ig{ template <typename TClass> struct SLessPointerFunctor{ bool operator ()(const TClass * v1, const TClass * v2) const{ return *v1 < *v2; } }; } bool Vertex::operator<(const Vertex& other) const{ return (this->_x < other._x) || (this->_y < other._y) || (this->_z < other._z) || (this->_nx < other._nx) || (this->_ny < other._ny) || (this->_nz < other._nz); } for use the find method of the set container to check if a vertex already exist,but the normal values are different .if exist i duplicate the vertex , assign the new normal and insert it in the m_PresentVertex(for future check). If the vertex not exists i'm insert it in the index m_AllIndex.push_back(IndexFace->nVertex);and in the set container m_PresentVertex.insert(v1); i have a vector:m_AllVertex that contains all the vertex data (is imported before and contains all' the vertex of the mesh)and a vector m_AllIndex to insert tthe indexes of the mesh. m_pApi->NormalFaceReset(); m_pApi->FaceReset(); Vertex* vIter; int index = 0; typedef vector<Vertex*>::size_type sz; std::set<Vertex *, ig::SLessPointerFunctor <Vertex> >::iterator iter; for(index;m_pApi->NextFace();index++) { I_INDEXES *IndexFace = new I_INDEXES(); if(m_pApi->ImportFaces(IndexFace)) { //prendo il primo vertice Vertex * v1 = new Vertex(); v1->_nx =m_AllVertex[IndexFace->nVertex]->_nx; v1->_ny =m_AllVertex[IndexFace->nVertex]->_ny; v1->_nz =m_AllVertex[IndexFace->nVertex]->_nz; v1->_x =m_AllVertex[IndexFace->nVertex]->_x; v1->_y =m_AllVertex[IndexFace->nVertex]->_y; v1->_z =m_AllVertex[IndexFace->nVertex]->_z; //e la prima normale NORMAL * n1 = m_AllNormals[IndexFace->nNormal]; iter = m_PresentVertex.find(v1); //se il vertice è gia presente if(iter != m_PresentVertex.end()) { //leggo l'oggetto trovato vIter =*iter; //setto le nuove normali vIter->_nx = n1->nx; vIter->_ny = n1->ny; vIter->_nz = n1->nz; sz sizeArray = m_AllVertex.size(); // lo aggiungo ai vertici m_AllVertex.push_back(vIter); // il nuovo indice è la grandezza dell'array m_AllIndex.push_back((int)sizeArray); m_PresentVertex.insert(vIter);//i catch " invalid operator <" error!!!!! } else { m_AllIndex.push_back(IndexFace->nVertex); m_PresentVertex.insert(v1); } } the problem is that when i try to insert the first duplicate vertex with different normal i catch an error:" invalid operator <" I see that may be a problem of the functor , because if i change it the error disappear. Is the functor correct? ps. i use vc++ 8.0 thanks.
Advertisement
Your operator< is not correct. For sorting, it is necessary that operator< be a "strict weak ordering". Among other things, this means that you can't have a situation where a<b AND b<a. But that's exactly the situation you have there: For a vertex A with x=1 and y=0, and a vertex B with x=0 and y=1, A<B and B<A both return true, because each has at least one component less than the corresponding component on the other object.

The solution is to reconsider if and why you need your vertices to be sorted, as opposed to merely unique (as a hash table would provide). If you actually do, rewrite operator< in a way that will accomplish that. (Your current implementation accomplishes nothing useful.)
Just created a COLLADA loader there myself, it might have a slight issue with textures though :(. About to do some more work on it actually :p

Just to give you an idea of what direction i went with mine...

-I used a triangulated collada file, then loaded each xml node in to a custom TreeList.
-I loaded all the vertex positions first and created the vertex objects, note they only have position at this stage.
-Then i read the next 2 sources in to a normal and a uv std::vector<>.
-Then the triangle index data is read and the index numbers used to build the indice list and to add the normal and uv coordinates to the respective vertice.

Note the read order is maintained so as to make proper use of the index values in <triangles>

data assumptions
<mesh>
<source "positions">
<source "Normal">
<source "UVMap">
<triangles> ((VertexIndex) (Normal Index) (UVMap)) * 3 for each triangle
</mesh>
Innovation not reiterationIf at any point I look as if I know what I'm doing don't worry it was probably an accident.

This topic is closed to new replies.

Advertisement