mirror of
https://github.com/Scobalula/Tyrant
synced 2024-12-04 01:29:10 +00:00
Resident Evil 3 Support
This commit is contained in:
parent
38dae7b9f2
commit
493e5da2e6
4 changed files with 515 additions and 38 deletions
|
@ -81,6 +81,19 @@ namespace Tyrant.Logic
|
|||
public long TextureNamePointer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resident Evil 7 Material Texture Entry
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
internal struct MaterialTextureEntryRE3
|
||||
{
|
||||
public long TypePointer;
|
||||
public uint TypeHash;
|
||||
public uint UnkHash;
|
||||
public long TextureNamePointer;
|
||||
public long Padding;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resident Evil 7 Material Texture Entry
|
||||
/// </summary>
|
||||
|
@ -153,32 +166,59 @@ namespace Tyrant.Logic
|
|||
/// <summary>
|
||||
/// Converts the given material file
|
||||
/// </summary>
|
||||
public static Dictionary<string, Model.Material> Convert(byte[] buffer)
|
||||
public static Dictionary<string, Model.Material> ConvertRE3(BinaryReader reader)
|
||||
{
|
||||
var results = new Dictionary<string, Model.Material>();
|
||||
|
||||
{
|
||||
reader.BaseStream.Position = 0;
|
||||
var header = reader.ReadStruct<MaterialHeaderRE7>();
|
||||
var materials = reader.ReadArray<MaterialEntryRE2>(header.MaterialCount);
|
||||
|
||||
Console.WriteLine(Marshal.SizeOf<MaterialEntryRE2>());
|
||||
|
||||
foreach (var material in materials)
|
||||
{
|
||||
var result = new Model.Material(reader.ReadUTF16NullTerminatedString(material.NamePointer));
|
||||
|
||||
foreach (var texture in reader.ReadArray<MaterialTextureEntryRE3>(material.TexturesPointer, material.TextureCount))
|
||||
result.Images[reader.ReadUTF16NullTerminatedString(texture.TypePointer)] = reader.ReadUTF16NullTerminatedString(texture.TextureNamePointer).ToLower();
|
||||
//foreach (var setting in reader.ReadArray<MaterialSettingsInfoRE7>(material.SettingsInfoPointer, material.SettingsInfoCount))
|
||||
// result.Settings[reader.ReadUTF16NullTerminatedString(setting.NamePointer)] = reader.ReadArray<float>(material.SettingsBufferPointer + setting.DataOffset, setting.DataCount);
|
||||
|
||||
results[result.Name] = result;
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given material file
|
||||
/// </summary>
|
||||
public static Dictionary<string, Model.Material> Convert(byte[] buffer, string gameName = "13")
|
||||
{
|
||||
using (var stream = new MemoryStream(buffer))
|
||||
{
|
||||
return Convert(stream);
|
||||
return Convert(stream, gameName);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given material file
|
||||
/// </summary>
|
||||
public static Dictionary<string, Model.Material> Convert(Stream stream)
|
||||
public static Dictionary<string, Model.Material> Convert(Stream stream, string gameName = "13")
|
||||
{
|
||||
using (var reader = new BinaryReader(stream))
|
||||
{
|
||||
reader.BaseStream.Position = 28;
|
||||
switch(gameName)
|
||||
{
|
||||
case "6": return ConvertRE7(reader);
|
||||
case "10": return ConvertRE2(reader);
|
||||
case "13": return ConvertRE3(reader);
|
||||
}
|
||||
|
||||
// Check size of buffer
|
||||
if(reader.ReadUInt32() != 0)
|
||||
{
|
||||
return ConvertRE2(reader);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ConvertRE7(reader);
|
||||
}
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -150,6 +150,18 @@ namespace Tyrant.Logic
|
|||
public long KeysPointer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resident Evil 3 Bone Data
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
internal struct BoneDataRE3
|
||||
{
|
||||
public ushort BoneIndex;
|
||||
public DataPrecenseFlags Flags;
|
||||
public uint BoneHash; // MurMur3;
|
||||
public int KeysPointer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resident Evil 7 Key Data (per channel per bone)
|
||||
/// </summary>
|
||||
|
@ -165,6 +177,19 @@ namespace Tyrant.Logic
|
|||
public long UnpackDataPointer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resident Evil 3 Key Data (per channel per bone)
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
internal struct KeyDataRE3
|
||||
{
|
||||
public uint Flags;
|
||||
public int KeyCount;
|
||||
public int FramesPointer;
|
||||
public int DataPointer;
|
||||
public int UnpackDataPointer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Packed 16-Bit Vector 3
|
||||
/// </summary>
|
||||
|
@ -182,9 +207,10 @@ namespace Tyrant.Logic
|
|||
private static DataDecompressorList Vector3Decompressors = new DataDecompressorList()
|
||||
{
|
||||
{ 0x00000, LoadVector3sFull },
|
||||
{ 0x20000, LoadVector3s5Bit },
|
||||
{ 0x30000, LoadVector3s10Bit },
|
||||
{ 0x70000, LoadVector3s21Bit },
|
||||
{ 0x20000, LoadVector3s5BitA },
|
||||
{ 0x30000, LoadVector3s10BitA },
|
||||
{ 0x40000, LoadVector3s10BitA },
|
||||
{ 0x70000, LoadVector3s21BitA },
|
||||
{ 0x31000, LoadVector3sXAxis },
|
||||
{ 0x32000, LoadVector3sYAxis },
|
||||
{ 0x33000, LoadVector3sZAxis },
|
||||
|
@ -193,6 +219,26 @@ namespace Tyrant.Logic
|
|||
{ 0x23000, LoadVector3sZAxis16Bit },
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Vector 3 Decompressors, used by Translations and Scales for RE3
|
||||
/// </summary>
|
||||
private static DataDecompressorList Vector3DecompressorsRE3 = new DataDecompressorList()
|
||||
{
|
||||
{ 0x00000, LoadVector3sFull },
|
||||
{ 0x20000, LoadVector3s5BitB },
|
||||
{ 0x30000, LoadVector3s5BitB },
|
||||
{ 0x40000, LoadVector3s10BitB },
|
||||
{ 0x80000, LoadVector3s21BitB },
|
||||
{ 0x21000, LoadVector3sXAxis16Bit },
|
||||
{ 0x22000, LoadVector3sYAxis16Bit },
|
||||
{ 0x23000, LoadVector3sZAxis16Bit },
|
||||
{ 0x24000, LoadVector3sXYZAxis16Bit },
|
||||
{ 0x41000, LoadVector3sXAxis },
|
||||
{ 0x42000, LoadVector3sYAxis },
|
||||
{ 0x43000, LoadVector3sZAxis },
|
||||
{ 0x44000, LoadVector3sXYZAxis },
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Quaternion Decompressors, used by Rotations
|
||||
/// </summary>
|
||||
|
@ -200,15 +246,46 @@ namespace Tyrant.Logic
|
|||
{
|
||||
{ 0x00000, LoadQuaternionsFull },
|
||||
{ 0xB0000, LoadQuaternions3Component },
|
||||
{ 0xC0000, LoadQuaternions3Component },
|
||||
{ 0x30000, LoadQuaternions10Bit },
|
||||
{ 0x40000, LoadQuaternions10Bit },
|
||||
{ 0x50000, LoadQuaternions16Bit },
|
||||
{ 0x70000, LoadQuaternions21Bit },
|
||||
{ 0x21000, LoadQuaternionsXAxis16Bit },
|
||||
{ 0x22000, LoadQuaternionsYAxis16Bit },
|
||||
{ 0x23000, LoadQuaternionsZAxis16Bit },
|
||||
{ 0x31000, LoadQuaternionsXAxis },
|
||||
{ 0x41000, LoadQuaternionsXAxis },
|
||||
{ 0x32000, LoadQuaternionsYAxis },
|
||||
{ 0x42000, LoadQuaternionsYAxis },
|
||||
{ 0x33000, LoadQuaternionsZAxis },
|
||||
{ 0x43000, LoadQuaternionsZAxis },
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Quaternion Decompressors, used by Rotations
|
||||
/// </summary>
|
||||
private static DataDecompressorList QuaternionDecompressorsRE3 = new DataDecompressorList()
|
||||
{
|
||||
{ 0x00000, LoadQuaternionsFull },
|
||||
{ 0xB0000, LoadQuaternions3Component },
|
||||
{ 0xC0000, LoadQuaternions3Component },
|
||||
{ 0x20000, LoadQuaternions5Bit },
|
||||
{ 0x30000, LoadQuaternions8Bit },
|
||||
{ 0x40000, LoadQuaternions10Bit },
|
||||
{ 0x50000, LoadQuaternions13Bit },
|
||||
{ 0x60000, LoadQuaternions16Bit },
|
||||
{ 0x70000, LoadQuaternions18Bit },
|
||||
{ 0x80000, LoadQuaternions21Bit },
|
||||
{ 0x21000, LoadQuaternionsXAxis16Bit },
|
||||
{ 0x22000, LoadQuaternionsYAxis16Bit },
|
||||
{ 0x23000, LoadQuaternionsZAxis16Bit },
|
||||
{ 0x31000, LoadQuaternionsXAxis },
|
||||
{ 0x41000, LoadQuaternionsXAxis },
|
||||
{ 0x32000, LoadQuaternionsYAxis },
|
||||
{ 0x42000, LoadQuaternionsYAxis },
|
||||
{ 0x33000, LoadQuaternionsZAxis },
|
||||
{ 0x43000, LoadQuaternionsZAxis },
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
|
@ -231,7 +308,7 @@ namespace Tyrant.Logic
|
|||
/// <summary>
|
||||
/// Loads 5Bit Vector3s
|
||||
/// </summary>
|
||||
private static void LoadVector3s5Bit(BinaryReader reader, Animation.Bone bone, int[] frames, float[] unpackData, long dataPointer)
|
||||
private static void LoadVector3s5BitA(BinaryReader reader, Animation.Bone bone, int[] frames, float[] unpackData, long dataPointer)
|
||||
{
|
||||
var data = reader.ReadArray<ushort>(dataPointer, frames.Length);
|
||||
|
||||
|
@ -245,18 +322,52 @@ namespace Tyrant.Logic
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads 5Bit Vector3s
|
||||
/// </summary>
|
||||
private static void LoadVector3s5BitB(BinaryReader reader, Animation.Bone bone, int[] frames, float[] unpackData, long dataPointer)
|
||||
{
|
||||
var data = reader.ReadArray<ushort>(dataPointer, frames.Length);
|
||||
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
{
|
||||
var x = (unpackData[0] * ((data[i] >> 00) & 0x1F) / 31.0f) + unpackData[3];
|
||||
var y = (unpackData[1] * ((data[i] >> 05) & 0x1F) / 31.0f) + unpackData[4];
|
||||
var z = (unpackData[2] * ((data[i] >> 10) & 0x1F) / 31.0f) + unpackData[5];
|
||||
|
||||
bone.Translations[frames[i]] = new Vector3(x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads 10Bit Vector3s
|
||||
/// </summary>
|
||||
private static void LoadVector3s10Bit(BinaryReader reader, Animation.Bone bone, int[] frames, float[] unpackData, long dataPointer)
|
||||
private static void LoadVector3s10BitA(BinaryReader reader, Animation.Bone bone, int[] frames, float[] unpackData, long dataPointer)
|
||||
{
|
||||
var data = reader.ReadArray<uint>(dataPointer, frames.Length);
|
||||
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
{
|
||||
var x = (unpackData[0] * ((data[i] >> 00) & 0x3FF) / 1023.0f) + unpackData[4];
|
||||
var y = (unpackData[1] * ((data[i] >> 10) & 0x3FF) / 1023.0f) + unpackData[5];
|
||||
var z = (unpackData[2] * ((data[i] >> 20) & 0x3FF) / 1023.0f) + unpackData[6];
|
||||
var x = unpackData[0] * (((data[i] >> 00) & 0x3FF) * (1.0f / 0x3FF)) + unpackData[4];
|
||||
var y = unpackData[1] * (((data[i] >> 10) & 0x3FF) * (1.0f / 0x3FF)) + unpackData[5];
|
||||
var z = unpackData[2] * (((data[i] >> 20) & 0x3FF) * (1.0f / 0x3FF)) + unpackData[6];
|
||||
|
||||
bone.Translations[frames[i]] = new Vector3(x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads 10Bit Vector3s
|
||||
/// </summary>
|
||||
private static void LoadVector3s10BitB(BinaryReader reader, Animation.Bone bone, int[] frames, float[] unpackData, long dataPointer)
|
||||
{
|
||||
var data = reader.ReadArray<uint>(dataPointer, frames.Length);
|
||||
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
{
|
||||
var x = unpackData[0] * (((data[i] >> 00) & 0x3FF) * (1.0f / 0x3FF)) + unpackData[3];
|
||||
var y = unpackData[1] * (((data[i] >> 10) & 0x3FF) * (1.0f / 0x3FF)) + unpackData[4];
|
||||
var z = unpackData[2] * (((data[i] >> 20) & 0x3FF) * (1.0f / 0x3FF)) + unpackData[5];
|
||||
|
||||
bone.Translations[frames[i]] = new Vector3(x, y, z);
|
||||
}
|
||||
|
@ -265,7 +376,7 @@ namespace Tyrant.Logic
|
|||
/// <summary>
|
||||
/// Loads 21Bit Vector3s
|
||||
/// </summary>
|
||||
private static void LoadVector3s21Bit(BinaryReader reader, Animation.Bone bone, int[] frames, float[] unpackData, long dataPointer)
|
||||
private static void LoadVector3s21BitA(BinaryReader reader, Animation.Bone bone, int[] frames, float[] unpackData, long dataPointer)
|
||||
{
|
||||
var data = reader.ReadArray<ulong>(dataPointer, frames.Length);
|
||||
|
||||
|
@ -279,6 +390,23 @@ namespace Tyrant.Logic
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads 21Bit Vector3s
|
||||
/// </summary>
|
||||
private static void LoadVector3s21BitB(BinaryReader reader, Animation.Bone bone, int[] frames, float[] unpackData, long dataPointer)
|
||||
{
|
||||
var data = reader.ReadArray<ulong>(dataPointer, frames.Length);
|
||||
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
{
|
||||
var x = (unpackData[0] * ((data[i] >> 00) & 0x1FFFFF) / 2097151.0f) + unpackData[3];
|
||||
var y = (unpackData[1] * ((data[i] >> 21) & 0x1FFFFF) / 2097151.0f) + unpackData[4];
|
||||
var z = (unpackData[2] * ((data[i] >> 42) & 0x1FFFFF) / 2097151.0f) + unpackData[5];
|
||||
|
||||
bone.Translations[frames[i]] = new Vector3(x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads Vector3s with 1 Component on X Axis
|
||||
/// </summary>
|
||||
|
@ -330,6 +458,23 @@ namespace Tyrant.Logic
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads Vector3s with 1 Component on Z Axis
|
||||
/// </summary>
|
||||
private static void LoadVector3sXYZAxis(BinaryReader reader, Animation.Bone bone, int[] frames, float[] unpackData, long dataPointer)
|
||||
{
|
||||
var data = reader.ReadArray<float>(dataPointer, frames.Length);
|
||||
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
{
|
||||
var x = data[i];
|
||||
var y = data[i];
|
||||
var z = data[i];
|
||||
|
||||
bone.Translations[frames[i]] = new Vector3(x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads Vector3s with 1 Component on X Axis
|
||||
/// </summary>
|
||||
|
@ -381,6 +526,25 @@ namespace Tyrant.Logic
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads Vector3s with 1 Component on Y Axis
|
||||
/// </summary>
|
||||
private static void LoadVector3sXYZAxis16Bit(BinaryReader reader, Animation.Bone bone, int[] frames, float[] unpackData, long dataPointer)
|
||||
{
|
||||
var data = reader.ReadArray<ushort>(dataPointer, frames.Length);
|
||||
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
{
|
||||
var val = unpackData[0] * (data[i] / 65535.0f) + unpackData[3];
|
||||
|
||||
var x = val;
|
||||
var y = val;
|
||||
var z = val;
|
||||
|
||||
bone.Translations[frames[i]] = new Vector3(x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads Quaternions with all components
|
||||
/// </summary>
|
||||
|
@ -412,13 +576,64 @@ namespace Tyrant.Logic
|
|||
var x = data[i].X;
|
||||
var y = data[i].Y;
|
||||
var z = data[i].Z;
|
||||
var w = (float)Math.Sqrt(1 - x * x - y * y - z * z);
|
||||
var w = 1.0f - (x * x + y * y + z * z);
|
||||
|
||||
if (w > 0.0f)
|
||||
w = (float)Math.Sqrt(w);
|
||||
else
|
||||
w = 0.0f;
|
||||
|
||||
bone.Rotations[frames[i]] = new Quaternion(x, y, z, w);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads 10Bit Quaternions
|
||||
/// </summary>
|
||||
private static void LoadQuaternions5Bit(BinaryReader reader, Animation.Bone bone, int[] frames, float[] unpackData, long dataPointer)
|
||||
{
|
||||
var data = reader.ReadArray<ushort>(dataPointer, frames.Length);
|
||||
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
{
|
||||
var x = (unpackData[0] * ((data[i] >> 00) & 0x1F) * (1.0f / 0x1F)) + unpackData[4];
|
||||
var y = (unpackData[1] * ((data[i] >> 05) & 0x1F) * (1.0f / 0x1F)) + unpackData[5];
|
||||
var z = (unpackData[2] * ((data[i] >> 10) & 0x1F) * (1.0f / 0x1F)) + unpackData[6];
|
||||
var w = 1.0f - (x * x + y * y + z * z);
|
||||
|
||||
if (w > 0.0f)
|
||||
w = (float)Math.Sqrt(w);
|
||||
else
|
||||
w = 0.0f;
|
||||
|
||||
bone.Rotations[frames[i]] = new Quaternion(x, y, z, w);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads 10Bit Quaternions
|
||||
/// </summary>
|
||||
private static void LoadQuaternions8Bit(BinaryReader reader, Animation.Bone bone, int[] frames, float[] unpackData, long dataPointer)
|
||||
{
|
||||
reader.BaseStream.Position = dataPointer;
|
||||
|
||||
for (int i = 0; i < frames.Length; i++)
|
||||
{
|
||||
var x = (unpackData[0] * (reader.ReadByte() * 0.000015259022f)) + unpackData[4];
|
||||
var y = (unpackData[1] * (reader.ReadByte() * 0.000015259022f)) + unpackData[5];
|
||||
var z = (unpackData[2] * (reader.ReadByte() * 0.000015259022f)) + unpackData[6];
|
||||
var w = 1.0f - (x * x + y * y + z * z);
|
||||
|
||||
if (w > 0.0f)
|
||||
w = (float)Math.Sqrt(w);
|
||||
else
|
||||
w = 0.0f;
|
||||
|
||||
bone.Rotations[frames[i]] = new Quaternion(x, y, z, w);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads 10Bit Quaternions
|
||||
/// </summary>
|
||||
|
@ -431,7 +646,12 @@ namespace Tyrant.Logic
|
|||
var x = (unpackData[0] * ((data[i] >> 00) & 0x3FF) / 1023.0f) + unpackData[4];
|
||||
var y = (unpackData[1] * ((data[i] >> 10) & 0x3FF) / 1023.0f) + unpackData[5];
|
||||
var z = (unpackData[2] * ((data[i] >> 20) & 0x3FF) / 1023.0f) + unpackData[6];
|
||||
var w = (float)Math.Sqrt(1 - x * x - y * y - z * z);
|
||||
var w = 1.0f - (x * x + y * y + z * z);
|
||||
|
||||
if (w > 0.0f)
|
||||
w = (float)Math.Sqrt(w);
|
||||
else
|
||||
w = 0.0f;
|
||||
|
||||
bone.Rotations[frames[i]] = new Quaternion(x, y, z, w);
|
||||
}
|
||||
|
@ -449,7 +669,61 @@ namespace Tyrant.Logic
|
|||
var x = (unpackData[0] * (data[i].X / 65535.0f)) + unpackData[4];
|
||||
var y = (unpackData[1] * (data[i].Y / 65535.0f)) + unpackData[5];
|
||||
var z = (unpackData[2] * (data[i].Z / 65535.0f)) + unpackData[6];
|
||||
var w = (float)Math.Sqrt(1 - x * x - y * y - z * z);
|
||||
var w = (float)Math.Sqrt(Math.Abs(1 - x * x - y * y - z * z));
|
||||
|
||||
bone.Rotations[frames[i]] = new Quaternion(x, y, z, w);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads 10Bit Quaternions
|
||||
/// </summary>
|
||||
private static void LoadQuaternions13Bit(BinaryReader reader, Animation.Bone bone, int[] frames, float[] unpackData, long dataPointer)
|
||||
{
|
||||
reader.BaseStream.Position = dataPointer;
|
||||
|
||||
for (int i = 0; i < frames.Length; i++)
|
||||
{
|
||||
var data = reader.ReadBytes(5);
|
||||
ulong val = 0;
|
||||
for(int j = 0; j < 5; j++)
|
||||
val = data[j] | (val << 8);
|
||||
|
||||
var x = (unpackData[0] * ((val >> 00) & 0x1FFF) * 0.00012208521f) + unpackData[4];
|
||||
var y = (unpackData[1] * ((val >> 13) & 0x1FFF) * 0.00012208521f) + unpackData[5];
|
||||
var z = (unpackData[2] * ((val >> 26) & 0x1FFF) * 0.00012208521f) + unpackData[6];
|
||||
var w = 1.0f - (x * x + y * y + z * z);
|
||||
|
||||
if (w > 0.0f)
|
||||
w = (float)Math.Sqrt(w);
|
||||
else
|
||||
w = 0.0f;
|
||||
|
||||
bone.Rotations[frames[i]] = new Quaternion(x, y, z, w);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads 18Bit Quaternions
|
||||
/// </summary>
|
||||
private static void LoadQuaternions18Bit(BinaryReader reader, Animation.Bone bone, int[] frames, float[] unpackData, long dataPointer)
|
||||
{
|
||||
for (int i = 0; i < frames.Length; i++)
|
||||
{
|
||||
var data = reader.ReadBytes(7);
|
||||
ulong val = 0;
|
||||
for (int j = 0; j < 7; j++)
|
||||
val = data[j] | (val << 8);
|
||||
|
||||
var x = (unpackData[0] * ((val >> 00) & 0x1FFF) * 0.00012208521f) + unpackData[4];
|
||||
var y = (unpackData[1] * ((val >> 13) & 0x1FFF) * 0.00012208521f) + unpackData[5];
|
||||
var z = (unpackData[2] * ((val >> 26) & 0x1FFF) * 0.00012208521f) + unpackData[6];
|
||||
var w = 1.0f - (x * x + y * y + z * z);
|
||||
|
||||
if (w > 0.0f)
|
||||
w = (float)Math.Sqrt(w);
|
||||
else
|
||||
w = 0.0f;
|
||||
|
||||
bone.Rotations[frames[i]] = new Quaternion(x, y, z, w);
|
||||
}
|
||||
|
@ -467,7 +741,12 @@ namespace Tyrant.Logic
|
|||
var x = (unpackData[0] * ((data[i] >> 00) & 0x1FFFFF) / 2097151.0f) + unpackData[4];
|
||||
var y = (unpackData[1] * ((data[i] >> 21) & 0x1FFFFF) / 2097151.0f) + unpackData[5];
|
||||
var z = (unpackData[2] * ((data[i] >> 42) & 0x1FFFFF) / 2097151.0f) + unpackData[6];
|
||||
var w = (float)Math.Sqrt(1 - x * x - y * y - z * z);
|
||||
var w = 1.0f - (x * x + y * y + z * z);
|
||||
|
||||
if (w > 0.0f)
|
||||
w = (float)Math.Sqrt(w);
|
||||
else
|
||||
w = 0.0f;
|
||||
|
||||
bone.Rotations[frames[i]] = new Quaternion(x, y, z, w);
|
||||
}
|
||||
|
@ -485,7 +764,12 @@ namespace Tyrant.Logic
|
|||
var x = data[i];
|
||||
var y = 0.0f;
|
||||
var z = 0.0f;
|
||||
var w = (float)Math.Sqrt(1 - x * x - y * y - z * z);
|
||||
var w = 1.0f - (x * x + y * y + z * z);
|
||||
|
||||
if (w > 0.0f)
|
||||
w = (float)Math.Sqrt(w);
|
||||
else
|
||||
w = 0.0f;
|
||||
|
||||
bone.Rotations[frames[i]] = new Quaternion(x, y, z, w);
|
||||
}
|
||||
|
@ -503,7 +787,12 @@ namespace Tyrant.Logic
|
|||
var x = 0.0f;
|
||||
var y = data[i];
|
||||
var z = 0.0f;
|
||||
var w = (float)Math.Sqrt(1 - x * x - y * y - z * z);
|
||||
var w = 1.0f - (x * x + y * y + z * z);
|
||||
|
||||
if (w > 0.0f)
|
||||
w = (float)Math.Sqrt(w);
|
||||
else
|
||||
w = 0.0f;
|
||||
|
||||
bone.Rotations[frames[i]] = new Quaternion(x, y, z, w);
|
||||
}
|
||||
|
@ -521,7 +810,12 @@ namespace Tyrant.Logic
|
|||
var x = 0.0f;
|
||||
var y = 0.0f;
|
||||
var z = data[i];
|
||||
var w = (float)Math.Sqrt(1 - x * x - y * y - z * z);
|
||||
var w = 1.0f - (x * x + y * y + z * z);
|
||||
|
||||
if (w > 0.0f)
|
||||
w = (float)Math.Sqrt(w);
|
||||
else
|
||||
w = 0.0f;
|
||||
|
||||
bone.Rotations[frames[i]] = new Quaternion(x, y, z, w);
|
||||
}
|
||||
|
@ -540,7 +834,12 @@ namespace Tyrant.Logic
|
|||
var x = unpackData[0] * (data[i] / 65535.0f) + unpackData[1];
|
||||
var y = 0.0f;
|
||||
var z = 0.0f;
|
||||
var w = (float)Math.Sqrt(1 - x * x - y * y - z * z);
|
||||
var w = 1.0f - (x * x + y * y + z * z);
|
||||
|
||||
if (w > 0.0f)
|
||||
w = (float)Math.Sqrt(w);
|
||||
else
|
||||
w = 0.0f;
|
||||
|
||||
bone.Rotations[frames[i]] = new Quaternion(x, y, z, w);
|
||||
}
|
||||
|
@ -558,7 +857,12 @@ namespace Tyrant.Logic
|
|||
var x = 0.0f;
|
||||
var y = unpackData[0] * (data[i] / 65535.0f) + unpackData[1];
|
||||
var z = 0.0f;
|
||||
var w = (float)Math.Sqrt(1 - x * x - y * y - z * z);
|
||||
var w = 1.0f - (x * x + y * y + z * z);
|
||||
|
||||
if (w > 0.0f)
|
||||
w = (float)Math.Sqrt(w);
|
||||
else
|
||||
w = 0.0f;
|
||||
|
||||
bone.Rotations[frames[i]] = new Quaternion(x, y, z, w);
|
||||
}
|
||||
|
@ -576,7 +880,12 @@ namespace Tyrant.Logic
|
|||
var x = 0.0f;
|
||||
var y = 0.0f;
|
||||
var z = unpackData[0] * (data[i] / 65535.0f) + unpackData[1];
|
||||
var w = (float)Math.Sqrt(1 - x * x - y * y - z * z);
|
||||
var w = 1.0f - (x * x + y * y + z * z);
|
||||
|
||||
if (w > 0.0f)
|
||||
w = (float)Math.Sqrt(w);
|
||||
else
|
||||
w = 0.0f;
|
||||
|
||||
bone.Rotations[frames[i]] = new Quaternion(x, y, z, w);
|
||||
}
|
||||
|
@ -587,6 +896,15 @@ namespace Tyrant.Logic
|
|||
/// </summary>
|
||||
private static int[] LoadFrames(BinaryReader reader, long framesPointer, int frameCount, uint frameDataType)
|
||||
{
|
||||
|
||||
if(frameCount < 2)
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
0
|
||||
};
|
||||
}
|
||||
|
||||
var results = new int[frameCount];
|
||||
|
||||
reader.BaseStream.Position = framesPointer;
|
||||
|
@ -698,6 +1016,7 @@ namespace Tyrant.Logic
|
|||
|
||||
var keyFrames = LoadFrames(reader, keyData.FramesPointer, keyData.KeyCount, keyFrameDataType);
|
||||
|
||||
|
||||
if (QuaternionDecompressors.TryGetValue(compression, out var decompressionMethod))
|
||||
decompressionMethod(reader, bones[bone.BoneHash], keyFrames, unpackData, keyData.DataPointer);
|
||||
else
|
||||
|
@ -808,10 +1127,116 @@ namespace Tyrant.Logic
|
|||
return new Tuple<string, Animation>(reader.ReadUTF16NullTerminatedString(header.NamePointer), animation);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts an RE3 Motion File to a SEAnim
|
||||
/// </summary>
|
||||
private static Tuple<string, Animation> ConvertRE3(BinaryReader reader, Dictionary<uint, Animation.Bone> bones)
|
||||
{
|
||||
var animation = new Animation(Animation.DataType.Absolute);
|
||||
|
||||
var header = reader.ReadStruct<MotionHeaderRE2>();
|
||||
|
||||
var name = reader.ReadUTF16NullTerminatedString(header.NamePointer);
|
||||
|
||||
var localBones = new Dictionary<uint, Animation.Bone>();
|
||||
|
||||
{
|
||||
if(bones.Count <= 0)
|
||||
{
|
||||
reader.BaseStream.Position = header.BoneBaseDataPointer;
|
||||
|
||||
var baseDataOffset = reader.ReadInt64();
|
||||
var baseDataCount = reader.ReadInt32();
|
||||
|
||||
var boneBaseData = reader.ReadArray<BoneBaseDataRE7>(baseDataOffset, baseDataCount);
|
||||
|
||||
foreach (var boneBase in boneBaseData)
|
||||
{
|
||||
var bone = new Animation.Bone(reader.ReadUTF16NullTerminatedString(boneBase.NamePointer));
|
||||
|
||||
bone.Translations[0] = boneBase.Translation.ToVector3();
|
||||
bone.Rotations[0] = boneBase.Rotation;
|
||||
bones[boneBase.Hash] = bone;
|
||||
}
|
||||
}
|
||||
|
||||
// Add base data
|
||||
foreach(var bone in bones)
|
||||
{
|
||||
var nbone = new Animation.Bone(bone.Value.Name);
|
||||
|
||||
nbone.Translations[0] = bone.Value.Translations[0];
|
||||
nbone.Rotations[0] = bone.Value.Rotations[0];
|
||||
|
||||
localBones[bone.Key] = nbone;
|
||||
}
|
||||
|
||||
if (header.BoneDataPointer > 0)
|
||||
{
|
||||
var boneData = reader.ReadArray<BoneDataRE3>(header.BoneDataPointer, header.BoneDataCount);
|
||||
|
||||
foreach (var bone in boneData)
|
||||
{
|
||||
var keyDataOffset = bone.KeysPointer;
|
||||
|
||||
if (bone.Flags.HasFlag(DataPrecenseFlags.Translations))
|
||||
{
|
||||
var keyData = reader.ReadStruct<KeyDataRE3>(keyDataOffset);
|
||||
|
||||
float[] unpackData = null;
|
||||
uint keyFrameDataType = keyData.Flags & 0xF00000;
|
||||
uint compression = keyData.Flags & 0xFF000;
|
||||
uint unkFlag = keyData.Flags & 0xFFF;
|
||||
|
||||
if (keyData.UnpackDataPointer > 0)
|
||||
unpackData = reader.ReadArray<float>(keyData.UnpackDataPointer, 16);
|
||||
|
||||
var keyFrames = LoadFrames(reader, keyData.FramesPointer, keyData.KeyCount, keyFrameDataType);
|
||||
|
||||
if (Vector3DecompressorsRE3.TryGetValue(compression, out var decompressionMethod))
|
||||
decompressionMethod(reader, localBones[bone.BoneHash], keyFrames, unpackData, keyData.DataPointer);
|
||||
else
|
||||
throw new Exception(string.Format("Unknown Vector3 compression type: 0x{0:X}", compression));
|
||||
|
||||
keyDataOffset += Marshal.SizeOf<KeyDataRE3>();
|
||||
}
|
||||
|
||||
if (bone.Flags.HasFlag(DataPrecenseFlags.Rotations))
|
||||
{
|
||||
var keyData = reader.ReadStruct<KeyDataRE3>(keyDataOffset);
|
||||
|
||||
float[] unpackData = null;
|
||||
uint keyFrameDataType = keyData.Flags & 0xF00000;
|
||||
uint compression = keyData.Flags & 0xFF000;
|
||||
uint unkFlag = keyData.Flags & 0xFFF;
|
||||
|
||||
if (keyData.UnpackDataPointer > 0)
|
||||
unpackData = reader.ReadArray<float>(keyData.UnpackDataPointer, 16);
|
||||
|
||||
var keyFrames = LoadFrames(reader, keyData.FramesPointer, keyData.KeyCount, keyFrameDataType);
|
||||
|
||||
|
||||
if (QuaternionDecompressorsRE3.TryGetValue(compression, out var decompressionMethod))
|
||||
decompressionMethod(reader, localBones[bone.BoneHash], keyFrames, unpackData, keyData.DataPointer);
|
||||
else
|
||||
throw new Exception(string.Format("Unknown Quaternion compression type: 0x{0:X}", compression));
|
||||
|
||||
keyDataOffset += Marshal.SizeOf<KeyDataRE3>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var bone in localBones)
|
||||
animation.Bones.Add(bone.Value);
|
||||
}
|
||||
|
||||
return new Tuple<string, Animation>(reader.ReadUTF16NullTerminatedString(header.NamePointer), animation);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given Motion
|
||||
/// </summary>
|
||||
public static Tuple<string, Animation> Convert(Stream stream)
|
||||
public static Tuple<string, Animation> Convert(Stream stream, Dictionary<uint, Animation.Bone> bones)
|
||||
{
|
||||
using (var reader = new BinaryReader(stream))
|
||||
{
|
||||
|
@ -822,6 +1247,7 @@ namespace Tyrant.Logic
|
|||
{
|
||||
case 0x2B: return ConvertRE7(reader);
|
||||
case 0x41: return ConvertRE2(reader);
|
||||
case 0x4E: return ConvertRE3(reader, bones);
|
||||
default: throw new Exception("Invalid Motion Version");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ namespace Tyrant.Logic
|
|||
|
||||
using (var stream = new MemoryStream(reader.ReadBytes((int)(endOffset - offsets[i]))))
|
||||
{
|
||||
results.Add(Motion.Convert(stream));
|
||||
results.Add(Motion.Convert(stream, null));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,6 +103,7 @@ namespace Tyrant.Logic
|
|||
{
|
||||
var header = reader.ReadStruct<MotionListHeaderRE2>();
|
||||
var results = new List<Tuple<string, Animation>>();
|
||||
var bones = new Dictionary<uint, Animation.Bone>();
|
||||
|
||||
// Sort by offsets since they don't store sizes, we also need to remove dupes as some entries point to another
|
||||
var offsets = reader.ReadArray<long>(header.AssetsPointer, header.AssetCount).Distinct().OrderBy(x => x).ToArray();
|
||||
|
@ -122,9 +123,11 @@ namespace Tyrant.Logic
|
|||
|
||||
reader.BaseStream.Position = offsets[i];
|
||||
|
||||
using (var stream = new MemoryStream(reader.ReadBytes((int)(endOffset - offsets[i]))))
|
||||
var buffer = reader.ReadBytes((int)(endOffset - offsets[i]));
|
||||
|
||||
using (var stream = new MemoryStream(buffer))
|
||||
{
|
||||
results.Add(Motion.Convert(stream));
|
||||
results.Add(Motion.Convert(stream, bones));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -154,6 +157,7 @@ namespace Tyrant.Logic
|
|||
{
|
||||
case 0x3C: return ConvertRE7(reader);
|
||||
case 0x55: return ConvertRE2(reader);
|
||||
case 0x63: return ConvertRE2(reader);
|
||||
default: throw new Exception("Invalid Motion List Version");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,6 +70,8 @@ namespace Tyrant
|
|||
{
|
||||
"natives/x64/streaming/",
|
||||
"natives/x64/",
|
||||
"natives/stm/streaming/",
|
||||
"natives/stm/",
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
|
@ -81,9 +83,12 @@ namespace Tyrant
|
|||
"_mat.mdf2.10",
|
||||
".mdf2.6",
|
||||
"_mat.mdf2.6",
|
||||
".mdf2.13",
|
||||
"_mat.mdf2.13",
|
||||
".10",
|
||||
".11",
|
||||
".8",
|
||||
".190820018"
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
|
@ -278,7 +283,6 @@ namespace Tyrant
|
|||
var folder = Path.Combine(path, motions.Item1);
|
||||
|
||||
var result = path;
|
||||
|
||||
Directory.CreateDirectory(folder);
|
||||
|
||||
foreach(var motion in motions.Item2)
|
||||
|
@ -390,7 +394,7 @@ namespace Tyrant
|
|||
{
|
||||
try
|
||||
{
|
||||
materials = MaterialDefs.Convert(ActivePackage.LoadEntry(result));
|
||||
materials = MaterialDefs.Convert(ActivePackage.LoadEntry(result), prefix.Split('.').Last());
|
||||
break;
|
||||
}
|
||||
catch
|
||||
|
@ -487,6 +491,9 @@ namespace Tyrant
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
#if DEBUG
|
||||
File.WriteAllBytes("BAD_BUFFER.dat", ActivePackage.LoadEntry(asset.PackageEntry));
|
||||
#endif
|
||||
Log(string.Format("Error has occured while exporting {0}: {1}", Path.GetFileNameWithoutExtension(asset.Name), e), "ERROR");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue