我的实现:
class VertexMap {
public:
VertexMap(double tolerance): m_tolerance(tolerance), m_invTolerance(1 / tolerance), m_offset(m_tolerance * 0.1) {
m_offset = m_tolerance * 0.1;
m_offset2 = m_offset * 2.0;
}
void add(const MbFloatPoint3D &pos, const MbFloatVector3D &normal, const MbFloatPoint &texture, size_t index) {
m_vertices.emplace(pos, normal, texture, index, m_invTolerance);
}
size_t findIndex(const MbFloatPoint3D &pos, const MbFloatVector3D &normal, const MbFloatPoint &texture) {
auto vertex = Vertex(pos, normal, texture, 0, m_invTolerance);
auto it = m_vertices.find(vertex);
auto itEnd = m_vertices.end();
if (it == itEnd) {
vertex.pos.x -= m_offset;
vertex.pos.y -= m_offset;
vertex.pos.z -= m_offset;
it = m_vertices.find(vertex); // (---)
if (it == itEnd) {
vertex.pos.x += m_offset2;
it = m_vertices.find(vertex); // (+--)
if (it != itEnd) {
vertex.pos.y += m_offset2;
it = m_vertices.find(vertex); // (++-)
if (it != itEnd) {
vertex.pos.x -= m_offset2;
it = m_vertices.find(vertex); // (-+-)
if (it != itEnd) {
vertex.pos.z += m_offset2;
it = m_vertices.find(vertex); // (-++)
if (it != itEnd) {
vertex.pos.y -= m_offset2;
it = m_vertices.find(vertex); // (--+)
if (it != itEnd) {
vertex.pos.x += m_offset2;
it = m_vertices.find(vertex); // (+-+)
if (it != itEnd) {
vertex.pos.y += m_offset2;
it = m_vertices.find(vertex); // (+++)
}
}
}
}
}
}
}
}
if (it != itEnd)
return it->index;
else
return SIZE_MAX;
}
private:
class Vertex {
public:
Vertex(const MbFloatPoint3D &pos, const MbFloatVector3D &normal, const MbFloatPoint &texture, size_t index, double invTolerance):
pos(pos), normal(normal),texture(texture), index(index) {
normalizedx = pos.x * invTolerance;
normalizedy = pos.y * invTolerance;
normalizedz = pos.z * invTolerance;
}
MbFloatPoint3D pos;
MbFloatVector3D normal;
MbFloatPoint texture;
size_t index;
int64_t normalizedx;
int64_t normalizedy;
int64_t normalizedz;
bool operator==(const Vertex &other) const {
return Equalsd(pos, other.pos) && Equalsd(normal, other.normal) && Equalsd(texture, other.texture);
}
};
struct VertexHasher
{
size_t operator()(const Vertex& k) const
{
size_t h1 = std::hash<int64_t>()(k.normalizedx);
size_t h2 = std::hash<int64_t>()(k.normalizedy);
size_t h3 = std::hash<int64_t>()(k.normalizedz);
return (h1 ^ (h2 << 1)) ^ h3;
}
};
double m_tolerance;
double m_invTolerance;
double m_offset;
double m_offset2;
std::unordered_set<Vertex, VertexHasher> m_vertices;
};