|
- import bpy
- from mathutils import Vector, Euler
- from math import pi
- import json
- import os
- import bpy_extras
- import bmesh
- import time
-
- class ModalTimerOperator(bpy.types.Operator):
- """Operator which runs its self from a timer"""
- bl_idname = "wm.modal_timer_operator"
- bl_label = "Modal Timer Operator"
-
- _timer = None
- index = 0
-
- def menu_func(self, context):
- self.layout.operator(ModalTimerOperator.bl_idname)
-
- def modal(self, context, event):
- scene = context.scene
- if self.index >= len(self.sides):
- self.cancel(context)
- return {'CANCELLED'}
-
- if event.type == 'TIMER':
- print("HOLY COW!!!")
- self.capture(self.sides[self.index])
- self.index += 1
- if self.index < len(self.sides):
- self.position_camera(self.sides[self.index])
- else:
- self.export_data()
-
- return {'PASS_THROUGH'}
-
- def execute(self, context):
- print("execute!")
- self.c = bpy.data.objects["cam"]
- self.scene = bpy.context.scene
- selected = bpy.context.selected_objects[0]
-
- bpy.ops.object.mode_set(mode="OBJECT")
- bpy.ops.object.transform_apply( rotation = True )
-
- self.data = {}
-
- self.b = selected
-
- FRONT = [0, 1, 2, "Front"]
- SIDE = [1, 1, 2, "Side"]
- TOP = [0, 0, 1, "Top"]
- ANGLED = [0.5, 1, 2, "Angled"]
-
- self.sides = [FRONT, SIDE, TOP, ANGLED]
-
- path = "/tmp/macrovision/"
-
- media_path = "/home/crux/furry/macrovision/media/"
- media_folder = "buildings/Houses/"
-
- os.makedirs(path, exist_ok=True)
- os.makedirs(os.path.join(media_path, media_folder), exist_ok=True)
- wm = context.window_manager
- self._timer = wm.event_timer_add(0.25, window=context.window)
- wm.modal_handler_add(self)
- self.position_camera(self.sides[self.index])
- return {'RUNNING_MODAL'}
-
- def cancel(self, context):
- wm = context.window_manager
- wm.event_timer_remove(self._timer)
-
-
- def getView3dAreaAndRegion(self, context):
- for area in context.screen.areas:
- if area.type == "VIEW_3D":
- for region in area.regions:
- if region.type == "WINDOW":
- print("Found WINDOW")
- return area, region
-
- def select_border(self, context, view3dAreaAndRegion=None, extend=True):
- if not view3dAreaAndRegion:
- view3dAreaAndRegion = self.getView3dAreaAndRegion(context)
- print(view3dAreaAndRegion)
- view3dArea, view3dRegion = view3dAreaAndRegion
- override = context.copy()
- override['area'] = view3dArea
- override['region'] = view3dRegion
- bpy.ops.view3d.select_box(override,xmin=0,xmax=view3dArea.width,ymin=0,ymax=view3dArea.height,mode='SET')
-
- def position_camera(self, angles):
- bpy.ops.object.mode_set(mode="OBJECT")
- local_bbox_center = 0.125 * sum((Vector(box) for box in self.b.bound_box), Vector())
- global_bbox_center = self.b.matrix_world @ local_bbox_center
- self.c.data.ortho_scale = max(self.b.dimensions) * 1.3
- self.c.location = global_bbox_center
- self.c.rotation_euler = Euler([angles[1] * pi / 2, 0, angles[0] * pi / 2])
- rot = self.c.rotation_euler.to_matrix()
- rot.invert()
- self.c.location = self.c.location + Vector([0, 0, 100]) @ rot
- self.data[angles[3]] = self.b.dimensions[angles[2]]
-
- def capture(self, angles):
- bpy.ops.object.mode_set(mode="EDIT")
- bpy.ops.mesh.select_all(action="SELECT")
- bpy.ops.mesh.sort_elements(type='VIEW_ZAXIS', elements={'FACE'}, reverse=False)
- bm = bmesh.from_edit_mesh(bpy.context.active_object.data)
- polygons = []
- edges = []
-
- self.select_border(bpy.context)
- bm.faces.ensure_lookup_table()
- bm.verts.ensure_lookup_table()
- bm.edges.ensure_lookup_table()
- for face in bm.faces:
- if not face.select:
- continue
- verts = []
- for vert in face.verts:
- co = bpy_extras.object_utils.world_to_camera_view(self.scene, self.c, vert.co)
- verts.append([co[0], co[1]])
- verts.append(verts[0])
- polygons.append({"verts": verts, "type": "bright" if face.material_index == 1 else "dark"})
- for edge in face.edges:
- if not edge.select:
- continue
- co1 = bpy_extras.object_utils.world_to_camera_view(self.scene, self.c, edge.verts[0].co)
- co2 = bpy_extras.object_utils.world_to_camera_view(self.scene, self.c, edge.verts[1].co)
- polygons.append({"type": "edge", "verts": [
- [co1[0], co1[1]],
- [co2[0], co2[1]]
- ]})
- bm.free()
- bpy.ops.object.mode_set(mode="OBJECT")
-
-
- with open(f"/tmp/polygons-{angles[3]}.json", "w", encoding="utf-8") as file:
- json.dump({"polygons": polygons}, file)
-
-
- def export_data(self):
- with open(f"/tmp/data-{self.b.name}.json", "w", encoding="utf-8") as file:
- json.dump({"name": self.b.name, "views": self.data}, file)
-
-
- def register():
- bpy.utils.register_class(ModalTimerOperator)
- bpy.types.VIEW3D_MT_object.append(ModalTimerOperator.menu_func)
-
- def unregister():
- bpy.utils.unregister_class(ModalTimerOperator)
-
-
- register()
|