internal static W3dAdaptiveDeltaAnimationChannel Parse(BinaryReader reader, W3dParseContext context, W3dAdaptiveDeltaBitCount bitCount) { return ParseChunk(reader, context, header => { var result = new W3dAdaptiveDeltaAnimationChannel { NumTimeCodes = reader.ReadUInt32(), Pivot = reader.ReadUInt16(), VectorLength = reader.ReadByte(), ChannelType = reader.ReadByteAsEnum<W3dAnimationChannelType>(), Scale = reader.ReadSingle(), }; W3dAnimationChannel.ValidateChannelDataSize(result.ChannelType, result.VectorLength); result.Data = W3dAdaptiveDeltaData.Parse( reader, result.NumTimeCodes, result.ChannelType, result.VectorLength, bitCount); // Skip 3 unknown bytes at chunk end. reader.BaseStream.Seek(3, SeekOrigin.Current); return result; }); }
public static W3dAnimationChannelDatum[] Decode( W3dAdaptiveDeltaData data, uint numFrames, float scale) { var scaleFactor = 1.0f; switch (data.BitCount) { // Do nothing for 4 bit deltas since they already map to [-16;16] case W3dAdaptiveDeltaBitCount.FourBits: break; // When deltas are 8 bits large we need to scale them to the range [-16;16] case W3dAdaptiveDeltaBitCount.EightBits: scaleFactor = 1 / 16.0f; break; default: throw new InvalidOperationException("Adaptive delta only supported 4 bit & 8 bit!"); } var result = new W3dAnimationChannelDatum[numFrames]; result[0] = data.InitialDatum; for (var i = 0; i < data.DeltaBlocks.Length; i++) { var deltaBlock = data.DeltaBlocks[i]; var blockIndex = deltaBlock.BlockIndex; var blockScale = Table[blockIndex]; var deltaScale = blockScale * scale * scaleFactor; var vectorIndex = deltaBlock.VectorIndex; var deltas = deltaBlock.GetDeltas(data.BitCount); for (var j = 0; j < deltas.Length; j++) { var idx = ((i / data.VectorLength) * 16) + j + 1; if (idx >= numFrames) { break; } var value = result[idx - 1].GetValue(vectorIndex) + deltaScale * deltas[j]; result[idx] = result[idx].WithValue(value, vectorIndex); idx++; } } return(result); }
internal static W3dMotionChannelAdaptiveDeltaData Parse( BinaryReader reader, uint numTimeCodes, W3dAnimationChannelType channelType, int vectorLen, W3dAdaptiveDeltaBitCount bitCount) { return(new W3dMotionChannelAdaptiveDeltaData { Scale = reader.ReadSingle(), Data = W3dAdaptiveDeltaData.Parse( reader, numTimeCodes, channelType, vectorLen, bitCount) }); }
internal static W3dAdaptiveDeltaData Parse( BinaryReader reader, uint numFrames, W3dAnimationChannelType type, int vectorLength, W3dAdaptiveDeltaBitCount bitCount) { var count = (numFrames + 15) >> 4; // First read all initial values var result = new W3dAdaptiveDeltaData { BitCount = bitCount, VectorLength = vectorLength, InitialDatum = W3dAnimationChannelDatum.Parse(reader, type) }; var numBits = (int)bitCount; // Then read the interleaved delta blocks var deltaBlocks = new W3dAdaptiveDeltaBlock[count * vectorLength]; for (var i = 0; i < count; i++) { for (var j = 0; j < vectorLength; j++) { deltaBlocks[(i * vectorLength) + j] = W3dAdaptiveDeltaBlock.Parse( reader, j, numBits); } } result.DeltaBlocks = deltaBlocks; return(result); }