public RwKeyFrame(float time, Quaternion rotation, Vector3 translation, RwKeyFrame previous) { Time = time; Rotation = rotation; Translation = translation; Previous = previous; }
private void ReadUncompressedKeyFrames(BinaryReader reader) { var keyFrameByOffsetMap = new Dictionary <int, RwKeyFrame>(); for (int i = 0; i < KeyFrames.Capacity; i++) { var keyFrame = new RwKeyFrame { Time = reader.ReadSingle(), Rotation = new Quaternion(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()), Translation = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()) }; int previousKeyFrameOffset = reader.ReadInt32(); if (keyFrame.Time != 0.0f) { keyFrame.Previous = keyFrameByOffsetMap[previousKeyFrameOffset]; } keyFrameByOffsetMap[i * UNCOMPRESSED_KEYFRAME_SIZE] = keyFrame; KeyFrames.Add(keyFrame); } }
private void DecompressKeyframes(List <RwCompressedKeyFrame> compressedKeyFrames, RwCompressedKeyFrameCustomData customData) { var keyFrameByOffsetMap = new Dictionary <int, RwKeyFrame>(); for (int i = 0; i < compressedKeyFrames.Count; i++) { var compressedKeyFrame = compressedKeyFrames[i]; var keyFrame = new RwKeyFrame { Time = compressedKeyFrame.Time, Rotation = new Quaternion ( DecompressFloat(compressedKeyFrame.RotationX), DecompressFloat(compressedKeyFrame.RotationY), DecompressFloat(compressedKeyFrame.RotationZ), DecompressFloat(compressedKeyFrame.RotationW) ), Translation = new Vector3 ( (DecompressFloat(compressedKeyFrame.TranslationX) * customData.Scalar.X) + customData.Offset.X, (DecompressFloat(compressedKeyFrame.TranslationY) * customData.Scalar.Y) + customData.Offset.Y, (DecompressFloat(compressedKeyFrame.TranslationZ) * customData.Scalar.Z) + customData.Offset.Z ) }; if (keyFrame.Time != 0.0f) { keyFrame.Previous = keyFrameByOffsetMap[compressedKeyFrame.PreviousFrameOffset]; } keyFrameByOffsetMap[i * COMPRESSED_KEYFRAME_SIZE] = keyFrame; keyFrame.Dirty = false; KeyFrames.Add(keyFrame); } }
public static RwAnimationNode FromAssimpScene(RwNode parent, RwFrameListNode frameList, string path) { var aiContext = new Assimp.AssimpContext(); var aiScene = aiContext.ImportFile(path); var aiAnimation = aiScene.Animations.FirstOrDefault(); RwAnimationNode animationNode; if (aiAnimation != null) { animationNode = new RwAnimationNode(parent, RwKeyFrameType.Uncompressed, ( float )(aiAnimation.DurationInTicks / aiAnimation.TicksPerSecond)); var nodeNameToHAnimId = aiAnimation.NodeAnimationChannels.ToDictionary(x => x.NodeName, x => frameList.GetNameIdByName(x.NodeName)); var nodeKeyframeTimes = aiAnimation.NodeAnimationChannels.SelectMany(x => x.PositionKeys) .Select(x => x.Time) .Concat(aiAnimation.NodeAnimationChannels.SelectMany(x => x.RotationKeys.Select(y => y.Time))) .Distinct() .OrderBy(x => x) .ToList(); var previousKeyFrames = new Dictionary <int, RwKeyFrame>(); var nodeKeyFrames = new Dictionary <int, List <RwKeyFrame> >(); // Add initial pose foreach (var hierarchyNode in frameList.AnimationRootNode.HAnimFrameExtensionNode.Hierarchy.Nodes) { var frame = frameList[frameList.GetFrameIndexByNameId(hierarchyNode.NodeId)]; var firstRotation = Quaternion.CreateFromRotationMatrix(frame.Transform); var firstTranslation = frame.Transform.Translation; var channel = aiAnimation.NodeAnimationChannels.FirstOrDefault(x => nodeNameToHAnimId[x.NodeName] == hierarchyNode.NodeId); if (channel != null) { if (channel.HasRotationKeys) { firstRotation = ToQuaternion(channel.RotationKeys.First().Value); } if (channel.HasPositionKeys) { firstTranslation = ToVector3(channel.PositionKeys.First().Value); } } var keyFrame = new RwKeyFrame(0, firstRotation, firstTranslation, null); animationNode.KeyFrames.Add(keyFrame); previousKeyFrames[hierarchyNode.NodeId] = keyFrame; nodeKeyFrames[hierarchyNode.NodeId] = new List <RwKeyFrame>(); } foreach (var keyFrameTime in nodeKeyframeTimes) { if (keyFrameTime == 0.0f) { continue; } foreach (var channel in aiAnimation.NodeAnimationChannels) { if (!channel.HasPositionKeys && !channel.HasRotationKeys) { continue; } if (!channel.RotationKeys.Any(x => x.Time == keyFrameTime) || !channel.PositionKeys.Any(x => x.Time == keyFrameTime)) { continue; } var hierarchAnimNodeId = nodeNameToHAnimId[channel.NodeName]; var previousKeyFrame = previousKeyFrames[hierarchAnimNodeId]; var rotation = previousKeyFrame.Rotation; var translation = previousKeyFrame.Translation; var rotationKeys = channel.RotationKeys.Where(x => x.Time == keyFrameTime); if (rotationKeys.Any()) { var aiRotation = rotationKeys.First().Value; rotation = new Quaternion(aiRotation.X, aiRotation.Y, aiRotation.Z, aiRotation.W); } var translationKeys = channel.PositionKeys.Where(x => x.Time == keyFrameTime); if (translationKeys.Any()) { var aiTranslation = translationKeys.First().Value; translation = new Vector3(aiTranslation.X, aiTranslation.Y, aiTranslation.Z); } var keyFrame = new RwKeyFrame(( float )(keyFrameTime / aiAnimation.TicksPerSecond), rotation, translation, previousKeyFrame); nodeKeyFrames[hierarchAnimNodeId].Add(keyFrame); previousKeyFrames[hierarchAnimNodeId] = keyFrame; } } while (!nodeKeyFrames.All(x => x.Value.Count == 0)) { foreach (var kvp in nodeKeyFrames) { if (animationNode.KeyFrames.Count == 0) { continue; } var keyFrame = kvp.Value.First(); animationNode.KeyFrames.Add(keyFrame); kvp.Value.Remove(keyFrame); if (animationNode.KeyFrames.Count == 0) { var previousKeyFrame = previousKeyFrames[kvp.Key]; if (previousKeyFrame.Time != animationNode.Duration) { var lastRotation = previousKeyFrame.Rotation; var lastTranslation = previousKeyFrame.Translation; var channel = aiAnimation.NodeAnimationChannels.SingleOrDefault(x => nodeNameToHAnimId[x.NodeName] == kvp.Key); if (channel != null) { if (channel.HasRotationKeys) { lastRotation = ToQuaternion(channel.RotationKeys.Last().Value); } if (channel.HasPositionKeys) { lastTranslation = ToVector3(channel.PositionKeys.Last().Value); } } animationNode.KeyFrames.Add(new RwKeyFrame(animationNode.Duration, lastRotation, lastTranslation, previousKeyFrame)); } } } } } else { animationNode = new RwAnimationNode(null, RwKeyFrameType.Uncompressed, 0f); } return(animationNode); }