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>2020-02-23 13:46:59 +0300
committerJulien Duroure <julien.duroure@gmail.com>2020-02-23 13:46:59 +0300
commitb4fc9fbcf4e2d766143d6e88b57e892a12b6fe88 (patch)
tree398f400ccbc505b6e182ff5c1fd433f8c817ed62 /io_scene_gltf2/blender
parentffd8a687247da9695857d5b58ce759eecb016c38 (diff)
glTF importer: code cleanup. Better distinction between edit / pose / bind pose
Diffstat (limited to 'io_scene_gltf2/blender')
-rwxr-xr-xio_scene_gltf2/blender/imp/gltf2_blender_animation_bone.py43
-rwxr-xr-xio_scene_gltf2/blender/imp/gltf2_blender_node.py11
-rwxr-xr-xio_scene_gltf2/blender/imp/gltf2_blender_primitive.py4
-rw-r--r--io_scene_gltf2/blender/imp/gltf2_blender_vnode.py39
4 files changed, 63 insertions, 34 deletions
diff --git a/io_scene_gltf2/blender/imp/gltf2_blender_animation_bone.py b/io_scene_gltf2/blender/imp/gltf2_blender_animation_bone.py
index 96524d5b..4d834611 100755
--- a/io_scene_gltf2/blender/imp/gltf2_blender_animation_bone.py
+++ b/io_scene_gltf2/blender/imp/gltf2_blender_animation_bone.py
@@ -20,8 +20,8 @@ from ...io.imp.gltf2_io_binary import BinaryData
from .gltf2_blender_animation_utils import simulate_stash, make_fcurve
-# The glTF curves store the value of the final transform, but in Blender
-# curves animate a pose bone that is relative to the edit bone
+# In Blender we animate a pose bone. The final TRS of the bone depends on
+# both the edit bone and pose bone
#
# Final = EditBone * PoseBone
# where
@@ -29,7 +29,7 @@ from .gltf2_blender_animation_utils import simulate_stash, make_fcurve
# EditBone = Trans[et] Rot[er] (edit bones have no scale)
# PoseBone = Trans[pt] Rot[pr] Scale[ps]
#
-# Solving for the PoseBone gives the change we need to apply to the curves
+# Given Final we can solve for the PoseBone we need to use with
#
# pt = Rot[er^{-1}] (ft - et)
# pr = er^{-1} fr
@@ -58,18 +58,18 @@ class BlenderBoneAnim():
else:
translation_keyframes = (gltf.loc_gltf_to_blender(vals) for vals in values)
- bind_trans, bind_rot, _ = vnode.trs
- bind_rot_inv = bind_rot.conjugated()
-
- final_translations = [
- bind_rot_inv @ (trans - bind_trans)
+ # Calculate pose bone trans from final bone trans
+ edit_trans, edit_rot = vnode.editbone_trans, vnode.editbone_rot
+ edit_rot_inv = edit_rot.conjugated()
+ pose_translations = [
+ edit_rot_inv @ (trans - edit_trans)
for trans in translation_keyframes
]
BlenderBoneAnim.fill_fcurves(
obj.animation_data.action,
keys,
- final_translations,
+ pose_translations,
group_name,
blender_path,
animation.samplers[channel.sampler].interpolation
@@ -93,24 +93,23 @@ class BlenderBoneAnim():
else:
quat_keyframes = [gltf.quaternion_gltf_to_blender(vals) for vals in values]
- _, bind_rot, _ = vnode.trs
- bind_rot_inv = bind_rot.conjugated()
-
-
- final_rots = [
- bind_rot_inv @ rot
+ # Calculate pose bone rotation from final bone rotation
+ edit_rot = vnode.editbone_rot
+ edit_rot_inv = edit_rot.conjugated()
+ pose_rots = [
+ edit_rot_inv @ rot
for rot in quat_keyframes
]
# Manage antipodal quaternions
- for i in range(1, len(final_rots)):
- if final_rots[i].dot(final_rots[i-1]) < 0:
- final_rots[i] = -final_rots[i]
+ for i in range(1, len(pose_rots)):
+ if pose_rots[i].dot(pose_rots[i-1]) < 0:
+ pose_rots[i] = -pose_rots[i]
BlenderBoneAnim.fill_fcurves(
obj.animation_data.action,
keys,
- final_rots,
+ pose_rots,
group_name,
blender_path,
animation.samplers[channel.sampler].interpolation
@@ -127,17 +126,17 @@ class BlenderBoneAnim():
if animation.samplers[channel.sampler].interpolation == "CUBICSPLINE":
# TODO manage tangent?
- final_scales = [
+ scale_keyframes = [
gltf.scale_gltf_to_blender(values[idx * 3 + 1])
for idx in range(0, len(keys))
]
else:
- final_scales = [gltf.scale_gltf_to_blender(vals) for vals in values]
+ scale_keyframes = [gltf.scale_gltf_to_blender(vals) for vals in values]
BlenderBoneAnim.fill_fcurves(
obj.animation_data.action,
keys,
- final_scales,
+ scale_keyframes,
group_name,
blender_path,
animation.samplers[channel.sampler].interpolation
diff --git a/io_scene_gltf2/blender/imp/gltf2_blender_node.py b/io_scene_gltf2/blender/imp/gltf2_blender_node.py
index bab22599..590a4fa5 100755
--- a/io_scene_gltf2/blender/imp/gltf2_blender_node.py
+++ b/io_scene_gltf2/blender/imp/gltf2_blender_node.py
@@ -134,7 +134,7 @@ class BlenderNode():
editbone.use_connect = False # TODO?
# Give the position of the bone in armature space
- arma_mat = vnode.bone_arma_mat
+ arma_mat = vnode.editbone_arma_mat
editbone.head = arma_mat @ Vector((0, 0, 0))
editbone.tail = arma_mat @ Vector((0, 1, 0))
editbone.align_roll(arma_mat @ Vector((0, 0, 1)) - editbone.head)
@@ -159,8 +159,13 @@ class BlenderNode():
vnode = gltf.vnodes[id]
pose_bone = blender_arma.pose.bones[vnode.blender_bone_name]
- # Put scale on pose bone (edit bones have no scale)
- _, _, s = vnode.trs
+ # BoneTRS = EditBone * PoseBone
+ # Set PoseBone to make BoneTRS = vnode.trs.
+ t, r, s = vnode.trs
+ et, er = vnode.editbone_trans, vnode.editbone_rot
+ pose_bone.location = er.conjugated() @ (t - et)
+ pose_bone.rotation_mode = 'QUATERNION'
+ pose_bone.rotation_quaternion = er.conjugated() @ r
pose_bone.scale = s
if isinstance(id, int):
diff --git a/io_scene_gltf2/blender/imp/gltf2_blender_primitive.py b/io_scene_gltf2/blender/imp/gltf2_blender_primitive.py
index fb515e0f..07030a62 100755
--- a/io_scene_gltf2/blender/imp/gltf2_blender_primitive.py
+++ b/io_scene_gltf2/blender/imp/gltf2_blender_primitive.py
@@ -78,8 +78,8 @@ class BlenderPrimitive():
inv_binds = [gltf.matrix_gltf_to_blender(m) for m in inv_binds]
else:
inv_binds = [Matrix.Identity(4) for i in range(len(pyskin.joints))]
- arma_mats = [gltf.vnodes[joint].bone_arma_mat for joint in pyskin.joints]
- joint_mats = [arma_mat @ inv_bind for arma_mat, inv_bind in zip(arma_mats, inv_binds)]
+ bind_mats = [gltf.vnodes[joint].bind_arma_mat for joint in pyskin.joints]
+ joint_mats = [bind_mat @ inv_bind for bind_mat, inv_bind in zip(bind_mats, inv_binds)]
def skin_vert(pos, pidx):
out = Vector((0, 0, 0))
diff --git a/io_scene_gltf2/blender/imp/gltf2_blender_vnode.py b/io_scene_gltf2/blender/imp/gltf2_blender_vnode.py
index 8ab0da32..bd5edcd1 100644
--- a/io_scene_gltf2/blender/imp/gltf2_blender_vnode.py
+++ b/io_scene_gltf2/blender/imp/gltf2_blender_vnode.py
@@ -25,6 +25,7 @@ def compute_vnodes(gltf):
move_skinned_meshes(gltf)
fixup_multitype_nodes(gltf)
correct_cameras_and_lights(gltf)
+ pick_bind_pose(gltf)
calc_bone_matrices(gltf)
@@ -181,7 +182,7 @@ def move_skinned_meshes(gltf):
* Move a skinned mesh to become a child of the armature that skins it.
Have to ensure the mesh and arma have the same world transform.
* When we do mesh creation, we will also need to put all the verts in
- their rest pose (ie. the pose the edit bones are in)
+ the bind pose in arma space.
"""
ids = list(gltf.vnodes.keys())
for id in ids:
@@ -334,22 +335,46 @@ def correct_cameras_and_lights(gltf):
vnode.light_node_idx = None
+def pick_bind_pose(gltf):
+ """
+ Pick the bind pose for all bones. Skinned meshes will be retargeted onto
+ this bind pose during mesh creation.
+ """
+ for vnode_id in gltf.vnodes:
+ vnode = gltf.vnodes[vnode_id]
+ if vnode.type == VNode.Bone:
+ # For now, use the node TR for bind pose.
+ # TODO: try calculating from inverseBindMatices?
+ vnode.bind_trans = Vector(vnode.trs[0])
+ vnode.bind_rot = Quaternion(vnode.trs[1])
+
+ # Initialize editbones to match bind pose
+ vnode.editbone_trans = Vector(vnode.bind_trans)
+ vnode.editbone_rot = Quaternion(vnode.bind_rot)
+
+
def calc_bone_matrices(gltf):
"""
- Calculate bone_arma_mat, the transformation from bone space to armature
- space for the edit bone, for each bone.
+ Calculate the transformations from bone space to arma space in the bind
+ pose and in the edit bone pose.
"""
def visit(vnode_id): # Depth-first walk
vnode = gltf.vnodes[vnode_id]
if vnode.type == VNode.Bone:
if gltf.vnodes[vnode.parent].type == VNode.Bone:
- parent_arma_mat = gltf.vnodes[vnode.parent].bone_arma_mat
+ parent_bind_mat = gltf.vnodes[vnode.parent].bind_arma_mat
+ parent_editbone_mat = gltf.vnodes[vnode.parent].editbone_arma_mat
else:
- parent_arma_mat = Matrix.Identity(4)
+ parent_bind_mat = Matrix.Identity(4)
+ parent_editbone_mat = Matrix.Identity(4)
+
+ t, r = vnode.bind_trans, vnode.bind_rot
+ local_to_parent = Matrix.Translation(t) @ Quaternion(r).to_matrix().to_4x4()
+ vnode.bind_arma_mat = parent_bind_mat @ local_to_parent
- t, r, _ = vnode.trs
+ t, r = vnode.editbone_trans, vnode.editbone_rot
local_to_parent = Matrix.Translation(t) @ Quaternion(r).to_matrix().to_4x4()
- vnode.bone_arma_mat = parent_arma_mat @ local_to_parent
+ vnode.editbone_arma_mat = parent_editbone_mat @ local_to_parent
for child in vnode.children:
visit(child)