wip(assembler): M2 round 2 -- same-LOD borders watertight for MC/hybrid/DC; LOD0/1 transitions still open
Shared halo + deterministic border-quad ownership + T-junction conformance: 625/625 same-LOD for all three. LOD 2:1 prototype (collar zipper) fails MC 5 / hybrid 38 / DC 40 cases (corners, overhangs). Hybrid is bit-identical to MC on a sampled native SurfaceWorld cliff; DC rougher. Standalone only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MmSoF64BbRFmk9C3p1VsBJ
This commit is contained in:
1 parent
6953254349
commit
a3b7d2015e
34 files changed
+5028
-2048
No files matched your search
@@ -19,6 +19,7 @@ PIECES = (
|
||||
("riser1m", "one metre riser"),
|
||||
("cliff_overhang", "cliff ledge / overhang"),
|
||||
("organic_cave_chamber", "organic cave chamber wall"),
|
||||
("native_surface_cliff", "sampled SurfaceWorld cliff"),
|
||||
)
|
||||
WIDTH, HEIGHT = 288, 216
|
||||
BG = (239, 242, 244)
|
||||
@@ -56,14 +57,26 @@ def read_obj(path: Path):
|
||||
return vertices, normals, faces
|
||||
|
||||
|
||||
def project_mesh(vertices, faces, seam=False):
|
||||
def project_mesh(vertices, faces, seam=False, target=None):
|
||||
# One view is reused for every candidate in a row: azimuth 38°, elevation 27°.
|
||||
target = (0.0, 0.0, 0.0)
|
||||
if target is None:
|
||||
if vertices:
|
||||
bounds_min = tuple(min(v[i] for v in vertices) for i in range(3))
|
||||
bounds_max = tuple(max(v[i] for v in vertices) for i in range(3))
|
||||
target = tuple((bounds_min[i] + bounds_max[i]) * 0.5 for i in range(3))
|
||||
else:
|
||||
target = (0.0, 0.0, 0.0)
|
||||
view_dir = normalize((8.0, -10.0, 7.0))
|
||||
forward = tuple(-c for c in view_dir)
|
||||
right = normalize(cross(forward, (0.0, 0.0, 1.0)))
|
||||
up = normalize(cross(right, forward))
|
||||
scale = 20.2
|
||||
projected_bounds = []
|
||||
for point in vertices:
|
||||
rel = tuple(point[i] - target[i] for i in range(3))
|
||||
projected_bounds.append((dot(rel, right), dot(rel, up)))
|
||||
span_x = max((point[0] for point in projected_bounds), default=0.0) - min((point[0] for point in projected_bounds), default=0.0)
|
||||
span_y = max((point[1] for point in projected_bounds), default=0.0) - min((point[1] for point in projected_bounds), default=0.0)
|
||||
scale = min(20.2, 0.84 * min((WIDTH - 24) / max(span_x, 1.0e-6), (HEIGHT - 24) / max(span_y, 1.0e-6)))
|
||||
projected = []
|
||||
for p in vertices:
|
||||
rel = tuple(p[i] - target[i] for i in range(3))
|
||||
@@ -102,7 +115,10 @@ def raster(path: Path, color_by_x=False):
|
||||
for i in range(1, len(clipped) - 1):
|
||||
clipped_faces.append(((first, first), (first + i, first + i), (first + i + 1, first + i + 1)))
|
||||
vertices, normals, faces = clipped_vertices, clipped_normals, clipped_faces
|
||||
projected = project_mesh(vertices, faces, color_by_x)
|
||||
bounds_min = tuple(min(v[i] for v in vertices) for i in range(3))
|
||||
bounds_max = tuple(max(v[i] for v in vertices) for i in range(3))
|
||||
target = tuple((bounds_min[i] + bounds_max[i]) * 0.5 for i in range(3))
|
||||
projected = project_mesh(vertices, faces, color_by_x, target)
|
||||
pixels = Image.new("RGB", (WIDTH, HEIGHT), BG)
|
||||
zbuf = [float("inf")] * (WIDTH * HEIGHT)
|
||||
px = pixels.load()
|
||||
@@ -146,7 +162,7 @@ def raster(path: Path, color_by_x=False):
|
||||
draw = ImageDraw.Draw(pixels)
|
||||
# Project a visible segment on the LOD boundary plane, x=0.
|
||||
seam_world = [(-0.0, y, z) for y, z in ((-4, -4), (4, -4), (4, 4), (-4, 4), (-4, -4))]
|
||||
seam_points = project_mesh(seam_world, [], True)
|
||||
seam_points = project_mesh(seam_world, [], True, target)
|
||||
draw.line([(p[0], p[1]) for p in seam_points], fill=(181, 55, 49), width=2)
|
||||
return pixels
|
||||
|
||||
@@ -174,14 +190,14 @@ def main():
|
||||
captures.append(row)
|
||||
seam_row = []
|
||||
for method in METHODS:
|
||||
obj = RESULTS / "meshes" / f"lodseam_cliff_overhang_{method}.obj"
|
||||
image = capture_title(raster(obj, color_by_x=True), "LOD0 to LOD1 cliff seam", f"{method} | fine left, coarse right, x=0 seam")
|
||||
path = CAPTURES / f"lodseam_{method}.jpg"
|
||||
obj = RESULTS / "meshes" / f"lodseam_cliff_crossing_{method}.obj"
|
||||
image = capture_title(raster(obj, color_by_x=True), "Sharp cliff across LOD border", f"{method} | LOD0 left, LOD1 right, x=0")
|
||||
path = CAPTURES / f"lodseam_cliff_crossing_{method}.jpg"
|
||||
image.save(path, quality=86, optimize=True)
|
||||
seam_row.append(image)
|
||||
captures.append(seam_row)
|
||||
|
||||
sheet = Image.new("RGB", (WIDTH * 3, (HEIGHT + 30) * 6), (221, 227, 230))
|
||||
sheet = Image.new("RGB", (WIDTH * 3, (HEIGHT + 30) * len(captures)), (221, 227, 230))
|
||||
draw = ImageDraw.Draw(sheet)
|
||||
for row_index, row in enumerate(captures):
|
||||
for col_index, image in enumerate(row):
|
||||
|
||||
Reference in new issue
Block a user