Skip to content
Snippets Groups Projects
Commit 58db76bc authored by Julien Duroure's avatar Julien Duroure
Browse files

glTF exporter: manage delta transform animation

parent b9c0e287
No related branches found
No related tags found
No related merge requests found
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
bl_info = { bl_info = {
'name': 'glTF 2.0 format', 'name': 'glTF 2.0 format',
'author': 'Julien Duroure, Scurest, Norbert Nopper, Urs Hanselmann, Moritz Becher, Benjamin Schmithüsen, Jim Eckerlein, and many external contributors', 'author': 'Julien Duroure, Scurest, Norbert Nopper, Urs Hanselmann, Moritz Becher, Benjamin Schmithüsen, Jim Eckerlein, and many external contributors',
"version": (3, 4, 15), "version": (3, 4, 16),
'blender': (3, 3, 0), 'blender': (3, 3, 0),
'location': 'File > Import-Export', 'location': 'File > Import-Export',
'description': 'Import-Export as glTF 2.0', 'description': 'Import-Export as glTF 2.0',
......
...@@ -15,20 +15,33 @@ def get_target_object_path(data_path: str) -> str: ...@@ -15,20 +15,33 @@ def get_target_object_path(data_path: str) -> str:
return "" return ""
return path_split[0] return path_split[0]
def get_rotation_modes(target_property: str) -> str: def get_rotation_modes(target_property: str):
"""Retrieve rotation modes based on target_property""" """Retrieve rotation modes based on target_property"""
if target_property == "rotation_euler": if target_property == "rotation_euler":
return True, False, ["XYZ", "XZY", "YXZ", "YZX", "ZXY", "ZYX"] return True, ["XYZ", "XZY", "YXZ", "YZX", "ZXY", "ZYX"]
elif target_property == "delta_rotation_euler": elif target_property == "delta_rotation_euler":
return True, True, ["XYZ", "XZY", "YXZ", "YZX", "ZXY", "ZYX"] return True, ["XYZ", "XZY", "YXZ", "YZX", "ZXY", "ZYX"]
elif target_property == "rotation_quaternion": elif target_property == "rotation_quaternion":
return True, False, ["QUATERNION"] return True, ["QUATERNION"]
elif target_property == "delta_rotation_quaternion": elif target_property == "delta_rotation_quaternion":
return True, True, ["QUATERNION"] return True, ["QUATERNION"]
elif target_property in ["rotation_axis_angle"]: elif target_property in ["rotation_axis_angle"]:
return True, False, ["AXIS_ANGLE"] return True, ["AXIS_ANGLE"]
else: else:
return False, False, [] return False, []
def is_location(target_property):
return "location" in target_property
def is_rotation(target_property):
return "rotation" in target_property
def is_scale(target_property):
return "scale" in target_property
def get_delta_modes(target_property: str) -> str:
"""Retrieve location based on target_property"""
return target_property.startswith("delta_")
def is_bone_anim_channel(data_path: str) -> bool: def is_bone_anim_channel(data_path: str) -> bool:
return data_path[:10] == "pose.bones" return data_path[:10] == "pose.bones"
\ No newline at end of file
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
import bpy import bpy
import typing import typing
from ..com.gltf2_blender_data_path import get_target_object_path, get_target_property_name, get_rotation_modes from ..com.gltf2_blender_data_path import get_target_object_path, get_target_property_name, get_rotation_modes, get_delta_modes, is_location, is_rotation, is_scale
from io_scene_gltf2.io.com import gltf2_io from io_scene_gltf2.io.com import gltf2_io
from io_scene_gltf2.io.com import gltf2_io_debug from io_scene_gltf2.io.com import gltf2_io_debug
from io_scene_gltf2.blender.exp.gltf2_blender_gather_cache import cached from io_scene_gltf2.blender.exp.gltf2_blender_gather_cache import cached
...@@ -364,6 +364,8 @@ def __get_channel_groups(blender_action: bpy.types.Action, blender_object: bpy.t ...@@ -364,6 +364,8 @@ def __get_channel_groups(blender_action: bpy.types.Action, blender_object: bpy.t
targets = {} targets = {}
multiple_rotation_mode_detected = False multiple_rotation_mode_detected = False
delta_rotation_detection = [False, False] # Normal / Delta delta_rotation_detection = [False, False] # Normal / Delta
delta_location_detection = [False, False] # Normal / Delta
delta_scale_detection = [False, False] # Normal / Delta
for fcurve in blender_action.fcurves: for fcurve in blender_action.fcurves:
# In some invalid files, channel hasn't any keyframes ... this channel need to be ignored # In some invalid files, channel hasn't any keyframes ... this channel need to be ignored
if len(fcurve.keyframe_points) == 0: if len(fcurve.keyframe_points) == 0:
...@@ -405,24 +407,46 @@ def __get_channel_groups(blender_action: bpy.types.Action, blender_object: bpy.t ...@@ -405,24 +407,46 @@ def __get_channel_groups(blender_action: bpy.types.Action, blender_object: bpy.t
# Detect that object or bone are not multiple keyed for euler and quaternion # Detect that object or bone are not multiple keyed for euler and quaternion
# Keep only the current rotation mode used by object # Keep only the current rotation mode used by object
rotation, delta, rotation_modes = get_rotation_modes(target_property) rotation, rotation_modes = get_rotation_modes(target_property)
delta = get_delta_modes(target_property)
# Delta rotation management # Delta rotation management
if delta is False: if is_rotation(target_property) :
if delta_rotation_detection[1] is True: # normal rotation coming, but delta is already present if delta is False:
multiple_rotation_mode_detected = True if delta_rotation_detection[1] is True: # normal rotation coming, but delta is already present
continue continue
delta_rotation_detection[0] = True delta_rotation_detection[0] = True
else: else:
if delta_rotation_detection[0] is True: # delta rotation coming, but normal is already present if delta_rotation_detection[0] is True: # delta rotation coming, but normal is already present
continue
delta_rotation_detection[1] = True
if rotation and target.rotation_mode not in rotation_modes:
multiple_rotation_mode_detected = True multiple_rotation_mode_detected = True
continue continue
delta_rotation_detection[1] = True
# Delta location management
if is_location(target_property):
if delta is False:
if delta_location_detection[1] is True: # normal location coming, but delta is already present
continue
delta_location_detection[0] = True
else:
if delta_location_detection[0] is True: # delta location coming, but normal is already present
continue
delta_location_detection[1] = True
if rotation and target.rotation_mode not in rotation_modes: # Delta scale management
multiple_rotation_mode_detected = True if is_scale(target_property):
continue if delta is False:
if delta_scale_detection[1] is True: # normal scale coming, but delta is already present
continue
delta_scale_detection[0] = True
else:
if delta_scale_detection[0] is True: # delta scale coming, but normal is already present
continue
delta_scale_detection[1] = True
# group channels by target object and affected property of the target # group channels by target object and affected property of the target
target_properties = targets.get(target, {}) target_properties = targets.get(target, {})
......
...@@ -45,6 +45,7 @@ class Keyframe: ...@@ -45,6 +45,7 @@ class Keyframe:
length = { length = {
"delta_location": 3, "delta_location": 3,
"delta_rotation_euler": 3, "delta_rotation_euler": 3,
"delta_scale": 3,
"location": 3, "location": 3,
"rotation_axis_angle": 4, "rotation_axis_angle": 4,
"rotation_euler": 3, "rotation_euler": 3,
...@@ -367,7 +368,10 @@ def gather_keyframes(blender_obj_uuid: str, ...@@ -367,7 +368,10 @@ def gather_keyframes(blender_obj_uuid: str,
"rotation_axis_angle": [rot.to_axis_angle()[1], rot.to_axis_angle()[0][0], rot.to_axis_angle()[0][1], rot.to_axis_angle()[0][2]], "rotation_axis_angle": [rot.to_axis_angle()[1], rot.to_axis_angle()[0][0], rot.to_axis_angle()[0][1], rot.to_axis_angle()[0][2]],
"rotation_euler": rot.to_euler(), "rotation_euler": rot.to_euler(),
"rotation_quaternion": rot, "rotation_quaternion": rot,
"scale": sca "scale": sca,
"delta_location": trans,
"delta_rotation_euler": rot.to_euler(),
"delta_scale": sca
}[target] }[target]
else: else:
key.value = get_sk_driver_values(driver_obj_uuid, frame, channels, export_settings) key.value = get_sk_driver_values(driver_obj_uuid, frame, channels, export_settings)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment