summaryrefslogtreecommitdiff
path: root/thirdparty/thekla_atlas/nvmesh/weld/Snap.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/thekla_atlas/nvmesh/weld/Snap.cpp')
-rw-r--r--thirdparty/thekla_atlas/nvmesh/weld/Snap.cpp100
1 files changed, 100 insertions, 0 deletions
diff --git a/thirdparty/thekla_atlas/nvmesh/weld/Snap.cpp b/thirdparty/thekla_atlas/nvmesh/weld/Snap.cpp
new file mode 100644
index 0000000000..b6bff4d83d
--- /dev/null
+++ b/thirdparty/thekla_atlas/nvmesh/weld/Snap.cpp
@@ -0,0 +1,100 @@
+// This code is in the public domain -- castanyo@yahoo.es
+
+#include <nvcore/RadixSort.h>
+
+#include <nvmesh/weld/Snap.h>
+#include <nvmesh/TriMesh.h>
+#include <nvmesh/geometry/Bounds.h>
+
+using namespace nv;
+
+namespace {
+
+ // Snap the given vertices.
+ void Snap(TriMesh::Vertex & a, TriMesh::Vertex & b, float texThreshold, float norThreshold)
+ {
+ a.pos = b.pos = (a.pos + b.pos) * 0.5f;
+
+ if (equal(a.tex.x, b.tex.x, texThreshold) && equal(a.tex.y, b.tex.y, texThreshold)) {
+ b.tex = a.tex = (a.tex + b.tex) * 0.5f;
+ }
+
+ if (equal(a.nor.x, b.nor.x, norThreshold) && equal(a.nor.y, b.nor.y, norThreshold) && equal(a.nor.z, b.nor.z, norThreshold)) {
+ b.nor = a.nor = (a.nor + b.nor) * 0.5f;
+ }
+ };
+
+} // nv namespace
+
+uint nv::SnapVertices(TriMesh * mesh, float posThreshold, float texThreshold, float norThreshold)
+{
+ nvDebug("--- Snapping vertices.\n");
+
+ // Determine largest axis.
+ Box box = MeshBounds::box(mesh);
+ Vector3 extents = box.extents();
+
+ int axis = 2;
+ if( extents.x > extents.y ) {
+ if( extents.x > extents.z ) {
+ axis = 0;
+ }
+ }
+ else if(extents.y > extents.z) {
+ axis = 1;
+ }
+
+ // @@ Use diagonal instead!
+
+
+ // Sort vertices according to the largest axis.
+ const uint vertexCount = mesh->vertexCount();
+ nvCheck(vertexCount > 2); // Must have at least two vertices.
+
+ // Get pos channel.
+ //PiMesh::Channel * pos_channel = mesh->GetChannel(mesh->FindChannel(VS_POS));
+ //nvCheck( pos_channel != NULL );
+
+ //const PiArray<Vec4> & pos_array = pos_channel->data;
+
+ Array<float> distArray;
+ distArray.resize(vertexCount);
+
+ for(uint v = 0; v < vertexCount; v++) {
+ if (axis == 0) distArray[v] = mesh->vertexAt(v).pos.x;
+ else if (axis == 1) distArray[v] = mesh->vertexAt(v).pos.y;
+ else distArray[v] = mesh->vertexAt(v).pos.z;
+ }
+
+ RadixSort radix;
+ const uint * xrefs = radix.sort(distArray.buffer(), distArray.count()).ranks();
+ nvCheck(xrefs != NULL);
+
+ uint snapCount = 0;
+ for(uint v = 0; v < vertexCount-1; v++) {
+ for(uint n = v+1; n < vertexCount; n++) {
+ nvDebugCheck( distArray[xrefs[v]] <= distArray[xrefs[n]] );
+
+ if (fabs(distArray[xrefs[n]] - distArray[xrefs[v]]) > posThreshold) {
+ break;
+ }
+
+ TriMesh::Vertex & v0 = mesh->vertexAt(xrefs[v]);
+ TriMesh::Vertex & v1 = mesh->vertexAt(xrefs[n]);
+
+ const float dist = length(v0.pos - v1.pos);
+
+ if (dist <= posThreshold) {
+ Snap(v0, v1, texThreshold, norThreshold);
+ snapCount++;
+ }
+ }
+ }
+
+ // @@ todo: debug, make sure that the distance between vertices is now >= threshold
+
+ nvDebug("--- %u vertices snapped\n", snapCount);
+
+ return snapCount;
+};
+