83 lines
3.0 KiB
Python
83 lines
3.0 KiB
Python
import json
|
|
import os
|
|
import sys
|
|
|
|
import bpy
|
|
|
|
|
|
TYPE_NAMES = {
|
|
"CURVE": "CURVE",
|
|
"SURFACE": "SURFACE",
|
|
"FONT": "FONT",
|
|
"META": "METABALL",
|
|
}
|
|
|
|
|
|
def rounded(value):
|
|
return round(float(value), 7)
|
|
|
|
|
|
def geometry_record(obj, depsgraph):
|
|
evaluated = obj.evaluated_get(depsgraph)
|
|
mesh = evaluated.to_mesh()
|
|
try:
|
|
mesh.calc_loop_triangles()
|
|
positions = [component for vertex in mesh.vertices for component in vertex.co]
|
|
edge_indices = [index for edge in mesh.edges for index in edge.vertices]
|
|
indices = [index for triangle in mesh.loop_triangles for index in triangle.vertices]
|
|
point_count = len(mesh.vertices)
|
|
bounds_min = [min((vertex.co[axis] for vertex in mesh.vertices), default=0.0) for axis in range(3)]
|
|
bounds_max = [max((vertex.co[axis] for vertex in mesh.vertices), default=0.0) for axis in range(3)]
|
|
centroid = [
|
|
sum((vertex.co[axis] for vertex in mesh.vertices), 0.0) / point_count
|
|
if point_count else 0.0
|
|
for axis in range(3)
|
|
]
|
|
return {
|
|
"object": obj.name,
|
|
"sourceType": TYPE_NAMES[obj.type],
|
|
"vertexCount": point_count,
|
|
"edgeCount": len(mesh.edges),
|
|
"triangleCount": len(mesh.loop_triangles),
|
|
"boundsMin": [rounded(value) for value in bounds_min],
|
|
"boundsMax": [rounded(value) for value in bounds_max],
|
|
"centroid": [rounded(value) for value in centroid],
|
|
"surfaceArea": rounded(sum((triangle.area for triangle in mesh.loop_triangles), 0.0)),
|
|
"positionMoment": rounded(sum((index + 1) * value for index, value in enumerate(positions))),
|
|
"edgeIndexMoment": sum((index + 1) * (value + 1) for index, value in enumerate(edge_indices)),
|
|
"indexMoment": sum((index + 1) * (value + 1) for index, value in enumerate(indices)),
|
|
}
|
|
finally:
|
|
evaluated.to_mesh_clear()
|
|
|
|
|
|
def main(output_path):
|
|
depsgraph = bpy.context.evaluated_depsgraph_get()
|
|
records = [
|
|
geometry_record(obj, depsgraph)
|
|
for obj in bpy.context.scene.objects
|
|
if obj.type in TYPE_NAMES
|
|
]
|
|
records.sort(key=lambda record: record["object"])
|
|
payload = {
|
|
"schemaVersion": 1,
|
|
"blenderVersion": bpy.app.version_string,
|
|
"fixture": os.path.basename(bpy.data.filepath),
|
|
"tolerance": {
|
|
"coordinate": 0.00001,
|
|
"surfaceArea": 0.0001,
|
|
"positionMoment": 0.001,
|
|
},
|
|
"geometries": records,
|
|
}
|
|
with open(output_path, "w", encoding="ascii") as output:
|
|
json.dump(payload, output, indent=2, sort_keys=True)
|
|
output.write("\n")
|
|
print(f"nonmesh-desktop-golden-generated output={os.path.abspath(output_path)} geometries={len(records)}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
if "--" not in sys.argv or len(sys.argv) <= sys.argv.index("--") + 1:
|
|
raise SystemExit("usage: blender -b fixture.blend --python generate-nonmesh-desktop-golden.py -- output.json")
|
|
main(sys.argv[sys.argv.index("--") + 1])
|