From 0358bc07b8b9759f2edf332a4b296830961d6360 Mon Sep 17 00:00:00 2001 From: Eric Wasylishen Date: Sun, 23 Apr 2017 02:06:20 -0600 Subject: [PATCH] common: mesh_t: first draft of tjunc fixing --- common/mesh.cc | 139 ++++++++++++++++++++++++++++++++++++++--- include/common/mesh.hh | 13 +++- light/test_light.cc | 15 ++++- 3 files changed, 156 insertions(+), 11 deletions(-) diff --git a/common/mesh.cc b/common/mesh.cc index f7555680..85856a86 100644 --- a/common/mesh.cc +++ b/common/mesh.cc @@ -21,10 +21,25 @@ #include #include +// FIXME: Remove +#include +#include + +#include +#include #include using namespace std; +// FIXME: Remove +std::vector qvecsToGlm(std::vector qvecs) { + std::vector res; + for (const auto &qvec : qvecs) { + res.push_back(glm::vec3(qvec[0], qvec[1], qvec[2])); + } + return res; +} + mesh_t buildMesh(const vector> &faces) { // FIXME: this is ugly @@ -33,11 +48,21 @@ mesh_t buildMesh(const vector> &faces) int nextVert = 0; map posToVertIndex; + vector faceplanes; vector> facesWithIndices; for (const auto &face : faces) { vector vertIndices; + // compute face plane + const auto glmvecs = qvecsToGlm(face); + glm::vec4 gp = GLM_PolyPlane(glmvecs); + qplane3f qp(qvec3f(gp.x, gp.y, gp.z), gp.w); + faceplanes.push_back(qp); + for (const auto &vert : face) { + float distOff = qp.distAbove(vert); + Q_assert(fabs(distOff) < 0.001); + const pos_t pos = make_tuple(vert[0], vert[1], vert[2]); const auto it = posToVertIndex.find(pos); @@ -65,6 +90,7 @@ mesh_t buildMesh(const vector> &faces) mesh_t res; res.verts = vertsVec; res.faces = facesWithIndices; + res.faceplanes = faceplanes; return res; } @@ -83,19 +109,118 @@ std::vector> meshToFaces(const mesh_t &mesh) return res; } - -static aabb3f mesh_face_bbox(const mesh_t &mesh, int facenum) +aabb3f mesh_face_bbox(const mesh_t &mesh, facenum_t facenum) { const std::vector &face = mesh.faces.at(facenum); + const qvec3f vert0 = mesh.verts.at(face.at(0)); + aabb3f bbox(vert0, vert0); + + for (int vert_i : face) { + const qvec3f vert = mesh.verts.at(vert_i); + bbox = bbox.expand(vert); + } + return bbox; +} + +static octree_t build_vert_octree(const mesh_t &mesh) +{ + std::vector> vertBboxNumPairs; + + for (int i=0; i TJUNC_DIST_EPSILON) + return; // not on the face plane + + // N.B. we will modify the `face` std::vector within this loop + for (int i=0; i TJUNC_DIST_EPSILON) + continue; + + // N.B.: not a distance + float fracOfLine = FractionOfLine(qToG(v0), qToG(v1), qToG(potentialVertPos)); + if (fracOfLine < 0 || fracOfLine > 1) + continue; + + // do it + auto it = face.begin(); + std::advance(it, i + 1); + face.insert(it, vnum); + Q_assert(face.at(i + 1) == vnum); + return; + } + + // didn't do it + return; +} + +template +static set vecToSet(const vector &vec) { + set res; + for (const auto &item : vec) { + res.insert(item); + } + return res; +} + +void cleanupFace(mesh_t &mesh, + facenum_t i, + const octree_t &vertoctree) { + + aabb3f facebbox = mesh_face_bbox(mesh, i); + facebbox = facebbox.grow(qvec3f(1,1,1)); + + const set face_vert_set = vecToSet(mesh.faces.at(i)); + const vector nearbyverts = vertoctree.queryTouchingBBox(facebbox); + + for (vertnum_t vnum : nearbyverts) { + // skip verts that are already on the face + if (face_vert_set.find(vnum) != face_vert_set.end()) { + continue; + } + + // possibly add this vert + face_InsertVertIfNeeded(mesh, i, vnum); + } } void cleanupMesh(mesh_t &mesh) { - using facenum_t = int; - - std::vector> faces; - - octree_t octree = makeOctree(faces); + const octree_t vertoctree = build_vert_octree(mesh); + for (int i=0; i #include +#include + +using facenum_t = int; +using vertnum_t = int; +using meshface_t = std::vector; + +#define TJUNC_DIST_EPSILON 0.01 class mesh_t { public: std::vector verts; - std::vector> faces; + std::vector faces; + // this is redundant data with the verts, but we know the planes in advance + // and this saves having to estimate them from the verts + std::vector faceplanes; }; // Welds vertices at exactly the same position mesh_t buildMesh(const std::vector> &faces); std::vector> meshToFaces(const mesh_t &mesh); +aabb3f mesh_face_bbox(const mesh_t &mesh, facenum_t facenum); // Preserves the number and order of faces. // doesn't merge verts. diff --git a/light/test_light.cc b/light/test_light.cc index 371a505c..2dcc2ae9 100644 --- a/light/test_light.cc +++ b/light/test_light.cc @@ -616,16 +616,25 @@ TEST(mathlib, meshFixTJuncs) { const vector> polys { poly1, poly2, poly3 }; mesh_t m = buildMesh(polys); + + ASSERT_EQ(aabb3f(qvec3f(0,0,0), qvec3f(64,64,0)), mesh_face_bbox(m, 0)); + ASSERT_EQ(8, m.verts.size()); ASSERT_EQ(3, m.faces.size()); ASSERT_EQ(polys, meshToFaces(m)); cleanupMesh(m); + + const vector poly1_fixed { + { 0,0,0 }, + { 0,64,0 }, + { 64,64,0 }, + { 64,32,0 }, + { 64,0,0 } + }; const auto newFaces = meshToFaces(m); -#if 0 - EXPECT_NE(poly1, newFaces.at(0)); -#endif + EXPECT_EQ(poly1_fixed, newFaces.at(0)); EXPECT_EQ(poly2, newFaces.at(1)); EXPECT_EQ(poly3, newFaces.at(2)); }