ModelTranslator: use adaptive ray distance in bake (auto), report source
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
3ae981e40d
commit
e66ba296c1
@@ -98,6 +98,30 @@ def _import_fbx_joined(path, warnings):
|
||||
return obj
|
||||
|
||||
|
||||
def _measure_separation(low, high, limit=10000):
|
||||
"""低模面心到高模表面最近距离数组(供自适应射线)。超 limit 面则均匀采样。
|
||||
高模 BVH 无命中的面丢弃;返回距离列表(可能为空)。"""
|
||||
from mathutils.bvhtree import BVHTree
|
||||
hv = [high.matrix_world @ v.co for v in high.data.vertices]
|
||||
hp = [tuple(p.vertices) for p in high.data.polygons]
|
||||
bvh = BVHTree.FromPolygons(hv, hp, all_triangles=False)
|
||||
polys = low.data.polygons
|
||||
n = len(polys)
|
||||
if n == 0:
|
||||
return []
|
||||
if n <= limit:
|
||||
idxs = range(n)
|
||||
else:
|
||||
idxs = [round(i * (n - 1) / float(limit - 1)) for i in range(limit)]
|
||||
mw = low.matrix_world
|
||||
dists = []
|
||||
for i in idxs:
|
||||
hit = bvh.find_nearest(mw @ polys[i].center)
|
||||
if hit[0] is not None and hit[3] is not None:
|
||||
dists.append(hit[3])
|
||||
return dists
|
||||
|
||||
|
||||
def _setup_bake_target(low, stem):
|
||||
"""低模换成单一烘焙材质,返回接收烘焙结果的 image 节点。"""
|
||||
import bpy
|
||||
@@ -210,7 +234,25 @@ def main():
|
||||
% (BBOX_TOL * 100,
|
||||
[round(d, 3) for d in high_dims],
|
||||
[round(d, 3) for d in low_dims]))
|
||||
ray = estimate_ray_distance(low_dims) if ray_arg == "auto" else float(ray_arg)
|
||||
if ray_arg != "auto":
|
||||
ray = float(ray_arg)
|
||||
ray_info = {"source": "explicit", "distance_p99": None,
|
||||
"value": ray, "capped": False}
|
||||
else:
|
||||
dists = _measure_separation(low, high)
|
||||
try:
|
||||
if not dists:
|
||||
raise ValueError("低模面心到高模无有效最近距离")
|
||||
ray_info = adaptive_ray_distance(dists, low_dims)
|
||||
ray_info["source"] = "adaptive"
|
||||
ray = ray_info["value"]
|
||||
if ray_info["capped"]:
|
||||
warnings.append("自适应射线达包围盒对角线 1% 上限,请检查高低模对应关系")
|
||||
except ValueError as e:
|
||||
ray = estimate_ray_distance(low_dims)
|
||||
ray_info = {"source": "fixed_fallback", "distance_p99": None,
|
||||
"value": ray, "capped": False}
|
||||
warnings.append("自适应射线测量失败(%s),回退固定射线" % e)
|
||||
|
||||
stem = output_stem(os.path.splitext(os.path.basename(low_fbx))[0])
|
||||
os.makedirs(outdir, exist_ok=True)
|
||||
@@ -238,9 +280,13 @@ def main():
|
||||
bpy.ops.export_scene.fbx(filepath=out_fbx, use_selection=True,
|
||||
path_mode='STRIP', embed_textures=False)
|
||||
|
||||
ray_info = dict(ray_info)
|
||||
ray_info["distance_p99"] = (None if ray_info["distance_p99"] is None
|
||||
else round(ray_info["distance_p99"], 6))
|
||||
ray_info["value"] = round(ray_info["value"], 6)
|
||||
print("MT_SUMMARY " + json.dumps(
|
||||
{"stem": stem, "fbx": os.path.basename(out_fbx), "outputs": outputs,
|
||||
"size": size, "ray_distance": round(ray, 6),
|
||||
"size": size, "ray_distance": round(ray, 6), "ray": ray_info,
|
||||
"high_tris": len(high.data.polygons), "low_tris": len(low.data.polygons),
|
||||
"warnings": warnings}, ensure_ascii=False))
|
||||
|
||||
|
||||
@@ -33,6 +33,11 @@ def main():
|
||||
blender_args=("-t", "1"))
|
||||
print("== %s(高 %d 面 / 低 %d 面,射线距离 %.4f)-> %s" %
|
||||
(s["stem"], s["high_tris"], s["low_tris"], s["ray_distance"], outdir))
|
||||
r = s.get("ray", {})
|
||||
p99 = "n/a" if r.get("distance_p99") is None else "%.4f" % r["distance_p99"]
|
||||
print(" 射线: 来源=%s P99=%s 距离=%.4f%s" %
|
||||
(r.get("source", "?"), p99, r.get("value", s["ray_distance"]),
|
||||
"(已夹取)" if r.get("capped") else ""))
|
||||
for name, fname in s["outputs"].items():
|
||||
print(" %-10s %s" % (name, fname))
|
||||
for w in s["warnings"]:
|
||||
|
||||
Reference in New Issue
Block a user