1 # SPDX-FileCopyrightText: 2018-2021 The glTF-Blender-IO authors
3 # SPDX-License-Identifier: Apache-2.0
6 from ...io
.com
import gltf2_io
, gltf2_io_constants
7 from ...io
.exp
import gltf2_io_binary_data
8 from ...io
.exp
.gltf2_io_user_extensions
import export_user_extensions
9 from . import gltf2_blender_gather_accessors
10 from . import gltf2_blender_gather_joints
11 from .gltf2_blender_gather_tree
import VExportNode
12 from .gltf2_blender_gather_cache
import cached
15 def gather_skin(armature_uuid
, export_settings
):
17 Gather armatures, bones etc into a glTF2 skin object.
19 :param blender_object: the object which may contain a skin
20 :param export_settings:
21 :return: a glTF2 skin object
24 if armature_uuid
not in export_settings
['vtree'].nodes
:
25 # User filtered objects to export, and keep the skined mesh, without keeping the armature
28 blender_armature_object
= export_settings
['vtree'].nodes
[armature_uuid
].blender_object
30 if not __filter_skin(blender_armature_object
, export_settings
):
34 extensions
=__gather_extensions(blender_armature_object
, export_settings
),
35 extras
=__gather_extras(blender_armature_object
, export_settings
),
36 inverse_bind_matrices
=__gather_inverse_bind_matrices(armature_uuid
, export_settings
),
37 joints
=__gather_joints(armature_uuid
, export_settings
),
38 name
=__gather_name(blender_armature_object
, export_settings
),
39 skeleton
=__gather_skeleton(blender_armature_object
, export_settings
)
42 # If armature is not exported, joints will be empty.
43 # Do not construct skin in that case
44 if len(skin
.joints
) == 0:
47 export_user_extensions('gather_skin_hook', export_settings
, skin
, blender_armature_object
)
52 def __filter_skin(blender_armature_object
, export_settings
):
53 if not export_settings
['gltf_skins']:
55 if blender_armature_object
.type != 'ARMATURE' or len(blender_armature_object
.pose
.bones
) == 0:
61 def __gather_extensions(blender_armature_object
, export_settings
):
65 def __gather_extras(blender_armature_object
, export_settings
):
68 def __gather_inverse_bind_matrices(armature_uuid
, export_settings
):
70 blender_armature_object
= export_settings
['vtree'].nodes
[armature_uuid
].blender_object
72 axis_basis_change
= mathutils
.Matrix
.Identity(4)
73 if export_settings
['gltf_yup']:
74 axis_basis_change
= mathutils
.Matrix(
75 ((1.0, 0.0, 0.0, 0.0), (0.0, 0.0, 1.0, 0.0), (0.0, -1.0, 0.0, 0.0), (0.0, 0.0, 0.0, 1.0)))
77 # store matrix_world of armature in case we need to add a neutral bone
78 export_settings
['vtree'].nodes
[armature_uuid
].matrix_world_armature
= blender_armature_object
.matrix_world
.copy()
80 bones_uuid
= export_settings
['vtree'].get_all_bones(armature_uuid
)
81 def __collect_matrices(bone
):
82 inverse_bind_matrix
= (
85 blender_armature_object
.matrix_world
@
86 bone
.bone
.matrix_local
89 matrices
.append(inverse_bind_matrix
)
93 if export_settings
['vtree'].nodes
[b
].leaf_reference
is None:
94 __collect_matrices(blender_armature_object
.pose
.bones
[export_settings
['vtree'].nodes
[b
].blender_bone
.name
])
96 inverse_bind_matrix
= (
99 blender_armature_object
.matrix_world
@
100 export_settings
['vtree'].nodes
[export_settings
['vtree'].nodes
[b
].leaf_reference
].matrix_world_tail
103 matrices
.append(inverse_bind_matrix
) # Leaf bone
105 # flatten the matrices
106 inverse_matrices
= []
107 for matrix
in matrices
:
108 for column
in range(0, 4):
109 for row
in range(0, 4):
110 inverse_matrices
.append(matrix
[row
][column
])
112 binary_data
= gltf2_io_binary_data
.BinaryData
.from_list(inverse_matrices
, gltf2_io_constants
.ComponentType
.Float
)
113 return gltf2_blender_gather_accessors
.gather_accessor(
115 gltf2_io_constants
.ComponentType
.Float
,
116 len(inverse_matrices
) // gltf2_io_constants
.DataType
.num_elements(gltf2_io_constants
.DataType
.Mat4
),
119 gltf2_io_constants
.DataType
.Mat4
,
124 def __gather_joints(armature_uuid
, export_settings
):
126 all_armature_children
= export_settings
['vtree'].nodes
[armature_uuid
].children
127 root_bones_uuid
= [c
for c
in all_armature_children
if export_settings
['vtree'].nodes
[c
].blender_type
== VExportNode
.BONE
]
130 for root_bone_uuid
in root_bones_uuid
:
131 gltf2_blender_gather_joints
.gather_joint_vnode(root_bone_uuid
, export_settings
)
133 bones_uuid
= export_settings
['vtree'].get_all_bones(armature_uuid
)
134 joints
= [export_settings
['vtree'].nodes
[b
].node
for b
in bones_uuid
]
138 def __gather_name(blender_armature_object
, export_settings
):
139 return blender_armature_object
.name
142 def __gather_skeleton(blender_armature_object
, export_settings
):
143 # In the future support the result of https://github.com/KhronosGroup/glTF/pull/1195