diff --git a/AssetStudio/Classes/Mesh.cs b/AssetStudio/Classes/Mesh.cs index 4efc15c..8b1ffd8 100644 --- a/AssetStudio/Classes/Mesh.cs +++ b/AssetStudio/Classes/Mesh.cs @@ -166,19 +166,19 @@ namespace AssetStudio if (version[0] < 4) //4.0 down { - GetChannels(); + GetChannels(version); } } else //5.0 and up { - GetStreams(); + GetStreams(version); } m_DataSize = reader.ReadBytes(reader.ReadInt32()); reader.AlignStream(); } - private void GetStreams() + private void GetStreams(int[] version) { var streamCount = m_Channels.Max(x => x.stream) + 1; m_Streams = new StreamInfo[streamCount]; @@ -195,7 +195,7 @@ namespace AssetStudio if (m_Channel.dimension > 0) { chnMask |= 1u << chn; - stride += m_Channel.dimension * MeshHelper.GetChannelFormatSize(m_Channel.format); + stride += m_Channel.dimension * MeshHelper.GetFormatSize(version, m_Channel.format); } } } @@ -213,7 +213,7 @@ namespace AssetStudio } } - private void GetChannels() + private void GetChannels(int[] version) { m_Channels = new ChannelInfo[6]; for (int i = 0; i < 6; i++) @@ -253,7 +253,7 @@ namespace AssetStudio m_Channel.dimension = 4; break; } - offset += (byte)(m_Channel.dimension * MeshHelper.GetChannelFormatSize(m_Channel.format)); + offset += (byte)(m_Channel.dimension * MeshHelper.GetFormatSize(version, m_Channel.format)); } } } @@ -705,7 +705,7 @@ namespace AssetStudio m_Channel.dimension = 4; } - var componentByteSize = (int)MeshHelper.GetChannelFormatSize(m_Channel.format); + var componentByteSize = (int)MeshHelper.GetFormatSize(version, m_Channel.format); var componentBytes = new byte[m_VertexCount * m_Channel.dimension * componentByteSize]; for (int v = 0; v < m_VertexCount; v++) { @@ -730,8 +730,8 @@ namespace AssetStudio int[] componentsIntArray = null; float[] componentsFloatArray = null; - if (m_Channel.format == 10 || m_Channel.format == 11) - componentsIntArray = MeshHelper.BytesToIntArray(componentBytes); + if (MeshHelper.IsIntFormat(version, m_Channel.format)) + componentsIntArray = MeshHelper.BytesToIntArray(componentBytes, componentByteSize); else componentsFloatArray = MeshHelper.BytesToFloatArray(componentBytes, componentByteSize); @@ -1132,26 +1132,149 @@ namespace AssetStudio public static class MeshHelper { - public static uint GetChannelFormatSize(int format) + private enum VertexChannelFormat { - switch (format) + kChannelFormatFloat, + kChannelFormatFloat16, + kChannelFormatColor, + kChannelFormatByte, + kChannelFormatUInt32 + } + + private enum VertexFormat + { + kVertexFormatFloat, + kVertexFormatFloat16, + kVertexFormatColor, + kVertexFormatUNorm8, + kVertexFormatSNorm8, + kVertexFormatUNorm16, + kVertexFormatSNorm16, + kVertexFormatUInt8, + kVertexFormatSInt8, + kVertexFormatUInt16, + kVertexFormatSInt16, + kVertexFormatUInt32, + kVertexFormatSInt32 + } + + private enum VertexFormatV2019 + { + kVertexFormatFloat, + kVertexFormatFloat16, + kVertexFormatUNorm8, + kVertexFormatSNorm8, + kVertexFormatUNorm16, + kVertexFormatSNorm16, + kVertexFormatUInt8, + kVertexFormatSInt8, + kVertexFormatUInt16, + kVertexFormatSInt16, + kVertexFormatUInt32, + kVertexFormatSInt32 + } + + public static uint GetFormatSize(int[] version, int format) + { + if (version[0] < 2017) { - case 0: //kChannelFormatFloat - return 4u; - case 1: //kChannelFormatFloat16 - return 2u; - case 2: //kChannelFormatColor - return 1u; - case 3: //kChannelFormatByte - return 1u; - case 4: //kChannelFormatUInt32 - return 4u; - case 10: //kChannelFormatInt32 - return 4u; - case 11: //kChannelFormatInt32 - return 4u; - default: - return 0; + switch ((VertexChannelFormat)format) + { + case VertexChannelFormat.kChannelFormatFloat: + return 4u; + case VertexChannelFormat.kChannelFormatFloat16: + return 2u; + case VertexChannelFormat.kChannelFormatColor: //in 4.x is size 4 + return 1u; + case VertexChannelFormat.kChannelFormatByte: + return 1u; + case VertexChannelFormat.kChannelFormatUInt32: //in 5.x + return 4u; + default: + throw new ArgumentOutOfRangeException(nameof(format), format, null); + } + } + else if (version[0] < 2019) + { + switch ((VertexFormat)format) + { + case VertexFormat.kVertexFormatFloat: + return 4u; + case VertexFormat.kVertexFormatFloat16: + return 2u; + case VertexFormat.kVertexFormatColor: + return 1u; + case VertexFormat.kVertexFormatUNorm8: + return 1u; + case VertexFormat.kVertexFormatSNorm8: + return 1u; + case VertexFormat.kVertexFormatUNorm16: + return 2u; + case VertexFormat.kVertexFormatSNorm16: + return 2u; + case VertexFormat.kVertexFormatUInt8: + return 1u; + case VertexFormat.kVertexFormatSInt8: + return 1u; + case VertexFormat.kVertexFormatUInt16: + return 2u; + case VertexFormat.kVertexFormatSInt16: + return 2u; + case VertexFormat.kVertexFormatUInt32: + return 4u; + case VertexFormat.kVertexFormatSInt32: + return 4u; + default: + throw new ArgumentOutOfRangeException(nameof(format), format, null); + } + } + else + { + switch ((VertexFormatV2019)format) + { + case VertexFormatV2019.kVertexFormatFloat: + return 4u; + case VertexFormatV2019.kVertexFormatFloat16: + return 2u; + case VertexFormatV2019.kVertexFormatUNorm8: + return 1u; + case VertexFormatV2019.kVertexFormatSNorm8: + return 1u; + case VertexFormatV2019.kVertexFormatUNorm16: + return 2u; + case VertexFormatV2019.kVertexFormatSNorm16: + return 2u; + case VertexFormatV2019.kVertexFormatUInt8: + return 1u; + case VertexFormatV2019.kVertexFormatSInt8: + return 1u; + case VertexFormatV2019.kVertexFormatUInt16: + return 2u; + case VertexFormatV2019.kVertexFormatSInt16: + return 2u; + case VertexFormatV2019.kVertexFormatUInt32: + return 4u; + case VertexFormatV2019.kVertexFormatSInt32: + return 4u; + default: + throw new ArgumentOutOfRangeException(nameof(format), format, null); + } + } + } + + public static bool IsIntFormat(int[] version, int format) + { + if (version[0] < 2017) + { + return format == 4; + } + else if (version[0] < 2019) + { + return format >= 7; + } + else + { + return format >= 6; } } @@ -1178,12 +1301,23 @@ namespace AssetStudio return result; } - public static int[] BytesToIntArray(byte[] inputBytes) + public static int[] BytesToIntArray(byte[] inputBytes, int size) { - var result = new int[inputBytes.Length / 4]; - for (int i = 0; i < inputBytes.Length / 4; i++) + var result = new int[inputBytes.Length / size]; + for (int i = 0; i < inputBytes.Length / size; i++) { - result[i] = BitConverter.ToInt32(inputBytes, i * 4); + switch (size) + { + case 1: + result[i] = inputBytes[i]; + break; + case 2: + result[i] = BitConverter.ToInt16(inputBytes, i * 2); + break; + case 4: + result[i] = BitConverter.ToInt32(inputBytes, i * 4); + break; + } } return result; }