1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
|
# SPDX-License-Identifier: Apache-2.0
# Copyright 2018-2021 The glTF-Blender-IO authors.
import mathutils
from . import gltf2_blender_export_keys
from io_scene_gltf2.blender.exp.gltf2_blender_gather_cache import cached
from io_scene_gltf2.io.com import gltf2_io
from io_scene_gltf2.io.exp import gltf2_io_binary_data
from io_scene_gltf2.io.com import gltf2_io_constants
from io_scene_gltf2.blender.exp import gltf2_blender_gather_accessors
from io_scene_gltf2.blender.exp import gltf2_blender_gather_joints
from io_scene_gltf2.io.exp.gltf2_io_user_extensions import export_user_extensions
from io_scene_gltf2.blender.exp import gltf2_blender_gather_tree
from io_scene_gltf2.blender.exp.gltf2_blender_gather_tree import VExportNode
@cached
def gather_skin(armature_uuid, export_settings):
"""
Gather armatures, bones etc into a glTF2 skin object.
:param blender_object: the object which may contain a skin
:param export_settings:
:return: a glTF2 skin object
"""
blender_armature_object = export_settings['vtree'].nodes[armature_uuid].blender_object
if not __filter_skin(blender_armature_object, export_settings):
return None
skin = gltf2_io.Skin(
extensions=__gather_extensions(blender_armature_object, export_settings),
extras=__gather_extras(blender_armature_object, export_settings),
inverse_bind_matrices=__gather_inverse_bind_matrices(armature_uuid, export_settings),
joints=__gather_joints(armature_uuid, export_settings),
name=__gather_name(blender_armature_object, export_settings),
skeleton=__gather_skeleton(blender_armature_object, export_settings)
)
# If armature is not exported, joints will be empty.
# Do not construct skin in that case
if len(skin.joints) == 0:
return None
export_user_extensions('gather_skin_hook', export_settings, skin, blender_armature_object)
return skin
def __filter_skin(blender_armature_object, export_settings):
if not export_settings[gltf2_blender_export_keys.SKINS]:
return False
if blender_armature_object.type != 'ARMATURE' or len(blender_armature_object.pose.bones) == 0:
return False
return True
def __gather_extensions(blender_armature_object, export_settings):
return None
def __gather_extras(blender_armature_object, export_settings):
return None
def __gather_inverse_bind_matrices(armature_uuid, export_settings):
blender_armature_object = export_settings['vtree'].nodes[armature_uuid].blender_object
axis_basis_change = mathutils.Matrix.Identity(4)
if export_settings[gltf2_blender_export_keys.YUP]:
axis_basis_change = mathutils.Matrix(
((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)))
# store matrix_world of armature in case we need to add a neutral bone
export_settings['vtree'].nodes[armature_uuid].matrix_world_armature = blender_armature_object.matrix_world.copy()
bones_uuid = export_settings['vtree'].get_all_bones(armature_uuid)
def __collect_matrices(bone):
inverse_bind_matrix = (
axis_basis_change @
(
blender_armature_object.matrix_world @
bone.bone.matrix_local
)
).inverted_safe()
matrices.append(inverse_bind_matrix)
matrices = []
for b in bones_uuid:
__collect_matrices(blender_armature_object.pose.bones[export_settings['vtree'].nodes[b].blender_bone.name])
# flatten the matrices
inverse_matrices = []
for matrix in matrices:
for column in range(0, 4):
for row in range(0, 4):
inverse_matrices.append(matrix[row][column])
binary_data = gltf2_io_binary_data.BinaryData.from_list(inverse_matrices, gltf2_io_constants.ComponentType.Float)
return gltf2_blender_gather_accessors.gather_accessor(
binary_data,
gltf2_io_constants.ComponentType.Float,
len(inverse_matrices) // gltf2_io_constants.DataType.num_elements(gltf2_io_constants.DataType.Mat4),
None,
None,
gltf2_io_constants.DataType.Mat4,
export_settings
)
def __gather_joints(armature_uuid, export_settings):
blender_armature_object = export_settings['vtree'].nodes[armature_uuid].blender_object
all_armature_children = export_settings['vtree'].nodes[armature_uuid].children
root_bones_uuid = [c for c in all_armature_children if export_settings['vtree'].nodes[c].blender_type == VExportNode.BONE]
# Create bone nodes
for root_bone_uuid in root_bones_uuid:
gltf2_blender_gather_joints.gather_joint_vnode(root_bone_uuid, export_settings)
bones_uuid = export_settings['vtree'].get_all_bones(armature_uuid)
joints = [export_settings['vtree'].nodes[b].node for b in bones_uuid]
return joints
def __gather_name(blender_armature_object, export_settings):
return blender_armature_object.name
def __gather_skeleton(blender_armature_object, export_settings):
# In the future support the result of https://github.com/KhronosGroup/glTF/pull/1195
return None
|