From 4700f4dcc4ec21f04fa1b5a1d129dc147e253c78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laura=20Kl=C3=BCnder?= Date: Tue, 4 Dec 2018 01:15:52 +0100 Subject: [PATCH] some more blender render engine stuff --- src/c3nav/mapdata/render/engines/blender.py | 58 +++++++++++++++++---- 1 file changed, 49 insertions(+), 9 deletions(-) diff --git a/src/c3nav/mapdata/render/engines/blender.py b/src/c3nav/mapdata/render/engines/blender.py index dc779af4..e98b0043 100644 --- a/src/c3nav/mapdata/render/engines/blender.py +++ b/src/c3nav/mapdata/render/engines/blender.py @@ -16,14 +16,39 @@ class BlenderEngine(Base3DEngine): super().__init__(*args, **kwargs) self.result = '' self._add_python(''' + import bpy + + def deselect_all(): + bpy.ops.object.select_all(action='DESELECT') + + def select_object(obj): + deselect_all() + obj.select = True + bpy.context.scene.objects.active = obj + def add_polygon(exterior, interiors, minz, maxz): - add_ring(exterior, minz, maxz) + bpy.ops.object.mode_set(mode='OBJECT') + deselect_all() + exterior = add_ring(exterior, minz, maxz) + for interior_coords in interiors: + interior = add_ring(interior_coords, minz-1, maxz+1) + select_object(exterior) + bpy.ops.object.modifier_add(type='BOOLEAN') + mod = exterior.modifiers + mod[0].name = 'Difference' + mod[0].operation = 'DIFFERENCE' + mod[0].object = interior + bpy.ops.object.modifier_apply(apply_as='DATA', modifier=mod[0].name) + select_object(interior) + bpy.ops.object.delete() def add_ring(coords, minz, maxz): if coords[0] == coords[-1]: coords = coords[:-1] if len(coords) < 3: raise ValueError('Ring with less than 3 points.') + + # create ring indices = tuple(range(len(coords))) mesh = bpy.data.meshes.new(name='Test') mesh.from_pydata( @@ -31,9 +56,22 @@ class BlenderEngine(Base3DEngine): tuple(zip(indices, indices[1:]+(0, ))), (indices, ), ) + + # add ring to scene obj = bpy.data.objects.new('Test', mesh) scene = bpy.context.scene scene.objects.link(obj) + + # extrude it + select_object(obj) + bpy.ops.object.mode_set(mode='EDIT') + bpy.ops.mesh.select_mode(type='FACE') + bpy.ops.mesh.select_all(action='SELECT') + bpy.ops.mesh.extrude_region_move( + TRANSFORM_OT_translate={'value': (0, 0, maxz-minz)} + ) + bpy.ops.object.mode_set(mode='OBJECT') + obj.select = False return obj ''') @@ -70,18 +108,20 @@ class BlenderEngine(Base3DEngine): restricted_spaces = unary_union((restricted_spaces_indoors, restricted_spaces_outdoors)) # noqa for altitudearea in geoms.altitudeareas: - self._add_polygon(altitudearea.geometry.geom) - break + self._add_polygon(altitudearea.geometry.geom, min_altitude-1, altitudearea.altitude) break - def _add_polygon(self, geometry): + def _add_polygon(self, geometry, minz, maxz): for polygon in assert_multipolygon(geometry): - self._add_python('add_polygon(exterior=%(exterior)r, interiors=%(interiors)r, minz=0, maxz=1)' % { - 'exterior': tuple(polygon.exterior.coords), - 'interiors': tuple(tuple(interior.coords) for interior in polygon.interiors), - }) - continue + self._add_python( + 'add_polygon(exterior=%(exterior)r, interiors=%(interiors)r, minz=%(minz)f, maxz=%(maxz)f)' % { + 'exterior': tuple(polygon.exterior.coords), + 'interiors': tuple(tuple(interior.coords) for interior in polygon.interiors), + 'minz': minz/1000, + 'maxz': maxz/1000, + } + ) def render(self, filename=None): return self.result.encode()