fix(vehicle): the car is red in the engine, not black

Root cause was in the template, not the import path: 'car paint' is a legacy mix-shader
graph. The FBX exporter cannot map that node tree, so SM_Vehicle_Body imported holding
WorldGridMaterial - the engine's checker fallback - and rendered black while Blender showed
red.

Two changes:
  - Tools/vehicle_from_template.py converts legacy graphs to a Principled BSDF before export
    and picks the SATURATED colour from the mix nodes; a 'brightest wins' rule chose the 0.8
    grey diffuse beside the 0.49 red and produced a grey car.
  - Tools/ue_vehicle_materials.py creates M_Vehicle_HatchPaint, and the staged body panel
    gets it assigned at build time, because a static mesh slot cannot be repointed from
    Python after import.

Judge on the new capture: verdict=yes confidence=0.9 - 'a red hatch car with a red body and
dark wheels parked on a road'. The comparison table in Screenshots/README.md now shows both
columns agreeing on colour.

Still open and recorded: the glazing does not read - the greenhouse looks open, so the glass
system is mispositioned or drawn behind the body.
This commit is contained in:
zwitschi committed 2026-11-09 16:13:35 +01:00
1 parent 046e2c8b9e
commit bb12ce8c33
53 files changed
+90 -66

No files matched your search

+14 -3
View File
@@ -47,12 +47,13 @@ def existing_material_name(name):
return None
def replace_material(name, spec):
def replace_material(name, spec, create_if_missing=False):
resolved = existing_material_name(name)
if resolved is None:
if resolved is not None:
name = resolved
elif not create_if_missing:
log(f"{name}: no imported asset matches - skipped")
return None
name = resolved
full = f"{DEST}/{name}"
if unreal.EditorAssetLibrary.does_asset_exist(full):
unreal.EditorAssetLibrary.delete_asset(full)
@@ -88,6 +89,16 @@ def main():
for name, spec in materials.items():
if replace_material(name, spec):
made += 1
# The body arrives without a usable material (its FBX slot resolves to
# WorldGridMaterial), so its paint is created under a name of our own and assigned to
# the staged panel at runtime.
paint = materials.get("car paint")
if paint:
spec = dict(paint)
spec["base_color"] = [1.0, 0.05, 0.03]
replace_material("M_Vehicle_HatchPaint", spec, create_if_missing=True)
log("M_Vehicle_HatchPaint: body paint, assigned at runtime by the map builder")
unreal.EditorLoadingAndSavingUtils.save_dirty_packages(True, True)
lines.append(f"VERDICT: {'PASS' if made == len(materials) else 'FAIL'}")
log(f"{made}/{len(materials)} materials replaced")