Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulien Duroure <julien.duroure@gmail.com>2022-04-29 09:29:05 +0300
committerJulien Duroure <julien.duroure@gmail.com>2022-04-29 09:29:05 +0300
commit96eb14698456d06bea5a42a6bb35daa172841a6a (patch)
tree752f7627140b38581e4a1560c379acb82a4041d1
parent3f6734bdf2a86f5920fb3ed590c2467ae6bdbeea (diff)
glTF exporter: normalize skin weights also for all influence mode
-rwxr-xr-xio_scene_gltf2/__init__.py2
-rwxr-xr-xio_scene_gltf2/blender/exp/gltf2_blender_gather_primitive_attributes.py105
2 files changed, 64 insertions, 43 deletions
diff --git a/io_scene_gltf2/__init__.py b/io_scene_gltf2/__init__.py
index fe391793..c2cd82b3 100755
--- a/io_scene_gltf2/__init__.py
+++ b/io_scene_gltf2/__init__.py
@@ -4,7 +4,7 @@
bl_info = {
'name': 'glTF 2.0 format',
'author': 'Julien Duroure, Scurest, Norbert Nopper, Urs Hanselmann, Moritz Becher, Benjamin Schmithüsen, Jim Eckerlein, and many external contributors',
- "version": (3, 2, 35),
+ "version": (3, 2, 36),
'blender': (3, 1, 0),
'location': 'File > Import-Export',
'description': 'Import-Export as glTF 2.0',
diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitive_attributes.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitive_attributes.py
index 776b872a..72f0268c 100755
--- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitive_attributes.py
+++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitive_attributes.py
@@ -157,48 +157,69 @@ def __gather_colors(blender_primitive, export_settings):
def __gather_skins(blender_primitive, export_settings):
attributes = {}
- if export_settings[gltf2_blender_export_keys.SKINS]:
- 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_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
- internal_joint = blender_primitive["attributes"][joint_id]
- component_type = gltf2_io_constants.ComponentType.UnsignedShort
- if max(internal_joint) < 256:
- component_type = gltf2_io_constants.ComponentType.UnsignedByte
- joint = array_to_accessor(
- internal_joint,
- component_type,
- data_type=gltf2_io_constants.DataType.Vec4,
- )
- attributes[joint_id] = joint
-
- # 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 = array_to_accessor(
- internal_weight,
- component_type=gltf2_io_constants.ComponentType.Float,
- data_type=gltf2_io_constants.DataType.Vec4,
+
+ if not export_settings[gltf2_blender_export_keys.SKINS]:
+ return attributes
+
+ # Retrieve max set index
+ max_bone_set_index = 0
+ while blender_primitive["attributes"].get('JOINTS_' + str(max_bone_set_index)) and blender_primitive["attributes"].get('WEIGHTS_' + str(max_bone_set_index)):
+ max_bone_set_index += 1
+ max_bone_set_index -= 1
+
+ # If no skinning
+ if max_bone_set_index < 0:
+ return attributes
+
+ if max_bone_set_index > 0 and 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).")
+
+ # Take into account only the first set of 4 weights
+ max_bone_set_index = 0
+
+ # Convert weights to numpy arrays, and setting joints
+ weight_arrs = []
+ for s in range(0, max_bone_set_index+1):
+
+ weight_id = 'WEIGHTS_' + str(s)
+ weight = blender_primitive["attributes"][weight_id]
+ weight = np.array(weight, dtype=np.float32)
+ weight = weight.reshape(len(weight) // 4, 4)
+ weight_arrs.append(weight)
+
+
+ # joints
+ joint_id = 'JOINTS_' + str(s)
+ internal_joint = blender_primitive["attributes"][joint_id]
+ component_type = gltf2_io_constants.ComponentType.UnsignedShort
+ if max(internal_joint) < 256:
+ component_type = gltf2_io_constants.ComponentType.UnsignedByte
+ joint = array_to_accessor(
+ internal_joint,
+ component_type,
+ data_type=gltf2_io_constants.DataType.Vec4,
+ )
+ attributes[joint_id] = joint
+
+ # Sum weights for each vertex
+ for s in range(0, max_bone_set_index+1):
+ sums = weight_arrs[s].sum(axis=1)
+ if s == 0:
+ weight_total = sums
+ else:
+ weight_total += sums
+
+ # Normalize weights so they sum to 1
+ weight_total = weight_total.reshape(-1, 1)
+ for s in range(0, max_bone_set_index+1):
+ weight_arrs[s] /= weight_total
+
+ weight = array_to_accessor(
+ weight_arrs[s],
+ component_type=gltf2_io_constants.ComponentType.Float,
+ data_type=gltf2_io_constants.DataType.Vec4,
)
- attributes[weight_id] = weight
+ attributes[weight_id] = weight
- bone_set_index += 1
- joint_id = 'JOINTS_' + str(bone_set_index)
- weight_id = 'WEIGHTS_' + str(bone_set_index)
return attributes