Improve vertex format parsing. Close #689

This commit is contained in:
Perfare 2021-04-12 15:11:17 +08:00
parent f1f2430f97
commit 6d99f5ebf6

View File

@ -195,7 +195,7 @@ namespace AssetStudio
if (m_Channel.dimension > 0) if (m_Channel.dimension > 0)
{ {
chnMask |= 1u << chn; chnMask |= 1u << chn;
stride += m_Channel.dimension * MeshHelper.GetFormatSize(version, m_Channel.format); stride += m_Channel.dimension * MeshHelper.GetFormatSize(MeshHelper.ToVertexFormat(m_Channel.format, version));
} }
} }
} }
@ -253,7 +253,7 @@ namespace AssetStudio
m_Channel.dimension = 4; m_Channel.dimension = 4;
break; break;
} }
offset += (byte)(m_Channel.dimension * MeshHelper.GetFormatSize(version, m_Channel.format)); offset += (byte)(m_Channel.dimension * MeshHelper.GetFormatSize(MeshHelper.ToVertexFormat(m_Channel.format, version)));
} }
} }
} }
@ -711,12 +711,13 @@ namespace AssetStudio
var channelMask = new BitArray(new[] { (int)m_Stream.channelMask }); var channelMask = new BitArray(new[] { (int)m_Stream.channelMask });
if (channelMask.Get(chn)) if (channelMask.Get(chn))
{ {
if (version[0] < 2018 && chn == 2 && m_Channel.format == 2) if (version[0] < 2018 && chn == 2 && m_Channel.format == 2) //kShaderChannelColor && kChannelFormatColor
{ {
m_Channel.dimension = 4; m_Channel.dimension = 4;
} }
var componentByteSize = (int)MeshHelper.GetFormatSize(version, m_Channel.format); var vertexFormat = MeshHelper.ToVertexFormat(m_Channel.format, version);
var componentByteSize = (int)MeshHelper.GetFormatSize(vertexFormat);
var componentBytes = new byte[m_VertexCount * m_Channel.dimension * componentByteSize]; var componentBytes = new byte[m_VertexCount * m_Channel.dimension * componentByteSize];
for (int v = 0; v < m_VertexCount; v++) for (int v = 0; v < m_VertexCount; v++)
{ {
@ -741,10 +742,10 @@ namespace AssetStudio
int[] componentsIntArray = null; int[] componentsIntArray = null;
float[] componentsFloatArray = null; float[] componentsFloatArray = null;
if (MeshHelper.IsIntFormat(version, m_Channel.format)) if (MeshHelper.IsIntFormat(vertexFormat))
componentsIntArray = MeshHelper.BytesToIntArray(componentBytes, componentByteSize); componentsIntArray = MeshHelper.BytesToIntArray(componentBytes, vertexFormat);
else else
componentsFloatArray = MeshHelper.BytesToFloatArray(componentBytes, componentByteSize); componentsFloatArray = MeshHelper.BytesToFloatArray(componentBytes, vertexFormat);
if (version[0] >= 2018) if (version[0] >= 2018)
{ {
@ -1190,7 +1191,7 @@ namespace AssetStudio
public static class MeshHelper public static class MeshHelper
{ {
private enum VertexChannelFormat public enum VertexChannelFormat
{ {
kChannelFormatFloat, kChannelFormatFloat,
kChannelFormatFloat16, kChannelFormatFloat16,
@ -1199,7 +1200,7 @@ namespace AssetStudio
kChannelFormatUInt32 kChannelFormatUInt32
} }
private enum VertexFormat public enum VertexFormat2017
{ {
kVertexFormatFloat, kVertexFormatFloat,
kVertexFormatFloat16, kVertexFormatFloat16,
@ -1216,7 +1217,7 @@ namespace AssetStudio
kVertexFormatSInt32 kVertexFormatSInt32
} }
private enum VertexFormatV2019 public enum VertexFormat
{ {
kVertexFormatFloat, kVertexFormatFloat,
kVertexFormatFloat16, kVertexFormatFloat16,
@ -1232,147 +1233,146 @@ namespace AssetStudio
kVertexFormatSInt32 kVertexFormatSInt32
} }
public static uint GetFormatSize(int[] version, int format) public static VertexFormat ToVertexFormat(int format, int[] version)
{ {
if (version[0] < 2017) if (version[0] < 2017)
{ {
switch ((VertexChannelFormat)format) switch ((VertexChannelFormat)format)
{ {
case VertexChannelFormat.kChannelFormatFloat: case VertexChannelFormat.kChannelFormatFloat:
return 4u; return VertexFormat.kVertexFormatFloat;
case VertexChannelFormat.kChannelFormatFloat16: case VertexChannelFormat.kChannelFormatFloat16:
return 2u; return VertexFormat.kVertexFormatFloat16;
case VertexChannelFormat.kChannelFormatColor: //in 4.x is size 4 case VertexChannelFormat.kChannelFormatColor: //in 4.x is size 4
return 1u; return VertexFormat.kVertexFormatUNorm8;
case VertexChannelFormat.kChannelFormatByte: case VertexChannelFormat.kChannelFormatByte:
return 1u; return VertexFormat.kVertexFormatUInt8;
case VertexChannelFormat.kChannelFormatUInt32: //in 5.x case VertexChannelFormat.kChannelFormatUInt32: //in 5.x
return 4u; return VertexFormat.kVertexFormatUInt32;
default: default:
throw new ArgumentOutOfRangeException(nameof(format), format, null); throw new ArgumentOutOfRangeException(nameof(format), format, null);
} }
} }
else if (version[0] < 2019) else if (version[0] < 2019)
{ {
switch ((VertexFormat)format) switch ((VertexFormat2017)format)
{
case VertexFormat2017.kVertexFormatFloat:
return VertexFormat.kVertexFormatFloat;
case VertexFormat2017.kVertexFormatFloat16:
return VertexFormat.kVertexFormatFloat16;
case VertexFormat2017.kVertexFormatColor:
case VertexFormat2017.kVertexFormatUNorm8:
return VertexFormat.kVertexFormatUNorm8;
case VertexFormat2017.kVertexFormatSNorm8:
return VertexFormat.kVertexFormatSNorm8;
case VertexFormat2017.kVertexFormatUNorm16:
return VertexFormat.kVertexFormatUNorm16;
case VertexFormat2017.kVertexFormatSNorm16:
return VertexFormat.kVertexFormatSNorm16;
case VertexFormat2017.kVertexFormatUInt8:
return VertexFormat.kVertexFormatUInt8;
case VertexFormat2017.kVertexFormatSInt8:
return VertexFormat.kVertexFormatSInt8;
case VertexFormat2017.kVertexFormatUInt16:
return VertexFormat.kVertexFormatUInt16;
case VertexFormat2017.kVertexFormatSInt16:
return VertexFormat.kVertexFormatSInt16;
case VertexFormat2017.kVertexFormatUInt32:
return VertexFormat.kVertexFormatUInt32;
case VertexFormat2017.kVertexFormatSInt32:
return VertexFormat.kVertexFormatSInt32;
default:
throw new ArgumentOutOfRangeException(nameof(format), format, null);
}
}
else
{
return (VertexFormat)format;
}
}
public static uint GetFormatSize(VertexFormat format)
{
switch (format)
{ {
case VertexFormat.kVertexFormatFloat: 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: case VertexFormat.kVertexFormatUInt32:
return 4u;
case VertexFormat.kVertexFormatSInt32: case VertexFormat.kVertexFormatSInt32:
return 4u; return 4u;
case VertexFormat.kVertexFormatFloat16:
case VertexFormat.kVertexFormatUNorm16:
case VertexFormat.kVertexFormatSNorm16:
case VertexFormat.kVertexFormatUInt16:
case VertexFormat.kVertexFormatSInt16:
return 2u;
case VertexFormat.kVertexFormatUNorm8:
case VertexFormat.kVertexFormatSNorm8:
case VertexFormat.kVertexFormatUInt8:
case VertexFormat.kVertexFormatSInt8:
return 1u;
default: default:
throw new ArgumentOutOfRangeException(nameof(format), format, null); throw new ArgumentOutOfRangeException(nameof(format), format, null);
} }
} }
else
public static bool IsIntFormat(VertexFormat format)
{ {
switch ((VertexFormatV2019)format) return format >= VertexFormat.kVertexFormatUInt8;
{
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) public static float[] BytesToFloatArray(byte[] inputBytes, VertexFormat format)
{ {
if (version[0] < 2017) var size = GetFormatSize(format);
var len = inputBytes.Length / size;
var result = new float[len];
for (int i = 0; i < len; i++)
{ {
return format == 4; switch (format)
}
else if (version[0] < 2019)
{ {
return format >= 7; case VertexFormat.kVertexFormatFloat:
} result[i] = BitConverter.ToSingle(inputBytes, i * 4);
else
{
return format >= 6;
}
}
public static float[] BytesToFloatArray(byte[] inputBytes, int size)
{
var result = new float[inputBytes.Length / size];
for (int i = 0; i < inputBytes.Length / size; i++)
{
var value = 0f;
switch (size)
{
case 1:
value = inputBytes[i] / 255.0f;
break; break;
case 2: case VertexFormat.kVertexFormatFloat16:
value = Half.ToHalf(inputBytes, i * 2); result[i] = Half.ToHalf(inputBytes, i * 2);
break; break;
case 4: case VertexFormat.kVertexFormatUNorm8:
value = BitConverter.ToSingle(inputBytes, i * 4); result[i] = inputBytes[i] / 255f;
break;
case VertexFormat.kVertexFormatSNorm8:
result[i] = Math.Max((sbyte)inputBytes[i] / 127f, -1f);
break;
case VertexFormat.kVertexFormatUNorm16:
result[i] = BitConverter.ToUInt16(inputBytes, i * 2) / 65535f;
break;
case VertexFormat.kVertexFormatSNorm16:
result[i] = Math.Max(BitConverter.ToInt16(inputBytes, i * 2) / 32767f, -1f);
break; break;
} }
result[i] = value;
} }
return result; return result;
} }
public static int[] BytesToIntArray(byte[] inputBytes, int size) public static int[] BytesToIntArray(byte[] inputBytes, VertexFormat format)
{ {
var result = new int[inputBytes.Length / size]; var size = GetFormatSize(format);
for (int i = 0; i < inputBytes.Length / size; i++) var len = inputBytes.Length / size;
var result = new int[len];
for (int i = 0; i < len; i++)
{ {
switch (size) switch (format)
{ {
case 1: case VertexFormat.kVertexFormatUInt8:
case VertexFormat.kVertexFormatSInt8:
result[i] = inputBytes[i]; result[i] = inputBytes[i];
break; break;
case 2: case VertexFormat.kVertexFormatUInt16:
case VertexFormat.kVertexFormatSInt16:
result[i] = BitConverter.ToInt16(inputBytes, i * 2); result[i] = BitConverter.ToInt16(inputBytes, i * 2);
break; break;
case 4: case VertexFormat.kVertexFormatUInt32:
case VertexFormat.kVertexFormatSInt32:
result[i] = BitConverter.ToInt32(inputBytes, i * 4); result[i] = BitConverter.ToInt32(inputBytes, i * 4);
break; break;
} }