-
Notifications
You must be signed in to change notification settings - Fork 0
/
utils.py
173 lines (120 loc) · 4.66 KB
/
utils.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
import json
import bpy
from .evertims import ( EvertMaterial )
def dict2str(d):
return json.dumps(d)
def str2dict(s):
return json.loads(s)
# convert dict of mat to dict of arrays, json dumpable
def matDict2str(matDict):
d = dict()
for m in matDict:
d[m] = [matDict[m].absorptions, matDict[m].scatterings]
return dict2str(d)
# convert back
def str2matDict(s):
d = json.loads(s)
matDict = dict()
for m in d:
matDict[m] = EvertMaterial(m)
matDict[m].absorptions = d[m][0]
matDict[m].scatterings = d[m][1]
return matDict
# check if a file can be created at filePath
def isValidExportPath(filePath):
if( not filePath.lower().endswith('.txt') ):
return({'ERROR'}, 'Export file should be a .txt')
try:
open(filePath,'w')
return({'PASS'}, '')
except IOError:
return({'ERROR'}, 'Invalid export file path')
def loadMaterialFile(filePath):
fileObj = open(filePath, 'r')
matDict = dict()
# loop over lines
lines = fileObj.readlines()
for line in lines:
# shape data (remove leading / trailing spaces and \n\r charact)
l = line.lstrip().rstrip().split(' ')
header = l[0]
# detect new material addition
if( header.startswith('/material/name') ):
# shape data
name = l[1].rstrip()
# save to locals
matDict[name] = EvertMaterial(name)
else:
# shape data
values = [float(x) for x in l[1::]]
# detect absorption definition
if( header.endswith('/absorption') ):
matDict[name].absorptions = values
# detect scattering definition
elif( header.endswith('/scattering') ):
matDict[name].scatterings = values
# return mat list
return matDict
def checkMaterialsIntegrity(matDict):
# loop over materials
for k in matDict:
m = matDict[k]
# check that material has same number of absorptions and scattering coefficients
if( len(m.absorptions) != len(m.scatterings) ):
return({'ERROR'}, 'Material ' + m.name + ' number of absorption coefs does not match number of scatterings coefs')
# all passed
return({'PASS'}, '')
def loadMaterials(context, evertims, forceUpdate = False):
# sanity check: room materials are acoustic materials
if forceUpdate or not evertims.materials:
# get material file path
addon_prefs = context.preferences.addons[__package__].preferences
# load material file if path defined
if addon_prefs.material_file_path:
filePath = bpy.path.abspath(addon_prefs.material_file_path)
matDict = loadMaterialFile(filePath)
# check material integrity
(status, msg) = checkMaterialsIntegrity(matDict)
if status != {'PASS'}:
return (status, msg)
# shape output
evertims.materials = matDict2str(matDict)
# return error otherwise
else:
return ({'ERROR'}, 'Undefined material file path')
else: print('evertims.material already defined, skipping init')
# notify success
return ({'PASS'}, '')
def checkSceneIntegrity(context, evertims):
# sanity check: room defined
if not evertims.room_group:
return({'ERROR'}, 'No room defined')
# sanity check: source defined
if not evertims.source_object:
return({'ERROR'}, 'No source defined')
# sanity check: listener defined
if not evertims.listener_object:
return({'ERROR'}, 'No listener defined')
# load materials if need be
(status, msg) = loadMaterials(context, evertims)
if status != {'PASS'}:
return (status, msg)
# sanity check: room group contains at least one object
roomObjects = bpy.data.collections[evertims.room_group].objects
if( len(roomObjects) == 0 ):
return({'ERROR'}, 'Room group is empty')
# sanity check: all objects in room group have acoustic materials
for obj in roomObjects:
# get object materials
materialSlots = obj.material_slots
# abort if no material defined
if( len( materialSlots ) == 0 ):
return({'ERROR'}, 'Room object ' + obj.name +' has no material')
# get list of acoustic materials
matDict = str2dict(evertims.materials)
# loop over materials in object, check if member of acoustic materials
for mat in materialSlots:
if not mat.name in matDict:
return({'ERROR'}, 'Room object ' + obj.name +' material ' + mat.name + ': not an acoustic material')
# notify success
return ({'PASS'}, '')