[Bf-extensions-cvs] [e15b620] fbx_io_development: Merge branch 'master' into fbx_io_development
Bastien Montagne
noreply at git.blender.org
Sun Jul 6 19:16:00 CEST 2014
Commit: e15b62020ac5675cd830a1854c8e108412132f32
Author: Bastien Montagne
Date: Sat Jul 5 18:39:02 2014 +0200
https://developer.blender.org/rBAe15b62020ac5675cd830a1854c8e108412132f32
Merge branch 'master' into fbx_io_development
===================================================================
===================================================================
diff --cc io_scene_fbx/fbx_utils.py
index 4b477e8,5ee70fe..70606b8
--- a/io_scene_fbx/fbx_utils.py
+++ b/io_scene_fbx/fbx_utils.py
@@@ -603,139 -578,13 +603,143 @@@ def fbx_templates_generate(root, fbx_te
elem = elem_data_single_string(template, b"PropertyTemplate", prop_type_name)
props = elem_properties(elem)
for name, (value, ptype, animatable) in properties.items():
- elem_props_set(props, ptype, name, value, animatable=animatable)
+ try:
+ elem_props_set(props, ptype, name, value, animatable=animatable)
+ except Exception as e:
+ print("Failed to write template prop (%r)" % e)
+ print(props, ptype, name, value, animatable)
+##### FBX animation helpers. #####
+
+
+class AnimationCurveNodeWrapper:
+ """
+ This class provides a same common interface for all (FBX-wise) AnimationCurveNode and AnimationCurve elements,
+ and easy API to handle those.
+ """
+ __slots__ = ('elem_keys', '_keys', 'default_values', 'fbx_group', 'fbx_gname', 'fbx_props')
+
+ kinds = {
+ 'LCL_TRANSLATION': ("Lcl Translation", "T", ("X", "Y", "Z")),
+ 'LCL_ROTATION': ("Lcl Rotation", "R", ("X", "Y", "Z")),
+ 'LCL_SCALING': ("Lcl Scaling", "S", ("X", "Y", "Z")),
+ 'SHAPE_KEY': ("DeformPercent", "DeformPercent", ("DeformPercent",)),
+ }
+
+ def __init__(self, elem_key, kind, default_values=...):
+ """
+ bdata might be an Object, DupliObject, Bone or PoseBone.
+ If Bone or PoseBone, armature Object must be provided.
+ """
+ self.elem_keys = [elem_key]
+ assert(kind in self.kinds)
+ self.fbx_group = [self.kinds[kind][0]]
+ self.fbx_gname = [self.kinds[kind][1]]
+ self.fbx_props = [self.kinds[kind][2]]
+ self._keys = [] # (frame, values, write_flags)
+ if default_values is not ...:
+ assert(len(default_values) == len(self.fbx_props[0]))
+ self.default_values = default_values
+ else:
+ self.default_values = (0.0) * len(self.fbx_props[0])
+
+ def __bool__(self):
+ # We are 'True' if we do have some validated keyframes...
+ return self._keys and True in ((True in k[2]) for k in self._keys)
+
+ def add_group(self, elem_key, fbx_group, fbx_gname, fbx_props):
+ """
+ Add another whole group stuff (curvenode, animated item/prop + curvnode/curve identifiers).
+ E.g. Shapes animations is written twice, houra!
+ """
+ assert(len(fbx_props) == len(self.fbx_props[0]))
+ self.elem_keys.append(elem_key)
+ self.fbx_group.append(fbx_group)
+ self.fbx_gname.append(fbx_gname)
+ self.fbx_props.append(fbx_props)
+
+ def add_keyframe(self, frame, values):
+ """
+ Add a new keyframe to all curves of the group.
+ """
+ assert(len(values) == len(self.fbx_props[0]))
+ self._keys.append((frame, values, [True] * len(values))) # write everything by default.
+
+ def simplfy(self, fac, step):
+ """
+ Simplifies sampled curves by only enabling samples when:
+ * their values differ significantly from the previous sample ones, or
+ * their values differ significantly from the previous validated sample ones, or
+ * the previous validated samples are far enough from current ones in time.
+ """
+ if not self._keys:
+ return
+
+ # So that, with default factor and step values (1), we get:
+ max_frame_diff = step * fac * 10 # max step of 10 frames.
+ value_diff_fac = fac / 1000 # min value evolution: 0.1% of whole range.
+ min_significant_diff = 1.0e-6
+ keys = self._keys
+
+ extremums = tuple((min(values), max(values)) for values in zip(*(k[1] for k in keys)))
+ min_diffs = tuple(max((mx - mn) * value_diff_fac, min_significant_diff) for mn, mx in extremums)
+
+ p_currframe, p_key, p_key_write = keys[0]
+ p_keyed = [(p_currframe - max_frame_diff, val) for val in p_key]
+ are_keyed = [False] * len(p_key)
+ for currframe, key, key_write in keys:
+ for idx, (val, p_val) in enumerate(zip(key, p_key)):
+ key_write[idx] = False
+ p_keyedframe, p_keyedval = p_keyed[idx]
+ if val == p_val:
+ # Never write keyframe when value is exactly the same as prev one!
+ continue
+ if abs(val - p_val) >= min_diffs[idx]:
+ # If enough difference from previous sampled value, key this value *and* the previous one!
+ key_write[idx] = True
+ p_key_write[idx] = True
+ p_keyed[idx] = (currframe, val)
+ are_keyed[idx] = True
+ else:
+ frame_diff = currframe - p_keyedframe
+ val_diff = abs(val - p_keyedval)
+ if ((val_diff >= min_diffs[idx]) or
+ ((val_diff >= min_significant_diff) and (frame_diff >= max_frame_diff))):
+ # Else, if enough difference from previous keyed value
+ # (or any significant difference and max gap between keys is reached),
+ # key this value only!
+ key_write[idx] = True
+ p_keyed[idx] = (currframe, val)
+ are_keyed[idx] = True
+ p_currframe, p_key, p_key_write = currframe, key, key_write
+ # If we did key something, ensure first and last sampled values are keyed as well.
+ for idx, is_keyed in enumerate(are_keyed):
+ if is_keyed:
+ keys[0][2][idx] = keys[-1][2][idx] = True
+
+ def get_final_data(self, scene, ref_id, force_keep=False):
+ """
+ Yield final anim data for this 'curvenode' (for all curvenodes defined).
+ force_keep is to force to keep a curve even if it only has one valid keyframe.
+ """
+ curves = [[] for k in self._keys[0][1]]
+ for currframe, key, key_write in self._keys:
+ for curve, val, wrt in zip(curves, key, key_write):
+ if wrt:
+ curve.append((currframe, val))
+
+ for elem_key, fbx_group, fbx_gname, fbx_props in zip(self.elem_keys, self.fbx_group, self.fbx_gname, self.fbx_props):
+ group_key = get_blender_anim_curve_node_key(scene, ref_id, elem_key, fbx_group)
+ group = OrderedDict()
+ for c, def_val, fbx_item in zip(curves, self.default_values, fbx_props):
+ fbx_item = FBX_ANIM_PROPSGROUP_NAME + "|" + fbx_item
+ curve_key = get_blender_anim_curve_key(scene, ref_id, elem_key, fbx_group, fbx_item)
+ # (curve key, default value, keyframes, write flag).
+ group[fbx_item] = (curve_key, def_val, c, True if (len(c) > 1 or (len(c) > 0 and force_keep)) else False)
+ yield elem_key, group_key, group, fbx_group, fbx_gname
+
+
##### FBX objects generators. #####
# FBX Model-like data (i.e. Blender objects, dupliobjects and bones) are wrapped in ObjectWrapper.
More information about the Bf-extensions-cvs
mailing list