// Build+run: g++ -std=c++17 test_snap.cpp -o test_snap && ./test_snap
// CPU oracle for the plane-snap math (before any GPU/shader change).
// Verifies: cluster a cell's edge normals into distinct planes, then snap the
// vertex onto the exact plane (face) / crease-line (edge) / corner-point (corner).
// The snapped vertex MUST satisfy the exact plane equations — that's what makes it
// grid-independent and razor-sharp.
#include <cstdio>
#include <cmath>
#include <vector>
struct V3 { float x, y, z; };
static V3 sub(V3 a, V3 b){ return {a.x-b.x, a.y-b.y, a.z-b.z}; }
static V3 add(V3 a, V3 b){ return {a.x+b.x, a.y+b.y, a.z+b.z}; }
static V3 mul(V3 a, float s){ return {a.x*s, a.y*s, a.z*s}; }
static float dot(V3 a, V3 b){ return a.x*b.x + a.y*b.y + a.z*b.z; }
static V3 cross(V3 a, V3 b){ return {a.y*b.z-a.z*b.y, a.z*b.x-a.x*b.z, a.x*b.y-a.y*b.x}; }
struct Plane { V3 n; float d; }; // n·x = d (n unit)
struct Edge { V3 pos; V3 norm; }; // Hermite: crossing position + surface normal
// Cluster the cell's edge normals into <=3 distinct planes (tight, sign-agnostic).
// clean=false if a 4th distinct direction appears (=> organic, don't snap).
static int cluster(const std::vector<Edge>& edges, Plane out[3], bool& clean) {
int nc = 0; clean = true;
for (const auto& e : edges) {
float pd = dot(e.norm, e.pos); // plane offset for this edge
int matched = -1;
for (int c = 0; c < nc; c++)
if (std::fabs(dot(e.norm, out[c].n)) > 0.985f) { matched = c; break; }
if (matched < 0) {
if (nc < 3) { out[nc].n = e.norm; out[nc].d = pd; nc++; }
else clean = false;
}
}
return nc;
}
static V3 snap_plane(V3 x, Plane p) { // project x onto n·x=d
return sub(x, mul(p.n, dot(p.n, x) - p.d));
}
static V3 snap_line(V3 x, Plane a, Plane b) { // project x onto the two-plane crease
float c = dot(a.n, b.n);
float det = 1.0f - c*c;
if (std::fabs(det) < 1e-5f) return snap_plane(x, a); // near-parallel => 1 plane
float r0 = a.d - dot(a.n, x), r1 = b.d - dot(b.n, x);
float t0 = (r0 - c*r1) / det, t1 = (r1 - c*r0) / det;
return add(x, add(mul(a.n, t0), mul(b.n, t1)));
}
static V3 snap_corner(Plane a, Plane b, Plane c) { // 3-plane intersection point
float denom = dot(a.n, cross(b.n, c.n));
if (std::fabs(denom) < 1e-6f) return {1e30f,0,0}; // degenerate
V3 t = add(add(mul(cross(b.n, c.n), a.d), mul(cross(c.n, a.n), b.d)),
mul(cross(a.n, b.n), c.d));
return mul(t, 1.0f/denom);
}
static V3 do_snap(V3 x, const std::vector<Edge>& edges) {
Plane p[3]; bool clean;
int nc = cluster(edges, p, clean);
if (!clean) return x; // organic: leave the QEF result
if (nc == 1) return snap_plane(x, p[0]);
if (nc == 2) return snap_line(x, p[0], p[1]);
if (nc >= 3) return snap_corner(p[0], p[1], p[2]);
return x;
}
static float plane_err(V3 x, Plane p){ return std::fabs(dot(p.n, x) - p.d); }
int main() {
int fails = 0;
// Planes of a cube face at z=5 (up), side at x=3 (right), side at y=2 (fwd).
Plane pz{{0,0,1}, 5}, px{{1,0,0}, 3}, py{{0,1,0}, 2};
// --- FACE cell: all crossings on plane z=5, scattered in x,y ---------------
{
std::vector<Edge> es = {
{{1.2f, 0.4f, 5.0f}, {0,0,1}}, {{1.8f, 0.9f, 5.0f}, {0,0,-1}}, // sign flip ok
{{1.5f, 0.1f, 5.0f}, {0,0,1}},
};
V3 x = {1.5f, 0.5f, 4.3f}; // QEF vertex off the plane
V3 s = do_snap(x, es);
float e = plane_err(s, pz);
printf("FACE snap=(%.3f,%.3f,%.3f) plane_err=%.5f %s\n", s.x,s.y,s.z, e, e<1e-4f?"OK":"FAIL");
if (e >= 1e-4f) fails++;
}
// --- EDGE cell: crossings on z=5 and x=3 -> snap onto the crease line ------
{
std::vector<Edge> es = {
{{3.0f, 0.4f, 5.0f}, {0,0,1}}, {{3.0f, 0.9f, 5.0f}, {0,0,1}}, // top face
{{3.0f, 0.2f, 4.6f}, {1,0,0}}, {{3.0f, 0.7f, 4.2f}, {-1,0,0}}, // side face
};
V3 x = {2.6f, 0.5f, 4.4f};
V3 s = do_snap(x, es);
float e = plane_err(s, pz) + plane_err(s, px);
printf("EDGE snap=(%.3f,%.3f,%.3f) on-both-planes_err=%.5f %s\n", s.x,s.y,s.z, e, e<1e-4f?"OK":"FAIL");
if (e >= 1e-4f) fails++;
}
// --- CORNER cell: crossings on z=5, x=3, y=2 -> snap to the corner point ---
{
std::vector<Edge> es = {
{{3.0f, 2.0f, 5.0f}, {0,0,1}}, {{2.9f, 1.9f, 5.0f}, {0,0,1}},
{{3.0f, 1.8f, 4.7f}, {1,0,0}}, {{2.7f, 2.0f, 4.6f}, {0,1,0}},
};
V3 x = {2.5f, 1.5f, 4.5f};
V3 s = do_snap(x, es);
float e = plane_err(s, pz) + plane_err(s, px) + plane_err(s, py);
printf("CORNER snap=(%.3f,%.3f,%.3f) expect(3,2,5) err=%.5f %s\n", s.x,s.y,s.z, e, e<1e-4f?"OK":"FAIL");
if (e >= 1e-4f) fails++;
}
// --- ORGANIC cell: many varied normals (>3 clusters) -> must NOT snap ------
{
std::vector<Edge> es = {
{{0,0,0},{1,0,0}}, {{0,0,0},{0,1,0}}, {{0,0,0},{0,0,1}},
{{0,0,0},{0.7f,0.7f,0}}, {{0,0,0},{0,0.7f,0.7f}}, // 4th/5th direction
};
V3 x = {9,9,9};
V3 s = do_snap(x, es);
bool unchanged = (s.x==9 && s.y==9 && s.z==9);
printf("ORGANIC unchanged=%s %s\n", unchanged?"yes":"no", unchanged?"OK":"FAIL");
if (!unchanged) fails++;
}
printf("\n%s (%d failures)\n", fails==0?"ALL PASS":"FAILURES", fails);
return fails ? 1 : 0;
}