Asset Pipeline: Improve Performance #235
@ -121,84 +121,69 @@ def apply_transfer_data(context: bpy.types.Context, transfer_data_map) -> None:
|
||||
|
||||
|
||||
def apply_transfer_data_items(context, td_type_key: str, transfer_data_items: List[PropertyGroup]):
|
||||
for transfer_data_item in transfer_data_items:
|
||||
target_obj = transfer_data_item.target_obj
|
||||
source_obj = transfer_data_item.obj
|
||||
# Get source/target from first item in list, because all items in list are same object/type
|
||||
target_obj = transfer_data_items[0].target_obj
|
||||
source_obj = transfer_data_items[0].obj
|
||||
|
||||
if target_obj is None:
|
||||
logger.warning(f"Failed to Transfer Data for {transfer_data_item.id_data.name}")
|
||||
continue
|
||||
if transfer_data_item is None:
|
||||
continue
|
||||
if source_obj != target_obj:
|
||||
if transfer_data_item.type == constants.VERTEX_GROUP_KEY:
|
||||
logger.debug(
|
||||
f"Transferring Vertex Group {transfer_data_item.name} from {source_obj.name} to {target_obj.name}."
|
||||
)
|
||||
vertex_groups.transfer_vertex_group(
|
||||
context=context,
|
||||
vertex_group_name=transfer_data_item.name,
|
||||
print(f"Failed to Transfer Data for {transfer_data_item.id_data.name}")
|
||||
return
|
||||
|
||||
for transfer_data_item in transfer_data_items:
|
||||
transfer_data_item.copy_transfer_data_ownership()
|
||||
|
||||
if source_obj == target_obj:
|
||||
return
|
||||
|
||||
if td_type_key == constants.VERTEX_GROUP_KEY:
|
||||
# Transfer All Vertex Groups in one go
|
||||
print(f"Transferring all Vertex Groups from {source_obj.name} to {target_obj.name}")
|
||||
vertex_groups.transfer_vertex_groups(
|
||||
vertex_group_names=[item.name for item in transfer_data_items],
|
||||
target_obj=target_obj,
|
||||
source_obj=source_obj,
|
||||
)
|
||||
if transfer_data_item.type == constants.MODIFIER_KEY:
|
||||
logger.debug(
|
||||
f"Transferring Modifier{transfer_data_item.name} from {source_obj.name} to {target_obj.name}."
|
||||
)
|
||||
if td_type_key == constants.MODIFIER_KEY:
|
||||
for transfer_data_item in transfer_data_items:
|
||||
modifers.transfer_modifier(
|
||||
modifier_name=transfer_data_item.name,
|
||||
target_obj=target_obj,
|
||||
source_obj=source_obj,
|
||||
)
|
||||
if transfer_data_item.type == constants.CONSTRAINT_KEY:
|
||||
logger.debug(
|
||||
f"Transferring Constraint {transfer_data_item.name} from {source_obj.name} to {target_obj.name}."
|
||||
)
|
||||
if td_type_key == constants.CONSTRAINT_KEY:
|
||||
for transfer_data_item in transfer_data_items:
|
||||
constraints.transfer_constraint(
|
||||
constraint_name=transfer_data_item.name,
|
||||
target_obj=target_obj,
|
||||
source_obj=source_obj,
|
||||
)
|
||||
if transfer_data_item.type == constants.MATERIAL_SLOT_KEY:
|
||||
logger.debug(f"Transferring Materiald from {source_obj.name} to {target_obj.name}.")
|
||||
if td_type_key == constants.MATERIAL_SLOT_KEY:
|
||||
for transfer_data_item in transfer_data_items:
|
||||
materials.transfer_materials(
|
||||
target_obj=target_obj,
|
||||
source_obj=source_obj,
|
||||
)
|
||||
if transfer_data_item.type == constants.SHAPE_KEY_KEY:
|
||||
logger.debug(
|
||||
f"Transferring Shape Key {transfer_data_item.name} from {source_obj.name} to {target_obj.name}."
|
||||
)
|
||||
if td_type_key == constants.SHAPE_KEY_KEY:
|
||||
for transfer_data_item in transfer_data_items:
|
||||
shape_keys.transfer_shape_key(
|
||||
context=context,
|
||||
target_obj=target_obj,
|
||||
source_obj=source_obj,
|
||||
shape_key_name=transfer_data_item.name,
|
||||
)
|
||||
if transfer_data_item.type == constants.ATTRIBUTE_KEY:
|
||||
logger.debug(
|
||||
f"Transferring Attribute {transfer_data_item.name} from {source_obj.name} to {target_obj.name}."
|
||||
)
|
||||
if td_type_key == constants.ATTRIBUTE_KEY:
|
||||
for transfer_data_item in transfer_data_items:
|
||||
attributes.transfer_attribute(
|
||||
target_obj=target_obj,
|
||||
source_obj=source_obj,
|
||||
attribute_name=transfer_data_item.name,
|
||||
)
|
||||
if transfer_data_item.type == constants.PARENT_KEY:
|
||||
logger.debug(
|
||||
f"Transferring Parent Relationship from {source_obj.name} to {target_obj.name}."
|
||||
)
|
||||
if td_type_key == constants.PARENT_KEY:
|
||||
for transfer_data_item in transfer_data_items:
|
||||
parent.transfer_parent(
|
||||
target_obj=target_obj,
|
||||
source_obj=source_obj,
|
||||
)
|
||||
logger.debug(
|
||||
f"Copying Ownership Data for {transfer_data_item.name} from {source_obj.name} to {target_obj.name}."
|
||||
)
|
||||
copy_transfer_data_ownership(
|
||||
transfer_data_item=transfer_data_item,
|
||||
target_obj=target_obj,
|
||||
)
|
||||
transfer_data_item.copy_transfer_data_ownership()
|
||||
|
||||
|
||||
def apply_transfer_data(context: bpy.types.Context, transfer_data_map) -> None:
|
||||
|
@ -35,33 +35,26 @@ def init_vertex_groups(scene, obj):
|
||||
)
|
||||
|
||||
|
||||
def transfer_vertex_group(
|
||||
context,
|
||||
vertex_group_name: str,
|
||||
def transfer_vertex_groups(
|
||||
vertex_group_names: List[str],
|
||||
target_obj: bpy.types.Object,
|
||||
source_obj: bpy.types.Object,
|
||||
):
|
||||
logger = logging.get_logger()
|
||||
if target_obj == source_obj:
|
||||
return
|
||||
|
||||
for vertex_group_name in vertex_group_names:
|
||||
if not source_obj.vertex_groups.get(vertex_group_name):
|
||||
logger.error(f"Vertex Group {vertex_group_name} not found in {source_obj.name}")
|
||||
print(f"ERROR Vertex Group {vertex_group_name} not found in {source_obj.name}")
|
||||
return
|
||||
|
||||
# If topology matches transfer directly, otherwise use vertex proximity
|
||||
if is_obdata_identical(source_obj, target_obj):
|
||||
transfer_single_vgroup_by_topology(
|
||||
source_obj, target_obj, vertex_group_name
|
||||
)
|
||||
for vertex_group_name in vertex_group_names:
|
||||
transfer_single_vgroup_by_topology(source_obj, target_obj, vertex_group_name)
|
||||
else:
|
||||
precalc_and_transfer_single_group(
|
||||
source_obj, target_obj, vertex_group_name, expand=2
|
||||
)
|
||||
precalc_and_transfer_multiple_groups(source_obj, target_obj, vertex_group_names, expand=2)
|
||||
|
||||
|
||||
def transfer_single_vgroup_by_topology(source_obj, target_obj, vgroup_name):
|
||||
""" Function to quickly transfer single vertex group between mesh objects in case of matching topology.
|
||||
"""
|
||||
"""Function to quickly transfer single vertex group between mesh objects in case of matching topology."""
|
||||
|
||||
# Remove group from the target obj if it already exists. TODO: de-duplicate
|
||||
tgt_vg = target_obj.vertex_groups.get(vgroup_name)
|
||||
@ -75,6 +68,33 @@ def transfer_single_vgroup_by_topology(source_obj, target_obj, vgroup_name):
|
||||
if vgroup_src.index in [g.group for g in v.groups]:
|
||||
vgroup_tgt.add([v.index], vgroup_src.weight(v.index), 'REPLACE')
|
||||
|
||||
|
||||
def precalc_and_transfer_multiple_groups(source_obj, target_obj, vgroup_names, expand=2):
|
||||
"""Convenience function to transfer a single group. For transferring multiple groups,
|
||||
this is very inefficient and shouldn't be used.
|
||||
|
||||
Instead, you should:
|
||||
- build_kd_tree ONCE per source mesh.
|
||||
- build_vert_influence_map and transfer_vertex_groups ONCE per object pair.
|
||||
"""
|
||||
|
||||
# Remove group from the target obj if it already exists. TODO: de-duplicate
|
||||
vgroups = [source_obj.vertex_groups[name] for name in vgroup_names]
|
||||
for vgroup_name in vgroup_names:
|
||||
target_vgroup = target_obj.vertex_groups.get(vgroup_name)
|
||||
if target_vgroup:
|
||||
target_obj.vertex_groups.remove(target_vgroup)
|
||||
|
||||
kd_tree = build_kdtree(source_obj.data)
|
||||
vert_influence_map = build_vert_influence_map(source_obj, target_obj, kd_tree, expand)
|
||||
transfer_multiple_vertex_groups(
|
||||
source_obj,
|
||||
target_obj,
|
||||
vert_influence_map,
|
||||
vgroups,
|
||||
)
|
||||
|
||||
|
||||
def precalc_and_transfer_single_group(source_obj, target_obj, vgroup_name, expand=2):
|
||||
"""Convenience function to transfer a single group. For transferring multiple groups,
|
||||
this is very inefficient and shouldn't be used.
|
||||
@ -90,10 +110,9 @@ def precalc_and_transfer_single_group(source_obj, target_obj, vgroup_name, expan
|
||||
target_obj.vertex_groups.remove(tgt_vg)
|
||||
|
||||
kd_tree = build_kdtree(source_obj.data)
|
||||
vert_influence_map = build_vert_influence_map(
|
||||
source_obj, target_obj, kd_tree, expand
|
||||
)
|
||||
transfer_vertex_groups(
|
||||
vert_influence_map = build_vert_influence_map(source_obj, target_obj, kd_tree, expand)
|
||||
|
||||
transfer_multiple_vertex_groups(
|
||||
source_obj,
|
||||
target_obj,
|
||||
vert_influence_map,
|
||||
@ -110,9 +129,7 @@ def build_kdtree(mesh):
|
||||
|
||||
|
||||
def build_vert_influence_map(obj_from, obj_to, kd_tree, expand=2):
|
||||
verts_of_edge = {
|
||||
i: (e.vertices[0], e.vertices[1]) for i, e in enumerate(obj_from.data.edges)
|
||||
}
|
||||
verts_of_edge = {i: (e.vertices[0], e.vertices[1]) for i, e in enumerate(obj_from.data.edges)}
|
||||
|
||||
edges_of_vert: Dict[int, List[int]] = {}
|
||||
for edge_idx, edge in enumerate(obj_from.data.edges):
|
||||
@ -166,29 +183,24 @@ def get_source_vert_influences(
|
||||
parts_sum = sum(parts)
|
||||
|
||||
influences = [
|
||||
(idx, 1 if dist == 0 else part / parts_sum)
|
||||
for part, dist in zip(parts, distances)
|
||||
(idx, 1 if dist == 0 else part / parts_sum) for part, dist in zip(parts, distances)
|
||||
]
|
||||
|
||||
return influences
|
||||
|
||||
|
||||
def get_nearest_vert(
|
||||
coords: Vector, kd_tree: kdtree.KDTree
|
||||
) -> Tuple[Vector, int, float]:
|
||||
def get_nearest_vert(coords: Vector, kd_tree: kdtree.KDTree) -> Tuple[Vector, int, float]:
|
||||
"""Return coordinate, index, and distance of nearest vert to coords in kd_tree."""
|
||||
return kd_tree.find(coords)
|
||||
|
||||
|
||||
def other_vert_of_edge(
|
||||
edge: int, vert: int, verts_of_edge: Dict[int, Tuple[int, int]]
|
||||
) -> int:
|
||||
def other_vert_of_edge(edge: int, vert: int, verts_of_edge: Dict[int, Tuple[int, int]]) -> int:
|
||||
verts = verts_of_edge[edge]
|
||||
assert vert in verts, f"Vert {vert} not part of edge {edge}."
|
||||
return verts[0] if vert == verts[1] else verts[1]
|
||||
|
||||
|
||||
def transfer_vertex_groups(obj_from, obj_to, vert_influence_map, src_vgroups):
|
||||
def transfer_multiple_vertex_groups(obj_from, obj_to, vert_influence_map, src_vgroups):
|
||||
"""Transfer src_vgroups in obj_from to obj_to using a pre-calculated vert_influence_map."""
|
||||
|
||||
for src_vg in src_vgroups:
|
||||
|
Loading…
Reference in New Issue
Block a user