diff --git a/src/Tyrant.Logic/AssetHandlers/MaterialDefs.cs b/src/Tyrant.Logic/AssetHandlers/MaterialDefs.cs
index bf8cfd7..5b2a881 100644
--- a/src/Tyrant.Logic/AssetHandlers/MaterialDefs.cs
+++ b/src/Tyrant.Logic/AssetHandlers/MaterialDefs.cs
@@ -81,6 +81,19 @@ namespace Tyrant.Logic
public long TextureNamePointer;
}
+ ///
+ /// Resident Evil 7 Material Texture Entry
+ ///
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ internal struct MaterialTextureEntryRE3
+ {
+ public long TypePointer;
+ public uint TypeHash;
+ public uint UnkHash;
+ public long TextureNamePointer;
+ public long Padding;
+ }
+
///
/// Resident Evil 7 Material Texture Entry
///
@@ -153,32 +166,59 @@ namespace Tyrant.Logic
///
/// Converts the given material file
///
- public static Dictionary Convert(byte[] buffer)
+ public static Dictionary ConvertRE3(BinaryReader reader)
+ {
+ var results = new Dictionary();
+
+ {
+ reader.BaseStream.Position = 0;
+ var header = reader.ReadStruct();
+ var materials = reader.ReadArray(header.MaterialCount);
+
+ Console.WriteLine(Marshal.SizeOf());
+
+ foreach (var material in materials)
+ {
+ var result = new Model.Material(reader.ReadUTF16NullTerminatedString(material.NamePointer));
+
+ foreach (var texture in reader.ReadArray(material.TexturesPointer, material.TextureCount))
+ result.Images[reader.ReadUTF16NullTerminatedString(texture.TypePointer)] = reader.ReadUTF16NullTerminatedString(texture.TextureNamePointer).ToLower();
+ //foreach (var setting in reader.ReadArray(material.SettingsInfoPointer, material.SettingsInfoCount))
+ // result.Settings[reader.ReadUTF16NullTerminatedString(setting.NamePointer)] = reader.ReadArray(material.SettingsBufferPointer + setting.DataOffset, setting.DataCount);
+
+ results[result.Name] = result;
+ }
+ }
+
+ return results;
+ }
+
+ ///
+ /// Converts the given material file
+ ///
+ public static Dictionary Convert(byte[] buffer, string gameName = "13")
{
using (var stream = new MemoryStream(buffer))
{
- return Convert(stream);
+ return Convert(stream, gameName);
}
}
///
/// Converts the given material file
///
- public static Dictionary Convert(Stream stream)
+ public static Dictionary 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();
}
}
}
diff --git a/src/Tyrant.Logic/AssetHandlers/Motion.cs b/src/Tyrant.Logic/AssetHandlers/Motion.cs
index f3e4a27..c35c9b8 100644
--- a/src/Tyrant.Logic/AssetHandlers/Motion.cs
+++ b/src/Tyrant.Logic/AssetHandlers/Motion.cs
@@ -150,6 +150,18 @@ namespace Tyrant.Logic
public long KeysPointer;
}
+ ///
+ /// Resident Evil 3 Bone Data
+ ///
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ internal struct BoneDataRE3
+ {
+ public ushort BoneIndex;
+ public DataPrecenseFlags Flags;
+ public uint BoneHash; // MurMur3;
+ public int KeysPointer;
+ }
+
///
/// Resident Evil 7 Key Data (per channel per bone)
///
@@ -165,6 +177,19 @@ namespace Tyrant.Logic
public long UnpackDataPointer;
}
+ ///
+ /// Resident Evil 3 Key Data (per channel per bone)
+ ///
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ internal struct KeyDataRE3
+ {
+ public uint Flags;
+ public int KeyCount;
+ public int FramesPointer;
+ public int DataPointer;
+ public int UnpackDataPointer;
+ }
+
///
/// Packed 16-Bit Vector 3
///
@@ -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 },
};
+ ///
+ /// Vector 3 Decompressors, used by Translations and Scales for RE3
+ ///
+ 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 },
+ };
+
///
/// Quaternion Decompressors, used by Rotations
///
@@ -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 },
+ };
+
+ ///
+ /// Quaternion Decompressors, used by Rotations
+ ///
+ 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 },
};
///
@@ -231,7 +308,7 @@ namespace Tyrant.Logic
///
/// Loads 5Bit Vector3s
///
- 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(dataPointer, frames.Length);
@@ -245,18 +322,52 @@ namespace Tyrant.Logic
}
}
+ ///
+ /// Loads 5Bit Vector3s
+ ///
+ private static void LoadVector3s5BitB(BinaryReader reader, Animation.Bone bone, int[] frames, float[] unpackData, long dataPointer)
+ {
+ var data = reader.ReadArray(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);
+ }
+ }
+
///
/// Loads 10Bit Vector3s
///
- 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(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);
+ }
+ }
+
+ ///
+ /// Loads 10Bit Vector3s
+ ///
+ private static void LoadVector3s10BitB(BinaryReader reader, Animation.Bone bone, int[] frames, float[] unpackData, long dataPointer)
+ {
+ var data = reader.ReadArray(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
///
/// Loads 21Bit Vector3s
///
- 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(dataPointer, frames.Length);
@@ -279,6 +390,23 @@ namespace Tyrant.Logic
}
}
+ ///
+ /// Loads 21Bit Vector3s
+ ///
+ private static void LoadVector3s21BitB(BinaryReader reader, Animation.Bone bone, int[] frames, float[] unpackData, long dataPointer)
+ {
+ var data = reader.ReadArray(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);
+ }
+ }
+
///
/// Loads Vector3s with 1 Component on X Axis
///
@@ -330,6 +458,23 @@ namespace Tyrant.Logic
}
}
+ ///
+ /// Loads Vector3s with 1 Component on Z Axis
+ ///
+ private static void LoadVector3sXYZAxis(BinaryReader reader, Animation.Bone bone, int[] frames, float[] unpackData, long dataPointer)
+ {
+ var data = reader.ReadArray(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);
+ }
+ }
+
///
/// Loads Vector3s with 1 Component on X Axis
///
@@ -381,6 +526,25 @@ namespace Tyrant.Logic
}
}
+ ///
+ /// Loads Vector3s with 1 Component on Y Axis
+ ///
+ private static void LoadVector3sXYZAxis16Bit(BinaryReader reader, Animation.Bone bone, int[] frames, float[] unpackData, long dataPointer)
+ {
+ var data = reader.ReadArray(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);
+ }
+ }
+
///
/// Loads Quaternions with all components
///
@@ -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);
}
}
+ ///
+ /// Loads 10Bit Quaternions
+ ///
+ private static void LoadQuaternions5Bit(BinaryReader reader, Animation.Bone bone, int[] frames, float[] unpackData, long dataPointer)
+ {
+ var data = reader.ReadArray(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);
+ }
+ }
+
+ ///
+ /// Loads 10Bit Quaternions
+ ///
+ 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);
+ }
+ }
+
///
/// Loads 10Bit Quaternions
///
@@ -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);
+ }
+ }
+
+ ///
+ /// Loads 10Bit Quaternions
+ ///
+ 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);
+ }
+ }
+
+ ///
+ /// Loads 18Bit Quaternions
+ ///
+ 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
///
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(reader.ReadUTF16NullTerminatedString(header.NamePointer), animation);
}
+ ///
+ /// Converts an RE3 Motion File to a SEAnim
+ ///
+ private static Tuple ConvertRE3(BinaryReader reader, Dictionary bones)
+ {
+ var animation = new Animation(Animation.DataType.Absolute);
+
+ var header = reader.ReadStruct();
+
+ var name = reader.ReadUTF16NullTerminatedString(header.NamePointer);
+
+ var localBones = new Dictionary();
+
+ {
+ if(bones.Count <= 0)
+ {
+ reader.BaseStream.Position = header.BoneBaseDataPointer;
+
+ var baseDataOffset = reader.ReadInt64();
+ var baseDataCount = reader.ReadInt32();
+
+ var boneBaseData = reader.ReadArray(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(header.BoneDataPointer, header.BoneDataCount);
+
+ foreach (var bone in boneData)
+ {
+ var keyDataOffset = bone.KeysPointer;
+
+ if (bone.Flags.HasFlag(DataPrecenseFlags.Translations))
+ {
+ var keyData = reader.ReadStruct(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(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();
+ }
+
+ if (bone.Flags.HasFlag(DataPrecenseFlags.Rotations))
+ {
+ var keyData = reader.ReadStruct(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(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();
+ }
+ }
+ }
+
+ foreach (var bone in localBones)
+ animation.Bones.Add(bone.Value);
+ }
+
+ return new Tuple(reader.ReadUTF16NullTerminatedString(header.NamePointer), animation);
+ }
+
///
/// Converts the given Motion
///
- public static Tuple Convert(Stream stream)
+ public static Tuple Convert(Stream stream, Dictionary 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");
}
}
diff --git a/src/Tyrant.Logic/AssetHandlers/MotionList.cs b/src/Tyrant.Logic/AssetHandlers/MotionList.cs
index 72db47f..cd64722 100644
--- a/src/Tyrant.Logic/AssetHandlers/MotionList.cs
+++ b/src/Tyrant.Logic/AssetHandlers/MotionList.cs
@@ -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();
var results = new List>();
+ var bones = new Dictionary();
// 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(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");
}
}
diff --git a/src/Tyrant/Windows/MainWindow.xaml.cs b/src/Tyrant/Windows/MainWindow.xaml.cs
index 5b111fa..abbe563 100644
--- a/src/Tyrant/Windows/MainWindow.xaml.cs
+++ b/src/Tyrant/Windows/MainWindow.xaml.cs
@@ -70,6 +70,8 @@ namespace Tyrant
{
"natives/x64/streaming/",
"natives/x64/",
+ "natives/stm/streaming/",
+ "natives/stm/",
};
///
@@ -81,9 +83,12 @@ namespace Tyrant
"_mat.mdf2.10",
".mdf2.6",
"_mat.mdf2.6",
+ ".mdf2.13",
+ "_mat.mdf2.13",
".10",
".11",
".8",
+ ".190820018"
};
///
@@ -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");
}
}