glTF exporter: Auto limit and normalize skin weights

This commit is contained in:
Julien Duroure 2019-02-14 21:21:11 +01:00
parent 5c254fc8c3
commit eb33af1379
2 changed files with 24 additions and 10 deletions

View File

@ -18,6 +18,7 @@
from mathutils import Vector, Quaternion
from mathutils.geometry import tessellate_polygon
from operator import attrgetter
from . import gltf2_blender_export_keys
from ...io.com.gltf2_io_debug import print_console
@ -639,7 +640,11 @@ def extract_primitives(glTF, blender_mesh, blender_vertex_groups, modifiers, exp
if blender_vertex_groups is not None and vertex.groups is not None and len(vertex.groups) > 0 and export_settings[gltf2_blender_export_keys.SKINS]:
joint = []
weight = []
for group_element in vertex.groups:
vertex_groups = vertex.groups
if not export_settings['gltf_all_vertex_influences']:
# sort groups by weight descending
vertex_groups = sorted(vertex.groups, key=attrgetter('weight'), reverse=True)
for group_element in vertex_groups:
if len(joint) == 4:
bone_count += 1

View File

@ -161,14 +161,14 @@ def __gather_colors(blender_primitive, export_settings):
def __gather_skins(blender_primitive, export_settings):
attributes = {}
if export_settings[gltf2_blender_export_keys.SKINS]:
bone_index = 0
joint_id = 'JOINTS_' + str(bone_index)
weight_id = 'WEIGHTS_' + str(bone_index)
bone_set_index = 0
joint_id = 'JOINTS_' + str(bone_set_index)
weight_id = 'WEIGHTS_' + str(bone_set_index)
while blender_primitive["attributes"].get(joint_id) and blender_primitive["attributes"].get(weight_id):
if bone_index >= 4:
gltf2_io_debug.print_console("WARNING", "There are more than 4 joint vertex influences."
"Consider to apply blenders Limit Total function.")
if bone_set_index >= 1:
if not export_settings['gltf_all_vertex_influences']:
gltf2_io_debug.print_console("WARNING", "There are more than 4 joint vertex influences."
"The 4 with highest weight will be used (and normalized).")
break
# joints
@ -192,6 +192,15 @@ def __gather_skins(blender_primitive, export_settings):
# weights
internal_weight = blender_primitive["attributes"][weight_id]
# normalize first 4 weights, when not exporting all influences
if not export_settings['gltf_all_vertex_influences']:
for idx in range(0, len(internal_weight), 4):
weight_slice = internal_weight[idx:idx + 4]
total = sum(weight_slice)
if total > 0:
factor = 1.0 / total
internal_weight[idx:idx + 4] = [w * factor for w in weight_slice]
weight = gltf2_io.Accessor(
buffer_view=gltf2_io_binary_data.BinaryData.from_list(
internal_weight, gltf2_io_constants.ComponentType.Float),
@ -210,8 +219,8 @@ def __gather_skins(blender_primitive, export_settings):
)
attributes[weight_id] = weight
bone_index += 1
joint_id = 'JOINTS_' + str(bone_index)
weight_id = 'WEIGHTS_' + str(bone_index)
bone_set_index += 1
joint_id = 'JOINTS_' + str(bone_set_index)
weight_id = 'WEIGHTS_' + str(bone_set_index)
return attributes