Fixed shape keys

This commit is contained in:
2026-05-22 22:03:31 +03:00
parent 3a3edf785c
commit c7ef9283cd
3 changed files with 27 additions and 7 deletions
@@ -522,9 +522,9 @@ def enforce_side_constraint(pos, surface_point, reference_normal, target_side, c
# Very small offset to stay near surface
offset = abs((surface_point - pos).length) * 0.2
if target_side > 0:
return proj_point - reference_normal * offset
else:
return proj_point + reference_normal * offset
else:
return proj_point - reference_normal * offset
return pos
# Regular vertices - stronger enforcement
@@ -534,9 +534,9 @@ def enforce_side_constraint(pos, surface_point, reference_normal, target_side, c
offset = abs((surface_point - pos).length) * 0.95
if target_side > 0:
corrected_pos = proj_point - reference_normal * offset
else:
corrected_pos = proj_point + reference_normal * offset
else:
corrected_pos = proj_point - reference_normal * offset
return corrected_pos
@@ -879,7 +879,7 @@ def set_shape_key_with_side_preservation(target_obj, sk_name, mapping, source_da
smooth_penetration_areas(target_obj, sk_name, mapping, source_data)
def test_shape_key_quality(target_obj, sk_name, mapping, source_data):
"""Test shape key quality with side tracking"""
"""Test shape key quality with side tracking (READ-ONLY - does not modify shape key data)"""
sk = target_obj.data.shape_keys.key_blocks[sk_name]
@@ -889,6 +889,9 @@ def test_shape_key_quality(target_obj, sk_name, mapping, source_data):
prev_positions = None
boundary_vertices = mapping.get('boundary_vertices', set())
# Save original shape key data so we can restore it after testing
original_positions = [v.co.copy() for v in sk.data]
for val in test_values:
if val == 0.0:
sk.value = 0.0
@@ -932,6 +935,13 @@ def test_shape_key_quality(target_obj, sk_name, mapping, source_data):
prev_positions = [v.co.copy() for v in target_obj.data.vertices]
# Restore original shape key data (the test should not modify the shape key)
target_obj.data.shape_keys.use_relative = False
for i, v in enumerate(sk.data):
if i < len(original_positions):
v.co = original_positions[i]
target_obj.data.shape_keys.use_relative = True
sk.value = 0.0
target_obj.data.update_tag()
bpy.context.view_layer.update()
+5 -1
View File
@@ -376,10 +376,14 @@ for mapping in[CommandLineMapping()]:
save_data["tags"] = unique_tags
# Export shape keys if present
# IMPORTANT: Skip "Basis" to match OGRE's pose indexing.
# OGRE's blender2ogre exporter skips the Basis shape key (index 0),
# so pose index 0 in OGRE = first non-Basis shape key.
shape_keys = []
if obj.data.shape_keys and obj.data.shape_keys.key_blocks:
for sk in obj.data.shape_keys.key_blocks:
shape_keys.append(sk.name)
if sk.name != 'Basis':
shape_keys.append(sk.name)
save_data["shape_keys"] = shape_keys
save_data["mesh"] = obj.data.name + ".mesh"
@@ -614,7 +614,13 @@ void CharacterSlotSystem::applyShapeKeys(flecs::entity e, Ogre::Entity *ent,
as->setEnabled(true);
as->setLoop(false);
/* Build name -> pose index map from catalog */
/* Build name -> pose index map from catalog.
*
* IMPORTANT: The catalog now skips "Basis" to match OGRE's pose indexing.
* OGRE's blender2ogre exporter skips the Basis shape key (index 0),
* so pose index 0 in OGRE = first non-Basis shape key in the catalog.
* This means catalog index i directly maps to OGRE pose index i.
*/
const auto &shapeKeys =
entry->value("shape_keys", nlohmann::json::array());
std::unordered_map<Ogre::String, size_t> nameToIndex;