Spaces:
Paused
Paused
File size: 2,612 Bytes
381de33 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | """Reimport the delivery GLB and verify skinning plus actual animated deformation."""
import argparse
import json
from pathlib import Path
import sys
import bpy
import numpy as np
p = argparse.ArgumentParser()
p.add_argument("--input", required=True)
p.add_argument("--output", required=True)
a = p.parse_args(sys.argv[sys.argv.index("--") + 1 :])
bpy.ops.object.select_all(action="SELECT")
bpy.ops.object.delete(use_global=False)
bpy.context.scene.render.fps = 30
bpy.ops.import_scene.gltf(filepath=str(Path(a.input).resolve()))
meshes = [
obj
for obj in bpy.context.scene.objects
if obj.type == "MESH" and any(m.type == "ARMATURE" for m in obj.modifiers)
]
assert len(meshes) == 8, "Expected all eight skinned components"
rigs = [obj for obj in bpy.context.scene.objects if obj.type == "ARMATURE"]
assert len(rigs) == 1, "Expected one rig"
assert rigs[0].animation_data and rigs[0].animation_data.action, "Missing embedded animation"
assert len(rigs[0].data.bones) == 21
for obj in meshes:
assert all(v.groups for v in obj.data.vertices), f"Unweighted vertices in {obj.name}"
assert all(abs(sum(g.weight for g in v.groups) - 1) < 0.002 for v in obj.data.vertices)
assert any(m.type == "ARMATURE" for m in obj.modifiers)
assert obj.data.uv_layers, f"Missing UVs in {obj.name}"
assert obj.data.materials, f"Missing materials in {obj.name}"
positions = []
frames = list(range(1, 181))
for frame in frames:
bpy.context.scene.frame_set(frame)
depsgraph = bpy.context.evaluated_depsgraph_get()
coords = []
for obj in meshes:
evaluated = obj.evaluated_get(depsgraph)
mesh = evaluated.to_mesh()
coords.extend(tuple(evaluated.matrix_world @ v.co) for v in mesh.vertices)
evaluated.to_mesh_clear()
coords = np.array(coords)
assert np.isfinite(coords).all()
assert np.max(np.ptp(coords, axis=0)) < 1.6, "Implausible skin stretching"
positions.append(coords)
movement = np.max(np.linalg.norm(np.stack(positions) - positions[0], axis=-1), axis=0)
assert movement.max() > 0.1, "The skin does not move with the animation"
report = {
"verified": True,
"frames_checked": frames,
"mesh_objects": len(meshes),
"bones": 21,
"vertices": len(movement),
"moving_vertices": int((movement > 0.005).sum()),
"max_vertex_displacement": float(movement.max()),
"weights_normalized": True,
"uvs_and_materials_present": True,
"finite_deformed_positions": True,
"animation_name": rigs[0].animation_data.action.name,
}
Path(a.output).write_text(json.dumps(report, indent=2))
print(json.dumps(report))
|