public static void AddAnimationSIMD(ref ModelRoot model, animAnimationBufferSimd blob, string animName, Stream defferedBuffer, animAnimation animAnimDes) { var rootPositions = new Dictionary <ushort, Dictionary <float, Vec3> >(); var rootRotations = new Dictionary <ushort, Dictionary <float, Quat> >(); var hasRootMotion = animAnimDes.MotionExtraction.Chunk is not null; if (hasRootMotion) { ROOT_MOTION.AddRootMotion(ref rootPositions, ref rootRotations, animAnimDes); } var br = new BinaryReader(defferedBuffer); var jointsCountAligned = (blob.NumJoints + 3U) & (~3U); // simd 4 alignment var totalFloatCount = (blob.NumFrames * jointsCountAligned * 3 + 3U) & (~3U); // simd 4 alignment var rotCompressedBuffSize = totalFloatCount * blob.QuantizationBits / 8U; rotCompressedBuffSize = (rotCompressedBuffSize + 15U) & (~15U); // 16byte padding aligment var mask = (1U << blob.QuantizationBits) - 1U; var floatsPacked = new ushort[totalFloatCount]; for (uint i = 0; i < totalFloatCount; i++) { var bitOff = i * blob.QuantizationBits; var byteOff = bitOff / 8; var shift = (bitOff % 8); defferedBuffer.Position = byteOff; var val = br.ReadUInt32(); val = val >> (int)shift; floatsPacked[i] = Convert.ToUInt16(val & mask); } var floatsDecompressed = new float[totalFloatCount]; for (uint i = 0; i < totalFloatCount; i++) { floatsDecompressed[i] = ((1f / mask) * floatsPacked[i] * 2) - 1f; } var Rotations = new Quat[blob.NumFrames, blob.NumJoints]; for (uint i = 0; i < blob.NumFrames; i++) { for (uint e = 0; e < blob.NumJoints; e += 4) { for (uint eye = 0; eye < 4; eye++) { var q = new Quat { X = floatsDecompressed[i * jointsCountAligned * 3 + e * 3 + eye], Y = floatsDecompressed[i * jointsCountAligned * 3 + e * 3 + 4 + eye], Z = floatsDecompressed[i * jointsCountAligned * 3 + e * 3 + 8 + eye] }; var dotPr = (q.X * q.X + q.Y * q.Y + q.Z * q.Z); q.X = q.X * Convert.ToSingle(Math.Sqrt(2f - dotPr)); q.Y = q.Y * Convert.ToSingle(Math.Sqrt(2f - dotPr)); q.Z = q.Z * Convert.ToSingle(Math.Sqrt(2f - dotPr)); q.W = 1f - dotPr; q = Quat.Normalize(q); if (e + eye < blob.NumJoints) { Rotations[i, e + eye] = new Quat(q.X, q.Z, -q.Y, q.W); } } } } var EvalAlignedPositions = new float[blob.NumFrames * blob.NumTranslationsToEvalAlignedToSimd * 3]; defferedBuffer.Position = rotCompressedBuffSize; for (uint i = 0; i < blob.NumFrames * blob.NumTranslationsToEvalAlignedToSimd * 3; i++) { EvalAlignedPositions[i] = br.ReadSingle(); } var Scales = new Vec3[blob.NumFrames, blob.NumJoints]; if (blob.IsScaleConstant) { var scalesRaw = new float[4]; for (uint i = 0; i < 4; i++) { scalesRaw[i] = br.ReadSingle(); } for (uint i = 0; i < blob.NumFrames; i++) { for (uint e = 0; e < blob.NumJoints; e++) { var v = new Vec3 { X = scalesRaw[0], Y = scalesRaw[1], Z = scalesRaw[2] }; Scales[i, e] = v; } } } else { var scalesRaw = new float[blob.NumFrames * jointsCountAligned * 3]; for (uint i = 0; i < blob.NumFrames * jointsCountAligned * 3; i++) { scalesRaw[i] = br.ReadSingle(); } for (uint i = 0; i < blob.NumFrames; i++) { for (uint e = 0; e < blob.NumJoints; e += 4) { for (uint eye = 0; eye < 4; eye++) { var v = new Vec3 { X = scalesRaw[i * jointsCountAligned * 3 + e * 3 + eye], Y = scalesRaw[i * jointsCountAligned * 3 + e * 3 + 4 + eye], Z = scalesRaw[i * jointsCountAligned * 3 + e * 3 + 8 + eye] }; Scales[i, e + eye] = v; } } } } if (blob.NumTracks > 0) { if (!blob.IsTrackConstant) { uint asas = ((blob.NumTracks + 3U) & (~3U)) * blob.NumFrames * 4; defferedBuffer.Seek(asas, SeekOrigin.Current); } else { defferedBuffer.Seek(4, SeekOrigin.Current); } } var positionToCopy = new Vec3[blob.NumTranslationsToCopy]; for (uint e = 0; e < blob.NumTranslationsToCopy; e++) { positionToCopy[e].X = br.ReadSingle(); positionToCopy[e].Y = br.ReadSingle(); positionToCopy[e].Z = br.ReadSingle(); } var evalIndices = new short[blob.NumTranslationsToEvalAlignedToSimd]; var copyIndices = new short[blob.NumTranslationsToCopy]; for (uint e = 0; e < blob.NumTranslationsToCopy; e++) { copyIndices[e] = br.ReadInt16(); } for (uint e = 0; e < blob.NumTranslationsToEvalAlignedToSimd; e++) { evalIndices[e] = br.ReadInt16(); } var Positions = new Vec3[blob.NumFrames, blob.NumJoints]; for (uint i = 0; i < blob.NumFrames; i++) { for (uint e = 0; e < blob.NumTranslationsToEvalAlignedToSimd; e += 4) { for (uint eye = 0; eye < 4; eye++) { var v = new Vec3 { X = EvalAlignedPositions[i * blob.NumTranslationsToEvalAlignedToSimd * 3 + e * 3 + eye], Y = EvalAlignedPositions[i * blob.NumTranslationsToEvalAlignedToSimd * 3 + e * 3 + 4 + eye], Z = EvalAlignedPositions[i * blob.NumTranslationsToEvalAlignedToSimd * 3 + e * 3 + 8 + eye] }; if (evalIndices[e + eye] > -1) { Positions[i, evalIndices[e + eye]] = new Vec3(v.X, v.Z, -v.Y); } } } for (uint e = 0; e < copyIndices.Length; e++) { var v = new Vec3 { X = positionToCopy[e].X, Y = positionToCopy[e].Y, Z = positionToCopy[e].Z }; Positions[i, copyIndices[e]] = new Vec3(v.X, v.Z, -v.Y); } } var a = model.CreateAnimation(animName); for (var e = 0; e < blob.NumJoints - blob.NumExtraJoints; e++) { var pos = new Dictionary <float, Vec3>(); var rot = new Dictionary <float, Quat>(); var sca = new Dictionary <float, Vec3>(); var diff = blob.Duration / (blob.NumFrames - 1); for (var i = 0; i < blob.NumFrames; i++) { pos.Add(i * diff, Positions[i, e]); rot.Add(i * diff, Rotations[i, e]); sca.Add(i * diff, Scales[i, e]); } a.CreateRotationChannel(model.LogicalNodes[e], rot); a.CreateTranslationChannel(model.LogicalNodes[e], pos); a.CreateScaleChannel(model.LogicalNodes[e], sca); } }
public static void AddAnimationSIMD(ref ModelRoot model, animAnimationBufferSimd blob, string animName, Stream defferedBuffer, animAnimation animAnimDes) { Dictionary <UInt16, Dictionary <float, Vec3> > rootPositions = new Dictionary <ushort, Dictionary <float, Vec3> >(); Dictionary <UInt16, Dictionary <float, Quat> > rootRotations = new Dictionary <ushort, Dictionary <float, Quat> >(); bool hasRootMotion = animAnimDes.MotionExtraction.IsSerialized; if (hasRootMotion) { ROOT_MOTION.AddRootMotion(ref rootPositions, ref rootRotations, animAnimDes); } BinaryReader br = new BinaryReader(defferedBuffer); UInt32 jointsCountAligned = (blob.NumJoints.Value + 3U) & (~3U); // simd 4 alignment UInt32 totalFloatCount = (blob.NumFrames.Value * jointsCountAligned * 3 + 3U) & (~3U); // simd 4 alignment UInt32 rotCompressedBuffSize = totalFloatCount * blob.QuantizationBits.Value / 8U; rotCompressedBuffSize = (rotCompressedBuffSize + 15U) & (~15U); // 16byte padding aligment UInt32 mask = (1U << blob.QuantizationBits.Value) - 1U; UInt16[] floatsPacked = new UInt16[totalFloatCount]; for (UInt32 i = 0; i < totalFloatCount; i++) { UInt32 bitOff = i * blob.QuantizationBits.Value; UInt32 byteOff = bitOff / 8; UInt32 shift = (bitOff % 8); defferedBuffer.Position = byteOff; UInt32 val = br.ReadUInt32(); val = val >> (int)shift; floatsPacked[i] = Convert.ToUInt16(val & mask); } float[] floatsDecompressed = new float[totalFloatCount]; for (UInt32 i = 0; i < totalFloatCount; i++) { floatsDecompressed[i] = ((1f / mask) * floatsPacked[i] * 2) - 1f; } Quat[,] Rotations = new Quat[blob.NumFrames.Value, blob.NumJoints.Value]; for (UInt32 i = 0; i < blob.NumFrames.Value; i++) { for (UInt32 e = 0; e < blob.NumJoints.Value; e += 4) { for (UInt32 eye = 0; eye < 4; eye++) { Quat q = new Quat(); q.X = floatsDecompressed[i * jointsCountAligned * 3 + e * 3 + eye]; q.Y = floatsDecompressed[i * jointsCountAligned * 3 + e * 3 + 4 + eye]; q.Z = floatsDecompressed[i * jointsCountAligned * 3 + e * 3 + 8 + eye]; float dotPr = (q.X * q.X + q.Y * q.Y + q.Z * q.Z); q.X = q.X * Convert.ToSingle(Math.Sqrt(2f - dotPr)); q.Y = q.Y * Convert.ToSingle(Math.Sqrt(2f - dotPr)); q.Z = q.Z * Convert.ToSingle(Math.Sqrt(2f - dotPr)); q.W = 1f - dotPr; q = Quat.Normalize(q); if (e + eye < blob.NumJoints.Value) { Rotations[i, e + eye] = new Quat(q.X, q.Z, -q.Y, q.W); } } } } float[] EvalAlignedPositions = new float[blob.NumFrames.Value * blob.NumTranslationsToEvalAlignedToSimd.Value * 3]; defferedBuffer.Position = rotCompressedBuffSize; for (UInt32 i = 0; i < blob.NumFrames.Value * blob.NumTranslationsToEvalAlignedToSimd.Value * 3; i++) { EvalAlignedPositions[i] = br.ReadSingle(); } Vec3[,] Scales = new Vec3[blob.NumFrames.Value, blob.NumJoints.Value]; if (blob.IsScaleConstant.Value) { float[] scalesRaw = new float[4]; for (UInt32 i = 0; i < 4; i++) { scalesRaw[i] = br.ReadSingle(); } for (UInt32 i = 0; i < blob.NumFrames.Value; i++) { for (UInt32 e = 0; e < blob.NumJoints.Value; e++) { Vec3 v = new Vec3(); v.X = scalesRaw[0]; v.Y = scalesRaw[1]; v.Z = scalesRaw[2]; Scales[i, e] = v; } } } else { float[] scalesRaw = new float[blob.NumFrames.Value * jointsCountAligned * 3]; for (UInt32 i = 0; i < blob.NumFrames.Value * jointsCountAligned * 3; i++) { scalesRaw[i] = br.ReadSingle(); } for (UInt32 i = 0; i < blob.NumFrames.Value; i++) { for (UInt32 e = 0; e < blob.NumJoints.Value; e += 4) { for (UInt32 eye = 0; eye < 4; eye++) { Vec3 v = new Vec3(); v.X = scalesRaw[i * jointsCountAligned * 3 + e * 3 + eye]; v.Y = scalesRaw[i * jointsCountAligned * 3 + e * 3 + 4 + eye]; v.Z = scalesRaw[i * jointsCountAligned * 3 + e * 3 + 8 + eye]; Scales[i, e + eye] = v; } } } } if (blob.NumTracks.Value > 0) { if (!blob.IsTrackConstant.Value) { UInt32 asas = ((blob.NumTracks.Value + 3U) & (~3U)) * blob.NumFrames.Value * 4; defferedBuffer.Seek(asas, SeekOrigin.Current); } else { defferedBuffer.Seek(4, SeekOrigin.Current); } } Vec3[] positionToCopy = new Vec3[blob.NumTranslationsToCopy.Value]; for (UInt32 e = 0; e < blob.NumTranslationsToCopy.Value; e++) { positionToCopy[e].X = br.ReadSingle(); positionToCopy[e].Y = br.ReadSingle(); positionToCopy[e].Z = br.ReadSingle(); } Int16[] evalIndices = new Int16[blob.NumTranslationsToEvalAlignedToSimd.Value]; Int16[] copyIndices = new Int16[blob.NumTranslationsToCopy.Value]; for (UInt32 e = 0; e < blob.NumTranslationsToCopy.Value; e++) { copyIndices[e] = br.ReadInt16(); } for (UInt32 e = 0; e < blob.NumTranslationsToEvalAlignedToSimd.Value; e++) { evalIndices[e] = br.ReadInt16(); } Vec3[,] Positions = new Vec3[blob.NumFrames.Value, blob.NumJoints.Value]; for (UInt32 i = 0; i < blob.NumFrames.Value; i++) { for (UInt32 e = 0; e < blob.NumTranslationsToEvalAlignedToSimd.Value; e += 4) { for (UInt32 eye = 0; eye < 4; eye++) { Vec3 v = new Vec3(); v.X = EvalAlignedPositions[i * blob.NumTranslationsToEvalAlignedToSimd.Value * 3 + e * 3 + eye]; v.Y = EvalAlignedPositions[i * blob.NumTranslationsToEvalAlignedToSimd.Value * 3 + e * 3 + 4 + eye]; v.Z = EvalAlignedPositions[i * blob.NumTranslationsToEvalAlignedToSimd.Value * 3 + e * 3 + 8 + eye]; if (evalIndices[e + eye] > -1) { Positions[i, evalIndices[e + eye]] = new Vec3(v.X, v.Z, -v.Y); } } } for (UInt32 e = 0; e < copyIndices.Length; e++) { Vec3 v = new Vec3(); v.X = positionToCopy[e].X; v.Y = positionToCopy[e].Y; v.Z = positionToCopy[e].Z; Positions[i, copyIndices[e]] = new Vec3(v.X, v.Z, -v.Y); } } var a = model.CreateAnimation(animName); for (int e = 0; e < blob.NumJoints.Value - blob.NumExtraJoints.Value; e++) { var pos = new Dictionary <float, Vec3>(); var rot = new Dictionary <float, Quat>(); var sca = new Dictionary <float, Vec3>(); float diff = blob.Duration.Value / (blob.NumFrames.Value - 1); for (int i = 0; i < blob.NumFrames.Value; i++) { pos.Add(i * diff, Positions[i, e]); rot.Add(i * diff, Rotations[i, e]); sca.Add(i * diff, Scales[i, e]); } a.CreateRotationChannel(model.LogicalNodes[e], rot); a.CreateTranslationChannel(model.LogicalNodes[e], pos); a.CreateScaleChannel(model.LogicalNodes[e], sca); } }