static void AddAnimData(ExportSettings settings, AnimBone animBone, IOAnimationTrack track, ControlType ctype, TrackType ttype) { AnimData d = new AnimData(); d.controlType = ctype; d.type = ttype; d.preInfinity = CurveWrapModes[track.PreWrap]; d.postInfinity = CurveWrapModes[track.PostWrap]; //Check if any tangents include weights. d.weighted = track.KeyFrames.Any(x => x is IOKeyFrameHermite && ((IOKeyFrameHermite)x).IsWeighted); bool isAngle = ctype == ControlType.rotate; if (isAngle) { d.output = OutputType.angular; } float value = track.KeyFrames.Count > 0 ? (float)track.KeyFrames[0].Value : 0; bool IsConstant = true; foreach (var key in track.KeyFrames) { if ((float)key.Value != value) { IsConstant = false; break; } } foreach (var key in track.KeyFrames) { AnimKey animKey = new AnimKey() { input = key.Frame + 1, output = isAngle ? GetAngle(settings, (float)key.Value) : (float)key.Value, }; if (key is IOKeyFrameHermite) { animKey.intan = "fixed"; animKey.outtan = "fixed"; animKey.t1 = ((IOKeyFrameHermite)key).TangentSlopeInput; animKey.t2 = ((IOKeyFrameHermite)key).TangentSlopeOutput; animKey.w1 = ((IOKeyFrameHermite)key).TangentWeightInput; animKey.w2 = ((IOKeyFrameHermite)key).TangentWeightOutput; } d.keys.Add(animKey); if (IsConstant) { break; } } if (d.keys.Count > 0) { animBone.atts.Add(d); } }
private IOAnimationTrack GetTrack(AnimData data) { IOAnimationTrack track = new IOAnimationTrack(); switch (data.type) { case TrackType.translateX: track.ChannelType = IOAnimationTrackType.PositionX; break; case TrackType.translateY: track.ChannelType = IOAnimationTrackType.PositionY; break; case TrackType.translateZ: track.ChannelType = IOAnimationTrackType.PositionZ; break; case TrackType.rotateX: track.ChannelType = IOAnimationTrackType.RotationEulerX; break; case TrackType.rotateY: track.ChannelType = IOAnimationTrackType.RotationEulerY; break; case TrackType.rotateZ: track.ChannelType = IOAnimationTrackType.RotationEulerZ; break; case TrackType.scaleX: track.ChannelType = IOAnimationTrackType.ScaleX; break; case TrackType.scaleY: track.ChannelType = IOAnimationTrackType.ScaleY; break; case TrackType.scaleZ: track.ChannelType = IOAnimationTrackType.ScaleZ; break; case TrackType.visibility: track.ChannelType = IOAnimationTrackType.NodeVisibility; break; } track.PreWrap = CurveWrapModes.FirstOrDefault(x => x.Value == data.preInfinity).Key; track.PostWrap = CurveWrapModes.FirstOrDefault(x => x.Value == data.postInfinity).Key; foreach (var key in data.keys) { if (key.intan == "fixed" || key.outtan == "fixed") { track.KeyFrames.Add(new IOKeyFrameHermite() { Frame = key.input - header.startTime, Value = GetOutputValue(this, data, key.output), TangentSlopeInput = key.t1, TangentSlopeOutput = key.t2, TangentWeightInput = key.w1, TangentWeightOutput = key.w2, }); } else { track.KeyFrames.Add(new IOKeyFrame() { Frame = key.input - header.startTime, Value = GetOutputValue(this, data, key.output), }); } } return(track); }
private IOAnimationTrack LoadAnimationCurve(FbxNode node, string trackNodeType, int trackIndex) { IOAnimationTrack track = new IOAnimationTrack(); //Track types via the parent curve node. //Each child curve track has an index which assigns to X/Y/Z switch (trackNodeType) { case "AnimCurveNode::T": if (trackIndex == 0) { track.ChannelType = IOAnimationTrackType.PositionX; } if (trackIndex == 1) { track.ChannelType = IOAnimationTrackType.PositionY; } if (trackIndex == 2) { track.ChannelType = IOAnimationTrackType.PositionZ; } break; case "AnimCurveNode::R": if (trackIndex == 0) { track.ChannelType = IOAnimationTrackType.RotationEulerX; } if (trackIndex == 1) { track.ChannelType = IOAnimationTrackType.RotationEulerY; } if (trackIndex == 2) { track.ChannelType = IOAnimationTrackType.RotationEulerZ; } break; case "AnimCurveNode::S": if (trackIndex == 0) { track.ChannelType = IOAnimationTrackType.ScaleX; } if (trackIndex == 1) { track.ChannelType = IOAnimationTrackType.ScaleY; } if (trackIndex == 2) { track.ChannelType = IOAnimationTrackType.ScaleZ; } break; } //Duriation of the key frame var keyTime = node["KeyTime"].Value as long[]; //The key data var keyFloats = node["KeyValueFloat"].Value as float[]; //Determines how a key is handled var keyAttributes = node["KeyAttrDataFloat"].Value as float[]; //How many references used in each attribute var keyAttributeRefs = node["KeyAttrRefCount"].Value as int[]; //The flags for key data. These determine interpolation info var keyAttributeFlags = node["KeyAttrFlags"].Value as int[]; int k = 0; for (int i = 0; i < keyAttributeRefs.Length; i++) { //4 attributes. float rightSlope = keyAttributes[4 * i + 0]; float nextLeftSlope = keyAttributes[4 * i + 1]; //Tangent data is encoded as an int. Convert float to int. int tangentWeightData = BitConverter.ToInt32(BitConverter.GetBytes(keyAttributes[4 * i + 2]), 0); //Decode the weights. float weight1 = (tangentWeightData & 0x0000ffff) / 9999.0f; float weight2 = ((tangentWeightData >> 16) & 0xffff) / 9999.0f; int flags = keyAttributeFlags[i]; var attrCount = keyAttributeRefs[i]; var interpolation = (EInterpolationType)(flags & 0x0000000e); for (int j = 0; j < attrCount; j++) { //Time to frame units float frame = ConvertTimeUnits(keyTime[k]); float time = frame == 0 ? 0 : frame / 24.0f; //The raw key value float value = keyFloats[k]; //Create key frames. switch (interpolation) { case EInterpolationType.eInterpolationCubic: //Todo figure out tangents from attribute data track.KeyFrames.Add(new IOKeyFrameHermite() { Frame = frame, Time = time, Value = value, TangentSlopeInput = rightSlope, TangentSlopeOutput = nextLeftSlope, TangentWeightInput = weight1, TangentWeightOutput = weight2, }); break; default: track.KeyFrames.Add(new IOKeyFrame() { Frame = frame, Time = time, Value = value, }); break; } k++; } } return(track); }