/// <summary> /// Read the next value in the stream. Returns true if there is a new <see cref="Transform"/> avaliable /// </summary> /// <param name="reader"></param> /// <returns>Returns true if there is a new <see cref="Transform"/> avaliable</returns> /// <seealso cref="GetTransform"/> /// <remarks><para>Where possible, prefer using the byte[] version of this method</para></remarks> public bool MoveNext(BinaryReader reader) { //value hasn't changed if (repeats > 0) { repeats--; return true; } TransformStorage store = (TransformStorage)reader.ReadByte(); if (store == 0) return false; if (initalised == 0) { initalised = 1; value = Transform.Identity; } //value hasn't changed if ((store & TransformStorage.RepeatPrevious) == TransformStorage.RepeatPrevious) { this.repeats = (short)((store & (~TransformStorage.RepeatPrevious)) - 1); return true; } //read compressed data/deltas //scale changed? if ((store & TransformStorage.ScaleChange) == TransformStorage.ScaleChange) { if ((store & TransformStorage.ScaleHalf) == TransformStorage.ScaleHalf) { //scale is stored as a HalfFloat Microsoft.Xna.Framework.Graphics.PackedVector.HalfSingle value = new Microsoft.Xna.Framework.Graphics.PackedVector.HalfSingle(); value.PackedValue = reader.ReadUInt16(); this.value.Scale = value.ToSingle(); } else { //scale is 1 this.value.Scale = 1; } } //transform delta? if ((store & TransformStorage.TranslateChange) == TransformStorage.TranslateChange) { Vector4 delta4; if ((store & TransformStorage.TranslateDeltaHalf) == TransformStorage.TranslateDeltaHalf) { //delta stored as half in 6 bytes Microsoft.Xna.Framework.Graphics.PackedVector.HalfVector4 delta = new Microsoft.Xna.Framework.Graphics.PackedVector.HalfVector4(); #if !XBOX360 delta.PackedValue = (ulong)reader.ReadUInt32() | ((ulong)reader.ReadUInt16() << 32); #else delta.PackedValue = (ulong)reader.ReadUInt16() | ((ulong)reader.ReadUInt32() << 16); #endif delta4 = delta.ToVector4(); } else { //delta stored normalised, in 3 bytes Microsoft.Xna.Framework.Graphics.PackedVector.NormalizedByte4 delta = new Microsoft.Xna.Framework.Graphics.PackedVector.NormalizedByte4(); #if !XBOX360 delta.PackedValue = reader.ReadUInt16() | ((uint)reader.ReadByte() << 16); #else delta.PackedValue = (uint)reader.ReadByte() | ((uint)reader.ReadUInt16() << 8); #endif delta4 = delta.ToVector4(); } this.value.Translation.X += delta4.X; this.value.Translation.Y += delta4.Y; this.value.Translation.Z += delta4.Z; } //rotation delta? if ((store & TransformStorage.RotationChange) == TransformStorage.RotationChange) { Quaternion rotation; Vector4 delta4; if ((store & TransformStorage.RotationDeltaHalf) == TransformStorage.RotationDeltaHalf) { //delta stored as normalised short in 8 bytes Microsoft.Xna.Framework.Graphics.PackedVector.NormalizedShort4 delta = new Microsoft.Xna.Framework.Graphics.PackedVector.NormalizedShort4(); delta.PackedValue = reader.ReadUInt64(); delta4 = delta.ToVector4(); } else { //delta stored as normalised in 4 bytes Microsoft.Xna.Framework.Graphics.PackedVector.NormalizedByte4 delta = new Microsoft.Xna.Framework.Graphics.PackedVector.NormalizedByte4(); delta.PackedValue = reader.ReadUInt32(); delta4 = delta.ToVector4(); } rotation = new Quaternion(delta4.X, delta4.Y, delta4.Z, delta4.W); Quaternion.Multiply(ref rotation, ref this.value.Rotation, out this.value.Rotation); float length = this.value.Rotation.X * this.value.Rotation.X + this.value.Rotation.Y * this.value.Rotation.Y + this.value.Rotation.Z * this.value.Rotation.Z + this.value.Rotation.W * this.value.Rotation.W; if (length > 1.0001f || length < 0.9999f) { //normalize length = 1.0f / (float)Math.Sqrt(length); this.value.Rotation.X *= length; this.value.Rotation.Y *= length; this.value.Rotation.Z *= length; this.value.Rotation.W *= length; } } if ((store & TransformStorage.Keyframe) == TransformStorage.Keyframe) { //read exact float data... TransformKeyframe keyframe = (TransformKeyframe)reader.ReadByte(); if ((keyframe & TransformKeyframe.ScaleChange) == TransformKeyframe.ScaleChange) { this.value.Scale = reader.ReadSingle(); } if ((keyframe & TransformKeyframe.TranslateChange) == TransformKeyframe.TranslateChange) { this.value.Translation.X = reader.ReadSingle(); this.value.Translation.Y = reader.ReadSingle(); this.value.Translation.Z = reader.ReadSingle(); } if ((keyframe & TransformKeyframe.RotationChange) == TransformKeyframe.RotationChange) { this.value.Rotation.X = reader.ReadSingle(); this.value.Rotation.Y = reader.ReadSingle(); this.value.Rotation.Z = reader.ReadSingle(); this.value.Rotation.W = reader.ReadSingle(); } } #if DEBUG this.value.Validate(); #endif return true; }
/// <summary> /// Read the next value from a data array. Returns true if there is a new <see cref="Transform"/> avaliable /// </summary> /// <returns>Returns true if there is a new <see cref="Transform"/> avaliable</returns> /// <param name="index">index in the source data to begin reading (this value will be modified to indicated how many bytes were read)</param> /// <remarks><para>This method will most likely be more efficient than the <see cref="BinaryReader"/> version</para></remarks> /// <param name="sourceData"></param> /// <seealso cref="GetTransform"/> public bool MoveNext(byte[] sourceData, ref int index) { BitCast cast = new BitCast(); //value hasn't changed if (repeats > 0) { repeats--; Quaternion.Multiply(ref this.accelerationR, ref this.value.Rotation, out this.value.Rotation); float length = this.value.Rotation.X * this.value.Rotation.X + this.value.Rotation.Y * this.value.Rotation.Y + this.value.Rotation.Z * this.value.Rotation.Z + this.value.Rotation.W * this.value.Rotation.W; if (length > 1.0001f || length < 0.9999f) { //normalize length = 1.0f / (float)Math.Sqrt(length); this.value.Rotation.X *= length; this.value.Rotation.Y *= length; this.value.Rotation.Z *= length; this.value.Rotation.W *= length; } this.value.Translation.X += this.accelerationT.X; this.value.Translation.Y += this.accelerationT.Y; this.value.Translation.Z += this.accelerationT.Z; #if DEBUG this.value.Validate(); #endif return true; } TransformStorage store = (TransformStorage)sourceData[index++]; if (store == 0) return false; if (initalised == 0) { initalised = 1; value = Transform.Identity; accelerationR = Quaternion.Identity; } //value hasn't changed if ((store & TransformStorage.RepeatPrevious) == TransformStorage.RepeatPrevious) { this.repeats = (short)((store & (~TransformStorage.RepeatPrevious)) - 1); Quaternion.Multiply(ref this.accelerationR, ref this.value.Rotation, out this.value.Rotation); float length = this.value.Rotation.X * this.value.Rotation.X + this.value.Rotation.Y * this.value.Rotation.Y + this.value.Rotation.Z * this.value.Rotation.Z + this.value.Rotation.W * this.value.Rotation.W; if (length > 1.0001f || length < 0.9999f) { //normalize length = 1.0f / (float)Math.Sqrt(length); this.value.Rotation.X *= length; this.value.Rotation.Y *= length; this.value.Rotation.Z *= length; this.value.Rotation.W *= length; } this.value.Translation.X += this.accelerationT.X; this.value.Translation.Y += this.accelerationT.Y; this.value.Translation.Z += this.accelerationT.Z; #if DEBUG this.value.Validate(); #endif return true; } //read compressed data/deltas //scale changed? if ((store & TransformStorage.ScaleChange) == TransformStorage.ScaleChange) { if ((store & TransformStorage.ScaleHalf) == TransformStorage.ScaleHalf) { //scale is stored as a HalfFloat Microsoft.Xna.Framework.Graphics.PackedVector.HalfSingle value = new Microsoft.Xna.Framework.Graphics.PackedVector.HalfSingle(); cast.Byte0 = sourceData[index++]; cast.Byte1 = sourceData[index++]; value.PackedValue = cast.UInt16; this.value.Scale = value.ToSingle(); } else { //scale is 1 this.value.Scale = 1; } } //transform delta? if ((store & TransformStorage.TranslateChange) == TransformStorage.TranslateChange) { Vector4 delta4; if ((store & TransformStorage.TranslateDeltaHalf) == TransformStorage.TranslateDeltaHalf) { //delta stored as half in 6 bytes Microsoft.Xna.Framework.Graphics.PackedVector.HalfVector4 delta = new Microsoft.Xna.Framework.Graphics.PackedVector.HalfVector4(); cast.Byte0 = sourceData[index++]; cast.Byte1 = sourceData[index++]; cast.Byte2 = sourceData[index++]; cast.Byte3 = sourceData[index++]; cast.Byte4 = sourceData[index++]; cast.Byte5 = sourceData[index++]; cast.Byte6 = 0; cast.Byte7 = 0; delta.PackedValue = cast.UInt64; delta4 = delta.ToVector4(); } else { //delta stored normalised, in 3 bytes Microsoft.Xna.Framework.Graphics.PackedVector.NormalizedByte4 delta = new Microsoft.Xna.Framework.Graphics.PackedVector.NormalizedByte4(); cast.Byte0 = sourceData[index++]; cast.Byte1 = sourceData[index++]; cast.Byte2 = sourceData[index++]; cast.Byte3 = 0; delta.PackedValue = cast.UInt32; delta4 = delta.ToVector4(); } this.accelerationT.X += delta4.X; this.accelerationT.Y += delta4.Y; this.accelerationT.Z += delta4.Z; } //rotation delta? if ((store & TransformStorage.RotationChange) == TransformStorage.RotationChange) { Quaternion rotation; Vector4 delta4; if ((store & TransformStorage.RotationDeltaHalf) == TransformStorage.RotationDeltaHalf) { //delta stored as normalised short in 8 bytes Microsoft.Xna.Framework.Graphics.PackedVector.NormalizedShort4 delta = new Microsoft.Xna.Framework.Graphics.PackedVector.NormalizedShort4(); cast.Byte0 = sourceData[index++]; cast.Byte1 = sourceData[index++]; cast.Byte2 = sourceData[index++]; cast.Byte3 = sourceData[index++]; cast.Byte4 = sourceData[index++]; cast.Byte5 = sourceData[index++]; cast.Byte6 = sourceData[index++]; cast.Byte7 = sourceData[index++]; delta.PackedValue = cast.UInt64; delta4 = delta.ToVector4(); } else { //delta stored as normalised in 4 bytes Microsoft.Xna.Framework.Graphics.PackedVector.NormalizedByte4 delta = new Microsoft.Xna.Framework.Graphics.PackedVector.NormalizedByte4(); cast.Byte0 = sourceData[index++]; cast.Byte1 = sourceData[index++]; cast.Byte2 = sourceData[index++]; cast.Byte3 = sourceData[index++]; delta.PackedValue = cast.UInt32; delta4 = delta.ToVector4(); } rotation = new Quaternion(delta4.X, delta4.Y, delta4.Z, delta4.W); Quaternion.Multiply(ref rotation, ref this.accelerationR, out this.accelerationR); } { Quaternion.Multiply(ref this.accelerationR, ref this.value.Rotation, out this.value.Rotation); float length = this.value.Rotation.X * this.value.Rotation.X + this.value.Rotation.Y * this.value.Rotation.Y + this.value.Rotation.Z * this.value.Rotation.Z + this.value.Rotation.W * this.value.Rotation.W; if (length > 1.0001f || length < 0.9999f) { //normalize length = 1.0f / (float)Math.Sqrt(length); this.value.Rotation.X *= length; this.value.Rotation.Y *= length; this.value.Rotation.Z *= length; this.value.Rotation.W *= length; } this.value.Translation.X += this.accelerationT.X; this.value.Translation.Y += this.accelerationT.Y; this.value.Translation.Z += this.accelerationT.Z; } if ((store & TransformStorage.Keyframe) == TransformStorage.Keyframe) { //read exact float data... TransformKeyframe keyframe = (TransformKeyframe)sourceData[index++]; if ((keyframe & TransformKeyframe.ScaleChange) == TransformKeyframe.ScaleChange) { cast.Byte0 = sourceData[index++]; cast.Byte1 = sourceData[index++]; cast.Byte2 = sourceData[index++]; cast.Byte3 = sourceData[index++]; this.value.Scale = cast.Single; } if ((keyframe & TransformKeyframe.TranslateChange) == TransformKeyframe.TranslateChange) { cast.Byte0 = sourceData[index++]; cast.Byte1 = sourceData[index++]; cast.Byte2 = sourceData[index++]; cast.Byte3 = sourceData[index++]; this.value.Translation.X = cast.Single; cast.Byte0 = sourceData[index++]; cast.Byte1 = sourceData[index++]; cast.Byte2 = sourceData[index++]; cast.Byte3 = sourceData[index++]; this.value.Translation.Y = cast.Single; cast.Byte0 = sourceData[index++]; cast.Byte1 = sourceData[index++]; cast.Byte2 = sourceData[index++]; cast.Byte3 = sourceData[index++]; this.value.Translation.Z = cast.Single; } if ((keyframe & TransformKeyframe.RotationChange) == TransformKeyframe.RotationChange) { cast.Byte0 = sourceData[index++]; cast.Byte1 = sourceData[index++]; cast.Byte2 = sourceData[index++]; cast.Byte3 = sourceData[index++]; this.value.Rotation.X = cast.Single; cast.Byte0 = sourceData[index++]; cast.Byte1 = sourceData[index++]; cast.Byte2 = sourceData[index++]; cast.Byte3 = sourceData[index++]; this.value.Rotation.Y = cast.Single; cast.Byte0 = sourceData[index++]; cast.Byte1 = sourceData[index++]; cast.Byte2 = sourceData[index++]; cast.Byte3 = sourceData[index++]; this.value.Rotation.Z = cast.Single; cast.Byte0 = sourceData[index++]; cast.Byte1 = sourceData[index++]; cast.Byte2 = sourceData[index++]; cast.Byte3 = sourceData[index++]; this.value.Rotation.W = cast.Single; } } #if DEBUG this.value.Validate(); #endif return true; }
/// <summary> /// Write the transform to a byte[] buffer. Returns the number of bytes, if any, that were written /// </summary> /// <param name="transform"></param> /// <param name="index">index to begin writing to the buffer</param> /// <param name="writeTarget">buffer that transform data will be written to (this buffer should be at least 34 bytes in length)</param> /// <param name="forceWrite"><para>If true, the method call will always write at least 1 byte</para><para>When false, multiple identical transforms may be represented with a write of a single byte at the end of the sequence</para></param> /// <returns>Returns the number of bytes written</returns> public int Write(ref Transform transform, byte[] writeTarget, ref int index, bool forceWrite) { int bufferIndex = 0; TransformStorage store = 0; TransformKeyframe keyframe = 0; //if the scale has changed a considerable amount... if (Math.Abs(previous.Scale - transform.Scale) > scaleTolerance) { if (transform.Scale >= 1 - scaleTolerance && transform.Scale <= 1 + scaleTolerance) { store |= TransformStorage.ScaleOne | TransformStorage.ScaleChange; previous.Scale = 1; } else { Microsoft.Xna.Framework.Graphics.PackedVector.HalfSingle value = new Microsoft.Xna.Framework.Graphics.PackedVector.HalfSingle(transform.Scale); float valuef = value.ToSingle(); if (Math.Abs(transform.Scale - valuef) <= scaleTolerance) { ushort pack = value.PackedValue; writeBuffer[bufferIndex++] = (byte)((pack >> 0) & 0xFF); writeBuffer[bufferIndex++] = (byte)((pack >> 8) & 0xFF); store |= TransformStorage.ScaleHalf | TransformStorage.ScaleChange; previous.Scale = valuef; } else { //need full precision keyframe |= TransformKeyframe.ScaleChange; store |= TransformStorage.Keyframe; } } } { Vector3 deltaTranslation = new Vector3( (transform.Translation.X - previous.Translation.X) - acceleration.Translation.X, (transform.Translation.Y - previous.Translation.Y) - acceleration.Translation.Y, (transform.Translation.Z - previous.Translation.Z) - acceleration.Translation.Z); if (Math.Abs(deltaTranslation.X) > translateTolerance || Math.Abs(deltaTranslation.Y) > translateTolerance || Math.Abs(deltaTranslation.Z) > translateTolerance) { Microsoft.Xna.Framework.Graphics.PackedVector.NormalizedByte4 dif8 = new Microsoft.Xna.Framework.Graphics.PackedVector.NormalizedByte4(deltaTranslation.X, deltaTranslation.Y, deltaTranslation.Z, 0); Vector4 dif8v4 = dif8.ToVector4(); if (Math.Abs(dif8v4.X - deltaTranslation.X) <= translateTolerance && Math.Abs(dif8v4.Y - deltaTranslation.Y) <= translateTolerance && Math.Abs(dif8v4.Z - deltaTranslation.Z) <= translateTolerance) { store |= TransformStorage.TranslateDeltaNByte | TransformStorage.TranslateChange; acceleration.Translation.X += dif8v4.X; acceleration.Translation.Y += dif8v4.Y; acceleration.Translation.Z += dif8v4.Z; uint pack = dif8.PackedValue; writeBuffer[bufferIndex++] = (byte)((pack >> 0) & 0xFF); writeBuffer[bufferIndex++] = (byte)((pack >> 8) & 0xFF); writeBuffer[bufferIndex++] = (byte)((pack >> 16) & 0xFF); } else { Microsoft.Xna.Framework.Graphics.PackedVector.HalfVector4 difHalf = new Microsoft.Xna.Framework.Graphics.PackedVector.HalfVector4(deltaTranslation.X, deltaTranslation.Y, deltaTranslation.Z, 0); Vector4 difHalf4 = difHalf.ToVector4(); if (Math.Abs(difHalf4.X - deltaTranslation.X) <= translateTolerance && Math.Abs(difHalf4.Y - deltaTranslation.Y) <= translateTolerance && Math.Abs(difHalf4.Z - deltaTranslation.Z) <= translateTolerance) { store |= TransformStorage.TranslateDeltaHalf | TransformStorage.TranslateChange; acceleration.Translation.X += difHalf4.X; acceleration.Translation.Y += difHalf4.Y; acceleration.Translation.Z += difHalf4.Z; ulong pack = difHalf.PackedValue; writeBuffer[bufferIndex++] = (byte)((pack >> 0) & 0xFF); writeBuffer[bufferIndex++] = (byte)((pack >> 8) & 0xFF); writeBuffer[bufferIndex++] = (byte)((pack >> 16) & 0xFF); writeBuffer[bufferIndex++] = (byte)((pack >> 24) & 0xFF); writeBuffer[bufferIndex++] = (byte)((pack >> 32) & 0xFF); writeBuffer[bufferIndex++] = (byte)((pack >> 40) & 0xFF); } else { //need full precision keyframe |= TransformKeyframe.TranslateChange; store |= TransformStorage.Keyframe; } } } } { Quaternion deltaRotation; Quaternion.Multiply(ref acceleration.Rotation, ref previous.Rotation, out deltaRotation); deltaRotation.X = -deltaRotation.X; deltaRotation.Y = -deltaRotation.Y; deltaRotation.Z = -deltaRotation.Z; Quaternion.Multiply(ref transform.Rotation, ref deltaRotation, out deltaRotation); Quaternion.Normalize(ref deltaRotation, out deltaRotation); if (deltaRotation.W < cos2RotateTolerance) { Vector4 deltaRotV4 = new Vector4(deltaRotation.X, deltaRotation.Y, deltaRotation.Z, deltaRotation.W); Microsoft.Xna.Framework.Graphics.PackedVector.NormalizedByte4 dif8 = new Microsoft.Xna.Framework.Graphics.PackedVector.NormalizedByte4(deltaRotation.X, deltaRotation.Y, deltaRotation.Z, deltaRotation.W); Vector4 dif8v4 = dif8.ToVector4(); Quaternion quat = new Quaternion(dif8v4.X, dif8v4.Y, dif8v4.Z, dif8v4.W); Quaternion quatNorm; Quaternion.Normalize(ref quat, out quatNorm); //fast multiply, only care about W float quaternionW = (deltaRotation.W * quatNorm.W) - (((deltaRotation.X * -quatNorm.X) + (deltaRotation.Y * -quatNorm.Y)) + (deltaRotation.Z * -quatNorm.Z)); if (cos2RotateTolerance <= quaternionW) { store |= TransformStorage.RotationDeltaNByte | TransformStorage.RotationChange; Quaternion.Multiply(ref quat, ref acceleration.Rotation, out acceleration.Rotation); uint pack = dif8.PackedValue; writeBuffer[bufferIndex++] = (byte)((pack >> 0) & 0xFF); writeBuffer[bufferIndex++] = (byte)((pack >> 8) & 0xFF); writeBuffer[bufferIndex++] = (byte)((pack >> 16) & 0xFF); writeBuffer[bufferIndex++] = (byte)((pack >> 24) & 0xFF); } else { Microsoft.Xna.Framework.Graphics.PackedVector.NormalizedShort4 difHalf = new Microsoft.Xna.Framework.Graphics.PackedVector.NormalizedShort4(deltaRotV4); Vector4 difHalf4 = difHalf.ToVector4(); quat.X = difHalf4.X; quat.Y = difHalf4.Y; quat.Z = difHalf4.Z; quat.W = difHalf4.W; Quaternion.Normalize(ref quat, out quatNorm); //fast multiply, only care about W quaternionW = (deltaRotation.W * quat.W) - (((deltaRotation.X * -quat.X) + (deltaRotation.Y * -quat.Y)) + (deltaRotation.Z * -quat.Z)); if (quaternionW <= cos2RotateTolerance) { store |= TransformStorage.RotationDeltaHalf | TransformStorage.RotationChange; Quaternion.Multiply(ref quat, ref acceleration.Rotation, out acceleration.Rotation); ulong pack = difHalf.PackedValue; writeBuffer[bufferIndex++] = (byte)((pack >> 0) & 0xFF); writeBuffer[bufferIndex++] = (byte)((pack >> 8) & 0xFF); writeBuffer[bufferIndex++] = (byte)((pack >> 16) & 0xFF); writeBuffer[bufferIndex++] = (byte)((pack >> 24) & 0xFF); writeBuffer[bufferIndex++] = (byte)((pack >> 32) & 0xFF); writeBuffer[bufferIndex++] = (byte)((pack >> 40) & 0xFF); writeBuffer[bufferIndex++] = (byte)((pack >> 48) & 0xFF); writeBuffer[bufferIndex++] = (byte)((pack >> 56) & 0xFF); } else { //need full precision keyframe |= TransformKeyframe.RotationChange; store |= TransformStorage.Keyframe; } } } } Quaternion.Multiply(ref acceleration.Rotation, ref previous.Rotation, out previous.Rotation); float length = this.previous.Rotation.X * this.previous.Rotation.X + this.previous.Rotation.Y * this.previous.Rotation.Y + this.previous.Rotation.Z * this.previous.Rotation.Z + this.previous.Rotation.W * this.previous.Rotation.W; if (length > 1.0001f || length < 0.9999f) { //normalize length = 1.0f / (float)Math.Sqrt(length); this.previous.Rotation.X *= length; this.previous.Rotation.Y *= length; this.previous.Rotation.Z *= length; this.previous.Rotation.W *= length; } previous.Translation.X += acceleration.Translation.X; previous.Translation.Y += acceleration.Translation.Y; previous.Translation.Z += acceleration.Translation.Z; //nothing significant changed in the frame if (store == 0 && keyframe == 0) { repeat++; if (repeat == 127 || forceWrite) { writeTarget[index++] = (byte)(TransformStorage.RepeatPrevious | (TransformStorage)repeat); repeat = 0; return 1; } return 0; } int written = 0; if (repeat != 0) { writeTarget[index++] = (byte)(TransformStorage.RepeatPrevious | (TransformStorage)repeat); repeat = 0; written++; } //write in the data if (store != 0) { writeTarget[index++] = (byte)store; written++; } if (bufferIndex != 0) { for (int i = 0; i < bufferIndex; i++) writeTarget[index++] = writeBuffer[i]; written += bufferIndex; } if (keyframe != 0) { writeTarget[index++] = (byte)keyframe; written++; BitCast cast = new BitCast(); if ((keyframe & TransformKeyframe.ScaleChange) == TransformKeyframe.ScaleChange) { cast.Single = transform.Scale; writeTarget[index++] = cast.Byte0; writeTarget[index++] = cast.Byte1; writeTarget[index++] = cast.Byte2; writeTarget[index++] = cast.Byte3; previous.Scale = transform.Scale; written += 4; } if ((keyframe & TransformKeyframe.TranslateChange) == TransformKeyframe.TranslateChange) { cast.Single = transform.Translation.X; writeTarget[index++] = cast.Byte0; writeTarget[index++] = cast.Byte1; writeTarget[index++] = cast.Byte2; writeTarget[index++] = cast.Byte3; cast.Single = transform.Translation.Y; writeTarget[index++] = cast.Byte0; writeTarget[index++] = cast.Byte1; writeTarget[index++] = cast.Byte2; writeTarget[index++] = cast.Byte3; cast.Single = transform.Translation.Z; writeTarget[index++] = cast.Byte0; writeTarget[index++] = cast.Byte1; writeTarget[index++] = cast.Byte2; writeTarget[index++] = cast.Byte3; previous.Translation = transform.Translation; written += 12; } if ((keyframe & TransformKeyframe.RotationChange) == TransformKeyframe.RotationChange) { cast.Single = transform.Rotation.X; writeTarget[index++] = cast.Byte0; writeTarget[index++] = cast.Byte1; writeTarget[index++] = cast.Byte2; writeTarget[index++] = cast.Byte3; cast.Single = transform.Rotation.Y; writeTarget[index++] = cast.Byte0; writeTarget[index++] = cast.Byte1; writeTarget[index++] = cast.Byte2; writeTarget[index++] = cast.Byte3; cast.Single = transform.Rotation.Z; writeTarget[index++] = cast.Byte0; writeTarget[index++] = cast.Byte1; writeTarget[index++] = cast.Byte2; writeTarget[index++] = cast.Byte3; cast.Single = transform.Rotation.W; writeTarget[index++] = cast.Byte0; writeTarget[index++] = cast.Byte1; writeTarget[index++] = cast.Byte2; writeTarget[index++] = cast.Byte3; previous.Rotation = transform.Rotation; written += 16; } } return written; }