// Reproduce the ADJACENT-MERGE MATERIAL BLEED and validate a fix — CPU oracle.
//
// Symptom (in-game): where two brushes with DIFFERENT materials merge, the colour
// bleeds across the seam. Hypothesis: the plane-set bake dedups parallel faces
// (>0.999) into ONE plane, so two COPLANAR faces from different brushes collapse to a
// single plane whose material = the FIRST-captured brush. Everything on that merged
// face gets one material regardless of which brush is actually under each cell → bleed.
// (The deployed "nearest-to-snapped-vertex" material pick can't help: after dedup the
// cell has ONE plane, so there's nothing to choose between.)
//
// Geometry: two axis boxes sharing the x=0 plane, with COPLANAR tops (y=2), different
// materials (A=1 for x<0, B=2 for x>0). Also an OVERLAP variant (x in [-1,1]).
//
// Methods compared, per top-surface cell:
// FIRST — material of the first-captured plane after dedup (models the current bake).
// NEAREST — material of the plane whose |dist to cell CENTRE| is smallest (old bake).
// FIX — material of the brush with the smallest union-SDF at the cell centre
// (= the brush the cell is most INSIDE = the true surface owner).
// Correct owner: brush the cell centre is laterally inside (A: x<0, B: x>0).
#include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm>
struct V3 { float x, y, z; };
static V3 operator-(V3 a, V3 b) { return {a.x - b.x, a.y - b.y, a.z - b.z}; }
static float dot(V3 a, V3 b) { return a.x * b.x + a.y * b.y + a.z * b.z; }
struct Plane { V3 n; float d; };
struct Brush { std::vector<Plane> pl; int mat; };
static float bsdf(V3 p, const Brush& b) { float m = -1e30f; for (auto& q : b.pl) m = fmaxf(m, dot(q.n, p) - q.d); return m; }
static Brush box(V3 lo, V3 hi, int mat) {
Brush b; b.mat = mat;
b.pl = { {{1,0,0}, hi.x}, {{-1,0,0}, -lo.x},
{{0,1,0}, hi.y}, {{0,-1,0}, -lo.y},
{{0,0,1}, hi.z}, {{0,0,-1}, -lo.z} };
return b;
}
// Replicate bake_planeset per-cell capture (T window, onbrush, csg4 not-buried, dedup)
// and return the three material choices + the captured plane count.
struct Res { int first, nearest, fix, cl_count; };
static Res bakeCell(V3 c, const std::vector<Brush>& B, float vox) {
float T = vox * 1.2f;
V3 cl_n[3]; float cl_d[3]; int cl_mat[3]; int cl_count = 0;
int nearest_mat = 0; float best_absf = 1e30f;
for (size_t ei = 0; ei < B.size(); ei++) {
const Brush& ce = B[ei];
for (auto& pl : ce.pl) {
float fd = dot(pl.n, c) - pl.d;
if (fabsf(fd) >= T) continue;
bool onbrush = true; // cell inside this brush's OTHER planes (~T)
for (auto& q : ce.pl) { if (&q == &pl) continue; if (dot(q.n, c) - q.d > T) { onbrush = false; break; } }
if (!onbrush) continue;
V3 fpt = { c.x - pl.n.x * fd, c.y - pl.n.y * fd, c.z - pl.n.z * fd }; // point on the face
V3 qp = { fpt.x + pl.n.x * (vox * 0.5f), fpt.y + pl.n.y * (vox * 0.5f), fpt.z + pl.n.z * (vox * 0.5f) };
bool buried = false; // csg4: face buried inside another brush?
for (size_t ej = 0; ej < B.size() && !buried; ej++) {
if (ej == ei) continue;
if (bsdf(qp, B[ej]) < 0.0f) buried = true;
}
if (buried) continue;
int matched = -1; // dedup by parallel normal
for (int k = 0; k < cl_count; k++) if (fabsf(dot(pl.n, cl_n[k])) > 0.999f) { matched = k; break; }
if (matched < 0 && cl_count < 3) { cl_n[cl_count] = pl.n; cl_d[cl_count] = pl.d; cl_mat[cl_count] = ce.mat; cl_count++; }
if (fabsf(fd) < best_absf) { best_absf = fabsf(fd); nearest_mat = ce.mat; }
}
}
Res r; r.cl_count = cl_count;
r.first = cl_count > 0 ? cl_mat[0] : 0;
r.nearest = nearest_mat;
// FIX: material of the brush the cell is most INSIDE (smallest union-SDF), restricted
// to brushes that actually contributed a captured face at this cell.
int fix_mat = r.first; float best_sdf = 1e30f;
for (size_t ei = 0; ei < B.size(); ei++) {
bool contributes = false; // did this brush contribute a captured plane?
for (auto& pl : B[ei].pl) {
float fd = dot(pl.n, c) - pl.d; if (fabsf(fd) >= T) continue;
bool onbrush = true; for (auto& q : B[ei].pl) { if (&q == &pl) continue; if (dot(q.n, c) - q.d > T) { onbrush = false; break; } }
if (onbrush) { contributes = true; break; }
}
if (!contributes) continue;
float s = bsdf(c, B[ei]);
if (s < best_sdf) { best_sdf = s; fix_mat = B[ei].mat; }
}
r.fix = fix_mat;
return r;
}
static void run(const char* name, const std::vector<Brush>& B, float vox) {
int nfirst = 0, nnear = 0, nfix = 0, total = 0, band = 0;
for (float cx = -3.5f; cx <= 3.5f + 1e-4f; cx += vox) {
V3 c = { cx, 2.0f - vox * 0.5f, 0.0f }; // cell centre just under the coplanar top
int correct = (cx < 0.0f) ? 1 : 2;
Res r = bakeCell(c, B, vox);
if (r.cl_count == 0) continue; // no face here
total++;
if (r.cl_count >= 2) band++; // cells that captured >1 plane before dedup would-be
if (r.first != correct) nfirst++;
if (r.nearest != correct) nnear++;
if (r.fix != correct) nfix++;
}
printf("%-14s cells=%3d BLEED: first=%3d nearest=%3d FIX=%3d\n", name, total, nfirst, nnear, nfix);
}
int main() {
float vox = 0.224f;
// Adjacent: share x=0, coplanar tops y=2.
std::vector<Brush> adj = { box({-4,-4,-4},{0,2,4}, 1), box({0,-4,-4},{4,2,4}, 2) };
// Overlapping: A x[-4,1], B x[-1,4] overlap [-1,1], coplanar tops.
std::vector<Brush> ovl = { box({-4,-4,-4},{1,2,4}, 1), box({-1,-4,-4},{4,2,4}, 2) };
printf("Material-merge bleed oracle (correct = brush the cell is laterally inside):\n");
run("adjacent", adj, vox);
run("overlapping", ovl, vox);
printf("\nPASS if FIX == 0 while first/nearest > 0 (bleed reproduced AND fixed).\n");
return 0;
}