Fix Endfield

This commit is contained in:
Maverick Chang
2025-02-17 14:30:24 +09:00
parent dbf3a8f16a
commit 8446538322
17 changed files with 481 additions and 157 deletions

View File

@@ -17,6 +17,7 @@ namespace AssetStudio
m_Min = reader.ReadVector3();
m_Max = reader.ReadVector3();
}
}
public class CompressedMesh
@@ -146,6 +147,11 @@ namespace AssetStudio
for (int i = 0; i < m_ChannelsSize; i++)
{
m_Channels.Add(new ChannelInfo(reader));
////Kh0n5u Debug2
//if (i == 1){
// m_Channels[i].dimension = 3;
//}
}
}
@@ -801,6 +807,7 @@ namespace AssetStudio
GetTriangles();
}
private void ReadVertexData()
{
m_VertexCount = (int)m_VertexData.m_VertexCount;
@@ -818,6 +825,11 @@ namespace AssetStudio
{
m_Channel.dimension = 4;
}
////Kh0n5u Debug4
//if (reader.Game.Type.IsArknightsEndfield() && chn == 1)
//{
// m_Channel.dimension = 3;
//}
var vertexFormat = MeshHelper.ToVertexFormat(m_Channel.format, version);
var componentByteSize = (int)MeshHelper.GetFormatSize(vertexFormat);
@@ -845,10 +857,18 @@ namespace AssetStudio
int[] componentsIntArray = null;
float[] componentsFloatArray = null;
if (MeshHelper.IsIntFormat(vertexFormat))
componentsIntArray = MeshHelper.BytesToIntArray(componentBytes, vertexFormat);
if (reader.Game.Type.IsArknightsEndfield() && chn == 1)
{
//componentsFloatArray = MeshHelper.BytesToFloatArray(componentBytes, vertexFormat);
componentsFloatArray = MeshHelper.DecompressEndfieldNormal(componentBytes,vertexFormat);
}
else
componentsFloatArray = MeshHelper.BytesToFloatArray(componentBytes, vertexFormat);
{
if (MeshHelper.IsIntFormat(vertexFormat))
componentsIntArray = MeshHelper.BytesToIntArray(componentBytes, vertexFormat);
else
componentsFloatArray = MeshHelper.BytesToFloatArray(componentBytes, vertexFormat);
}
if (version[0] >= 2018)
{
@@ -858,7 +878,22 @@ namespace AssetStudio
m_Vertices = componentsFloatArray;
break;
case 1: //kShaderChannelNormal
m_Normals = componentsFloatArray;
//Kh0n5u Debug3
//if (reader.Game.Type.IsArknightsEndfield())
//{
// float[] m_Vertices_zero = new float[m_VertexCount * 3];
// for (int i = 0; i < m_VertexCount; i++)
// {
// m_Vertices_zero[i * 3] = 0.0f;
// m_Vertices_zero[i * 3 + 1] = 0.0f;
// m_Vertices_zero[i * 3 + 2] = 1.0f;
// }
// m_Normals = m_Vertices_zero;
//}
//else
//{
m_Normals = componentsFloatArray;
//}
break;
case 2: //kShaderChannelTangent
m_Tangents = componentsFloatArray;
@@ -1457,6 +1492,187 @@ namespace AssetStudio
return result;
}
public static UInt32[] BytesToUInt32Array(byte[] inputBytes, VertexFormat format)
{
var size = GetFormatSize(format);
var len = inputBytes.Length / size;
var result = new UInt32[len];
for (int i = 0; i < len; i++)
{
switch (format)
{
case VertexFormat.UInt32:
result[i] = BinaryPrimitives.ReadUInt32LittleEndian(inputBytes.AsSpan(i * 4));
break;
case VertexFormat.SInt32:
result[i] = (UInt32)BinaryPrimitives.ReadInt32LittleEndian(inputBytes.AsSpan(i * 4));
break;
}
}
return result;
}
public static int[] BytesToSInt32Array(byte[] inputBytes, VertexFormat format)
{
var size = GetFormatSize(format);
var len = inputBytes.Length / size;
var result = new int[len];
for (int i = 0; i < len; i++)
{
switch (format)
{
case VertexFormat.UInt32:
result[i] = (int)BinaryPrimitives.ReadUInt32LittleEndian(inputBytes.AsSpan(i * 4));
break;
case VertexFormat.SInt32:
result[i] = BinaryPrimitives.ReadInt32LittleEndian(inputBytes.AsSpan(i * 4));
break;
}
}
return result;
}
public static float[] DecompressEndfieldNormal(this byte[] inputBytes, VertexFormat format) // 8bits per component
{
var size = MeshHelper.GetFormatSize(format);
var len = inputBytes.Length / size;
var result = new float[len * 3];
var readFloat = new float[len];
readFloat = MeshHelper.BytesToFloatArray(inputBytes, format);
for (int i = 0; i < len; i++)
{
float value = readFloat[i];
float r0x = BitConverter.ToInt32(BitConverter.GetBytes(value)) & 0x40000000;
r0x = (BitConverter.ToUInt32(BitConverter.GetBytes(r0x)) > 0) ? 1.0f : 0.0f;
// (((int3)v2.xxx << (32 - int3(10,10,10) - int3(0,10,20))) >> (32 - int3(10,10,10)))
float r0y = (BitConverter.ToInt32(BitConverter.GetBytes(value)) << 22) >> 22;
float r0z = (BitConverter.ToInt32(BitConverter.GetBytes(value)) << 12) >> 22;
float r0w = (BitConverter.ToInt32(BitConverter.GetBytes(value)) << 2) >> 22;
float r1x = (BitConverter.ToUInt32(BitConverter.GetBytes(value))) >> 31;
float r1y = 0.00195694715f * r0y;
float r1z = 0.00195694715f * r0z;
float r1w = 0.00195694715f * r0w;
float leng = r1x * r1x + r1y * r1y + r1z * r1z + r1w * r1w;
float r2x = 1.0f - Math.Abs(r1y);
float r2y = 1.0f - Math.Abs(r1z);
float r2z = 1.0f - Math.Abs(r1y);
float r3z = r2x - Math.Abs(r1z);
r2x = r3z < 0.0f ? 1.0f : 0.0f;
r0y = r0y >= 0.0f ? 1.0f : 0.0f;
r0z = r0z >= 0.0f ? 1.0f : 0.0f;
r0y = r0y * 2.0f - 1.0f;
r0z = r0z * 2.0f - 1.0f;
r0y = r2y * r0y;
r0z = r2z * r0z;
float r3x = (r2x == 1.0f) ? r0y : r1y;
float r3y = (r2x == 1.0f) ? r0z : r1z;
r0y = r3x* r3x + r3y * r3y + r3z * r3z;
r0y = 1.0f / (float)Math.Sqrt(r0y);
r2x = r3x * r0y;
r2y = r3y * r0y;
r2z = r3z * r0y;
//float old_r3x = r3x;
//r3x = r3y * r0y - r2z;
//r3y = r3z * r0y - r2x;
//r3z = old_r3x * r0y - r2y;
//r0y = r3x * r2x + r3y * r2y + r3z * r2z;
//r3x = r3x - r0y;
//r3y = r3y - r0y;
//r3z = r3z - r0y;
//r0y = r3x * r3x + r3y * r3y + r3z * r3z;
//r0y = 1.0f / (float)Math.Sqrt(r0y);
//r3x = r3x * r0y;
//r3y = r3y * r0y;
//r3z = r3z * r0y;
//float length = r2x * r2x + r2y * r2y + r2z * r2z;
// 计算result[i * 3]的值
result[i * 3] = r2x;
result[i * 3 + 1] = r2y;
result[i * 3 + 2] = r2z;
//result[i * 3] = 0;
//result[i * 3 + 1] = 0;
//result[i * 3 + 2] = 1;
}
return result;
}
public static float[] DecompressOctahedron(this byte[] inputBytes, VertexFormat format) // 8bits per component
{
var size = GetFormatSize(format);
var len = inputBytes.Length / size;
var result = new float[len*3];
var readFloat = new UInt32[len];
readFloat = BytesToUInt32Array(inputBytes, VertexFormat.UInt32);
// read per 8 bits per component
for (int i = 0; i < len; i++)
{
var x = readFloat[i] & 0xFFFF;
var y = (readFloat[i] >> 16) & 0xFFFF;
var z = (readFloat[i] >> 16) & 0xFF;
var w = (readFloat[i] >> 24) & 0xFF;
/* HLSL Decode Example
* float3 Decode(float2 f)
* {
* f = f * 2.0 - 1.0;
* float3 n = float3(f.x, f.y, 1.0 - abs(f.x) - abs(f.y));
* float t = saturate(-n.z);
* n.xy += n.xy >= 0.0 ? -t : t;
* return normalize(n);
* }
*/
float f_x = x / 65535.0f * 2.0f - 1.0f;
float f_y = y / 65535.0f * 2.0f - 1.0f;
float f_z = 1.0f - Math.Abs(f_x) - Math.Abs(f_y);
if (f_z < 0.0f)
{
float f_t = Math.Max(Math.Min(-f_z, 1.0f), 0.0f);
f_x += f_x >= 0.0f ? -f_t : f_t;
f_y += f_y >= 0.0f ? -f_t : f_t;
}
float length = (float)Math.Sqrt(f_x * f_x + f_y * f_y + f_z * f_z);
if (length > 1e-6f)
{
f_x /= length;
f_y /= length;
f_z /= length;
}
result[i * 3] = f_x;
result[i * 3 + 1] = f_y;
result[i * 3 + 2] = f_z;
}
return result;
}
public static int[] BytesToIntArray(byte[] inputBytes, VertexFormat format)
{
var size = GetFormatSize(format);