ignore duplicate geometry when importing
parent
ab7961df0c
commit
f80535f543
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue