private Motion(bool isRaw) { IsRaw = isRaw; if (isRaw) { Raw = new RawMotion { Matrices = new List <Matrix4x4[]>(), }; } else { Interpolated = new InterpolatedMotion { Footer = new FooterTable(), IKChains = new List <IKChainTable>(), IKHelperAnimation = new List <BoneAnimationTable>(), IKHelpers = new List <IKHelperTable>(), Joints = new List <JointTable>(), ModelBoneAnimation = new List <BoneAnimationTable>(), StaticPose = new List <StaticPoseTable>(), Table6 = new List <UnknownTable6>(), Table7 = new List <UnknownTable7>(), Table8 = new List <UnknownTable8>(), Timeline = new List <TimelineTable>(), }; } }
private static void Write(Stream stream, InterpolatedMotion motion, bool unkFlag) { var valuePool = new PoolValues <float>(); var keyFramePool = new PoolValues <float>(motion.Timeline.Select(x => x.KeyFrame).Distinct().OrderBy(x => x)); var tangentPool = new PoolValues <float>(); var rawTimeline = new List <TimelineTableInternal>(motion.Timeline.Count); foreach (var item in motion.Timeline) { rawTimeline.Add(new TimelineTableInternal { Time = (short)(((int)item.Interpolation & 3) | (keyFramePool.GetIndex(item.KeyFrame) << 2)), ValueIndex = (short)valuePool.GetIndex(item.Value), TangentIndexEaseIn = (short)tangentPool.GetIndex(item.TangentEaseIn), TangentIndexEaseOut = (short)tangentPool.GetIndex(item.TangentEaseOut), }); } var writer = new BinaryWriter(stream); var header = new InterpolatedMotionInternal { BoneCount = motion.BoneCount, TotalFrameCount = motion.TotalFrameCount, Unk48 = motion.Unk48, BoundingBoxMinX = motion.BoundingBoxMinX, BoundingBoxMinY = motion.BoundingBoxMinY, BoundingBoxMinZ = motion.BoundingBoxMinZ, BoundingBoxMinW = motion.BoundingBoxMinW, BoundingBoxMaxX = motion.BoundingBoxMaxX, BoundingBoxMaxY = motion.BoundingBoxMaxY, BoundingBoxMaxZ = motion.BoundingBoxMaxZ, BoundingBoxMaxW = motion.BoundingBoxMaxW, FrameLoop = motion.FrameLoop, FrameEnd = motion.FrameEnd, FramePerSecond = motion.FramePerSecond, FrameCount = motion.FrameCount, Unk98 = motion.Unk98, Unk9c = motion.Unk9c, }; stream.Write(new byte[ReservedSize], 0, ReservedSize); BinaryMapping.WriteObject(stream, new Header { }); BinaryMapping.WriteObject(stream, new InterpolatedMotionInternal { }); header.StaticPoseCount = motion.StaticPose.Count; header.StaticPoseOffset = (int)(stream.Position - ReservedSize); foreach (var item in motion.StaticPose) { BinaryMapping.WriteObject(stream, item); } header.ModelBoneAnimationCount = motion.ModelBoneAnimation.Count; header.ModelBoneAnimationOffset = (int)(stream.Position - ReservedSize); foreach (var item in motion.ModelBoneAnimation.Select(Map)) { BinaryMapping.WriteObject(stream, item); } header.IKHelperAnimationCount = motion.IKHelperAnimation.Count; header.IKHelperAnimationOffset = (int)(stream.Position - ReservedSize); foreach (var item in motion.IKHelperAnimation.Select(Map)) { BinaryMapping.WriteObject(stream, item); } header.TimelineOffset = (int)(stream.Position - ReservedSize); foreach (var item in rawTimeline) { BinaryMapping.WriteObject(stream, item); } stream.AlignPosition(4); header.KeyFrameCount = keyFramePool.Values.Count; header.KeyFrameOffset = (int)(stream.Position - ReservedSize); foreach (var item in keyFramePool.Values) { writer.Write(item); } header.TransformationValueOffset = (int)(stream.Position - ReservedSize); foreach (var item in valuePool.Values) { writer.Write(item); } header.TangentOffset = (int)(stream.Position - ReservedSize); foreach (var item in tangentPool.Values) { writer.Write(item); } header.IKChainCount = motion.IKChains.Count; header.IKChainOffset = (int)(stream.Position - ReservedSize); foreach (var item in motion.IKChains) { BinaryMapping.WriteObject(stream, item); } header.Unk48 = (int)(stream.Position - ReservedSize); stream.AlignPosition(0x10); header.Table8Offset = (int)(stream.Position - ReservedSize); foreach (var item in motion.Table8) { BinaryMapping.WriteObject(stream, item); } stream.AlignPosition(0x10); header.Table7Count = motion.Table7.Count; header.Table7Offset = (int)(stream.Position - ReservedSize); foreach (var item in motion.Table7) { BinaryMapping.WriteObject(stream, item); } header.Table6Count = motion.Table6.Count; header.Table6Offset = (int)(stream.Position - ReservedSize); foreach (var item in motion.Table6) { BinaryMapping.WriteObject(stream, item); } stream.AlignPosition(0x10); header.TotalBoneCount = (short)(motion.BoneCount + motion.IKHelpers.Count); header.IKHelperOffset = (int)(stream.Position - ReservedSize); foreach (var item in motion.IKHelpers) { BinaryMapping.WriteObject(stream, item); } header.JointIndexOffset = (int)(stream.Position - ReservedSize); foreach (var item in motion.Joints) { BinaryMapping.WriteObject(stream, item); } stream.AlignPosition(0x10); header.FooterOffset = (int)(stream.Position - ReservedSize); BinaryMapping.WriteObject(stream, motion.Footer); header.UnknownTable1Offset = (int)(stream.Position - ReservedSize); header.UnknownTable1Count = 0; stream.AlignPosition(0x10); stream.SetLength(stream.Position); stream.SetPosition(ReservedSize); BinaryMapping.WriteObject(stream, new Header { Version = 0, Unk04 = unkFlag ? 1 : 0, ByteCount = (int)(stream.Length - ReservedSize), Unk0c = 0, }); BinaryMapping.WriteObject(stream, header); }
private Motion(Stream stream) { stream.Position += ReservedSize; var header = BinaryMapping.ReadObject <Header>(stream); IsRaw = header.Version == 1; UnkFlag = header.Unk04 != 0; if (IsRaw) { var raw = BinaryMapping.ReadObject <RawMotionInternal>(stream); Raw = new RawMotion { BoneCount = raw.BoneCount, Unk28 = raw.Unk28, Unk2c = raw.Unk2c, BoundingBoxMinX = raw.BoundingBoxMinX, BoundingBoxMinY = raw.BoundingBoxMinY, BoundingBoxMinZ = raw.BoundingBoxMinZ, BoundingBoxMinW = raw.BoundingBoxMinW, BoundingBoxMaxX = raw.BoundingBoxMaxX, BoundingBoxMaxY = raw.BoundingBoxMaxY, BoundingBoxMaxZ = raw.BoundingBoxMaxZ, BoundingBoxMaxW = raw.BoundingBoxMaxW, FrameLoop = raw.FrameLoop, FrameEnd = raw.FrameEnd, FramePerSecond = raw.FramePerSecond, FrameCount = raw.FrameCount }; var reader = new BinaryReader(stream); Raw.Matrices = new List <Matrix4x4[]>(raw.TotalFrameCount); for (var i = 0; i < raw.TotalFrameCount; i++) { var matrices = new Matrix4x4[Raw.BoneCount]; for (var j = 0; j < Raw.BoneCount; j++) { matrices[j] = ReadMatrix(reader); } Raw.Matrices.Add(matrices); } if (raw.Unk2c > 0) { stream.Position = ReservedSize + raw.Unk2c; Raw.Matrices2 = new Matrix4x4[raw.TotalFrameCount]; for (var j = 0; j < Raw.Matrices2.Length; j++) { Raw.Matrices2[j] = ReadMatrix(reader); } } else { Raw.Matrices2 = new Matrix4x4[0]; } } else { var reader = new BinaryReader(stream); var motion = BinaryMapping.ReadObject <InterpolatedMotionInternal>(stream); Interpolated = new InterpolatedMotion { BoneCount = motion.BoneCount, TotalFrameCount = motion.TotalFrameCount, Unk48 = motion.Unk48, BoundingBoxMinX = motion.BoundingBoxMinX, BoundingBoxMinY = motion.BoundingBoxMinY, BoundingBoxMinZ = motion.BoundingBoxMinZ, BoundingBoxMinW = motion.BoundingBoxMinW, BoundingBoxMaxX = motion.BoundingBoxMaxX, BoundingBoxMaxY = motion.BoundingBoxMaxY, BoundingBoxMaxZ = motion.BoundingBoxMaxZ, BoundingBoxMaxW = motion.BoundingBoxMaxW, FrameLoop = motion.FrameLoop, FrameEnd = motion.FrameEnd, FramePerSecond = motion.FramePerSecond, FrameCount = motion.FrameCount, Unk98 = motion.Unk98, Unk9c = motion.Unk9c, }; stream.Position = ReservedSize + motion.StaticPoseOffset; Interpolated.StaticPose = Enumerable .Range(0, motion.StaticPoseCount) .Select(x => BinaryMapping.ReadObject <StaticPoseTable>(stream)) .ToList(); stream.Position = ReservedSize + motion.ModelBoneAnimationOffset; Interpolated.ModelBoneAnimation = Enumerable .Range(0, motion.ModelBoneAnimationCount) .Select(x => BinaryMapping.ReadObject <BoneAnimationTableInternal>(stream)) .Select(Map) .ToList(); stream.Position = ReservedSize + motion.IKHelperAnimationOffset; Interpolated.IKHelperAnimation = Enumerable .Range(0, motion.IKHelperAnimationCount) .Select(x => BinaryMapping.ReadObject <BoneAnimationTableInternal>(stream)) .Select(Map) .ToList(); stream.Position = ReservedSize + motion.TimelineOffset; var estimatedTimelineCount = (motion.KeyFrameOffset - motion.TimelineOffset) / 8; var rawTimeline = Enumerable .Range(0, estimatedTimelineCount) .Select(x => BinaryMapping.ReadObject <TimelineTableInternal>(stream)) .ToList(); stream.Position = ReservedSize + motion.KeyFrameOffset; var keyFrames = Enumerable .Range(0, motion.KeyFrameCount) .Select(x => reader.ReadSingle()) .ToList(); stream.Position = ReservedSize + motion.TransformationValueOffset; var estimatedKeyFrameCount = (motion.TangentOffset - motion.TransformationValueOffset) / 4; var transformationValues = Enumerable .Range(0, estimatedKeyFrameCount) .Select(x => reader.ReadSingle()) .ToList(); stream.Position = ReservedSize + motion.TangentOffset; var estimatedTangentCount = (motion.IKChainOffset - motion.TangentOffset) / 4; var tangentValues = Enumerable .Range(0, estimatedTangentCount) .Select(x => reader.ReadSingle()) .ToList(); stream.Position = ReservedSize + motion.IKChainOffset; Interpolated.IKChains = Enumerable .Range(0, motion.IKChainCount) .Select(x => BinaryMapping.ReadObject <IKChainTable>(stream)) .ToList(); stream.Position = ReservedSize + motion.Table8Offset; var estimatedTable8Count = (motion.Table7Offset - motion.Table8Offset) / 0x30; Interpolated.Table8 = Enumerable .Range(0, estimatedTable8Count) .Select(x => BinaryMapping.ReadObject <UnknownTable8>(stream)) .ToList(); stream.Position = ReservedSize + motion.Table7Offset; Interpolated.Table7 = Enumerable .Range(0, motion.Table7Count) .Select(x => BinaryMapping.ReadObject <UnknownTable7>(stream)) .ToList(); stream.Position = ReservedSize + motion.Table6Offset; Interpolated.Table6 = Enumerable .Range(0, motion.Table6Count) .Select(x => BinaryMapping.ReadObject <UnknownTable6>(stream)) .ToList(); stream.Position = ReservedSize + motion.IKHelperOffset; Interpolated.IKHelpers = Enumerable .Range(0, motion.TotalBoneCount - motion.BoneCount) .Select(x => BinaryMapping.ReadObject <IKHelperTable>(stream)) .ToList(); stream.Position = ReservedSize + motion.JointIndexOffset; Interpolated.Joints = Enumerable .Range(0, motion.TotalBoneCount + 1) .Select(x => BinaryMapping.ReadObject <JointTable>(stream)) .ToList(); Interpolated.Timeline = rawTimeline .Select(x => new TimelineTable { Interpolation = (Interpolation)(x.Time & 3), KeyFrame = keyFrames[x.Time >> 2], Value = transformationValues[x.ValueIndex], TangentEaseIn = tangentValues[x.TangentIndexEaseIn], TangentEaseOut = tangentValues[x.TangentIndexEaseOut], }) .ToList(); stream.Position = ReservedSize + motion.FooterOffset; Interpolated.Footer = BinaryMapping.ReadObject <FooterTable>(stream); stream.Position = ReservedSize + motion.UnknownTable1Offset; } }