"""Import a browser-produced PLY in pinned Blender 5.2 and emit mapped fields.""" 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 attr_values(attribute): values = [] for item in attribute.data: if attribute.data_type == "FLOAT_COLOR": values.append([float(value) for value in item.color]) elif attribute.data_type == "FLOAT_VECTOR": values.append([float(value) for value in item.vector]) elif attribute.data_type == "FLOAT": values.append(float(item.value)) elif attribute.data_type == "INT": values.append(int(item.value)) return values def main(ply_path, report_path): ply_path = Path(ply_path).resolve(); report_path = Path(report_path).resolve() bpy.ops.wm.read_factory_settings(use_empty=True) result = bpy.ops.wm.ply_import(filepath=str(ply_path), import_colors="SRGB", import_attributes=True, forward_axis="NEGATIVE_Z", up_axis="Y", global_scale=1.0) objects = [obj for obj in bpy.context.scene.objects if obj.type == "MESH"] if "FINISHED" not in result or not objects: raise RuntimeError("Blender PLY import did not produce a mesh") obj = objects[0]; mesh = obj.data; mesh.calc_loop_triangles() wanted = [attribute for attribute in mesh.attributes if attribute.name in {"Col", "temperature", "label"}] report = { "schemaVersion": 1, "operation": "DESKTOP_IMPORT_WEB_PLY", "sourceSha256": sha256_file(ply_path), "sourceBytes": ply_path.stat().st_size, "objectCount": len(objects), "vertexCount": len(mesh.vertices), "polygonCount": len(mesh.polygons), "triangleCount": len(mesh.loop_triangles), "positions": [[float(value) for value in vertex.co] for vertex in mesh.vertices], "attributes": [{"name": attribute.name, "dataType": attribute.data_type, "domain": attribute.domain, "values": attr_values(attribute)} for attribute in wanted], } 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("ply-web-roundtrip-desktop-imported vertices=%s faces=%s attrs=%s" % (report["vertexCount"], report["triangleCount"], len(report["attributes"]))) 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 check-ply-web-roundtrip.py -- PLY REPORT") main(args[0], args[1])