ignore duplicate geometry when importing

metadata
Wenzel Jakob 2010-09-03 09:37:58 +02:00
parent ab7961df0c
commit f80535f543
1 changed files with 91 additions and 24 deletions

View File

@ -203,34 +203,72 @@ VertexData *fetchVertexData(Transform transform, std::ostream &os,
/// For using vertices as keys in an associative structure
struct vertex_key_order : public
std::binary_function<Vertex, Vertex, bool> {
public:
static int compare(const Vertex &v1, const Vertex &v2) {
if (v1.v.x < v2.v.x) return -1;
else if (v1.v.x > v2.v.x) return 1;
if (v1.v.y < v2.v.y) return -1;
else if (v1.v.y > v2.v.y) return 1;
if (v1.v.z < v2.v.z) return -1;
else if (v1.v.z > v2.v.z) return 1;
if (v1.n.x < v2.n.x) return -1;
else if (v1.n.x > v2.n.x) return 1;
if (v1.n.y < v2.n.y) return -1;
else if (v1.n.y > v2.n.y) return 1;
if (v1.n.z < v2.n.z) return -1;
else if (v1.n.z > v2.n.z) return 1;
if (v1.uv.x < v2.uv.x) return -1;
else if (v1.uv.x > v2.uv.x) return 1;
if (v1.uv.y < v2.uv.y) return -1;
else if (v1.uv.y > v2.uv.y) return 1;
return 0;
}
bool operator()(const Vertex &v1, const Vertex &v2) const {
if (v1.v.x < v2.v.x) return true;
else if (v1.v.x > v2.v.x) return false;
if (v1.v.y < v2.v.y) return true;
else if (v1.v.y > v2.v.y) return false;
if (v1.v.z < v2.v.z) return true;
else if (v1.v.z > v2.v.z) return false;
if (v1.n.x < v2.n.x) return true;
else if (v1.n.x > v2.n.x) return false;
if (v1.n.y < v2.n.y) return true;
else if (v1.n.y > v2.n.y) return false;
if (v1.n.z < v2.n.z) return true;
else if (v1.n.z > v2.n.z) return false;
if (v1.uv.x < v2.uv.x) return true;
else if (v1.uv.x > v2.uv.x) return false;
if (v1.uv.y < v2.uv.y) return true;
else if (v1.uv.y > v2.uv.y) return false;
return compare(v1, v2) < 0;
}
};
struct SimpleTriangle {
Point p0, p1, p2;
inline SimpleTriangle() { }
inline SimpleTriangle(const Point &p0, const Point &p1, const Point &p2)
: p0(p0), p1(p1), p2(p2) { }
};
struct triangle_key_order : public std::binary_function<SimpleTriangle, SimpleTriangle, bool> {
static int compare(const Point &v1, const Point &v2) {
if (v1.x < v2.x) return -1;
else if (v1.x > v2.x) return 1;
if (v1.y < v2.y) return -1;
else if (v1.y > v2.y) return 1;
if (v1.z < v2.z) return -1;
else if (v1.z > v2.z) return 1;
return 0;
}
bool operator()(const SimpleTriangle &t1, const SimpleTriangle &t2) const {
int result;
result = compare(t1.p0, t2.p0);
if (result == -1) return true;
if (result == 1) return false;
result = compare(t1.p1, t2.p1);
if (result == -1) return true;
if (result == 1) return false;
result = compare(t1.p2, t2.p2);
if (result == -1) return true;
if (result == 1) return false;
return false;
}
};
typedef std::map<SimpleTriangle, bool, triangle_key_order> TriangleMap;
void writeGeometry(std::string prefixName, std::string id, int geomIndex, std::string matID, Transform transform,
std::ostream &os, VertexData *vData, const std::string &meshesDirectory) {
std::ostream &os, VertexData *vData, TriangleMap &triMap, const std::string &meshesDirectory) {
std::vector<Vertex> vertexBuffer;
std::vector<Triangle> triangles;
std::map<Vertex, int, vertex_key_order> vertexMap;
size_t numMerged = 0, triangleIdx = 0;
size_t numMerged = 0, triangleIdx = 0, duplicates = 0;
Triangle triangle;
if (tess_data.size() == 0)
return;
@ -263,11 +301,38 @@ void writeGeometry(std::string prefixName, std::string id, int geomIndex, std::s
}
triangle.idx[triangleIdx++] = key;
if (triangleIdx == 3) {
triangles.push_back(triangle);
Point p0 = vertexBuffer[triangle.idx[0]].v,
p1 = vertexBuffer[triangle.idx[1]].v,
p2 = vertexBuffer[triangle.idx[2]].v;
if (triMap.find(SimpleTriangle(p0, p1, p2)) != triMap.end() ||
triMap.find(SimpleTriangle(p2, p0, p1)) != triMap.end() ||
triMap.find(SimpleTriangle(p1, p2, p0)) != triMap.end() ||
triMap.find(SimpleTriangle(p1, p0, p2)) != triMap.end() ||
triMap.find(SimpleTriangle(p0, p2, p1)) != triMap.end() ||
triMap.find(SimpleTriangle(p2, p1, p0)) != triMap.end()) {
/* This triangle is a duplicate from another one which exists
in the same geometry group -- we may be dealing with SketchUp,
which sometimes exports every face TWICE! */
duplicates++;
} else {
triMap[SimpleTriangle(p0, p1, p2)] = true;
triangles.push_back(triangle);
}
triangleIdx = 0;
}
}
if (duplicates > 0) {
if (triangles.size() == 0) {
SLog(EWarn, "%s: Only contains duplicates of already-existing geometry. Ignoring.");
os << "\t<!-- Ignored shape \"" << prefixName << "/"
<< id << "\" (mat=\"" << matID << "\"), since it only contains duplicate geometry. -->" << endl << endl;
return;
} else {
SLog(EWarn, "Geometry contains %i duplicate triangles!", duplicates);
}
}
SAssert(triangleIdx == 0);
SLog(EInfo, "%s: Converted " SIZE_T_FMT " triangles, " SIZE_T_FMT
" vertices (merged " SIZE_T_FMT " vertices).", id.c_str(),
@ -315,8 +380,10 @@ void loadGeometry(std::string prefixName, Transform transform, std::ostream &os,
identifier = formatString("unnamedGeom_%i", unnamedCtr++);
}
}
TriangleMap triMap;
SLog(EInfo, "Converting geometry \"%s\" (instantiated by %s)..", identifier.c_str(), prefixName.c_str());
SLog(EInfo, "Converting geometry \"%s\" (instantiated by %s)..", identifier.c_str(),
prefixName == "" ? "/" : prefixName.c_str());
domMesh *mesh = geom.getMesh().cast();
if (!mesh)
SLog(EError, "Invalid geometry type encountered (must be a <mesh>)!");
@ -340,7 +407,7 @@ void loadGeometry(std::string prefixName, Transform transform, std::ostream &os,
SLog(EWarn, "Referenced material could not be found, substituting a lambertian BRDF.");
else
matID = matLookupTable[triangles->getMaterial()];
writeGeometry(prefixName, identifier, geomIndex, matID, transform, os, data, meshesDir);
writeGeometry(prefixName, identifier, geomIndex, matID, transform, os, data, triMap, meshesDir);
delete data;
++geomIndex;
}
@ -378,7 +445,7 @@ void loadGeometry(std::string prefixName, Transform transform, std::ostream &os,
else
matID = matLookupTable[polygons->getMaterial()];
writeGeometry(prefixName, identifier, geomIndex, matID, transform, os, data, meshesDir);
writeGeometry(prefixName, identifier, geomIndex, matID, transform, os, data, triMap, meshesDir);
delete data;
++geomIndex;
}
@ -418,7 +485,7 @@ void loadGeometry(std::string prefixName, Transform transform, std::ostream &os,
else
matID = matLookupTable[polylist->getMaterial()];
writeGeometry(prefixName, identifier, geomIndex, matID, transform, os, data, meshesDir);
writeGeometry(prefixName, identifier, geomIndex, matID, transform, os, data, triMap, meshesDir);
delete data;
++geomIndex;
}