|
- import bpy
- from mathutils import Vector, Euler
- from math import pi
- import json
- import os
- import subprocess
- import xml.etree.ElementTree as ET
-
- c = bpy.data.objects["cam"]
-
- selected = bpy.context.selected_objects[0]
-
- bpy.ops.object.transform_apply( rotation = True )
-
- data = {}
-
- b = selected
-
- FRONT = [0, 1, 2, "Front"]
- FRONT_CORNER = [0.5, 1, 2, "Front Corner"]
- SIDE = [1, 1, 2, "Side"]
- BACK_CORNER = [1.5, 1, 2, "Back Corner"]
- BACK = [2, 1, 2, "Back"]
- BOTTOM = [0, 2, 1, "Bottom"]
- TOP = [2, 0, 1, "Top"]
-
- sides = [FRONT, FRONT_CORNER, SIDE, BACK_CORNER, BACK, BOTTOM, TOP]
-
- path = "/tmp/macrovision/"
-
- media_path = "/home/crux/furry/macrovision/media/"
- media_folder = "clothing/Boots/"
-
- os.makedirs(path, exist_ok=True)
- os.makedirs(os.path.join(media_path, media_folder), exist_ok=True)
-
-
- ns = {"svg": "http://www.w3.org/2000/svg"}
- ET.register_namespace("", ns["svg"])
-
- TEMPLATE = """
- {{
- name: "{0}",
- sides: {{
- {1}
- }}
- }}"""
-
- VIEW_TEMPLATE = ' "{0}": {{ height: math.unit({1}, "meters") }}'
-
- for angles in sides:
- local_bbox_center = 0.125 * sum((Vector(box) for box in b.bound_box), Vector())
- global_bbox_center = b.matrix_world @ local_bbox_center
- c.location = global_bbox_center
- c.data.ortho_scale = max(b.dimensions) * 1.1
- c.rotation_euler = Euler([angles[1] * pi / 2, 0, angles[0] * pi / 2])
- rot = c.rotation_euler.to_matrix()
- rot.invert()
- c.location = c.location + Vector([0, 0, 100]) @ rot
- data[angles[3]] = b.dimensions[angles[2]]
- output_path = os.path.join(path, f"{b.name}-{angles[3]}")
- bpy.context.scene.render.filepath = output_path
-
- svg_path = output_path + "0001.svg"
-
- bpy.ops.render.render(write_still = True)
- os.rename(svg_path, output_path + ".svg")
-
- subprocess.check_output([
- "potrace",
- "-b",
- "svg",
- output_path + ".bmp",
- "-o",
- output_path + "-fill.svg"
- ])
-
- line_xml = ET.parse(output_path + ".svg")
- fill_xml = ET.parse(output_path + "-fill.svg")
-
- style = None
-
- for elem in line_xml.findall(".//svg:path", namespaces=ns):
- if style is None:
- style = {}
- for key in elem.attrib:
- if not key == "d":
- style[key] = elem.attrib[key]
- for key in style:
- del elem.attrib[key]
- parts = elem.attrib["d"].strip().split(" ")
- if len(parts) > 6 and parts[1] == parts[3] == parts[5] and parts[2] == parts[4] == parts[6]:
- elem.attrib["DELETEME"] = True
-
- while True:
- child = line_xml.find(".//svg:path[@DELETEME]", namespaces=ns)
- parent = line_xml.find(".//svg:path[@DELETEME]...", namespaces=ns)
- print(parent, child)
- if parent is None:
- break
- parent.remove(child)
-
- for key in style:
- line_xml.find("./svg:g", namespaces=ns).attrib[key] = style[key]
-
- line_xml.write(output_path + "-cleaned.svg")
-
- subprocess.check_output([
- "inkscape",
- output_path + "-cleaned.svg",
- "--batch-process",
- "--actions=EditSelectAll;SelectionSimplify;FileSave",
- ])
-
- optimized = ET.parse(output_path + "-cleaned.svg")
-
- lines = optimized.find("./svg:g", namespaces=ns)
-
- fill_xml.find("svg:g[@fill='#000000']", namespaces=ns).attrib["fill"] = "#1a1a1a"
-
- fill_xml.iter().__next__().append(lines)
-
- fill_xml.write(output_path + "-combined.svg")
-
- subprocess.check_output([
- "inkscape",
- "--batch-process",
- "--export-plain-svg=" + output_path + "-prepared.svg",
- "--export-area-drawing",
- output_path + "-combined.svg"
- ])
-
- subprocess.check_output([
- "svgo",
- output_path + "-prepared.svg",
- "-o",
- os.path.join(media_path, media_folder, f"{b.name}-{angles[3]}.svg")
- ])
-
- lines = []
- for key, value in data.items():
- lines.append(VIEW_TEMPLATE.format(key, value))
-
- print(TEMPLATE.format(b.name, ",\n".join(lines)))
|