Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 88 additions & 56 deletions mesh2hrtf/Mesh2Input/Meshes/AssignMaterials/AssignMaterials.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ class AssignMaterials(bpy.types.Operator):
ear : StringProperty
The ear canals to assign the materials to. Can be ``'Both ears'``,
``'Left ear'`` or ``'Right ear'``. The default is 'Both ears'.

tolerance_mode : StringProperty
Mode of tolerance.
``'y_distance'`` minimizes xz_distance and tolerates deviation along the y axis,
``'xz_distance'`` minimizes abs(y) and tolerates radial deviation normal to the y axis.
'''
bl_idname = "object.assignmaterials"
bl_label = "AssignMaterials"
Expand All @@ -63,6 +66,13 @@ class AssignMaterials(bpy.types.Operator):
The default is 'Both ears'.",
default = "Both ears",
)
tolerance_mode: StringProperty(
name = "tolerance_mode",
description = "Mode of tolerance. \
``'y_distance'`` minimizes xz_distance and tolerates deviation along the y axis, \
``'xz_distance'`` minimizes abs(y) and tolerates radial deviation normal to the y axis.",
default = "y_distance",
)

def execute(self, context):
# unit = 'mm'
Expand Down Expand Up @@ -96,66 +106,88 @@ def setup_materials(obj):
bpy.context.object.active_material.name = name


def get_ear_indices(bm, obj, tolerance, ear):
'''Return indicees of faces at the entrance to the ear channels'''
def get_ear_indices(bm, obj, tolerance, ear, tolerance_mode="y_distance"):
'''Return indices of faces at the entrance to the ear channels'''

bm.verts.ensure_lookup_table()
bm.faces.ensure_lookup_table()

# initialize helper variables
left_indices = []
left_xy_distance = []
left_y = []
right_indices = []
right_xy_distance = []
right_y = []
# initialize helper variable
min_y = [1000, 1000]

# world matrix for obtaining vertex positions in world coorindates
world = obj.matrix_world

# find possible faces at the ear channel entrances
for face in bm.faces:

# current face location in world coordinates
xyz = world @ face.calc_center_median()
# distance from y axis, and y-value
xy_distance = abs(xyz[0]) + abs(xyz[2])
y = xyz[1]

# potential left ear
if y > 0 and abs(xyz[0]) < tolerance and abs(xyz[2]) < tolerance:
left_indices.append(face.index)
left_xy_distance.append(xy_distance)
left_y.append(abs(y))
if abs(y) < min_y[0]:
min_y[0] = abs(y)
# potential right ear
elif y < 0 and abs(xyz[0]) < tolerance and abs(xyz[2]) < tolerance:
right_indices.append(face.index)
right_xy_distance.append(xy_distance)
right_y.append(abs(y))
if abs(y) < min_y[1]:
min_y[1] = abs(y)

# find left ear element and try to exclude faces at the tragus
left_index = None
if ear in ("Both ears", "Left ear"):
min_xy_dist = 1000
for n in range(len(left_indices)):
if left_y[n] < min_y[0] + tolerance and left_xy_distance[n] < \
min_xy_dist:
min_xy_dist = left_xy_distance[n]
left_index = left_indices[n]
# find left ear element and try to exclude faces at the tragus
right_index = None
if ear in ("Both ears", "Right ear"):
min_xy_dist = 1000
for n in range(len(right_indices)):
if right_y[n] < min_y[1] + tolerance and right_xy_distance[n] < \
min_xy_dist:
min_xy_dist = right_xy_distance[n]
right_index = right_indices[n]

if tolerance_mode == "y_distance":
# minimizes xz_distance and tolerates deviation along the y axis
# initialize helper variables
left_indices = []
left_xy_distance = []
left_y = []
right_indices = []
right_xy_distance = []
right_y = []

# world matrix for obtaining vertex positions in world coorindates
world = obj.matrix_world

# find possible faces at the ear channel entrances
for face in bm.faces:

# current face location in world coordinates
xyz = world @ face.calc_center_median()
# distance from y axis, and y-value
xy_distance = abs(xyz[0]) + abs(xyz[2])
y = xyz[1]

# potential left ear
if y > 0 and abs(xyz[0]) < tolerance and abs(xyz[2]) < tolerance:
left_indices.append(face.index)
left_xy_distance.append(xy_distance)
left_y.append(abs(y))
if abs(y) < min_y[0]:
min_y[0] = abs(y)
# potential right ear
elif y < 0 and abs(xyz[0]) < tolerance and abs(xyz[2]) < tolerance:
right_indices.append(face.index)
right_xy_distance.append(xy_distance)
right_y.append(abs(y))
if abs(y) < min_y[1]:
min_y[1] = abs(y)

# find left ear element and try to exclude faces at the tragus
left_index = None
if ear in ("Both ears", "Left ear"):
min_xy_dist = 1000
for n in range(len(left_indices)):
if left_y[n] < min_y[0] + tolerance and left_xy_distance[n] < \
min_xy_dist:
min_xy_dist = left_xy_distance[n]
left_index = left_indices[n]
# find left ear element and try to exclude faces at the tragus
right_index = None
if ear in ("Both ears", "Right ear"):
min_xy_dist = 1000
for n in range(len(right_indices)):
if right_y[n] < min_y[1] + tolerance and right_xy_distance[n] < \
min_xy_dist:
min_xy_dist = right_xy_distance[n]
right_index = right_indices[n]

elif tolerance_mode == "xz_distance":
# find optimal faces for left and right mic position
# by choosing the face with min y value in the area around the y axis with radius=tolerance
for f in bm.faces:
f_median= f.calc_center_median() # compute face location
xz_distance = np.sqrt(f_median.x**2 + f_median.z**2) # compute distance to y axis
if xz_distance < tolerance:
if f_median.y > 0 and ear in ("Both ears", "Left ear"): # Left
if f_median.y < min_y[0]:
min_y[0] = f_median.y
left_index = f.index
elif f_median.y < 0 and ear in ("Both ears", "Right ear"): # Right
if abs(f_median.y) < min_y[1]:
min_y[1] = abs(f_median.y)
right_index = f.index

return left_index, right_index

Expand All @@ -172,11 +204,11 @@ def assign_material(obj, tolerance, ear):
bm = bmesh.new()
bm.from_mesh(obj.data)

# get indicees
# get indices
print(f"Search tolerance: {tolerance} blender units")
left_index, right_index = get_ear_indices(bm, obj, tolerance, ear)

# assign indicees
# assign indices
if ear in ("Both ears", "Left ear"):
if left_index is not None:
bm.faces[left_index].material_index = 1
Expand Down