generate_asset: --baker vertex — IDW voxel-grid vertex-color baker (dark-patch fix)
Same sampler as trellis-mac TRELLIS2_BAKER=vertex; Metal texel path retained as-is. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
754d403e62
commit
746e727da2
@ -212,6 +212,40 @@ def _export_pbr(mesh, path: Path, *, baker: str, target: Optional[int], texture_
|
||||
faces = torch.from_numpy(simplified_faces).to(dtype=mesh.faces.dtype)
|
||||
pre_simplified = True
|
||||
|
||||
if baker == "vertex":
|
||||
# Dark-patch fix (MODELBEAST BENCHMARKS 2026-07-19): the Metal texel
|
||||
# sampler mangles clean decoder attrs; sample the voxel grid at mesh
|
||||
# vertices (cKDTree IDW, ~0.3s) and ship linear vertex colors.
|
||||
import numpy as np
|
||||
import trimesh
|
||||
from scipy.spatial import cKDTree
|
||||
|
||||
v_np = vertices.numpy()
|
||||
f_np = faces.numpy()
|
||||
coords_np = mesh.coords.cpu().numpy().astype(np.float32)
|
||||
if coords_np.shape[1] == 4:
|
||||
coords_np = coords_np[:, 1:4]
|
||||
attrs_np = mesh.attrs.float().cpu().numpy()
|
||||
vsz = float(mesh.voxel_size)
|
||||
origin = np.array([-0.5, -0.5, -0.5], np.float32)
|
||||
tree = cKDTree(coords_np * vsz + origin + vsz * 0.5)
|
||||
d, idx = tree.query(v_np, k=4, workers=-1)
|
||||
w = 1.0 / (d + vsz * 0.05) ** 2
|
||||
w[d > vsz * 1.5] = 0.0
|
||||
ws = w.sum(1, keepdims=True)
|
||||
has = (ws > 0).squeeze()
|
||||
ws[ws == 0] = 1.0
|
||||
rgb = np.clip(((attrs_np[idx] * (w / ws)[..., None]).sum(1))[:, 0:3], 0, 1)
|
||||
rgb[~has] = np.clip(attrs_np[idx[~has, 0], 0:3], 0, 1)
|
||||
v_gltf = np.stack([v_np[:, 0], v_np[:, 2], -v_np[:, 1]], axis=1)
|
||||
out = trimesh.Trimesh(vertices=v_gltf, faces=f_np, process=False)
|
||||
rgba = np.concatenate([rgb, np.ones((len(v_gltf), 1))], 1)
|
||||
out.visual = trimesh.visual.ColorVisuals(
|
||||
out, vertex_colors=(rgba * 255).astype(np.uint8)) # LINEAR
|
||||
out.export(str(path))
|
||||
return {"baker": "vertex", "pre_simplified": pre_simplified,
|
||||
"triangles": int(len(f_np)), "vertices": int(len(v_np))}
|
||||
|
||||
if baker == "metal":
|
||||
available, reason = _metal_baker_available()
|
||||
if not available:
|
||||
@ -394,7 +428,7 @@ def _parse_args():
|
||||
parser.add_argument("image", type=Path)
|
||||
parser.add_argument("--output-dir", type=Path, required=True)
|
||||
parser.add_argument("--backend", choices=("auto", "mps", "mlx-experimental"), default="auto")
|
||||
parser.add_argument("--baker", choices=("auto", "metal", "kdtree"), default="auto")
|
||||
parser.add_argument("--baker", choices=("auto", "metal", "kdtree", "vertex"), default="auto")
|
||||
parser.add_argument("--pipeline-type", choices=("512", "1024", "1024_cascade"), default="512")
|
||||
parser.add_argument("--seed", type=int, default=42)
|
||||
parser.add_argument("--steps", type=int)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user