75 lines
2.9 KiB
Python
75 lines
2.9 KiB
Python
"""Probe STL normal/unit/edge behavior in pinned Blender 5.2 for M12-07E."""
|
|
|
|
import hashlib
|
|
import json
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
import bpy
|
|
|
|
|
|
def sha256_file(path):
|
|
digest = hashlib.sha256()
|
|
with open(path, "rb") as handle:
|
|
for chunk in iter(lambda: handle.read(1024 * 1024), b""):
|
|
digest.update(chunk)
|
|
return digest.hexdigest()
|
|
|
|
|
|
def import_case(path, global_scale):
|
|
bpy.ops.wm.read_factory_settings(use_empty=True)
|
|
result = bpy.ops.wm.stl_import(
|
|
filepath=str(path),
|
|
directory=str(path.parent),
|
|
forward_axis="NEGATIVE_Z",
|
|
up_axis="Y",
|
|
global_scale=global_scale,
|
|
use_scene_unit=False,
|
|
use_facet_normal=True,
|
|
use_mesh_validate=True,
|
|
)
|
|
objects = [obj for obj in bpy.context.scene.objects if obj.type == "MESH"]
|
|
if "FINISHED" not in result or not objects:
|
|
return {"status": "BLOCKED", "objectCount": len(objects)}
|
|
mesh = objects[0].data
|
|
mesh.calc_loop_triangles()
|
|
coordinates = [[float(value) for value in (objects[0].matrix_world @ vertex.co)] for vertex in mesh.vertices]
|
|
bounds = {
|
|
"min": [min(values) for values in zip(*coordinates)],
|
|
"max": [max(values) for values in zip(*coordinates)],
|
|
} if coordinates else {"min": [0.0, 0.0, 0.0], "max": [0.0, 0.0, 0.0]}
|
|
return {
|
|
"status": "ACCEPTED",
|
|
"objectCount": len(objects),
|
|
"vertexCount": len(mesh.vertices),
|
|
"polygonCount": len(mesh.polygons),
|
|
"triangleCount": len(mesh.loop_triangles),
|
|
"bounds": bounds,
|
|
"polygonNormals": [[float(value) for value in polygon.normal] for polygon in mesh.polygons],
|
|
}
|
|
|
|
|
|
def main(fixture_root, report_path):
|
|
fixture_root = Path(fixture_root).resolve()
|
|
report_path = Path(report_path).resolve()
|
|
cases = []
|
|
for case_id, name, scale in (
|
|
("BINARY_UNIT_1", "capability-binary.stl", 1.0),
|
|
("BINARY_UNIT_001", "capability-binary.stl", 0.001),
|
|
("DEGENERATE_TRIANGLE", "degenerate-binary.stl", 1.0),
|
|
("TRAILING_BYTES", "trailing-binary.stl", 1.0),
|
|
):
|
|
path = fixture_root / name
|
|
cases.append({"id": case_id, "file": name, "globalScale": scale, "byteLength": path.stat().st_size, "sha256": sha256_file(path), "result": import_case(path, scale)})
|
|
report = {"schemaVersion": 1, "task": "M12-07E", "operation": "BLENDER_STL_EDGE_PROBE", "cases": cases, "nextTask": "M12-07F"}
|
|
report_path.parent.mkdir(parents=True, exist_ok=True)
|
|
report_path.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8")
|
|
print("stl-edge-probe-complete cases=%s next=%s" % (len(cases), report["nextTask"]))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
args = sys.argv[sys.argv.index("--") + 1 :] if "--" in sys.argv else []
|
|
if len(args) != 2:
|
|
raise SystemExit("usage: blender --background --python probe-stl-edge-fixtures.py -- FIXTURE_ROOT REPORT")
|
|
main(args[0], args[1])
|