static FQuat read_fixed32_quat(uint val, FVector min, FVector max) { var q = new FQuat { X = ((val >> 21) - 1023) / 1023f * max.X + min.X, Y = (((val & Y_MASK) >> 10) - 1023) / 1023f * max.Y + min.Y, Z = ((val & X_MASK) - 511) / 511f * max.Z + min.Z, W = 1 }; q.rebuild_w(); return(q); }
internal FTransform(BinaryReader reader) { rotation = new FQuat(reader); translation = new FVector(reader); scale_3d = new FVector(reader); }
private FTrack[] read_tracks(MemoryStream stream) { if (key_encoding_format != 2) { throw new NotImplementedException("Can only parse PerTrackCompression"); } using (stream) using (var reader = new BinaryReader(stream)) { var num_tracks = compressed_track_offsets.Length / 2; var num_frames = compressed_num_frames; FTrack[] ret = new FTrack[num_tracks]; for (int i = 0; i < ret.Length; i++) { FTrack track = new FTrack(); // translation var offset = compressed_track_offsets[i * 2]; if (offset != -1) { var header = new FAnimKeyHeader(reader); var min = new FVector(); var max = new FVector(); if (header.key_format == AnimationCompressionFormat.IntervalFixed32NoW) { if ((header.component_mask & 1) != 0) { min.X = reader.ReadSingle(); max.X = reader.ReadSingle(); } if ((header.component_mask & 2) != 0) { min.Y = reader.ReadSingle(); max.Y = reader.ReadSingle(); } if ((header.component_mask & 4) != 0) { min.Z = reader.ReadSingle(); max.Z = reader.ReadSingle(); } } track.translation = new FVector[header.num_keys]; for (int j = 0; j < track.translation.Length; j++) { switch (header.key_format) { case AnimationCompressionFormat.None: case AnimationCompressionFormat.Float96NoW: var fvec = new FVector(); if ((header.component_mask & 7) != 0) { if ((header.component_mask & 1) != 0) { fvec.X = reader.ReadSingle(); } if ((header.component_mask & 2) != 0) { fvec.Y = reader.ReadSingle(); } if ((header.component_mask & 4) != 0) { fvec.Z = reader.ReadSingle(); } } else { fvec = new FVector(reader); } track.translation[j] = fvec; break; case AnimationCompressionFormat.Fixed48NoW: fvec = new FVector(); if ((header.component_mask & 1) != 0) { fvec.X = read_fixed48(reader.ReadUInt16()); } if ((header.component_mask & 2) != 0) { fvec.Y = read_fixed48(reader.ReadUInt16()); } if ((header.component_mask & 4) != 0) { fvec.Z = read_fixed48(reader.ReadUInt16()); } track.translation[j] = fvec; break; case AnimationCompressionFormat.IntervalFixed32NoW: track.translation[j] = read_fixed32_vec(reader.ReadUInt32(), min, max); break; } } if (header.has_time_tracks) { track.translation_times = read_times(reader, header.num_keys, (uint)num_frames); } align_reader(reader); } // rotation offset = compressed_track_offsets[(i * 2) + 1]; if (offset != -1) { var header = new FAnimKeyHeader(reader); var min = new FVector(); var max = new FVector(); if (header.key_format == AnimationCompressionFormat.IntervalFixed32NoW) { if ((header.component_mask & 1) != 0) { min.X = reader.ReadSingle(); max.X = reader.ReadSingle(); } if ((header.component_mask & 2) != 0) { min.Y = reader.ReadSingle(); max.Y = reader.ReadSingle(); } if ((header.component_mask & 4) != 0) { min.Z = reader.ReadSingle(); max.Z = reader.ReadSingle(); } } track.rotation = new FQuat[header.num_keys]; for (int j = 0; j < track.rotation.Length; j++) { switch (header.key_format) { case AnimationCompressionFormat.None: case AnimationCompressionFormat.Float96NoW: var fvec = new FVector(); if ((header.component_mask & 7) != 0) { if ((header.component_mask & 1) != 0) { fvec.X = reader.ReadSingle(); } if ((header.component_mask & 2) != 0) { fvec.Y = reader.ReadSingle(); } if ((header.component_mask & 4) != 0) { fvec.Z = reader.ReadSingle(); } } else { fvec = new FVector(reader); } var fquat = new FQuat() { X = fvec.X, Y = fvec.Y, Z = fvec.Z }; fquat.rebuild_w(); track.rotation[j] = fquat; break; case AnimationCompressionFormat.Fixed48NoW: fquat = new FQuat(); if ((header.component_mask & 1) != 0) { fquat.X = read_fixed48_q(reader.ReadUInt16()); } if ((header.component_mask & 2) != 0) { fquat.Y = read_fixed48_q(reader.ReadUInt16()); } if ((header.component_mask & 4) != 0) { fquat.Z = read_fixed48_q(reader.ReadUInt16()); } fquat.rebuild_w(); track.rotation[j] = fquat; break; case AnimationCompressionFormat.IntervalFixed32NoW: track.rotation[j] = read_fixed32_quat(reader.ReadUInt32(), min, max); break; } } if (header.has_time_tracks) { track.rotation_times = read_times(reader, header.num_keys, (uint)num_frames); } align_reader(reader); } // scale offset = compressed_scale_offsets.offset_data[i * compressed_scale_offsets.strip_size]; if (offset != -1) { var header = new FAnimKeyHeader(reader); var min = new FVector(); var max = new FVector(); if (header.key_format == AnimationCompressionFormat.IntervalFixed32NoW) { if ((header.component_mask & 1) != 0) { min.X = reader.ReadSingle(); max.X = reader.ReadSingle(); } if ((header.component_mask & 2) != 0) { min.Y = reader.ReadSingle(); max.Y = reader.ReadSingle(); } if ((header.component_mask & 4) != 0) { min.Z = reader.ReadSingle(); max.Z = reader.ReadSingle(); } } track.scale = new FVector[header.num_keys]; for (int j = 0; j < track.scale.Length; j++) { switch (header.key_format) { case AnimationCompressionFormat.None: case AnimationCompressionFormat.Float96NoW: var fvec = new FVector(); if ((header.component_mask & 7) != 0) { if ((header.component_mask & 1) != 0) { fvec.X = reader.ReadSingle(); } if ((header.component_mask & 2) != 0) { fvec.Y = reader.ReadSingle(); } if ((header.component_mask & 4) != 0) { fvec.Z = reader.ReadSingle(); } } else { fvec = new FVector(reader); } track.scale[j] = fvec; break; case AnimationCompressionFormat.Fixed48NoW: fvec = new FVector(); if ((header.component_mask & 1) != 0) { fvec.X = read_fixed48(reader.ReadUInt16()); } if ((header.component_mask & 2) != 0) { fvec.Y = read_fixed48(reader.ReadUInt16()); } if ((header.component_mask & 4) != 0) { fvec.Z = read_fixed48(reader.ReadUInt16()); } track.scale[j] = fvec; break; case AnimationCompressionFormat.IntervalFixed32NoW: track.scale[j] = read_fixed32_vec(reader.ReadUInt32(), min, max); break; } } if (header.has_time_tracks) { track.scale_times = read_times(reader, header.num_keys, (uint)num_frames); } align_reader(reader); } ret[i] = track; } if (reader.BaseStream.Position != stream.Length) { throw new FileLoadException($"Could not read tracks correctly, {reader.BaseStream.Position - stream.Length} bytes remaining"); } return(ret); } }