private void InterpolateKeys(AssimpSharp.QuatKey[] valOut, KeyTimeList keys, KeyFrameListList inputs, bool geom, ref double maxTime, ref double minTime, Model.RotOrder order) { Debug.Assert(keys.Count > 0); Debug.Assert(valOut != null); var temp = new AssimpSharp.VectorKey[keys.Count]; InterpolateKeys(temp, keys, inputs, geom, ref maxTime, ref minTime); Matrix m; Quaternion lastq = Quaternion.Identity; for (int i = 0; i < keys.Count; i++) { valOut[i].Time = temp[i].Time; GetRotationMatrix(order, temp[i].Value, out m); var quat = Quaternion.RotationMatrix(m); if (Quaternion.Dot(quat, lastq) < 0) { quat = -quat; } lastq = quat; valOut[i].Value = quat; } }
/// <summary> /// generate node anim, extracting only Rotation, Scaling and Translation from the given chain /// </summary> private AssimpSharp.NodeAnim GenerateSimpleNodeAnim(string name, Model target, List<AnimationCurveNode>[] chain, LayerMap layerMap, long start, long stop, ref double maxTime, ref double minTime, bool reverseOrder = false) { var na = new AssimpSharp.NodeAnim(); na.NodeName = name; var props = target.Props; // need to convert from TRS order to SRT? if (reverseOrder) { var defScale = Vector3.Zero; var defTranslate = Vector3.Zero; var defRot = Quaternion.Identity; var scaling = new KeyFrameListList(); var translation = new KeyFrameListList(); var rotation = new KeyFrameListList(); if (chain[(int)TransformationComp.Scaling] != null) { scaling = GetKeyframeList(chain[(int)TransformationComp.Scaling], start, stop); } else { defScale = PropertyHelper.PropertyGet(props, "Lcl Scaling", new Vector3(1, 1, 1)); } if (chain[(int)TransformationComp.Translation] != null) { translation = GetKeyframeList(chain[(int)TransformationComp.Translation], start, stop); } else { defTranslate = PropertyHelper.PropertyGet(props, "Lcl Translation", new Vector3(0, 0, 0)); } if (chain[(int)TransformationComp.Rotation] != null) { rotation = GetKeyframeList(chain[(int)TransformationComp.Rotation], start, stop); } else { defRot = EulerToQuaternion(PropertyHelper.PropertyGet(props, "Lcl Rotation", new Vector3(0, 0, 0)), target.RotationOrder.Value); } var joined = new KeyFrameListList(); joined.AddRange(scaling); joined.AddRange(translation); joined.AddRange(rotation); var times = GetKeyTimeList(joined); var outQuat = new AssimpSharp.QuatKey[times.Count]; var outScale = new AssimpSharp.VectorKey[times.Count]; var outTranslation = new AssimpSharp.VectorKey[times.Count]; if (times.Count > 0) { ConvertTransformOrder_TRStoSRT(outQuat, outScale, outTranslation, scaling, translation, rotation, times, ref maxTime, ref minTime, target.RotationOrder.Value, defScale, defTranslate, defRot); } // XXX remove duplicates / redundant keys which this operation did // likely produce if not all three channels were equally dense. na.ScalingKeys = outScale; na.RotationKeys = outQuat; na.PositionKeys = outTranslation; } else { // if a particular transformation is not given, grab it from // the corresponding node to meet the semantics of aiNodeAnim, // which requires all of rotation, scaling and translation // to be set. if (chain[(int)TransformationComp.Scaling] != null) { ConvertScaleKeys(na, chain[(int)TransformationComp.Scaling], layerMap, start, stop, ref maxTime, ref minTime); } else { na.ScalingKeys = new AssimpSharp.VectorKey[1]; na.ScalingKeys[0].Time = 0; na.ScalingKeys[0].Value = PropertyHelper.PropertyGet(props, "Lcl Scaling", new Vector3(1, 1, 1)); } if (chain[(int)TransformationComp.Rotation] != null) { ConvertRotationKeys(na, chain[(int)TransformationComp.Rotation], layerMap, start, stop, ref maxTime, ref minTime, target.RotationOrder.Value); } else { na.RotationKeys = new AssimpSharp.QuatKey[1]; na.RotationKeys[0].Time = 0; na.RotationKeys[0].Value = EulerToQuaternion(PropertyHelper.PropertyGet(props, "Lcl Rotation", new Vector3(0, 0, 0)), target.RotationOrder.Value); } if (chain[(int)TransformationComp.Translation] != null) { ConvertTranslationKeys(na, chain[(int)TransformationComp.Translation], layerMap, start, stop, ref maxTime, ref minTime); } else { na.PositionKeys = new AssimpSharp.VectorKey[1]; na.PositionKeys[0].Time = 0; na.PositionKeys[0].Value = PropertyHelper.PropertyGet(props, "Lcl Translation", new Vector3(0, 0, 0)); } } return na; }