bootstrap: finish project bootstrap — scale test, MPFB character, build docs

- Static-mesh scale test passes: 1 m = 100.00 cm, origin preserved, axis
  mapping east→+X / north→−Y / up→+Z (named presets ue_metric_v1 both sides).
- MPFB 2.0.18 acceptance passes: generated human + standard 137-bone rig
  with weights + v2 skin baked to 1024² diffuse; imports as SkeletalMesh
  with Skeleton, Material, and Texture2D in /Game/Test/Character.
- MPFB headless requires XDG_CONFIG_HOME at the Flatpak config tree;
  documented in Art/blender/README.md, probe in Tools/addon_compat_probe.py.
- Docs/build.md completed: fresh-checkout build, packaging, headless checks.
- Docs/setup.md reconciled with reality; ROADMAP/bootstrap closed out.
This commit is contained in:
zwitschi committed 2026-11-07 09:29:11 +01:00
1 parent 01939de9a0
commit 1c6b956435
21 files changed
+614 -33

No files matched your search

+81
View File
@@ -0,0 +1,81 @@
# Scale-test scene builder and FBX exporter for the Blender -> Unreal pipeline.
#
# Builds three 1 m cubes in the project geographic frame (EPSG:26911, origin
# Hollywood x Highland, X east / Y north / Z up):
# ScaleTest_A centred at (0, 0, 0.5) - origin + 1 m size reference
# ScaleTest_B centred at (10, 0, 0.5) - +10 m east probe
# ScaleTest_C centred at (0, 10, 0.5) - +10 m north probe
# and exports them as one FBX with the named export preset "ue_metric_v1".
#
# Run headless (see Art/blender/README.md for the Flatpak invocation):
# blender -b --factory-startup --python Tools/scale_test_export.py -- \
# --out /tmp/gigline/scaletest.fbx --save-blend Art/blender/scaletest/scale-test-<date>.blend
import argparse
import os
import sys
import bpy
def build_scene():
scene = bpy.context.scene
for obj in list(bpy.data.objects):
bpy.data.objects.remove(obj, do_unlink=True)
mat = bpy.data.materials.new("M_ScaleTest_Red")
mat.use_nodes = True
bsdf = mat.node_tree.nodes.get("Principled BSDF")
bsdf.inputs["Base Color"].default_value = (0.8, 0.05, 0.05, 1.0)
specs = {
"ScaleTest_A": (0.0, 0.0, 0.5),
"ScaleTest_B": (10.0, 0.0, 0.5),
"ScaleTest_C": (0.0, 10.0, 0.5),
}
for name, loc in specs.items():
bpy.ops.mesh.primitive_cube_add(size=1.0, location=loc)
obj = bpy.context.active_object
obj.name = name
obj.data.materials.append(mat)
print(f"[scale_test] created {name} at {loc}")
def export_fbx(path):
os.makedirs(os.path.dirname(path), exist_ok=True)
# Named export preset "ue_metric_v1" - change only via a new preset name.
bpy.ops.export_scene.fbx(
filepath=path,
use_selection=False,
object_types={"MESH"},
apply_unit_scale=True,
apply_scale_options="FBX_SCALE_NONE",
axis_forward="-Y",
axis_up="Z",
use_space_transform=True,
use_mesh_modifiers=True,
mesh_smooth_type="OFF",
path_mode="AUTO",
bake_space_transform=False,
)
print(f"[scale_test] exported FBX preset ue_metric_v1 -> {path}")
def main():
argv = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
parser = argparse.ArgumentParser()
parser.add_argument("--out", default="/tmp/gigline/scaletest.fbx")
parser.add_argument("--save-blend", default=None)
args = parser.parse_args(argv)
build_scene()
if args.save_blend:
os.makedirs(os.path.dirname(args.save_blend), exist_ok=True)
bpy.ops.wm.save_as_mainfile(filepath=args.save_blend)
print(f"[scale_test] saved {args.save_blend}")
export_fbx(args.out)
main()