Created
April 24, 2024 02:01
-
-
Save unwave/7d360719853b67d7a1735700a34b2b6e to your computer and use it in GitHub Desktop.
traverse bmesh and decide on places and orientations to put physics forces
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import bpy | |
import bmesh | |
from blend_converter import bl_utils | |
BASE_LENGTH = 2 | |
MAX_LENGTH = 1.5 * BASE_LENGTH | |
TRAVERSE_SELECT = False | |
bl_utils.select(bpy.data.objects['level']) | |
bpy.ops.object.duplicate(linked=False) | |
level_copy = bpy.context.object | |
bl_utils.select(level_copy) | |
level_copy.modifiers['Skin'].show_viewport = False | |
level_path_object = bl_utils.convert_to_mesh(level_copy) | |
pushers_collection = bpy.data.collections.new('pushers') | |
bpy.context.scene.collection.children.link(pushers_collection) | |
def get_empty(): | |
empty_obj = bpy.data.objects.new("__blood_pusher__", None) | |
pushers_collection.objects.link(empty_obj) | |
empty_obj.empty_display_type = 'CUBE' | |
return empty_obj | |
def get_root_point_index(object): | |
for skin_v, v in zip(object.data.skin_vertices[0].data, object.data.vertices): | |
if skin_v.use_root: | |
return v.index | |
bl_utils.select(level_path_object) | |
bpy.ops.object.mode_set(mode='OBJECT') | |
skin_root_index = get_root_point_index(level_path_object) | |
bpy.ops.object.editmode_toggle() | |
bm = bmesh.from_edit_mesh(level_path_object.data) | |
bm.verts.ensure_lookup_table() | |
root_vertex = bm.verts[skin_root_index] | |
if TRAVERSE_SELECT: | |
bpy.ops.mesh.select_all(action='DESELECT') | |
segment_start_verts = [] | |
# tuple <start, root> | |
target_verts = [] | |
# tuple <target, prev> | |
seen_edges = set() | |
def get_root_vert(start_vert): | |
if not seen_edges: | |
return None | |
for edge in start_vert.link_edges: | |
if edge in seen_edges: | |
return edge.other_vert(start_vert) | |
if TRAVERSE_SELECT: | |
bpy.ops.mesh.select_all(action='DESELECT') | |
start_vert.select = True | |
raise Exception(f"root_vert not found for: {start_vert}") | |
def traverse(init_vert): | |
root_vert = get_root_vert(init_vert) | |
if root_vert is None: | |
# the skin modfier root | |
assert len(init_vert.link_edges) == 1 | |
skin_mod_root_edge = init_vert.link_edges[0] | |
root_vert = init_vert | |
init_vert = skin_mod_root_edge.other_vert(init_vert) | |
seen_edges.add(skin_mod_root_edge) | |
segment_start_verts.append((init_vert, root_vert)) | |
else: | |
segment_start_verts.append((init_vert, root_vert)) | |
if TRAVERSE_SELECT: | |
init_vert.select = True | |
length = 0 | |
pool = [init_vert] | |
while pool: | |
vert = pool.pop(0) | |
edges = vert.link_edges | |
if len(edges) == 1: | |
# ends of the polylines | |
if TRAVERSE_SELECT: | |
vert.select = True | |
elif len(edges) == 2: | |
for edge in edges: | |
if edge in seen_edges: | |
continue | |
seen_edges.add(edge) | |
length = length + edge.calc_length() | |
other_vert = edge.other_vert(vert) | |
if length >= MAX_LENGTH and len(other_vert.link_edges) == 2: | |
target_verts.append((other_vert, vert)) | |
if TRAVERSE_SELECT: | |
other_vert.select = True | |
length = 0 | |
pool.append(other_vert) | |
else: | |
for edge in edges: | |
if edge in seen_edges: | |
continue | |
seen_edges.add(edge) | |
traverse(edge.other_vert(vert)) | |
traverse(root_vertex) | |
def get_tangent_quat(vert, prev_vert): | |
return (vert.co - prev_vert.co).normalized().to_track_quat('Z') | |
for start, root in segment_start_verts: | |
quat = get_tangent_quat(start, root) | |
empty_obj = get_empty() | |
empty_obj.matrix_world = quat.to_matrix().to_4x4() | |
empty_obj.scale = (1, 1, BASE_LENGTH) | |
empty_obj.location = start.co | |
for target, prev in target_verts: | |
quat = get_tangent_quat(target, prev) | |
empty_obj = get_empty() | |
empty_obj.matrix_world = quat.to_matrix().to_4x4() | |
empty_obj.scale = (1, 1, BASE_LENGTH) | |
empty_obj.location = target.co | |
bmesh.update_edit_mesh(level_path_object.data, loop_triangles=False, destructive=False) | |
bpy.ops.object.editmode_toggle() | |
bpy.data.objects.remove(level_path_object) |
Author
unwave
commented
Apr 24, 2024
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment