www.pudn.com > tristripper-1.1.0-beta-5.zip > varrays_normalizer.cpp
#include "stdafx.h"
#include "varrays_normalizer.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
// Members Functions
//////////////////////////////////////////////////////////////////////
size_t varrays_normalizer::Normalize()
{
typedef std::vector indices_pointers;
typedef std::map vertex_map;
typedef vertex_map::const_iterator vertex_map_const_iterator;
if (m_Mesh.m_VArrays[gl_mesh::vertex].empty() || m_Mesh.m_VArrays[gl_mesh::normal].empty() || m_Mesh.m_VArrays[gl_mesh::texture_coord0].empty())
throw ("Normalizer: one of the vertex arrays is empty (need vertex/normal/texcoord0)");
cmp_lt_vertex CmpFct(
m_Mesh.m_VArrays[gl_mesh::vertex],
m_Mesh.m_VArrays[gl_mesh::normal],
m_Mesh.m_VArrays[gl_mesh::texture_coord0]
);
// Vertex Map:
// - key = position of a vertex in the vertex arrays
// - contains the list of indices referencing to that vertex
// - ensure there aren't duplicate vertex entries
// (two keys that are different by position will be equal for the map
// if they lead to equivalent vertices)
vertex_map VertexMap(CmpFct);
// Go tru all submeshes and all indices and put the indices into the map
// Note: unreference vertices will eliminated that way
for (size_t i = 0; i < m_Mesh.m_SubMeshes.size(); ++i) {
const indices & Indices = m_Mesh.m_SubMeshes[i].Indices();
for (size_t j = 0; j < Indices.size(); ++j)
VertexMap[Indices[j]].push_back((index *) &(Indices[j]));
}
// Create new vertex arrays and remap the indices
size_t NewVASize = VertexMap.size();
varray Vertex; Vertex.reserve(NewVASize);
varray Normal; Normal.reserve(NewVASize);
varray TexCoord; TexCoord.reserve(NewVASize);
varray & OldVertex = m_Mesh.m_VArrays[gl_mesh::vertex];
varray & OldNormal = m_Mesh.m_VArrays[gl_mesh::normal];
varray & OldTexCoord = m_Mesh.m_VArrays[gl_mesh::texture_coord0];
for (vertex_map_const_iterator It = VertexMap.begin(); It != VertexMap.end(); ++It) {
const index VAPos = (* It).first;
const indices_pointers & IndicesPtr = (* It).second;
const index NewIndex = index(Vertex.size() / 3);
Vertex.push_back(OldVertex[VAPos * 3 + 0]);
Vertex.push_back(OldVertex[VAPos * 3 + 1]);
Vertex.push_back(OldVertex[VAPos * 3 + 2]);
Normal.push_back(OldNormal[VAPos * 3 + 0]);
Normal.push_back(OldNormal[VAPos * 3 + 1]);
Normal.push_back(OldNormal[VAPos * 3 + 2]);
TexCoord.push_back(OldTexCoord[VAPos * 2 + 0]);
TexCoord.push_back(OldTexCoord[VAPos * 2 + 1]);
for (indices_pointers::const_iterator IndIt = IndicesPtr.begin(); IndIt != IndicesPtr.end(); ++IndIt)
** IndIt = NewIndex;
}
// Replace the old arrays with the new ones
std::swap(Vertex, OldVertex);
std::swap(Normal, OldNormal);
std::swap(TexCoord, OldTexCoord);
return NewVASize;
}
bool varrays_normalizer::cmp_lt_vertex::operator () (const index & a, const index & b) const {
// To find out whether the vertex referenced by a is less than the vertex referenced by b,
// we compare each coordinates of the 2 vertices one at the time.
// This can be seen as a comparison of two strings where the strings hold
// coordinates instead of characters.
// Compare the vertex coords
if (m_Vertex[a * 3 + 0] < m_Vertex[b * 3 + 0])
return true;
else if (m_Vertex[a * 3 + 0] > m_Vertex[b * 3 + 0])
return false;
else if (m_Vertex[a * 3 + 1] < m_Vertex[b * 3 + 1])
return true;
else if (m_Vertex[a * 3 + 1] > m_Vertex[b * 3 + 1])
return false;
else if (m_Vertex[a * 3 + 2] < m_Vertex[b * 3 + 2])
return true;
else if (m_Vertex[a * 3 + 2] > m_Vertex[b * 3 + 2])
return false;
// Compare the normal vector coords
if (m_Normal[a * 3 + 0] < m_Normal[b * 3 + 0])
return true;
else if (m_Normal[a * 3 + 0] > m_Normal[b * 3 + 0])
return false;
else if (m_Normal[a * 3 + 1] < m_Normal[b * 3 + 1])
return true;
else if (m_Normal[a * 3 + 1] > m_Normal[b * 3 + 1])
return false;
else if (m_Normal[a * 3 + 2] < m_Normal[b * 3 + 2])
return true;
else if (m_Normal[a * 3 + 2] > m_Normal[b * 3 + 2])
return false;
// Compare the texture coords
if (m_TexCoord[a * 2 + 0] < m_TexCoord[b * 2 + 0])
return true;
else if (m_TexCoord[a * 2 + 0] > m_TexCoord[b * 2 + 0])
return false;
else if (m_TexCoord[a * 2 + 1] < m_TexCoord[b * 2 + 1])
return true;
else if (m_TexCoord[a * 2 + 1] > m_TexCoord[b * 2 + 1])
return false;
return false;
}