Skip to content

Commit 8bfab38

Browse files
committed
add triangulation
1 parent 689457d commit 8bfab38

File tree

4 files changed

+76
-36
lines changed

4 files changed

+76
-36
lines changed

dataset/blender_utils.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,7 @@ def gancio(v1, v2, axis, border1=0, border2=0):
9191
mapping[abs(1 - border2)] * np.diff(coords1[abs(1 - axis)]) + \
9292
(0.5 * np.diff(coords2[abs(1-axis)]) * mapping[border2])
9393

94+
def select(_volume):
95+
_volume.select_set(True)
96+
bpy.context.view_layer.objects.active = _volume
97+

dataset/material.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ class Material:
1313
"""
1414
Class that represents a material object in Blender.
1515
"""
16-
def __init__(self, name, filename='material'):
16+
def __init__(self, name):
1717
self.name = name.lower().capitalize() # name of the material and its texture folder
18-
self.filename = filename
18+
self.filename = 'material'
1919
self._path = file_dir + '/Textures/{}.blend'.format(self.filename)
2020
self._add = '\\Material\\'
2121
self.value = self._load() # loads material into the scene
@@ -53,7 +53,10 @@ def _load_maps(self, map_type):
5353
try:
5454
bpy.ops.image.open(filepath=file_dir + '/Textures/{}/{}.png'.
5555
format(self.name, map_type.capitalize()))
56-
return bpy.data.images[-2]
56+
_images = [x.filepath for x in bpy.data.images]
57+
return bpy.data.images[_images.index('//Textures'
58+
'\\{}\\{}.png'.format(self.name,
59+
map_type))]
5760
except Exception as e:
5861
print('Failed to load {} texture of {}'.format(map_type, self.name))
5962
print(repr(e))

dataset/module.py

Lines changed: 52 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,38 @@
1313

1414
stdout = io.StringIO()
1515
from dataset_config import *
16-
from blender_utils import gancio, get_min_max
16+
from blender_utils import *
1717
from shp2obj import Collection, deselect_all
1818

1919

20+
class IdAssigner:
21+
"""
22+
Class that assigns an instance id based on the module type.
23+
"""
24+
def __init__(self):
25+
self.mapping = {x: y for (x, y) in zip(MODULES, range(2, len(MODULES) + 2))}
26+
27+
def make(self, name: str) -> int:
28+
"""
29+
Function that returns an id based on the module type. Numbering starts from
30+
1 since 0 is the building envelope.
31+
:param name: name of the module, str
32+
:return: id, int
33+
"""
34+
assert name in MODULES, "Expected name to be in MODULES, got {}".format(name)
35+
return self.mapping[name]
36+
37+
2038
class Connector:
21-
def __init__(self, module, volume, axis):
39+
def __init__(self, module, volume, axis, side=0):
2240
self.module = module
2341
self.axis = axis
42+
self.side = side
2443
self.volume = volume
2544
self._connect()
2645

2746
def _connect(self):
28-
gancio(self.volume, self.module, self.axis, 0, 1)
47+
gancio(self.volume, self.module, self.axis, self.side, 1)
2948

3049

3150
class Module:
@@ -37,9 +56,11 @@ def __init__(self, name='generic', scale=None, mask=(1.0, 0.0, 0.0)):
3756
or issubclass(mask.__class__, np.ndarray), "Expected mask to be an " \
3857
"array or a tuple, got {}".format(type(mask))
3958
assert len(mask) == 3, "Expected mask to have 3 colors, got {}".format(len(mask))
40-
self.mask = mask
59+
# self.mask = mask
4160
self.mesh = self._create()
4261
self.parent = self._nest()
62+
self._assign_id()
63+
self._triangulate()
4364

4465
def __copy__(self):
4566
m = self.__class__(self.name, scale=self.scale)
@@ -54,12 +75,12 @@ def apply(self, material=None):
5475
_material = MaterialFactory().produce()
5576
self.mesh.active_material = _material.value
5677

57-
def connect(self, volume, axis):
58-
self._connect(volume, axis)
78+
def connect(self, volume, axis, side=0):
79+
self._connect(volume, axis, side)
5980

60-
def mask(self):
61-
material = MaterialFactory().produce('mask', color=self.mask)
62-
self.mesh.active_material = material.value
81+
# def mask(self):
82+
# material = MaterialFactory().produce('mask', color=self.mask)
83+
# self.mesh.active_material = material.value
6384

6485
def position(self, position):
6586
assert isinstance(position, list) or isinstance(position, tuple) or \
@@ -77,8 +98,12 @@ def remove(self):
7798
with redirect_stdout(stdout), redirect_stderr(stdout):
7899
bpy.ops.object.delete()
79100

80-
def _connect(self, volume, axis):
81-
self.connector = self.ModuleConnector(self, volume, axis)
101+
def _assign_id(self):
102+
self.mesh["inst_id"] = IdAssigner().make(self.name)
103+
self.mesh.pass_index = IdAssigner().make(self.name)
104+
105+
def _connect(self, volume, axis, side):
106+
self.connector = self.ModuleConnector(self, volume, axis, side)
82107

83108
def _create(self):
84109
# rule how connects to mesh
@@ -93,13 +118,20 @@ def _nest(self):
93118
bpy.data.collections[self.name].objects.link(bpy.data.objects[self.mesh.name])
94119
return bpy.data.collections[self.name]
95120

121+
def _triangulate(self):
122+
deselect_all()
123+
if self.mesh:
124+
select(self.mesh)
125+
bpy.ops.object.modifier_add(type='TRIANGULATE')
126+
bpy.ops.object.modifier_apply()
127+
96128
class ModuleConnector(Connector):
97-
def __init__(self, module, volume, axis):
98-
Connector.__init__(self, module, volume, axis)
129+
def __init__(self, module, volume, axis, side):
130+
Connector.__init__(self, module, volume, axis, side)
99131

100132

101133
class Window(Module):
102-
def __init__(self, name='window', scale=(1.5, 0.05, 1.5)):
134+
def __init__(self, name: str='window', scale: tuple=(1.5, 0.05, 1.5)):
103135
Module.__init__(self, name, scale)
104136

105137
def _create(self):
@@ -109,13 +141,13 @@ def _create(self):
109141
return bpy.context.selected_objects[0]
110142

111143
class ModuleConnector(Connector):
112-
def __init__(self, module, volume, axis):
113-
Connector.__init__(self, module, volume, axis)
144+
def __init__(self, module: Module, volume, axis: bool, side):
145+
Connector.__init__(self, module, volume, axis, side)
114146

115147
def _connect(self):
116148
if self.axis == 0:
117-
self.module.mesh.rotation_euler = math.radians(90)
118-
gancio(self.volume, self.module, self.axis, 0, 1)
149+
self.module.mesh.rotation_euler[2] = math.radians(90)
150+
gancio(self.volume, self.module, self.axis, self.side, 1)
119151

120152

121153
class ModuleFactory:
@@ -125,11 +157,10 @@ class ModuleFactory:
125157
def __init__(self):
126158
self.mapping = {'generic': Module,
127159
'window': Window}
128-
self.mapping = {x:y for x,y in self.mapping.items() if x in MODULES or x=='generic'}
160+
self.mapping = {x: y for x, y in self.mapping.items() if x in MODULES or x == 'generic'}
129161
self.mask_colors = list(range(len(self.mapping)))
130-
self._mask_colors()
131162

132-
def produce(self, name):
163+
def produce(self, name: str) -> object:
133164
"""
134165
Function that produces a module based on its name.
135166
:param name: name of the module to produce, str, should be in mapping
@@ -141,16 +172,6 @@ def produce(self, name):
141172
else:
142173
return self.mapping['generic']()
143174

144-
def _mask_colors(self):
145-
if len(self.mask_colors) <= 3:
146-
for i in range(len(self.mask_colors)):
147-
self.mask_colors[i] = [0.0, 0.0, 0.0]
148-
self.mask_colors[i][i] = 1.0
149-
else:
150-
# Distribute colors around the color circle
151-
return NotImplementedError
152-
153-
154175

155176
class ModuleApplier:
156177
def __init__(self, module_type):

dataset/volume.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
file_dir = os.path.dirname(__file__)
99
sys.path.append(file_dir)
1010

11-
from blender_utils import extrude, gancio, get_min_max
11+
from blender_utils import *
1212
from dataset_config import *
1313
from material import Material
1414
from module import *
@@ -129,7 +129,10 @@ def create(self):
129129
self.mesh = bpy.data.objects[self.name]
130130
self._nest()
131131
self._extrude()
132+
self.mesh["inst_id"] = 1 # instance id for the building envelope
133+
self.mesh.pass_index = 1
132134
deselect_all()
135+
self._triangulate()
133136

134137
def _extrude(self):
135138
"""
@@ -141,10 +144,19 @@ def _extrude(self):
141144
extrude(self.mesh, self.height)
142145

143146
def _nest(self):
144-
if not self.name in bpy.data.collections['Building'].objects:
147+
names = [x.name for x in bpy.data.collections['Building'].objects]
148+
if not self.name in names:
145149
bpy.data.collections['Building'].objects.link(
146150
bpy.data.objects[self.name])
147151

152+
def _triangulate(self):
153+
deselect_all()
154+
if self.mesh:
155+
select(self.mesh)
156+
bpy.ops.object.modifier_add(type='TRIANGULATE')
157+
bpy.ops.object.modifier_apply()
158+
159+
148160

149161
if __name__ == '__main__':
150162
f = CollectionFactory()

0 commit comments

Comments
 (0)