Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Paint islands #4644

Merged
merged 4 commits into from
Sep 8, 2022
Merged
Show file tree
Hide file tree
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
6 changes: 4 additions & 2 deletions docs/nodes/analyzer/wave_paint.rst
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,17 @@ This node has the following outputs:
number of steps which should be taken from initially selected faces
(vertices), to take to this face (vertex), starting from 1 for initially
selected faces. In other words, this is the number of the wave front. This
output will contain 0 for obstacle faces / vertices.
output will contain 0 for obstacle faces / vertices and -1 if faces /
vertices are unreachable from selected elements.
- **WaveDistance**. For each face (or vertex) of the mesh, this contains the
length of the shortest path from initially selected faces (vertices) to this
face (vertex). The path is considered to be consisting of single steps from
one face / vertex to one of it's neighbours. The length of step between
neighbour vertices is the Euclidean distance between such vertices. The
length of step between neighbour faces is calculated as Euclidean distance
between the centers of such faces. This input will contain 0 for initially
selected faces as well as for obstacle faces.
selected faces as well as for obstacle faces and -1 for elements which are
unreachable from selected ones.
- **StartIdx**. For each face (or vertex) of the mesh, this contains the index
of one of initially selected faces / vertices, which is the nearest from this
face / vertex, in terms of the shortest path described above.
Expand Down
39 changes: 29 additions & 10 deletions utils/sv_bmesh_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,7 @@ def fill_verts_layer(bm, vert_mask, layer_name, layer_type, value, invert_mask =
if mask != invert_mask:
vert[layer] = value


def wave_markup_faces(bm, init_face_mask, neighbour_by_vert = True, find_shortest_path = False):
"""
Given initial faces, markup all mesh faces by wave algorithm:
Expand Down Expand Up @@ -694,13 +695,10 @@ def wave_markup_faces(bm, init_face_mask, neighbour_by_vert = True, find_shortes
path_prev_index = bm.faces.layers.int.new("wave_path_prev_index")
path_prev_distance = bm.faces.layers.float.new("wave_path_prev_distance")
path_distance = bm.faces.layers.float.new("wave_path_distance")
is_reached = bm.faces.layers.int.new("is_reached") # True for painted faces
obstacles = bm.faces.layers.int.get("wave_obstacle")
bm.faces.ensure_lookup_table()
bm.faces.index_update()
if obstacles is None:
n_total = len(bm.faces)
else:
n_total = len([face for face in bm.faces if face[obstacles] == 0])

if find_shortest_path:
face_center = dict([(face.index, face.calc_center_median()) for face in bm.faces])
Expand All @@ -723,11 +721,12 @@ def is_obstacle(face):
if find_shortest_path:
for face in init_faces:
face[init_index] = face.index
while len(done) < n_total:
while wave_front:
step += 1
new_wave_front = set()
for face in wave_front:
face[index] = step
face[is_reached] = 1
for face in wave_front:
if find_shortest_path:
this_center = face_center[face.index]
Expand All @@ -750,8 +749,19 @@ def is_obstacle(face):
done.update(wave_front)
wave_front = new_wave_front

# fix values for unpainted faces
for face in bm.faces:
if not face[is_reached] and not is_obstacle(face):
# is obstacle can be removed in next version to be consistent with
# unreached parts of the mesh
face[index] = -1
if find_shortest_path:
face[path_distance] = -1
face[init_index] = -1

return [face[index] for face in bm.faces]


def wave_markup_verts(bm, init_vert_mask, neighbour_by_edge = True, find_shortest_path = False):
"""
Given initial vertices, markup all mesh vertices by wave algorithm:
Expand All @@ -767,12 +777,9 @@ def wave_markup_verts(bm, init_vert_mask, neighbour_by_edge = True, find_shortes
path_prev_distance = bm.verts.layers.float.new("wave_path_prev_distance")
path_distance = bm.verts.layers.float.new("wave_path_distance")
obstacles = bm.verts.layers.int.get("wave_obstacle")
is_reached = bm.verts.layers.int.new("is_reached") # True for painted verts
bm.verts.ensure_lookup_table()
bm.verts.index_update()
if obstacles is None:
n_total = len(bm.verts)
else:
n_total = len([vert for vert in bm.verts if vert[obstacles] == 0])

init_verts = [vert for vert, mask in zip(bm.verts[:], init_vert_mask) if mask]
if not init_verts:
Expand All @@ -790,11 +797,12 @@ def is_obstacle(vert):
if find_shortest_path:
for vert in init_verts:
vert[init_index] = vert.index
while len(done) < n_total:
while wave_front:
step += 1
new_wave_front = set()
for vert in wave_front:
vert[index] = step
vert[is_reached] = 1
for vert in wave_front:
for other_vert in get_neighbour_verts(vert, neighbour_by_edge):
if is_obstacle(other_vert):
Expand All @@ -814,8 +822,19 @@ def is_obstacle(vert):
done.update(wave_front)
wave_front = new_wave_front

# fix values for unpainted vertices
for vert in bm.verts:
if not vert[is_reached] and not is_obstacle(vert):
# is obstacle can be removed in next version to be consistent with
# unreached parts of the mesh
vert[index] = -1
if find_shortest_path:
vert[path_distance] = -1
vert[init_index] = -1

return [vert[index] for vert in bm.verts]


def bmesh_bisect(bm, point, normal, fill):
bm.normal_update()
geom_in = bm.verts[:] + bm.edges[:] + bm.faces[:]
Expand Down