153 lines
5.0 KiB
Python
153 lines
5.0 KiB
Python
import json
|
|
import math
|
|
import os
|
|
import sys
|
|
|
|
import bpy
|
|
|
|
|
|
def mesh_object(name, vertices, edges, faces, location):
|
|
mesh = bpy.data.meshes.new(f"{name}Mesh")
|
|
mesh.from_pydata(vertices, edges, faces)
|
|
mesh.update()
|
|
obj = bpy.data.objects.new(name, mesh)
|
|
obj.location = location
|
|
bpy.context.scene.collection.objects.link(obj)
|
|
return obj
|
|
|
|
|
|
def modifier_type_code(modifier):
|
|
items = bpy.types.Modifier.bl_rna.properties["type"].enum_items
|
|
return items[modifier.type].value
|
|
|
|
|
|
def evaluated_mesh(obj, depsgraph):
|
|
evaluated = obj.evaluated_get(depsgraph)
|
|
mesh = evaluated.to_mesh(preserve_all_data_layers=True, depsgraph=depsgraph)
|
|
try:
|
|
mesh.calc_loop_triangles()
|
|
return {
|
|
"object": obj.name,
|
|
"vertexCount": len(mesh.vertices),
|
|
"triangleCount": len(mesh.loop_triangles),
|
|
"positions": [value for vertex in mesh.vertices for value in vertex.co],
|
|
"indices": [index for triangle in mesh.loop_triangles for index in triangle.vertices],
|
|
}
|
|
finally:
|
|
evaluated.to_mesh_clear()
|
|
|
|
|
|
def main(output_dir):
|
|
bpy.ops.wm.read_factory_settings(use_empty=True)
|
|
|
|
edge_split = mesh_object(
|
|
"ExtendedEdgeSplit",
|
|
[(0, 0, 0), (2, 0, 0), (0, 2, 0), (0, 0, 2)],
|
|
[],
|
|
[(0, 1, 2), (0, 3, 1)],
|
|
(-3, 0, 0),
|
|
)
|
|
edge_modifier = edge_split.modifiers.new("Native Edge Split", "EDGE_SPLIT")
|
|
edge_modifier.use_edge_angle = True
|
|
edge_modifier.use_edge_sharp = False
|
|
edge_modifier.split_angle = math.radians(30)
|
|
|
|
screw = mesh_object(
|
|
"ExtendedScrew",
|
|
[(1, 0, -1), (1, 0, 1)],
|
|
[(0, 1)],
|
|
[],
|
|
(3, 0, 0),
|
|
)
|
|
screw_modifier = screw.modifiers.new("Native Screw", "SCREW")
|
|
screw_modifier.axis = "Z"
|
|
screw_modifier.angle = math.tau
|
|
screw_modifier.steps = 8
|
|
screw_modifier.render_steps = 12
|
|
screw_modifier.iterations = 1
|
|
screw_modifier.use_merge_vertices = False
|
|
|
|
disabled = screw.modifiers.new("Disabled Edge Split", "EDGE_SPLIT")
|
|
disabled.show_viewport = False
|
|
disabled.show_render = True
|
|
disabled.show_in_editmode = True
|
|
|
|
displace = mesh_object(
|
|
"ExtendedDisplace",
|
|
[(-1, -1, -1), (1, -1, -1), (1, 1, -1), (-1, 1, -1),
|
|
(-1, -1, 1), (1, -1, 1), (1, 1, 1), (-1, 1, 1)],
|
|
[],
|
|
[(0, 1, 2, 3), (4, 7, 6, 5), (0, 4, 5, 1),
|
|
(1, 5, 6, 2), (2, 6, 7, 3), (4, 0, 3, 7)],
|
|
(7, 0, 0),
|
|
)
|
|
displace_modifier = displace.modifiers.new("Native Constant Displace", "DISPLACE")
|
|
displace_modifier.direction = "Z"
|
|
displace_modifier.space = "LOCAL"
|
|
displace_modifier.strength = 0.75
|
|
displace_modifier.mid_level = 0.25
|
|
|
|
blocked_displace = mesh_object(
|
|
"ExtendedDisplaceBlocked",
|
|
[(-1, -1, 0), (1, -1, 0), (1, 1, 0), (-1, 1, 0)],
|
|
[],
|
|
[(0, 1, 2, 3)],
|
|
(11, 0, 0),
|
|
)
|
|
blocked_modifier = blocked_displace.modifiers.new("Blocked RGB Displace", "DISPLACE")
|
|
blocked_modifier.direction = "RGB_TO_XYZ"
|
|
mesh_object(
|
|
"ExtendedDisplaceBlockedBaseline",
|
|
[(-1, -1, 0), (1, -1, 0), (1, 1, 0), (-1, 1, 0)],
|
|
[],
|
|
[(0, 1, 2, 3)],
|
|
(15, 0, 0),
|
|
)
|
|
|
|
scene = bpy.context.scene
|
|
scene.frame_set(1)
|
|
depsgraph = bpy.context.evaluated_depsgraph_get()
|
|
objects = [edge_split, screw, displace, blocked_displace]
|
|
golden = {
|
|
"schemaVersion": 1,
|
|
"taskId": "N-002",
|
|
"blenderVersion": bpy.app.version_string,
|
|
"fixture": "modifier_extended_native.blend",
|
|
"frame": scene.frame_current,
|
|
"objects": [
|
|
{
|
|
"name": obj.name,
|
|
"modifiers": [
|
|
{
|
|
"name": modifier.name,
|
|
"type": modifier.type,
|
|
"typeCode": modifier_type_code(modifier),
|
|
"showViewport": modifier.show_viewport,
|
|
"showRender": modifier.show_render,
|
|
"showEditmode": modifier.show_in_editmode,
|
|
"showOnCage": modifier.show_on_cage,
|
|
}
|
|
for modifier in obj.modifiers
|
|
],
|
|
}
|
|
for obj in objects
|
|
],
|
|
"meshes": [evaluated_mesh(obj, depsgraph) for obj in objects],
|
|
"tolerance": {"maxPositionError": 1e-5, "rmsPositionError": 1e-6},
|
|
}
|
|
|
|
os.makedirs(output_dir, exist_ok=True)
|
|
output_path = os.path.join(output_dir, golden["fixture"])
|
|
bpy.ops.wm.save_as_mainfile(filepath=output_path)
|
|
golden_dir = os.path.abspath(os.path.join(output_dir, "..", "..", "golden", "N-002"))
|
|
os.makedirs(golden_dir, exist_ok=True)
|
|
with open(os.path.join(golden_dir, "modifier_extended_native.json"), "w", encoding="utf-8") as handle:
|
|
json.dump(golden, handle, indent=2, sort_keys=True)
|
|
handle.write("\n")
|
|
print(f"modifier-extended-generated fixture={output_path}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
args = sys.argv[sys.argv.index("--") + 1:]
|
|
main(os.path.abspath(args[0]))
|