Asset Pipeline: Improve Performance #235
@ -121,85 +121,70 @@ 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]):
|
def apply_transfer_data_items(context, td_type_key: str, transfer_data_items: List[PropertyGroup]):
|
||||||
|
# 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:
|
||||||
|
print(f"Failed to Transfer Data for {transfer_data_item.id_data.name}")
|
||||||
|
return
|
||||||
|
|
||||||
for transfer_data_item in transfer_data_items:
|
for transfer_data_item in transfer_data_items:
|
||||||
target_obj = transfer_data_item.target_obj
|
|
||||||
source_obj = transfer_data_item.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,
|
|
||||||
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}."
|
|
||||||
)
|
|
||||||
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}."
|
|
||||||
)
|
|
||||||
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}.")
|
|
||||||
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}."
|
|
||||||
)
|
|
||||||
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}."
|
|
||||||
)
|
|
||||||
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}."
|
|
||||||
)
|
|
||||||
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()
|
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 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 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 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 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 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 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,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def apply_transfer_data(context: bpy.types.Context, transfer_data_map) -> None:
|
def apply_transfer_data(context: bpy.types.Context, transfer_data_map) -> None:
|
||||||
"""Apply all Transferable Data from Transferable Data map onto objects.
|
"""Apply all Transferable Data from Transferable Data map onto objects.
|
||||||
|
@ -35,33 +35,26 @@ def init_vertex_groups(scene, obj):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def transfer_vertex_group(
|
def transfer_vertex_groups(
|
||||||
context,
|
vertex_group_names: List[str],
|
||||||
vertex_group_name: str,
|
|
||||||
target_obj: bpy.types.Object,
|
target_obj: bpy.types.Object,
|
||||||
source_obj: bpy.types.Object,
|
source_obj: bpy.types.Object,
|
||||||
):
|
):
|
||||||
logger = logging.get_logger()
|
for vertex_group_name in vertex_group_names:
|
||||||
if target_obj == source_obj:
|
if not source_obj.vertex_groups.get(vertex_group_name):
|
||||||
return
|
print(f"ERROR Vertex Group {vertex_group_name} not found in {source_obj.name}")
|
||||||
|
return
|
||||||
if not source_obj.vertex_groups.get(vertex_group_name):
|
|
||||||
logger.error(f"Vertex Group {vertex_group_name} not found in {source_obj.name}")
|
|
||||||
return
|
|
||||||
|
|
||||||
# If topology matches transfer directly, otherwise use vertex proximity
|
# If topology matches transfer directly, otherwise use vertex proximity
|
||||||
if is_obdata_identical(source_obj, target_obj):
|
if is_obdata_identical(source_obj, target_obj):
|
||||||
transfer_single_vgroup_by_topology(
|
for vertex_group_name in vertex_group_names:
|
||||||
source_obj, target_obj, vertex_group_name
|
transfer_single_vgroup_by_topology(source_obj, target_obj, vertex_group_name)
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
precalc_and_transfer_single_group(
|
precalc_and_transfer_multiple_groups(source_obj, target_obj, vertex_group_names, expand=2)
|
||||||
source_obj, target_obj, vertex_group_name, expand=2
|
|
||||||
)
|
|
||||||
|
|
||||||
def transfer_single_vgroup_by_topology(source_obj, target_obj, vgroup_name):
|
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
|
# Remove group from the target obj if it already exists. TODO: de-duplicate
|
||||||
tgt_vg = target_obj.vertex_groups.get(vgroup_name)
|
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]:
|
if vgroup_src.index in [g.group for g in v.groups]:
|
||||||
vgroup_tgt.add([v.index], vgroup_src.weight(v.index), 'REPLACE')
|
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):
|
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,
|
"""Convenience function to transfer a single group. For transferring multiple groups,
|
||||||
this is very inefficient and shouldn't be used.
|
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)
|
target_obj.vertex_groups.remove(tgt_vg)
|
||||||
|
|
||||||
kd_tree = build_kdtree(source_obj.data)
|
kd_tree = build_kdtree(source_obj.data)
|
||||||
vert_influence_map = build_vert_influence_map(
|
vert_influence_map = build_vert_influence_map(source_obj, target_obj, kd_tree, expand)
|
||||||
source_obj, target_obj, kd_tree, expand
|
|
||||||
)
|
transfer_multiple_vertex_groups(
|
||||||
transfer_vertex_groups(
|
|
||||||
source_obj,
|
source_obj,
|
||||||
target_obj,
|
target_obj,
|
||||||
vert_influence_map,
|
vert_influence_map,
|
||||||
@ -110,9 +129,7 @@ def build_kdtree(mesh):
|
|||||||
|
|
||||||
|
|
||||||
def build_vert_influence_map(obj_from, obj_to, kd_tree, expand=2):
|
def build_vert_influence_map(obj_from, obj_to, kd_tree, expand=2):
|
||||||
verts_of_edge = {
|
verts_of_edge = {i: (e.vertices[0], e.vertices[1]) for i, e in enumerate(obj_from.data.edges)}
|
||||||
i: (e.vertices[0], e.vertices[1]) for i, e in enumerate(obj_from.data.edges)
|
|
||||||
}
|
|
||||||
|
|
||||||
edges_of_vert: Dict[int, List[int]] = {}
|
edges_of_vert: Dict[int, List[int]] = {}
|
||||||
for edge_idx, edge in enumerate(obj_from.data.edges):
|
for edge_idx, edge in enumerate(obj_from.data.edges):
|
||||||
@ -166,29 +183,24 @@ def get_source_vert_influences(
|
|||||||
parts_sum = sum(parts)
|
parts_sum = sum(parts)
|
||||||
|
|
||||||
influences = [
|
influences = [
|
||||||
(idx, 1 if dist == 0 else part / parts_sum)
|
(idx, 1 if dist == 0 else part / parts_sum) for part, dist in zip(parts, distances)
|
||||||
for part, dist in zip(parts, distances)
|
|
||||||
]
|
]
|
||||||
|
|
||||||
return influences
|
return influences
|
||||||
|
|
||||||
|
|
||||||
def get_nearest_vert(
|
def get_nearest_vert(coords: Vector, kd_tree: kdtree.KDTree) -> Tuple[Vector, int, float]:
|
||||||
coords: Vector, kd_tree: kdtree.KDTree
|
|
||||||
) -> Tuple[Vector, int, float]:
|
|
||||||
"""Return coordinate, index, and distance of nearest vert to coords in kd_tree."""
|
"""Return coordinate, index, and distance of nearest vert to coords in kd_tree."""
|
||||||
return kd_tree.find(coords)
|
return kd_tree.find(coords)
|
||||||
|
|
||||||
|
|
||||||
def other_vert_of_edge(
|
def other_vert_of_edge(edge: int, vert: int, verts_of_edge: Dict[int, Tuple[int, int]]) -> int:
|
||||||
edge: int, vert: int, verts_of_edge: Dict[int, Tuple[int, int]]
|
|
||||||
) -> int:
|
|
||||||
verts = verts_of_edge[edge]
|
verts = verts_of_edge[edge]
|
||||||
assert vert in verts, f"Vert {vert} not part 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]
|
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."""
|
"""Transfer src_vgroups in obj_from to obj_to using a pre-calculated vert_influence_map."""
|
||||||
|
|
||||||
for src_vg in src_vgroups:
|
for src_vg in src_vgroups:
|
||||||
|
Loading…
Reference in New Issue
Block a user