Replace uses of AssetReader with EndianSpanReader

This commit is contained in:
Jeremy Pritts 2023-11-06 23:01:33 -05:00
parent c217bf2d34
commit e272e6f9df
4 changed files with 63 additions and 30 deletions

View File

@ -1,6 +1,7 @@
using AssetRipper.Assets.Cloning;
using AssetRipper.Assets.IO.Reading;
using AssetRipper.Assets.Collections;
using AssetRipper.Checksum;
using AssetRipper.IO.Endian;
using AssetRipper.Processing.AnimationClips.Editor;
using AssetRipper.SourceGenerated;
using AssetRipper.SourceGenerated.Classes.ClassID_1;
@ -27,6 +28,7 @@ using AssetRipper.SourceGenerated.Subclasses.QuaternionCurve;
using AssetRipper.SourceGenerated.Subclasses.StreamedClip;
using AssetRipper.SourceGenerated.Subclasses.Vector3Curve;
using System.Buffers;
using System.Buffers.Binary;
using System.Runtime.InteropServices;
namespace AssetRipper.Processing.AnimationClips
@ -570,21 +572,47 @@ namespace AssetRipper.Processing.AnimationClips
public IReadOnlyList<StreamedFrame> GenerateFramesFromStreamedClip(StreamedClip clip)
{
List<StreamedFrame> frames = new();
byte[] memStreamBuffer = new byte[clip.Data.Count * sizeof(uint)];
{
Span<uint> span = MemoryMarshal.Cast<byte, uint>(memStreamBuffer);
clip.Data.CopyTo(span);
}
Span<byte> buffer = new byte[clip.Data.Count * sizeof(uint)];
AssetCollection collection = m_clip.Collection;
CopyDataToBuffer(clip, collection, buffer);
using MemoryStream stream = new MemoryStream(memStreamBuffer);
using AssetReader reader = new AssetReader(stream, m_clip.Collection);
while (reader.BaseStream.Position < reader.BaseStream.Length)
EndianSpanReader reader = new EndianSpanReader(buffer, collection.EndianType);
while (reader.Position < reader.Length)
{
StreamedFrame frame = new();
frame.Read(reader);
frame.Read(ref reader, collection.Version);
frames.Add(frame);
}
return frames;
static bool CpuEndiannessMatchesCollection(AssetCollection collection)
{
return (BitConverter.IsLittleEndian && collection.EndianType is EndianType.LittleEndian)
|| (!BitConverter.IsLittleEndian && collection.EndianType is EndianType.BigEndian);
}
static void CopyDataToBuffer(StreamedClip clip, AssetCollection collection, Span<byte> buffer)
{
if (CpuEndiannessMatchesCollection(collection))
{
Span<uint> span = MemoryMarshal.Cast<byte, uint>(buffer);
clip.Data.CopyTo(span);
}
else
{
for (int i = 0; i < clip.Data.Count; i++)
{
if (BitConverter.IsLittleEndian)
{
BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(i * sizeof(uint)), clip.Data[i]);
}
else
{
BinaryPrimitives.WriteUInt32BigEndian(buffer.Slice(i * sizeof(uint)), clip.Data[i]);
}
}
}
}
}
private UnityVersion Version => m_clip.Collection.Version;

View File

@ -1,4 +1,4 @@
using AssetRipper.Assets.IO.Reading;
using AssetRipper.IO.Endian;
using AssetRipper.SourceGenerated.Subclasses.AnimationCurve_Single;
using AssetRipper.SourceGenerated.Subclasses.Keyframe_Single;
using System.Numerics;
@ -48,7 +48,7 @@ namespace AssetRipper.Processing.AnimationClips.Editor
return curveKey;
}
public void Read(AssetReader reader)
public void Read(ref EndianSpanReader reader)
{
Index = reader.ReadInt32();
Coefficient = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());

View File

@ -1,38 +1,43 @@
using AssetRipper.Assets.IO.Reading;
using AssetRipper.IO.Endian;
namespace AssetRipper.Processing.AnimationClips.Editor
{
public sealed class StreamedFrame
{
public void Read(AssetReader reader)
public void Read(ref EndianSpanReader reader, UnityVersion version)
{
Time = reader.ReadSingle();
Curves = ReadAssetArray(reader);
Curves = ReadAssetArray(ref reader, version);
}
public float Time { get; set; }
public StreamedCurveKey[] Curves { get; set; } = Array.Empty<StreamedCurveKey>();
private static StreamedCurveKey[] ReadAssetArray(AssetReader reader)
private static StreamedCurveKey[] ReadAssetArray(ref EndianSpanReader reader, UnityVersion version)
{
int count = reader.ReadInt32();
if (count < 0)
{
throw new ArgumentOutOfRangeException(nameof(count), $"Cannot be negative: {count}");
}
ThrowIfNegative(count);
StreamedCurveKey[] array = count == 0 ? Array.Empty<StreamedCurveKey>() : new StreamedCurveKey[count];
for (int i = 0; i < count; i++)
{
StreamedCurveKey instance = new();
instance.Read(reader);
instance.Read(ref reader);
array[i] = instance;
}
if (reader.IsAlignArray)
if (version.IsGreaterEqual(2017, 1))
{
reader.AlignStream();
reader.Align();
}
return array;
static void ThrowIfNegative(int count)
{
if (count < 0)
{
throw new ArgumentOutOfRangeException(nameof(count), $"Cannot be negative: {count}");
}
}
}
}
}

View File

@ -1,5 +1,5 @@
using AssetRipper.Assets.Collections;
using AssetRipper.Assets.IO.Reading;
using AssetRipper.IO.Endian;
using AssetRipper.SourceGenerated.Classes.ClassID_43;
using AssetRipper.SourceGenerated.Enums;
using AssetRipper.SourceGenerated.Extensions;
@ -204,14 +204,14 @@ namespace AssetRipper.SourceGenerated.Extensions
int extraStride = streamStride - ShaderChannel.Vertex.GetStride(meshCollection.Version);
int vertexOffset = firstVertex * streamStride;
int begin = streamOffset + vertexOffset + channel.Offset;
using MemoryStream stream = new MemoryStream(vertexData.Data);
using AssetReader reader = new AssetReader(stream, meshCollection);
stream.Position = begin;
EndianSpanReader reader = new EndianSpanReader(vertexData.Data, meshCollection.EndianType);
reader.Position = begin;
Vector3 dummyVertex = reader.ReadVector3();
min = dummyVertex;
max = dummyVertex;
stream.Position = begin;
reader.Position = begin;
for (int i = 0; i < vertexCount; i++)
{
Vector3 vertex = reader.ReadVector3();
@ -239,11 +239,11 @@ namespace AssetRipper.SourceGenerated.Extensions
{
min.Z = vertex.Z;
}
stream.Position += extraStride;
reader.Position += extraStride;
}
}
private static Vector3 ReadVector3(this AssetReader reader)
private static Vector3 ReadVector3(this ref EndianSpanReader reader)
{
return new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
}