diff --git a/Warcraft.NET.Docs/ChunkAvailability.cs b/Warcraft.NET.Docs/ChunkAvailability.cs index f3d2d31..75169c5 100644 --- a/Warcraft.NET.Docs/ChunkAvailability.cs +++ b/Warcraft.NET.Docs/ChunkAvailability.cs @@ -107,7 +107,6 @@ internal static class ChunkAvailability "M2", new() { "MD21", - "PFID", "SFID", "AFID", "BFID", @@ -136,6 +135,32 @@ internal static class ChunkAvailability } }, } + },{ + "phys", new () + { + { + "PHYS", new() + { + "PHYS", + "PHYT", + "BDY4", + "SHP2", + "BOXS", + "CAPS", + "SPHS", + "PLYT", + "JOIN", + "WLJ3", + "SPHJ", + "SHJ2", + "PRS2", + "REV2", + "DSTJ", + "SHOJ", + "PHYV", + } + }, + } }, { "tex", new () diff --git a/Warcraft.NET.Docs/Program.cs b/Warcraft.NET.Docs/Program.cs index ce9d6ff..b4dde70 100644 --- a/Warcraft.NET.Docs/Program.cs +++ b/Warcraft.NET.Docs/Program.cs @@ -1,4 +1,5 @@ using Warcraft.NET.Docs.Steps; +using Warcraft.NET.Files.Skel; namespace Warcraft.NET.Docs { diff --git a/Warcraft.NET/Extensions/ExtendedIO.cs b/Warcraft.NET/Extensions/ExtendedIO.cs index 296f792..4cd1c0a 100644 --- a/Warcraft.NET/Extensions/ExtendedIO.cs +++ b/Warcraft.NET/Extensions/ExtendedIO.cs @@ -3,6 +3,7 @@ using System.IO; using System.Numerics; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using System.Text; using Warcraft.NET.Exceptions; using Warcraft.NET.Files.Interfaces; @@ -78,6 +79,22 @@ public static Vector3 ReadVector3(this BinaryReader binaryReader, AxisConfigurat } } + /// + /// Reads a 48-byte structure from the data stream and advances the position of the stream by + /// 48 bytes. + /// + /// The Mat3x4. + /// The reader. + /// Which axis configuration the read mat3x4 should be converted to. + public static Matrix3x4 ReadMatrix3x4(this BinaryReader binaryReader, AxisConfiguration convertTo = AxisConfiguration.YUp) + { + var a = binaryReader.ReadVector3(convertTo); + var b = binaryReader.ReadVector3(convertTo); + var c = binaryReader.ReadVector3(convertTo); + var pos = binaryReader.ReadVector3(convertTo); + return new Matrix3x4(a, b, c, pos); + } + /// /// Reads a 12-byte from the data stream and advances the position of the stream by /// 12 bytes. @@ -283,37 +300,37 @@ public static ShortVector3 ReadShortVector3(this BinaryReader binaryReader, Axis switch (convertTo) { case AxisConfiguration.Native: - { - return new ShortVector3(binaryReader.ReadInt16(), binaryReader.ReadInt16(), binaryReader.ReadInt16()); - } + { + return new ShortVector3(binaryReader.ReadInt16(), binaryReader.ReadInt16(), binaryReader.ReadInt16()); + } case AxisConfiguration.YUp: - { - var x1 = binaryReader.ReadInt16(); - var y1 = binaryReader.ReadInt16(); - var z1 = binaryReader.ReadInt16(); + { + var x1 = binaryReader.ReadInt16(); + var y1 = binaryReader.ReadInt16(); + var z1 = binaryReader.ReadInt16(); - var x = x1; - var y = z1; - var z = (short)-y1; + var x = x1; + var y = z1; + var z = (short)-y1; - return new ShortVector3(x, y, z); - } + return new ShortVector3(x, y, z); + } case AxisConfiguration.ZUp: - { - var x1 = binaryReader.ReadInt16(); - var y1 = binaryReader.ReadInt16(); - var z1 = binaryReader.ReadInt16(); + { + var x1 = binaryReader.ReadInt16(); + var y1 = binaryReader.ReadInt16(); + var z1 = binaryReader.ReadInt16(); - var x = x1; - var y = (short)-z1; - var z = y1; + var x = x1; + var y = (short)-z1; + var z = y1; - return new ShortVector3(x, y, z); - } + return new ShortVector3(x, y, z); + } default: - { - throw new ArgumentOutOfRangeException(nameof(convertTo), convertTo, null); - } + { + throw new ArgumentOutOfRangeException(nameof(convertTo), convertTo, null); + } } } @@ -432,6 +449,32 @@ public static void WriteChunkSignature(this BinaryWriter binaryWriter, string si } } + /// + /// Writes a struct to the BinaryWriter. + /// + /// The type of struct to write. + /// The BinaryWriter instance. + /// The struct value to write. + public static void WriteStruct(this BinaryWriter binaryWriter, T value) where T : struct + { + int size = Marshal.SizeOf(); + byte[] bytes = new byte[size]; + + IntPtr ptr = Marshal.AllocHGlobal(size); + try + { + Marshal.StructureToPtr(value, ptr, true); + Marshal.Copy(ptr, bytes, 0, size); + } + finally + { + Marshal.FreeHGlobal(ptr); + } + + // Write the padded bytes + binaryWriter.Write(bytes); + } + /// /// Writes a 12-byte value to the data stream in Pitch/Yaw/Roll order. /// @@ -560,6 +603,25 @@ public static void WriteVector3(this BinaryWriter binaryWriter, Vector3 vector, } } + /// + /// Writes a 48-byte value to the data stream. This function + /// + /// The current object. + /// The Vector to write. + /// Which axis configuration the read vector should be stored as. + public static void WriteMatrix3x4(this BinaryWriter binaryWriter, Matrix3x4 matrix, AxisConfiguration storeAs = AxisConfiguration.ZUp) + { + var column1 = matrix.RotationX * matrix.Scale.X; + var column2 = matrix.RotationY * matrix.Scale.Y; + var column3 = matrix.RotationZ * matrix.Scale.Z; + var column4 = matrix.Position; + + binaryWriter.WriteVector3(column1, storeAs); + binaryWriter.WriteVector3(column2, storeAs); + binaryWriter.WriteVector3(column3, storeAs); + binaryWriter.WriteVector3(column4, storeAs); + } + /// /// Writes a 16-byte to the data stream. /// @@ -597,23 +659,23 @@ public static void WriteShortVector3(this BinaryWriter binaryWriter, ShortVector { case AxisConfiguration.Native: case AxisConfiguration.YUp: - { - binaryWriter.Write(vector.X); - binaryWriter.Write(vector.Y); - binaryWriter.Write(vector.Z); - break; - } + { + binaryWriter.Write(vector.X); + binaryWriter.Write(vector.Y); + binaryWriter.Write(vector.Z); + break; + } case AxisConfiguration.ZUp: - { - binaryWriter.Write(vector.X); - binaryWriter.Write((short)(vector.Z * -1)); - binaryWriter.Write(vector.Y); - break; - } + { + binaryWriter.Write(vector.X); + binaryWriter.Write((short)(vector.Z * -1)); + binaryWriter.Write(vector.Y); + break; + } default: - { - throw new ArgumentOutOfRangeException(nameof(storeAs), storeAs, null); - } + { + throw new ArgumentOutOfRangeException(nameof(storeAs), storeAs, null); + } } } diff --git a/Warcraft.NET/Files/M2/Chunks/BfA/LDV1.cs b/Warcraft.NET/Files/M2/Chunks/BfA/LDV1.cs new file mode 100644 index 0000000..44a7e33 --- /dev/null +++ b/Warcraft.NET/Files/M2/Chunks/BfA/LDV1.cs @@ -0,0 +1,69 @@ +using System.Collections.Generic; +using System.IO; +using Warcraft.NET.Attribute; +using Warcraft.NET.Files.Interfaces; +using Warcraft.NET.Files.M2.Entries; + +namespace Warcraft.NET.Files.M2.Chunks.BfA +{ + [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterLegion, AutoDocChunkVersionHelper.VersionBeforeBfA)] + public class LDV1 : IIFFChunk, IBinarySerializable + { + /// + /// Holds the binary chunk signature. + /// + public const string Signature = "LDV1"; + + /// + /// Gets or sets the Lod Data Version 1 Entries + /// + public List LDV1Entries = new(); + + /// + /// Initializes a new instance of + /// + public LDV1() { } + + /// + /// Initializes a new instance of + /// + /// ExtendedData. + public LDV1(byte[] inData) => LoadBinaryData(inData); + + /// + public string GetSignature() { return Signature; } + + /// + public uint GetSize() { return (uint)Serialize().Length; } + + /// + public void LoadBinaryData(byte[] inData) + { + { + using (var ms = new MemoryStream(inData)) + using (var br = new BinaryReader(ms)) + { + var LDV1count = br.BaseStream.Length / LDV1Entry.GetSize(); + for (var i = 0; i < LDV1count; ++i) + { + LDV1Entries.Add(new LDV1Entry(br.ReadBytes(LDV1Entry.GetSize()))); + } + } + } + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + using (var bw = new BinaryWriter(ms)) + { + foreach (LDV1Entry obj in LDV1Entries) + { + bw.Write(obj.Serialize()); + } + return ms.ToArray(); + } + } + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/M2/Chunks/BfA/TXID.cs b/Warcraft.NET/Files/M2/Chunks/BfA/TXID.cs index 37daeb6..4f06227 100644 --- a/Warcraft.NET/Files/M2/Chunks/BfA/TXID.cs +++ b/Warcraft.NET/Files/M2/Chunks/BfA/TXID.cs @@ -61,4 +61,4 @@ public byte[] Serialize(long offset = 0) } } } -} +} \ No newline at end of file diff --git a/Warcraft.NET/Files/M2/Chunks/BfA/WFV1.cs b/Warcraft.NET/Files/M2/Chunks/BfA/WFV1.cs new file mode 100644 index 0000000..ee2e459 --- /dev/null +++ b/Warcraft.NET/Files/M2/Chunks/BfA/WFV1.cs @@ -0,0 +1,51 @@ +using System.Collections.Generic; +using System.IO; +using Warcraft.NET.Attribute; +using Warcraft.NET.Files.Interfaces; +using Warcraft.NET.Files.M2.Entries; + +namespace Warcraft.NET.Files.M2.Chunks.BfA +{ + [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterLegion, AutoDocChunkVersionHelper.VersionBeforeBfA)] + public class WFV1 : IIFFChunk, IBinarySerializable + { + /// + /// Holds the binary chunk signature. + /// + public const string Signature = "WFV1"; + + /// + /// Gets or sets the full data (deserialization NYI) + /// + public byte[] Data; + + /// + /// Initializes a new instance of + /// + public WFV1() { } + + /// + /// Initializes a new instance of + /// + /// ExtendedData. + public WFV1(byte[] inData) => LoadBinaryData(inData); + + /// + public string GetSignature() { return Signature; } + + /// + public uint GetSize() { return (uint)Serialize().Length; } + + /// + public void LoadBinaryData(byte[] inData) + { + Data = inData; + } + + /// + public byte[] Serialize(long offset = 0) + { + return Data; + } + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/M2/Chunks/BfA/WFV2.cs b/Warcraft.NET/Files/M2/Chunks/BfA/WFV2.cs new file mode 100644 index 0000000..3eacdc2 --- /dev/null +++ b/Warcraft.NET/Files/M2/Chunks/BfA/WFV2.cs @@ -0,0 +1,51 @@ +using System.Collections.Generic; +using System.IO; +using Warcraft.NET.Attribute; +using Warcraft.NET.Files.Interfaces; +using Warcraft.NET.Files.M2.Entries; + +namespace Warcraft.NET.Files.M2.Chunks.BfA +{ + [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterLegion, AutoDocChunkVersionHelper.VersionBeforeBfA)] + public class WFV2 : IIFFChunk, IBinarySerializable + { + /// + /// Holds the binary chunk signature. + /// + public const string Signature = "WFV2"; + + /// + /// Gets or sets the full data (deserialization NYI) + /// + public byte[] Data; + + /// + /// Initializes a new instance of + /// + public WFV2() { } + + /// + /// Initializes a new instance of + /// + /// ExtendedData. + public WFV2(byte[] inData) => LoadBinaryData(inData); + + /// + public string GetSignature() { return Signature; } + + /// + public uint GetSize() { return (uint)Serialize().Length; } + + /// + public void LoadBinaryData(byte[] inData) + { + Data = inData; + } + + /// + public byte[] Serialize(long offset = 0) + { + return Data; + } + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/M2/Chunks/DF/AFRA.cs b/Warcraft.NET/Files/M2/Chunks/DF/AFRA.cs new file mode 100644 index 0000000..3225f66 --- /dev/null +++ b/Warcraft.NET/Files/M2/Chunks/DF/AFRA.cs @@ -0,0 +1,49 @@ +using Warcraft.NET.Files.Interfaces; + +namespace Warcraft.NET.Files.M2.Chunks.DF +{ + public class AFRA : IIFFChunk, IBinarySerializable + { + /// + /// Holds the binary chunk signature. + /// + public const string Signature = "AFRA"; + + /// + /// Gets or sets the full data (deserialization NYI) + /// + public byte[] Data; + + /// + /// Initializes a new instance of + /// + public AFRA() { } + + /// + /// Initializes a new instance of + /// + /// ExtendedData. + public AFRA(byte[] inData) => LoadBinaryData(inData); + + /// + public string GetSignature() { return Signature; } + + /// + public uint GetSize() + { + return (uint)Serialize().Length; + } + + /// + public void LoadBinaryData(byte[] inData) + { + Data = inData; + } + + /// + public byte[] Serialize(long offset = 0) + { + return Data; + } + } +} diff --git a/Warcraft.NET/Files/M2/Chunks/Legion/AFID.cs b/Warcraft.NET/Files/M2/Chunks/Legion/AFID.cs index 91d0185..5be18b2 100644 --- a/Warcraft.NET/Files/M2/Chunks/Legion/AFID.cs +++ b/Warcraft.NET/Files/M2/Chunks/Legion/AFID.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.IO; using Warcraft.NET.Attribute; using Warcraft.NET.Files.Interfaces; @@ -43,7 +44,6 @@ public void LoadBinaryData(byte[] inData) using (var br = new BinaryReader(ms)) { var animCount = br.BaseStream.Length / AFIDEntry.GetSize(); - for (var i = 0; i < animCount; ++i) { AFIDEntries.Add(new AFIDEntry(br.ReadBytes(AFIDEntry.GetSize()))); @@ -61,9 +61,8 @@ public byte[] Serialize(long offset = 0) { bw.Write(obj.Serialize()); } - return ms.ToArray(); } } } -} +} \ No newline at end of file diff --git a/Warcraft.NET/Files/M2/Chunks/Legion/BFID.cs b/Warcraft.NET/Files/M2/Chunks/Legion/BFID.cs index 26b13ca..888cdc6 100644 --- a/Warcraft.NET/Files/M2/Chunks/Legion/BFID.cs +++ b/Warcraft.NET/Files/M2/Chunks/Legion/BFID.cs @@ -42,7 +42,6 @@ public void LoadBinaryData(byte[] inData) using (var br = new BinaryReader(ms)) { uint nBone = (uint)inData.Length / 4; - for (var i = 0; i < nBone; i++) BoneFileDataIds.Add(br.ReadUInt32()); } @@ -56,9 +55,8 @@ public byte[] Serialize(long offset = 0) { foreach(uint boneFileDataId in BoneFileDataIds) bw.Write(boneFileDataId); - return ms.ToArray(); } } } -} +} \ No newline at end of file diff --git a/Warcraft.NET/Files/M2/Chunks/Legion/EXP2.cs b/Warcraft.NET/Files/M2/Chunks/Legion/EXP2.cs new file mode 100644 index 0000000..155bdbc --- /dev/null +++ b/Warcraft.NET/Files/M2/Chunks/Legion/EXP2.cs @@ -0,0 +1,50 @@ +using System.Collections.Generic; +using System.IO; +using Warcraft.NET.Attribute; +using Warcraft.NET.Files.Interfaces; +using Warcraft.NET.Files.M2.Entries; + +namespace Warcraft.NET.Files.M2.Chunks.Legion +{ + public class EXP2 : IIFFChunk, IBinarySerializable + { + /// + /// Holds the binary chunk signature. + /// + public const string Signature = "EXP2"; + + /// + /// Gets or sets the EXP2 Data + /// + public byte[] Data; + + /// + /// Initializes a new instance of + /// + public EXP2() { } + + /// + /// Initializes a new instance of + /// + /// ExtendedData. + public EXP2(byte[] inData) => LoadBinaryData(inData); + + /// + public string GetSignature() { return Signature; } + + /// + public uint GetSize() { return (uint)Serialize().Length; } + + /// + public void LoadBinaryData(byte[] inData) + { + Data = inData; + } + + /// + public byte[] Serialize(long offset = 0) + { + return Data; + } + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/M2/Chunks/Legion/EXPT.cs b/Warcraft.NET/Files/M2/Chunks/Legion/EXPT.cs new file mode 100644 index 0000000..52fbf28 --- /dev/null +++ b/Warcraft.NET/Files/M2/Chunks/Legion/EXPT.cs @@ -0,0 +1,69 @@ +using System.Collections.Generic; +using System.IO; +using Warcraft.NET.Attribute; +using Warcraft.NET.Files.Interfaces; +using Warcraft.NET.Files.M2.Entries; + +namespace Warcraft.NET.Files.M2.Chunks.Legion +{ + [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterWoD, AutoDocChunkVersionHelper.VersionBeforeLegion)] + public class EXPT : IIFFChunk, IBinarySerializable + { + /// + /// Holds the binary chunk signature. + /// + public const string Signature = "EXPT"; + + /// + /// Gets or sets the EXPT Entries + /// + public List EXP2Entries = new(); + + /// + /// Initializes a new instance of + /// + public EXPT() { } + + /// + /// Initializes a new instance of + /// + /// ExtendedData. + public EXPT(byte[] inData) => LoadBinaryData(inData); + + /// + public string GetSignature() { return Signature; } + + /// + public uint GetSize() { return (uint)Serialize().Length; } + + /// + public void LoadBinaryData(byte[] inData) + { + { + using (var ms = new MemoryStream(inData)) + using (var br = new BinaryReader(ms)) + { + var exp2count = br.BaseStream.Length / EXPTEntry.GetSize(); + for (var i = 0; i < exp2count; ++i) + { + EXP2Entries.Add(new EXPTEntry(br.ReadBytes(EXPTEntry.GetSize()))); + } + } + } + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + using (var bw = new BinaryWriter(ms)) + { + foreach (EXPTEntry obj in EXP2Entries) + { + bw.Write(obj.Serialize()); + } + return ms.ToArray(); + } + } + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/M2/Chunks/Legion/PABC.cs b/Warcraft.NET/Files/M2/Chunks/Legion/PABC.cs new file mode 100644 index 0000000..d010543 --- /dev/null +++ b/Warcraft.NET/Files/M2/Chunks/Legion/PABC.cs @@ -0,0 +1,68 @@ +using System.Collections.Generic; +using System.IO; +using Warcraft.NET.Attribute; +using Warcraft.NET.Files.Interfaces; + +namespace Warcraft.NET.Files.M2.Chunks.Legion +{ + [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterWoD, AutoDocChunkVersionHelper.VersionBeforeLegion)] + public class PABC : IIFFChunk, IBinarySerializable + { + /// + /// Holds the binary chunk signature. + /// + public const string Signature = "PABC"; + + /// + /// Gets or sets the ParentSequenceBounds Entries + /// + public List PABCEntries = new(); + + /// + /// Initializes a new instance of + /// + public PABC() { } + + /// + /// Initializes a new instance of + /// + /// ExtendedData. + public PABC(byte[] inData) => LoadBinaryData(inData); + + /// + public string GetSignature() { return Signature; } + + /// + public uint GetSize() { return (uint)Serialize().Length; } + + /// + public void LoadBinaryData(byte[] inData) + { + { + using (var ms = new MemoryStream(inData)) + using (var br = new BinaryReader(ms)) + { + var PABCcount = br.BaseStream.Length / 2; + for (var i = 0; i < PABCcount; ++i) + { + PABCEntries.Add(br.ReadUInt16()); + } + } + } + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + using (var bw = new BinaryWriter(ms)) + { + foreach (ushort obj in PABCEntries) + { + bw.Write(obj); + } + return ms.ToArray(); + } + } + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/M2/Chunks/Legion/PADC.cs b/Warcraft.NET/Files/M2/Chunks/Legion/PADC.cs new file mode 100644 index 0000000..ec885fb --- /dev/null +++ b/Warcraft.NET/Files/M2/Chunks/Legion/PADC.cs @@ -0,0 +1,46 @@ +using Warcraft.NET.Files.Interfaces; + +namespace Warcraft.NET.Files.M2.Chunks.Legion +{ + public class PADC : IIFFChunk, IBinarySerializable + { + /// + /// Holds the binary chunk signature. + /// + public const string Signature = "PADC"; + + /// + /// Gets or sets the ParentAnimationData (deserialization NYI) + /// + public byte[] Data; + + /// + /// Initializes a new instance of + /// + public PADC() { } + + /// + /// Initializes a new instance of + /// + /// ExtendedData. + public PADC(byte[] inData) => LoadBinaryData(inData); + + /// + public string GetSignature() { return Signature; } + + /// + public uint GetSize() { return (uint)Serialize().Length; } + + /// + public void LoadBinaryData(byte[] inData) + { + Data = inData; + } + + /// + public byte[] Serialize(long offset = 0) + { + return Data; + } + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/M2/Chunks/Legion/PEDC.cs b/Warcraft.NET/Files/M2/Chunks/Legion/PEDC.cs new file mode 100644 index 0000000..3881430 --- /dev/null +++ b/Warcraft.NET/Files/M2/Chunks/Legion/PEDC.cs @@ -0,0 +1,48 @@ +using Warcraft.NET.Attribute; +using Warcraft.NET.Files.Interfaces; + +namespace Warcraft.NET.Files.M2.Chunks.Legion +{ + [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterWoD, AutoDocChunkVersionHelper.VersionBeforeLegion)] + public class PEDC : IIFFChunk, IBinarySerializable + { + /// + /// Holds the binary chunk signature. + /// + public const string Signature = "PEDC"; + + /// + /// Gets or sets the ParentEventData (deserialization NYI) + /// + public byte[] Data; + + /// + /// Initializes a new instance of + /// + public PEDC() { } + + /// + /// Initializes a new instance of + /// + /// ExtendedData. + public PEDC(byte[] inData) => LoadBinaryData(inData); + + /// + public string GetSignature() { return Signature; } + + /// + public uint GetSize() { return (uint)Serialize().Length; } + + /// + public void LoadBinaryData(byte[] inData) + { + Data = inData; + } + + /// + public byte[] Serialize(long offset = 0) + { + return Data; + } + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/M2/Chunks/Legion/PFID.cs b/Warcraft.NET/Files/M2/Chunks/Legion/PFID.cs index f92f272..729142a 100644 --- a/Warcraft.NET/Files/M2/Chunks/Legion/PFID.cs +++ b/Warcraft.NET/Files/M2/Chunks/Legion/PFID.cs @@ -61,4 +61,4 @@ public byte[] Serialize(long offset = 0) } } } -} +} \ No newline at end of file diff --git a/Warcraft.NET/Files/M2/Chunks/Legion/PGD1.cs b/Warcraft.NET/Files/M2/Chunks/Legion/PGD1.cs new file mode 100644 index 0000000..dba0ea2 --- /dev/null +++ b/Warcraft.NET/Files/M2/Chunks/Legion/PGD1.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.IO; +using Warcraft.NET.Attribute; +using Warcraft.NET.Files.Interfaces; + +namespace Warcraft.NET.Files.M2.Chunks.Legion +{ + [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterWoD, AutoDocChunkVersionHelper.VersionBeforeLegion)] + public class PGD1 : IIFFChunk, IBinarySerializable + { + /// + /// Holds the binary chunk signature. + /// + public const string Signature = "PGD1"; + + /// + /// Gets or sets the ParticleGeosetData1 Entries + /// + public List PGD1Entries = new(); + + /// + /// Initializes a new instance of + /// + public PGD1() { } + + /// + /// Initializes a new instance of + /// + /// ExtendedData. + public PGD1(byte[] inData) => LoadBinaryData(inData); + + /// + public string GetSignature() { return Signature; } + + /// + public uint GetSize() { return (uint)Serialize().Length; } + + /// + public void LoadBinaryData(byte[] inData) + { + { + using (var ms = new MemoryStream(inData)) + using (var br = new BinaryReader(ms)) + { + var PGD1count = br.BaseStream.Length / 2; + for (var i = 0; i < PGD1count; ++i) + { + PGD1Entries.Add(br.ReadUInt16()); + } + } + } + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + using (var bw = new BinaryWriter(ms)) + { + foreach (UInt16 obj in PGD1Entries) + { + bw.Write(obj); + } + return ms.ToArray(); + } + } + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/M2/Chunks/Legion/PSBC.cs b/Warcraft.NET/Files/M2/Chunks/Legion/PSBC.cs new file mode 100644 index 0000000..570981b --- /dev/null +++ b/Warcraft.NET/Files/M2/Chunks/Legion/PSBC.cs @@ -0,0 +1,51 @@ +using System.IO; +using Warcraft.NET.Files.Interfaces; + +namespace Warcraft.NET.Files.M2.Chunks.Legion +{ + public class PSBC : IIFFChunk, IBinarySerializable + { + /// + /// Holds the binary chunk signature. + /// + public const string Signature = "PSBC"; + + /// + /// Gets or sets the ParentSequenceBounds (deserialization NYI) + /// + public byte[] Data; + + /// + /// Initializes a new instance of + /// + public PSBC() { } + + /// + /// Initializes a new instance of + /// + /// ExtendedData. + public PSBC(byte[] inData) => LoadBinaryData(inData); + + /// + public string GetSignature() { return Signature; } + + /// + public uint GetSize() { return (uint)Serialize().Length; } + + /// + public void LoadBinaryData(byte[] inData) + { + using (var ms = new MemoryStream(inData)) + using (var br = new BinaryReader(ms)) + { + Data = inData; + } + } + + /// + public byte[] Serialize(long offset = 0) + { + return Data; + } + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/M2/Chunks/Legion/SFID.cs b/Warcraft.NET/Files/M2/Chunks/Legion/SFID.cs index bf6b4c3..90ff088 100644 --- a/Warcraft.NET/Files/M2/Chunks/Legion/SFID.cs +++ b/Warcraft.NET/Files/M2/Chunks/Legion/SFID.cs @@ -61,4 +61,4 @@ public byte[] Serialize(long offset = 0) } } } -} +} \ No newline at end of file diff --git a/Warcraft.NET/Files/M2/Chunks/Legion/SKID.cs b/Warcraft.NET/Files/M2/Chunks/Legion/SKID.cs index abcda1d..1908f10 100644 --- a/Warcraft.NET/Files/M2/Chunks/Legion/SKID.cs +++ b/Warcraft.NET/Files/M2/Chunks/Legion/SKID.cs @@ -51,9 +51,8 @@ public byte[] Serialize(long offset = 0) using (var bw = new BinaryWriter(ms)) { bw.Write(SkeletonFileDataId); - return ms.ToArray(); } } } -} +} \ No newline at end of file diff --git a/Warcraft.NET/Files/M2/Chunks/Legion/TXAC.cs b/Warcraft.NET/Files/M2/Chunks/Legion/TXAC.cs new file mode 100644 index 0000000..3ffe3d4 --- /dev/null +++ b/Warcraft.NET/Files/M2/Chunks/Legion/TXAC.cs @@ -0,0 +1,71 @@ +using System.IO; +using Warcraft.NET.Attribute; +using Warcraft.NET.Files.Interfaces; +using System.Collections.Generic; + +namespace Warcraft.NET.Files.M2.Chunks.Legion +{ + [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterWoD, AutoDocChunkVersionHelper.VersionBeforeLegion)] + public class TXAC : IIFFChunk, IBinarySerializable + { + /// + /// Holds the binary chunk signature. + /// + public const string Signature = "TXAC"; + + /// + /// 2 byte array + /// From Wiki: + /// likely used in CM2SceneRender::SetupTextureTransforms and uploaded to the shader directly. 0 otherwise. + /// This chunk doesn't seem to be used directly. Inside CParticleEmitter2 class there are non-null checks that deal with selection of VertexBufferFormat for particles. Apart from that, the usage of these fields is unknown + /// + public List TXACEntries = new(); + + /// + /// Initializes a new instance of + /// + public TXAC() { } + + /// + /// Initializes a new instance of + /// + /// ExtendedData. + public TXAC(byte[] inData) => LoadBinaryData(inData); + + /// + public string GetSignature() { return Signature; } + + /// + public uint GetSize() { return (uint)Serialize().Length; } + + /// + public void LoadBinaryData(byte[] inData) + { + using (var ms = new MemoryStream(inData)) + using (var br = new BinaryReader(ms)) + { + for (int i = 0; i < inData.Length / 2; i++) + { + var entry = new byte[2]; + entry[0] = br.ReadByte(); + entry[1] = br.ReadByte(); + TXACEntries.Add(entry); + } + } + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + using (var bw = new BinaryWriter(ms)) + { + foreach (var entry in TXACEntries) + { + bw.Write(entry); + } + return ms.ToArray(); + } + } + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/M2/Chunks/SL/DBOC.cs b/Warcraft.NET/Files/M2/Chunks/SL/DBOC.cs new file mode 100644 index 0000000..912a6e0 --- /dev/null +++ b/Warcraft.NET/Files/M2/Chunks/SL/DBOC.cs @@ -0,0 +1,69 @@ +using System.Collections.Generic; +using System.IO; +using Warcraft.NET.Attribute; +using Warcraft.NET.Files.Interfaces; +using Warcraft.NET.Files.M2.Entries; + +namespace Warcraft.NET.Files.M2.Chunks.Legion +{ + [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)] + public class DBOC : IIFFChunk, IBinarySerializable + { + /// + /// Holds the binary chunk signature. + /// + public const string Signature = "DBOC"; + + /// + /// Gets or sets the DBOC Entries + /// + public List DBOCEntries = new(); + + /// + /// Initializes a new instance of + /// + public DBOC() { } + + /// + /// Initializes a new instance of + /// + /// ExtendedData. + public DBOC(byte[] inData) => LoadBinaryData(inData); + + /// + public string GetSignature() { return Signature; } + + /// + public uint GetSize() { return (uint)Serialize().Length; } + + /// + public void LoadBinaryData(byte[] inData) + { + { + using (var ms = new MemoryStream(inData)) + using (var br = new BinaryReader(ms)) + { + var DBOCcount = br.BaseStream.Length / DBOCEntry.GetSize(); + for (var i = 0; i < DBOCcount; ++i) + { + DBOCEntries.Add(new DBOCEntry(br.ReadBytes(DBOCEntry.GetSize()))); + } + } + } + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + using (var bw = new BinaryWriter(ms)) + { + foreach (DBOCEntry obj in DBOCEntries) + { + bw.Write(obj.Serialize()); + } + return ms.ToArray(); + } + } + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/M2/Chunks/SL/DETL.cs b/Warcraft.NET/Files/M2/Chunks/SL/DETL.cs new file mode 100644 index 0000000..6a477a0 --- /dev/null +++ b/Warcraft.NET/Files/M2/Chunks/SL/DETL.cs @@ -0,0 +1,69 @@ +using System.Collections.Generic; +using System.IO; +using Warcraft.NET.Attribute; +using Warcraft.NET.Files.Interfaces; +using Warcraft.NET.Files.M2.Entries; + +namespace Warcraft.NET.Files.M2.Chunks.SL +{ + [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)] + public class DETL : IIFFChunk, IBinarySerializable + { + /// + /// Holds the binary chunk signature. + /// + public const string Signature = "DETL"; + + /// + /// Gets or sets the DETL Entries + /// + public List DETLEntries = new(); + + /// + /// Initializes a new instance of + /// + public DETL() { } + + /// + /// Initializes a new instance of + /// + /// ExtendedData. + public DETL(byte[] inData) => LoadBinaryData(inData); + + /// + public string GetSignature() { return Signature; } + + /// + public uint GetSize() { return (uint)Serialize().Length; } + + /// + public void LoadBinaryData(byte[] inData) + { + { + using (var ms = new MemoryStream(inData)) + using (var br = new BinaryReader(ms)) + { + var DETLcount = br.BaseStream.Length / DETLEntry.GetSize(); + for (var i = 0; i < DETLcount; ++i) + { + DETLEntries.Add(new DETLEntry(br.ReadBytes(DETLEntry.GetSize()))); + } + } + } + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + using (var bw = new BinaryWriter(ms)) + { + foreach (DETLEntry obj in DETLEntries) + { + bw.Write(obj.Serialize()); + } + return ms.ToArray(); + } + } + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/M2/Chunks/SL/EDGF.cs b/Warcraft.NET/Files/M2/Chunks/SL/EDGF.cs new file mode 100644 index 0000000..23634a1 --- /dev/null +++ b/Warcraft.NET/Files/M2/Chunks/SL/EDGF.cs @@ -0,0 +1,69 @@ +using System.Collections.Generic; +using System.IO; +using Warcraft.NET.Attribute; +using Warcraft.NET.Files.Interfaces; +using Warcraft.NET.Files.M2.Entries; + +namespace Warcraft.NET.Files.M2.Chunks.Legion +{ + [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)] + public class EDGF : IIFFChunk, IBinarySerializable + { + /// + /// Holds the binary chunk signature. + /// + public const string Signature = "EDGF"; + + /// + /// Gets or sets the EdgeFade Entries + /// + public List EDGFEntries = new(); + + /// + /// Initializes a new instance of + /// + public EDGF() { } + + /// + /// Initializes a new instance of + /// + /// ExtendedData. + public EDGF(byte[] inData) => LoadBinaryData(inData); + + /// + public string GetSignature() { return Signature; } + + /// + public uint GetSize() { return (uint)Serialize().Length; } + + /// + public void LoadBinaryData(byte[] inData) + { + { + using (var ms = new MemoryStream(inData)) + using (var br = new BinaryReader(ms)) + { + var EDGFcount = br.BaseStream.Length / EDGFEntry.GetSize(); + for (var i = 0; i < EDGFcount; ++i) + { + EDGFEntries.Add(new EDGFEntry(br.ReadBytes(EDGFEntry.GetSize()))); + } + } + } + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + using (var bw = new BinaryWriter(ms)) + { + foreach (EDGFEntry obj in EDGFEntries) + { + bw.Write(obj.Serialize()); + } + return ms.ToArray(); + } + } + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/M2/Chunks/SL/NERF.cs b/Warcraft.NET/Files/M2/Chunks/SL/NERF.cs new file mode 100644 index 0000000..cdc76a2 --- /dev/null +++ b/Warcraft.NET/Files/M2/Chunks/SL/NERF.cs @@ -0,0 +1,70 @@ +using System.Collections.Generic; +using System.IO; +using System.Numerics; +using Warcraft.NET.Attribute; +using Warcraft.NET.Files.Interfaces; + +namespace Warcraft.NET.Files.M2.Chunks.Legion +{ + [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)] + public class NERF : IIFFChunk, IBinarySerializable + { + /// + /// Holds the binary chunk signature. + /// + public const string Signature = "NERF"; + + /// + /// Gets or sets the NERF Entries + /// + public List NERFEntries = new(); + + /// + /// Initializes a new instance of + /// + public NERF() { } + + /// + /// Initializes a new instance of + /// + /// ExtendedData. + public NERF(byte[] inData) => LoadBinaryData(inData); + + /// + public string GetSignature() { return Signature; } + + /// + public uint GetSize() { return (uint)Serialize().Length; } + + /// + public void LoadBinaryData(byte[] inData) + { + { + using (var ms = new MemoryStream(inData)) + using (var br = new BinaryReader(ms)) + { + var NERFcount = br.BaseStream.Length / 8; + for (var i = 0; i < NERFcount; ++i) + { + NERFEntries.Add(new Vector2(br.ReadSingle(), br.ReadSingle())); + } + } + } + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + using (var bw = new BinaryWriter(ms)) + { + foreach (Vector2 obj in NERFEntries) + { + bw.Write(obj.X); + bw.Write(obj.Y); + } + return ms.ToArray(); + } + } + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/M2/Chunks/SL/PFDC.cs b/Warcraft.NET/Files/M2/Chunks/SL/PFDC.cs new file mode 100644 index 0000000..5c8bb6b --- /dev/null +++ b/Warcraft.NET/Files/M2/Chunks/SL/PFDC.cs @@ -0,0 +1,64 @@ +using System; +using Warcraft.NET.Attribute; +using Warcraft.NET.Files.Interfaces; +using Warcraft.NET.Files.Phys; + +namespace Warcraft.NET.Files.M2.Chunks.SL +{ + [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)] + public class PFDC : IIFFChunk, IBinarySerializable + { + /// + /// Holds the binary chunk signature. + /// + public const string Signature = "PFDC"; + + /// + /// Gets or sets the Physics for the M2 + /// + public Physics Physics { get; set; } = null; + + /// + /// Initializes a new instance of + /// + public PFDC() { } + + /// + /// Initializes a new instance of + /// + /// ExtendedData. + public PFDC(byte[] inData) => LoadBinaryData(inData); + + /// + public string GetSignature() { return Signature; } + + /// + public uint GetSize() { return (uint)Serialize().Length; } + + /// + public void LoadBinaryData(byte[] inData) + { + Physics = new Physics(inData); + } + + /// + public byte[] Serialize(long offset = 0) + { + return PadTo8Bytes(Physics.Serialize()); + } + + static byte[] PadTo8Bytes(byte[] input) + { + int paddingNeeded = 8 - (input.Length % 8); + if (paddingNeeded == 8) + paddingNeeded = 0; + byte[] paddedArray = new byte[input.Length + paddingNeeded]; + Array.Copy(input, paddedArray, input.Length); + for (int i = input.Length; i < paddedArray.Length; i++) + { + paddedArray[i] = 0x00; + } + return paddedArray; + } + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/M2/Chunks/SL/WFV3.cs b/Warcraft.NET/Files/M2/Chunks/SL/WFV3.cs new file mode 100644 index 0000000..c37dd2a --- /dev/null +++ b/Warcraft.NET/Files/M2/Chunks/SL/WFV3.cs @@ -0,0 +1,69 @@ +using System.Collections.Generic; +using System.IO; +using Warcraft.NET.Attribute; +using Warcraft.NET.Files.Interfaces; +using Warcraft.NET.Files.M2.Entries; + +namespace Warcraft.NET.Files.M2.Chunks.SL +{ + [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)] + public class WFV3 : IIFFChunk, IBinarySerializable + { + /// + /// Holds the binary chunk signature. + /// + public const string Signature = "WFV3"; + + /// + /// Gets or sets the WaterFallVersion3 Entries + /// + public List WFV3Entries = new(); + + /// + /// Initializes a new instance of + /// + public WFV3() { } + + /// + /// Initializes a new instance of + /// + /// ExtendedData. + public WFV3(byte[] inData) => LoadBinaryData(inData); + + /// + public string GetSignature() { return Signature; } + + /// + public uint GetSize() { return (uint)Serialize().Length; } + + /// + public void LoadBinaryData(byte[] inData) + { + { + using (var ms = new MemoryStream(inData)) + using (var br = new BinaryReader(ms)) + { + var WFV3count = br.BaseStream.Length / WFV3Entry.GetSize(); + for (var i = 0; i < WFV3count; ++i) + { + WFV3Entries.Add(new WFV3Entry(br.ReadBytes(WFV3Entry.GetSize()))); + } + } + } + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + using (var bw = new BinaryWriter(ms)) + { + foreach (WFV3Entry obj in WFV3Entries) + { + bw.Write(obj.Serialize()); + } + return ms.ToArray(); + } + } + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/M2/Entries/AFIDEntry.cs b/Warcraft.NET/Files/M2/Entries/AFIDEntry.cs index 45bb227..6c85f43 100644 --- a/Warcraft.NET/Files/M2/Entries/AFIDEntry.cs +++ b/Warcraft.NET/Files/M2/Entries/AFIDEntry.cs @@ -9,7 +9,6 @@ public class AFIDEntry /// public ushort AnimationId { get; set; } - /// /// Gets or sets the sub animation id. /// @@ -20,7 +19,6 @@ public class AFIDEntry /// public uint FileDataId { get; set; } - /// /// Initializes a new instance of the class. /// @@ -68,4 +66,4 @@ public byte[] Serialize(long offset = 0) } } } -} +} \ No newline at end of file diff --git a/Warcraft.NET/Files/M2/Entries/DBOCEntry.cs b/Warcraft.NET/Files/M2/Entries/DBOCEntry.cs new file mode 100644 index 0000000..58a8bf5 --- /dev/null +++ b/Warcraft.NET/Files/M2/Entries/DBOCEntry.cs @@ -0,0 +1,70 @@ +using System.IO; + +namespace Warcraft.NET.Files.M2.Entries +{ + public class DBOCEntry + { + /// + /// unknown float + /// + public float Unk0; + /// + /// unknown float + /// + public float Unk1; + /// + /// unknown int + /// + public uint Unk2; + /// + /// unknown int + /// + public uint Unk3; + + /// + /// Initializes a new instance of the class. + /// + public DBOCEntry(){} + + /// + /// Initializes a new instance of the class. + /// + /// ExtendedData. + public DBOCEntry(byte[] data) + { + using (var ms = new MemoryStream(data)) + using (var br = new BinaryReader(ms)) + { + Unk0 = br.ReadSingle(); + Unk1 = br.ReadSingle(); + Unk2 = br.ReadUInt32(); + Unk3 = br.ReadUInt32(); + } + } + + /// + /// Gets the size of a DBOC Entry + /// + /// The size. + public static int GetSize() + { + return 16; + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + { + using (var bw = new BinaryWriter(ms)) + { + bw.Write(Unk0); + bw.Write(Unk1); + bw.Write(Unk2); + bw.Write(Unk3); + } + return ms.ToArray(); + } + } + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/M2/Entries/DETLEntry.cs b/Warcraft.NET/Files/M2/Entries/DETLEntry.cs new file mode 100644 index 0000000..da70cdc --- /dev/null +++ b/Warcraft.NET/Files/M2/Entries/DETLEntry.cs @@ -0,0 +1,82 @@ +using System.IO; + +namespace Warcraft.NET.Files.M2.Entries +{ + public class DETLEntry + { + /// + /// unknown Flags + /// + public ushort Flags; + + /// + /// multiplier for M2Light.diffuse_color + /// + public ushort PackedFloat0; + + /// + /// multiplier for M2Light.diffuse_color + /// + public ushort PackedFloat1; + + /// + /// unknown field + /// + public ushort Unk0; + + /// + /// unknown field + /// + public uint Unk1; + + /// + /// Initializes a new instance of the class. + /// + public DETLEntry() + { + } + + /// + /// Initializes a new instance of the class. + /// + /// ExtendedData. + public DETLEntry(byte[] data) + { + using (var ms = new MemoryStream(data)) + using (var br = new BinaryReader(ms)) + { + Flags = br.ReadUInt16(); + PackedFloat0 = br.ReadUInt16(); + PackedFloat1 = br.ReadUInt16(); + Unk0 = br.ReadUInt16(); + Unk1 = br.ReadUInt32(); + } + } + + /// + /// Gets the size of a AFRA Entry + /// + /// The size. + public static int GetSize() + { + return 12; + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + { + using (var bw = new BinaryWriter(ms)) + { + bw.Write(Flags); + bw.Write(PackedFloat0); + bw.Write(PackedFloat1); + bw.Write(Unk0); + bw.Write(Unk1); + } + return ms.ToArray(); + } + } + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/M2/Entries/EDGFEntry.cs b/Warcraft.NET/Files/M2/Entries/EDGFEntry.cs new file mode 100644 index 0000000..346c50f --- /dev/null +++ b/Warcraft.NET/Files/M2/Entries/EDGFEntry.cs @@ -0,0 +1,71 @@ +using System.IO; + +namespace Warcraft.NET.Files.M2.Entries +{ + public class EDGFEntry + { + /// + /// unknown 2-floats array + /// + public float[] Unk0; + + /// + /// unknown float + /// + public float Unk1; + + /// + /// unknown 4 byte array + /// + public byte[] Unk2; + + /// + /// Initializes a new instance of the class. + /// + public EDGFEntry() + { + } + + /// + /// Initializes a new instance of the class. + /// + /// ExtendedData. + public EDGFEntry(byte[] data) + { + using (var ms = new MemoryStream(data)) + using (var br = new BinaryReader(ms)) + { + Unk0 = new float[2]; + Unk0[0] = br.ReadSingle(); + Unk0[1] = br.ReadSingle(); + Unk1 = br.ReadSingle(); + Unk2 = br.ReadBytes(4); + } + } + + /// + /// Gets the size of a EDGF Entry + /// + /// The size. + public static int GetSize() + { + return 16; + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + { + using (var bw = new BinaryWriter(ms)) + { + bw.Write(Unk0[0]); + bw.Write(Unk0[1]); + bw.Write(Unk1); + bw.Write(Unk2); + } + return ms.ToArray(); + } + } + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/M2/Entries/EXPTEntry.cs b/Warcraft.NET/Files/M2/Entries/EXPTEntry.cs new file mode 100644 index 0000000..ece3be3 --- /dev/null +++ b/Warcraft.NET/Files/M2/Entries/EXPTEntry.cs @@ -0,0 +1,64 @@ +using System.IO; + +namespace Warcraft.NET.Files.M2.Entries +{ + public class EXPTEntry + { + /// + /// replaces zSource from ParticleEmitter + /// + public float ZSource; + /// + /// colorMult is applied against particle's diffuse color + /// + public float ColorMult; + /// + ///alphaMult is applied against particle's opacity. + /// + public float AlphaMult; + + /// + /// Initializes a new instance of the class. + /// + public EXPTEntry() { } + + /// + /// Initializes a new instance of the class. + /// + /// ExtendedData. + public EXPTEntry(byte[] data) + { + using (var ms = new MemoryStream(data)) + using (var br = new BinaryReader(ms)) + { + ZSource = br.ReadSingle(); + ColorMult = br.ReadSingle(); + AlphaMult = br.ReadSingle(); + } + } + + /// + /// Gets the size of a animation file id entry. + /// + /// The size. + public static int GetSize() + { + return 12; + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + { + using (var bw = new BinaryWriter(ms)) + { + bw.Write(ZSource); + bw.Write(ColorMult); + bw.Write(AlphaMult); + } + return ms.ToArray(); + } + } + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/M2/Entries/LDV1Entry.cs b/Warcraft.NET/Files/M2/Entries/LDV1Entry.cs new file mode 100644 index 0000000..007466f --- /dev/null +++ b/Warcraft.NET/Files/M2/Entries/LDV1Entry.cs @@ -0,0 +1,80 @@ +using System.IO; + +namespace Warcraft.NET.Files.M2.Entries +{ + public class LDV1Entry + { + /// + /// unknown field + /// + public ushort Unk0; + + /// + /// the maximum lod count + /// + public ushort LodCount; + + /// + /// unknown field + /// + public float Unk1; + + /// + /// lod serves as indes into this array + /// + public byte[] ParticleBoneLod; + + /// + /// unknown field + /// + public uint Unk2; + + /// + /// Initializes a new instance of the class. + /// + public LDV1Entry() + { + } + + /// + /// Initializes a new instance of the class. + /// + /// ExtendedData. + public LDV1Entry(byte[] data) + { + using (var ms = new MemoryStream(data)) + using (var br = new BinaryReader(ms)) + { + Unk0 = br.ReadUInt16(); + LodCount = br.ReadUInt16(); + Unk1 = br.ReadSingle(); + ParticleBoneLod = br.ReadBytes(4); + Unk2 = br.ReadUInt32(); + } + } + + /// + /// Gets the size of a LDV1 Entry + /// + /// The size. + public static int GetSize() + { + return 16; + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + using (var bw = new BinaryWriter(ms)) + { + bw.Write(Unk0); + bw.Write(LodCount); + bw.Write(Unk1); + bw.Write(ParticleBoneLod); + bw.Write(Unk2); + return ms.ToArray(); + } + } + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/M2/Entries/WFV3Entry.cs b/Warcraft.NET/Files/M2/Entries/WFV3Entry.cs new file mode 100644 index 0000000..12d0463 --- /dev/null +++ b/Warcraft.NET/Files/M2/Entries/WFV3Entry.cs @@ -0,0 +1,196 @@ +using System.IO; +using Warcraft.NET.Extensions; +using Warcraft.NET.Files.Structures; + +namespace Warcraft.NET.Files.M2.Entries +{ + public class WFV3Entry + { + /// + /// BumpScale -> Passed to vertex shader + /// + public float BumpScale; + + /// + /// value 0 x + /// + public float Value0X; + + /// + /// value 0 y + /// + public float Value0Y; + + /// + /// value 0 z + /// + public float Value0Z; + + /// + /// value 1 W + /// + public float Value1W; + + /// + /// value 0 W + /// + public float Value0W; + + /// + /// value 1 x + /// + public float Value1X; + + /// + /// value 1 y + /// + public float Value1Y; + + /// + /// value 2 w + /// + public float Value2W; + + /// + /// value 3 y + /// + public float Value3Y; + + /// + /// value 3 x + /// + public float Value3X; + + /// + /// BaseColor in rgba (not bgra) + /// + public RGBA BaseColor; + + /// + /// unknown Flags + /// + public ushort Flags; + + /// + /// unknown field + /// + public ushort Unk0; + + /// + /// value 3 W + /// + public float Value3W; + + /// + /// value 3 Z + /// + public float Value3Z; + + /// + /// value 4 y + /// + public float Value4Y; + + /// + /// unknown field + /// + public float Unk1; + + /// + /// unknown field + /// + public float Unk2; + + /// + /// unknown field + /// + public float Unk3; + + /// + /// unknown field + /// + public float Unk4; + + /// + /// Initializes a new instance of the class. + /// + public WFV3Entry() + { + } + + /// + /// Initializes a new instance of the class. + /// + /// ExtendedData. + public WFV3Entry(byte[] data) + { + using (var ms = new MemoryStream(data)) + using (var br = new BinaryReader(ms)) + { + BumpScale = br.ReadSingle(); + Value0X = br.ReadSingle(); + Value0Y = br.ReadSingle(); + Value0Z = br.ReadSingle(); + Value1W = br.ReadSingle(); + Value0W = br.ReadSingle(); + Value1X = br.ReadSingle(); + Value1Y = br.ReadSingle(); + Value2W = br.ReadSingle(); + Value3Y = br.ReadSingle(); + Value3X = br.ReadSingle(); + BaseColor = br.ReadRGBA(); + Flags = br.ReadUInt16(); + Unk0 = br.ReadUInt16(); + Value3W = br.ReadSingle(); + Value3Z = br.ReadSingle(); + Value4Y = br.ReadSingle(); + Unk1 = br.ReadSingle(); + Unk2 = br.ReadSingle(); + Unk3 = br.ReadSingle(); + Unk4 = br.ReadSingle(); + } + } + + /// + /// Gets the size of a WFV3 Entry + /// + /// The size. + public static int GetSize() + { + return 80; + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + { + using (var bw = new BinaryWriter(ms)) + { + bw.Write(BumpScale); + bw.Write(Value0X); + bw.Write(Value0Y); + bw.Write(Value0Z); + bw.Write(Value1W); + bw.Write(Value0W); + bw.Write(Value1X); + bw.Write(Value1Y); + bw.Write(Value2W); + bw.Write(Value3Y); + bw.Write(Value3X); + bw.WriteRGBA(BaseColor); + bw.Write(Flags); + bw.Write(Unk0); + bw.Write(Value3W); + bw.Write(Value3Z); + bw.Write(Value4Y); + bw.Write(Unk1); + bw.Write(Unk2); + bw.Write(Unk3); + bw.Write(Unk4); + } + return ms.ToArray(); + } + } + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/M2/Model.cs b/Warcraft.NET/Files/M2/Model.cs index 9c251bf..e92e642 100644 --- a/Warcraft.NET/Files/M2/Model.cs +++ b/Warcraft.NET/Files/M2/Model.cs @@ -1,7 +1,9 @@ using Warcraft.NET.Attribute; using Warcraft.NET.Files.M2.Chunks; using Warcraft.NET.Files.M2.Chunks.BfA; +using Warcraft.NET.Files.M2.Chunks.DF; using Warcraft.NET.Files.M2.Chunks.Legion; +using Warcraft.NET.Files.M2.Chunks.SL; namespace Warcraft.NET.Files.M2 { @@ -15,53 +17,161 @@ public class Model : ChunkedFile public MD21 ModelInformation { get; set; } /// - /// Gets or sets the model phys file ids + /// Gets or sets the CParticleEmitter2 data /// - [ChunkOrder(2), ChunkOptional] - public PFID PhysFileIds { get; set; } + [ChunkOrder(2),ChunkOptional] + public TXAC CParticleEmitter2 { get; set; } /// - /// Gets or sets the model skin file ids + /// Gets or sets the ParentEventData /// - [ChunkOrder(3), ChunkOptional] - public SFID SkinFileIds { get; set; } + [ChunkOrder(3),ChunkOptional] + public PEDC M2InitParentEventData { get; set; } /// - /// Gets or sets the model anim file ids + /// Gets or sets the ExtendedParticle /// [ChunkOrder(4), ChunkOptional] + public EXPT ExtendedParticle { get; set; } + + /// + /// Gets or sets the ExtendedParticle2 + /// + [ChunkOrder(5),ChunkOptional] + public EXP2 ExtendedParticle2 { get; set; } + + /// + /// Gets or sets the ParticleGeosetData + /// + [ChunkOrder(6),ChunkOptional] + public PGD1 ParticleGeosetData { get; set; } + + /// + /// Gets or sets the model anim file ids + /// + [ChunkOrder(7), ChunkOptional] public AFID AnimFileIds { get; set; } /// /// Gets or sets the model bone file ids /// - [ChunkOrder(5), ChunkOptional] + [ChunkOrder(8), ChunkOptional] public BFID BoneFileIds { get; set; } /// - /// Gets or sets the model recursive particle file ids + /// Gets or sets the BlacklistAnimData /// - [ChunkOrder(6), ChunkOptional] - public RPID RecursiveParticleFileIds { get; set; } + [ChunkOrder(9), ChunkOptional] + public PABC M2InitBlacklistAnimData { get; set; } /// - /// Gets or sets the model geometry particle file ids + /// Gets or sets the LodDataVersion1 /// - [ChunkOrder(7), ChunkOptional] - public GPID GeometryParticleFileIds { get; set; } + [ChunkOrder(10), ChunkOptional] + public LDV1 LodDataVersion1 { get; set; } + + /// + /// Gets or sets the EdgeFade + /// + [ChunkOrder(11), ChunkOptional] + public EDGF EdgeFade { get; set; } + + /// + /// Gets or sets the Physics of the M2 + /// + [ChunkOrder(12),ChunkOptional] + public PFDC ModelPhysics { get; set; } /// /// Gets or sets the model skeleton file ids /// - [ChunkOrder(8), ChunkOptional] + [ChunkOrder(13), ChunkOptional] public SKID SkeletonFileIds { get; set; } + /// + /// Gets or sets the WaterFallVersion1 + /// + [ChunkOrder(14),ChunkOptional] + public WFV1 WaterFallVersion1 { get; set; } + + /// + /// Gets or sets the WaterFallVersion2 + /// + [ChunkOrder(15),ChunkOptional] + public WFV2 WaterFallVersion2 { get; set; } + + /// + /// Gets or sets the WaterFallVersion3 + /// + [ChunkOrder(16),ChunkOptional] + public WFV3 WaterFallVersion3 { get; set; } + + /// + /// Gets or sets the DBOC + /// + [ChunkOrder(17), ChunkOptional] + public DBOC DBOC { get; set; } + + /// + /// Gets or sets the model skin file ids + /// + [ChunkOrder(18), ChunkOptional] + public SFID SkinFileIds { get; set; } + + /// + /// Gets or sets the model phys file ids + /// + [ChunkOrder(19), ChunkOptional] + public PFID PhysFileIds { get; set; } + /// /// Gets or sets the model texture file ids /// - [ChunkOrder(9), ChunkOptional] + [ChunkOrder(20), ChunkOptional] public TXID TextureFileIds { get; set; } + /// + /// Gets or sets the ParentSequenceBoundsData + /// + [ChunkOrder(21),ChunkOptional] + public PSBC M2InitParentSequenceBoundsData { get; set; } + + /// + /// Gets or sets the model recursive particle file ids + /// + [ChunkOrder(22), ChunkOptional] + public RPID RecursiveParticleFileIds { get; set; } + + /// + /// Gets or sets the model geometry particle file ids + /// + [ChunkOrder(23), ChunkOptional] + public GPID GeometryParticleFileIds { get; set; } + + /// + /// Gets or sets the ParentAnimData + /// + [ChunkOrder(24),ChunkOptional] + public PADC M2InitParentAnimData { get; set; } + + /// + /// Gets or sets the NERF + /// + [ChunkOrder(25),ChunkOptional] + public NERF NERF { get; set; } + + /// + /// Gets or sets the DETL (light related) + /// + [ChunkOrder(26),ChunkOptional] + public DETL DETL { get; set; } + + /// + /// Gets or sets the AFRA + /// + [ChunkOrder(27),ChunkOptional] + public AFRA AFRA { get; set; } + /// /// Initializes a new instance of the class. /// diff --git a/Warcraft.NET/Files/Phys/Entries/SPHSEntry.cs b/Warcraft.NET/Files/Phys/Entries/SPHSEntry.cs new file mode 100644 index 0000000..51ceec7 --- /dev/null +++ b/Warcraft.NET/Files/Phys/Entries/SPHSEntry.cs @@ -0,0 +1,52 @@ +using System.IO; +using System.Numerics; +using Warcraft.NET.Extensions; + +namespace Warcraft.NET.Files.Phys.Entries +{ + public class SPHSEntry + { + /// + /// Gets or Sets the local position of the Sphere shape + /// + public Vector3 LocalPosition; + + /// + /// Gets or Sets the radius of the Sphere shape + /// + public float Radius; + + public SPHSEntry(byte[] data) + { + using (var ms = new MemoryStream(data)) + using (var br = new BinaryReader(ms)) + { + LocalPosition = br.ReadVector3(); + Radius = br.ReadSingle(); + } + } + + /// + /// Gets the size of a Sphere entry. + /// + /// The size. + public static int GetSize() + { + return 16; + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + { + using (var bw = new BinaryWriter(ms)) + { + bw.WriteVector3(LocalPosition); + bw.Write(Radius); + } + return ms.ToArray(); + } + } + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/Phys/Enums/BodyType.cs b/Warcraft.NET/Files/Phys/Enums/BodyType.cs new file mode 100644 index 0000000..070e59b --- /dev/null +++ b/Warcraft.NET/Files/Phys/Enums/BodyType.cs @@ -0,0 +1,9 @@ +namespace Warcraft.NET.Files.Phys.Enums +{ + public enum BodyType : ushort + { + Root = 0, + Dynamic = 1, + Unk = 2, + } +} diff --git a/Warcraft.NET/Files/Phys/Enums/JointType.cs b/Warcraft.NET/Files/Phys/Enums/JointType.cs new file mode 100644 index 0000000..0ea6327 --- /dev/null +++ b/Warcraft.NET/Files/Phys/Enums/JointType.cs @@ -0,0 +1,12 @@ +namespace Warcraft.NET.Files.Phys.Enums +{ + public enum JointType : ushort + { + SphericalJoint = 0, + ShoulderJoint = 1, + WeldJoint = 2, + RevoluteJoint = 3, + PrismaticJoint = 4, + DistanceJoint = 5, + } +} diff --git a/Warcraft.NET/Files/Phys/Enums/ShapeType.cs b/Warcraft.NET/Files/Phys/Enums/ShapeType.cs new file mode 100644 index 0000000..1f599e5 --- /dev/null +++ b/Warcraft.NET/Files/Phys/Enums/ShapeType.cs @@ -0,0 +1,10 @@ +namespace Warcraft.NET.Files.Phys.Enums +{ + public enum ShapeType : short + { + Box = 0, + Caps = 1, + Sphere = 2, + Polytope = 3, + } +} diff --git a/Warcraft.NET/Files/Phys/Structures/PlytData.cs b/Warcraft.NET/Files/Phys/Structures/PlytData.cs new file mode 100644 index 0000000..65ddf95 --- /dev/null +++ b/Warcraft.NET/Files/Phys/Structures/PlytData.cs @@ -0,0 +1,29 @@ +using System; +using System.Numerics; + +namespace Warcraft.NET.Files.Phys.Structures +{ + [Serializable] + public struct PlytData + { + /// + /// gets or sets the vertices. Amount is defined by header.VertexCount + /// + public Vector3[] Vertices; //amount = VertexCount in Header + + /// + /// gets or sets the Unk1 array. Unknown purpose. Amount is defined by header.Count10 + /// + public byte[] Unk1; //multiple of 16 -> amount = count_10 in Header + + /// + /// gets or sets the Unk2 array. Unknown purpose.Amount is defined by header.Count10 + /// + public byte[] Unk2; //amount = count_10 in Header + + /// + /// gets or sets the Unk2 array. Unknown purpose.Amount is defined by header.NodeCount + /// + public PlytNode[] Nodes; + } +} diff --git a/Warcraft.NET/Files/Phys/Structures/PlytHeader.cs b/Warcraft.NET/Files/Phys/Structures/PlytHeader.cs new file mode 100644 index 0000000..c6b871a --- /dev/null +++ b/Warcraft.NET/Files/Phys/Structures/PlytHeader.cs @@ -0,0 +1,62 @@ +using System; + +namespace Warcraft.NET.Files.Phys.Structures +{ + public struct PlytHeader + { + /// + /// gets or sets the amount of vertices for this polytope + /// + public uint VertexCount; + + /// + /// gets or sets unknown data + /// + public byte[] Unk0; + + /// + /// gets or sets certain runtime data. Unknown purpose + /// + public UInt64 RUNTIME08ptrData0; + + /// + /// gets or sets the count10, which defines how many Unk1[] and Unk2[] there are inside the Data. + /// + public uint Count10; + + /// + /// gets or sets the Unk1 array. Unknown purpose + /// + public byte[] Unk1; + + /// + /// gets or sets certain runtime data. Unknown purpose + /// + public UInt64 RUNTIME18ptrData1; + + /// + /// gets or sets certain runtime data. Unknown purpose + /// + public UInt64 RUNTIME20ptrData2; + + /// + /// gets or sets the amount of nodes. Defines how Vertices are connected + /// + public uint NodeCount; + + /// + /// gets or sets the Unk2 array. Unknown purpose + /// + public byte[] Unk2; + + /// + /// gets or sets certain runtime data. Unknown purpose + /// + public UInt64 RUNTIME30ptrData3; + + /// + /// gets or sets the Unk3 array. Unknown purpose + /// + public float[] Unk3; + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/Phys/Structures/PlytNode.cs b/Warcraft.NET/Files/Phys/Structures/PlytNode.cs new file mode 100644 index 0000000..c727e69 --- /dev/null +++ b/Warcraft.NET/Files/Phys/Structures/PlytNode.cs @@ -0,0 +1,29 @@ +using System; + +namespace Warcraft.NET.Files.Phys.Structures +{ + + [Serializable] + public struct PlytNode + { + /// + /// Unknown byte. Always 1 or -1 + /// + public byte Unk; // 1 or -1 + + /// + /// Index into the data.Vertices + /// + public byte VertexIndex; // index in vertex list + + /// + /// Index into data.Nodes + /// + public byte UnkIndex0; // index into the nodes + + /// + /// Index into data.Nodes + /// + public byte UnkIndex1; // index into the nodes + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/SKIN/Skin.cs b/Warcraft.NET/Files/SKIN/Skin.cs new file mode 100644 index 0000000..10e4511 --- /dev/null +++ b/Warcraft.NET/Files/SKIN/Skin.cs @@ -0,0 +1,179 @@ +using System.Collections.Generic; +using System.IO; +using Warcraft.NET.Attribute; +using Warcraft.NET.Extensions; +using Warcraft.NET.Files.Structures; + +namespace Warcraft.NET.Files.Skin +{ + [AutoDocFile("skin")] + public class Skin + { + /// + /// The list of Vertices used for this skin + /// indexed into M2s vertex list with offset 'GlobalVertexOffset' + /// + public List Vertices { get; set; } + + /// + /// the triangles used for this skin (Right Handed) + /// indexed into the local list of vertices + /// + public List Triangles { get; set; } + + /// + /// the bones used for this skin. + /// indexed into the bone lookup table of the m2 + /// + public List BoneIndices { get; set; } + + /// + /// the submeshes used for this skin + /// + public List Submeshes { get; set; } + + /// + /// the texture units used for this skin. + /// + public List TextureUnits { get; set; } + + /// + /// start offset into M2.Vertices -> something else in wotlk + /// + public uint GlobalVertexOffset; + + /// + /// the shadowbatches used in this skin + /// + public List ShadowBatches; + + /// + /// unknown field. Maybe padding? + /// + public byte[] Unk0; + + public Skin(byte[] inData) + { + using (var ms = new MemoryStream(inData)) + using (var br = new BinaryReader(ms)) + { + var magic = br.ReadUInt32(); + var nVertices = br.ReadUInt32(); + var ofsVertices = br.ReadUInt32(); + var nIndices = br.ReadUInt32(); + var ofsIndices = br.ReadUInt32(); + var nBones = br.ReadUInt32(); + var ofsBones = br.ReadUInt32(); + var nSubmeshes = br.ReadUInt32(); + var ofsSubmeshes = br.ReadUInt32(); + var nBatches = br.ReadUInt32(); + var ofsBatches = br.ReadUInt32(); + GlobalVertexOffset = br.ReadUInt32(); + + ShadowBatches = new List(); + Unk0 = new byte[8]; + var nShadow_batches = br.ReadUInt32(); + var ofsShadow_batches = br.ReadUInt32(); + Unk0 = br.ReadBytes(8); + ShadowBatches = ReadStructList(nShadow_batches, ofsShadow_batches, br); + Vertices = ReadStructList(nVertices, ofsVertices, br); + Triangles = ReadStructList(nIndices / 3, ofsIndices, br); + BoneIndices = ReadStructList(nBones, ofsBones, br); + Submeshes = ReadStructList(nSubmeshes, ofsSubmeshes, br); + TextureUnits = ReadStructList(nBatches, ofsBatches, br); + + } + } + private List ReadStructList(uint count, uint offset, BinaryReader br) where T : struct + { + br.BaseStream.Position = offset; + List list = new List(); + + for (var i = 0; i < count; i++) + list.Add(br.ReadStruct()); + + return list; + } + + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + using (var bw = new BinaryWriter(ms)) + { + bw.Write(new byte[64]); + foreach (ushort vertex in Vertices) + { + bw.Write(vertex); + } + + int _ofsTriangles = (int)bw.BaseStream.Position; + foreach (M2Triangle triangle in Triangles) + { + bw.WriteStruct(triangle); + } + + int _ofsBones = (int)bw.BaseStream.Position; + foreach (M2SkinBoneStruct bone in BoneIndices) + { + bw.WriteStruct(bone); + } + + int _ofsSubmeshes = (int)bw.BaseStream.Position; + foreach (M2SkinSection submesh in Submeshes) + { + bw.WriteStruct(submesh); + } + + int _ofsTexUnits = (int)bw.BaseStream.Position; + foreach (M2Batch texUnit in TextureUnits) + { + bw.WriteStruct(texUnit); + } + + int _ofsShadowBatches = (int)bw.BaseStream.Position; + foreach (M2ShadowBatch shadowBatch in ShadowBatches) + { + bw.WriteStruct(shadowBatch); + } + //Writing actual header data + bw.BaseStream.Position = 0; + bw.Write('S'); + bw.Write('K'); + bw.Write('I'); + bw.Write('N'); + + bw.Write(Vertices.Count); + var _ofsVertices = 64; + _ofsVertices = 48; + bw.Write(_ofsVertices); + + bw.Write(Triangles.Count * 3); + bw.Write(_ofsTriangles); + + bw.Write(BoneIndices.Count); + bw.Write(_ofsBones); + + bw.Write(Submeshes.Count); + bw.Write(_ofsSubmeshes); + + bw.Write(TextureUnits.Count); + bw.Write(_ofsTexUnits); + + bw.Write(GlobalVertexOffset); + + bw.Write(ShadowBatches.Count); + bw.Write(_ofsShadowBatches); + bw.Write(Unk0); + return ms.ToArray(); + } + } + + /// + public uint GetSize() + { + return (uint)Serialize().Length; + } + } +} + + diff --git a/Warcraft.NET/Files/SKIN/SkinStructs.cs b/Warcraft.NET/Files/SKIN/SkinStructs.cs new file mode 100644 index 0000000..eb386f1 --- /dev/null +++ b/Warcraft.NET/Files/SKIN/SkinStructs.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Warcraft.NET.Files.Structures; + +namespace Warcraft.NET.Files.SKIN +{ + public struct M2SkinSection + { + public UInt16 skinSectionId; // Mesh part ID, see below. + public UInt16 Level; // (level << 16) is added (|ed) to startTriangle and alike to avoid having to increase those fields to uint32s. + public UInt16 vertexStart; // Starting vertex number. + public UInt16 vertexCount; // Number of vertices. + public UInt16 indexStart; // Starting triangle index (that's 3* the number of triangles drawn so far). + public UInt16 indexCount; // Number of triangle indices. + public UInt16 boneCount; // Number of elements in the bone lookup table. Max seems to be 256 in Wrath. Shall be ≠ 0. + public UInt16 boneComboIndex; // Starting index in the bone lookup table. + public UInt16 boneInfluences; // <= 4 + // from <=BC documentation: Highest number of bones needed at one time in this Submesh --Tinyn (wowdev.org) + // In 2.x this is the amount of of bones up the parent-chain affecting the submesh --NaK + // Highest number of bones referenced by a vertex of this submesh. 3.3.5a and suspectedly all other client revisions. -- Skarn + public UInt16 centerBoneIndex; + public C3Vector centerPosition; // Average position of all the vertices in the sub mesh. + //≥BC + public C3Vector sortCenterPosition; // The center of the box when an axis aligned box is built around the vertices in the submesh. + public float sortRadius; // Distance of the vertex farthest from CenterBoundingBox. + } + + public struct BoneStruct + { + public byte b1; + public byte b2; + public byte b3; + public byte b4; + } + + public struct M2Batch + { + public byte flags; // Usually 16 for static textures, and 0 for animated textures. &0x1: materials invert something; &0x2: transform &0x4: projected texture; &0x10: something batch compatible; &0x20: projected texture?; &0x40: possibly don't multiply transparency by texture weight transparency to get final transparency value(?) + public sbyte priorityPlane; + public UInt16 shader_id; // See below. + public UInt16 skinSectionIndex; // A duplicate entry of a submesh from the list above. + public UInt16 geosetIndex; // See below. New name: flags2. 0x2 - projected. 0x8 - EDGF chunk in m2 is mandatory and data from is applied to this mesh + public UInt16 colorIndex; // A Color out of the Colors-Block or -1 if none. + public UInt16 materialIndex; // The renderflags used on this texture-unit. + public UInt16 materialLayer; // Capped at 7 (see CM2Scene::BeginDraw) + public UInt16 textureCount; // 1 to 4. See below. Also seems to be the number of textures to load, starting at the texture lookup in the next field (0x10). + public UInt16 textureComboIndex; // Index into Texture lookup table + public UInt16 textureCoordComboIndex; // Index into the texture mapping lookup table. + public UInt16 textureWeightComboIndex; // Index into transparency lookup table. + public UInt16 textureTransformComboIndex; // Index into uvanimation lookup table. + } + + public struct M2ShadowBatch + { + byte flags; // if auto-generated: M2Batch.flags & 0xFF + byte flags2; // if auto-generated: (renderFlag[i].flags & 0x04 ? 0x01 : 0x00) + // | (!renderFlag[i].blendingmode ? 0x02 : 0x00) + // | (renderFlag[i].flags & 0x80 ? 0x04 : 0x00) + // | (renderFlag[i].flags & 0x400 ? 0x06 : 0x00) + public UInt16 _unknown1; + public UInt16 submesh_id; + public UInt16 texture_id; // already looked-up + public UInt16 color_id; + public UInt16 transparency_id; // already looked-up + } + + public struct M2Triangle //Left handed + { + public ushort V1; + public ushort V3; + public ushort V2; + } +} diff --git a/Warcraft.NET/Files/Skel/Chunks/SKA1.cs b/Warcraft.NET/Files/Skel/Chunks/SKA1.cs new file mode 100644 index 0000000..760f8a0 --- /dev/null +++ b/Warcraft.NET/Files/Skel/Chunks/SKA1.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Net.Mail; +using Warcraft.NET.Extensions; +using Warcraft.NET.Files.Interfaces; +using Warcraft.NET.Files.M2.Entries; + +namespace Warcraft.NET.Files.Skel.Chunks +{ + public class SKA1 : IIFFChunk, IBinarySerializable + { + /// + /// Holds the binary chunk signature. + /// + public const string Signature = "SKA1"; + + /// + /// Gets or Sets the attachments + /// + public List Attachments { get; set; } + /// + /// Gets or Sets the AttachmentLookupTable + /// + public List AttachLookup { get; set; } + /// + /// Initializes a new instance of + /// + public SKA1() { } + + /// + /// Initializes a new instance of + /// + /// ExtendedData. + public SKA1(byte[] inData) => LoadBinaryData(inData); + + /// + public string GetSignature() { return Signature; } + + /// + public uint GetSize() { return (uint)Serialize().Length; } + + /// + public void LoadBinaryData(byte[] inData) + { + using (var ms = new MemoryStream(inData)) + using (var br = new BinaryReader(ms)) + { + var nAttachments = br.ReadUInt32(); + var ofsAttachments = br.ReadUInt32(); + var nAttachLookup = br.ReadUInt32(); + var ofsAttachLookup = br.ReadUInt32(); + Attachments = ReadStructList(nAttachments, ofsAttachments, br); + AttachLookup = ReadStructList(nAttachLookup, ofsAttachLookup, br); + } + Console.WriteLine("Finished SKA1"); + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + using (var bw = new BinaryWriter(ms)) + { + return null; + } + } + + private List ReadStructList(uint count, uint offset, BinaryReader br) where T : struct + { + br.BaseStream.Position = offset; + List list = new List(); + + for (var i = 0; i < count; i++) + list.Add(br.ReadStruct()); + + return list; + } + } +} diff --git a/Warcraft.NET/Files/Skel/Chunks/SKB1.cs b/Warcraft.NET/Files/Skel/Chunks/SKB1.cs new file mode 100644 index 0000000..5d5a963 --- /dev/null +++ b/Warcraft.NET/Files/Skel/Chunks/SKB1.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.IO; +using Warcraft.NET.Extensions; +using Warcraft.NET.Files.Interfaces; +using Warcraft.NET.Files.M2.Entries; + +namespace Warcraft.NET.Files.Skel.Chunks +{ + public class SKB1 : IIFFChunk, IBinarySerializable + { + /// + /// Holds the binary chunk signature. + /// + public const string Signature = "SKB1"; + + /// + /// Gets or Sets the bones + /// + public List Bones { get; set; } + + /// + /// Gets or Sets the KeyBoneLookupTable + /// + public List KeyBoneLookup { get; set; } + + /// + /// Initializes a new instance of + /// + public SKB1() { } + + /// + /// Initializes a new instance of + /// + /// ExtendedData. + public SKB1(byte[] inData) => LoadBinaryData(inData); + + /// + public string GetSignature() { return Signature; } + + /// + public uint GetSize() { return (uint)Serialize().Length; } + + /// + public void LoadBinaryData(byte[] inData) + { + using (var ms = new MemoryStream(inData)) + using (var br = new BinaryReader(ms)) + { + var nBones = br.ReadUInt32(); + var ofsBones = br.ReadUInt32(); + var nKeyboneLookup = br.ReadUInt32(); + var ofsKeyboneLookup = br.ReadUInt32(); + Bones = ReadStructList(nBones, ofsBones, br); + KeyBoneLookup = ReadStructList(nKeyboneLookup, ofsKeyboneLookup, br); + } + Console.WriteLine("Finished SKB1"); + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + using (var bw = new BinaryWriter(ms)) + { + return null; + } + } + + private List ReadStructList(uint count, uint offset, BinaryReader br) where T : struct + { + br.BaseStream.Position = offset; + List list = new List(); + + for (var i = 0; i < count; i++) + list.Add(br.ReadStruct()); + + return list; + } + } +} diff --git a/Warcraft.NET/Files/Skel/Chunks/SKL1.cs b/Warcraft.NET/Files/Skel/Chunks/SKL1.cs new file mode 100644 index 0000000..43d6309 --- /dev/null +++ b/Warcraft.NET/Files/Skel/Chunks/SKL1.cs @@ -0,0 +1,82 @@ +using System; +using System.Collections.Generic; +using System.IO; +using Warcraft.NET.Extensions; +using Warcraft.NET.Files.Interfaces; + +namespace Warcraft.NET.Files.Skel.Chunks +{ + public class SKL1 : IIFFChunk, IBinarySerializable + { + /// + /// Holds the binary chunk signature. + /// + public const string Signature = "SKL1"; + + /// + /// Gets or Sets the Unk Field (always 256 so far, possibly flags?) + /// + public uint Unk0; + + /// + /// Gets or Sets the KeyBoneLookupTable + /// + public List Name { get; set; } + + public uint Unk1; + + /// + /// Initializes a new instance of + /// + public SKL1() { } + + /// + /// Initializes a new instance of + /// + /// ExtendedData. + public SKL1(byte[] inData) => LoadBinaryData(inData); + + /// + public string GetSignature() { return Signature; } + + /// + public uint GetSize() { return (uint)Serialize().Length; } + + /// + public void LoadBinaryData(byte[] inData) + { + using (var ms = new MemoryStream(inData)) + using (var br = new BinaryReader(ms)) + { + Unk0 = br.ReadUInt32(); + uint count = br.ReadUInt32(); + uint offset = br.ReadUInt32(); + if(count>0) + Name = ReadStructList(count, offset, br); + Unk1 = br.ReadUInt32(); + } + Console.WriteLine("Finished SKL1"); + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + using (var bw = new BinaryWriter(ms)) + { + return null; + } + } + + private List ReadStructList(uint count, uint offset, BinaryReader br) where T : struct + { + br.BaseStream.Position = offset; + List list = new List(); + + for (var i = 0; i < count; i++) + list.Add(br.ReadStruct()); + + return list; + } + } +} diff --git a/Warcraft.NET/Files/Skel/Chunks/SKPD.cs b/Warcraft.NET/Files/Skel/Chunks/SKPD.cs new file mode 100644 index 0000000..2005215 --- /dev/null +++ b/Warcraft.NET/Files/Skel/Chunks/SKPD.cs @@ -0,0 +1,82 @@ +using System; +using System.Collections.Generic; +using System.IO; +using Warcraft.NET.Extensions; +using Warcraft.NET.Files.Interfaces; + +namespace Warcraft.NET.Files.Skel.Chunks +{ + public class SKPD : IIFFChunk, IBinarySerializable + { + /// + /// Holds the binary chunk signature. + /// + public const string Signature = "SKPD"; + + /// + /// unk + /// + public uint Unk0; + + /// + /// unk + /// + public uint Unk1; + + /// + /// unk + /// + public uint ParentSkeletonFileID; + + /// + /// unk + /// + public uint Unk2; + + /// + /// Gets or Sets the KeyBoneLookupTable + /// + public List Name { get; set; } + + /// + /// Initializes a new instance of + /// + public SKPD() { } + + /// + /// Initializes a new instance of + /// + /// ExtendedData. + public SKPD(byte[] inData) => LoadBinaryData(inData); + + /// + public string GetSignature() { return Signature; } + + /// + public uint GetSize() { return (uint)Serialize().Length; } + + /// + public void LoadBinaryData(byte[] inData) + { + using (var ms = new MemoryStream(inData)) + using (var br = new BinaryReader(ms)) + { + Unk0 = br.ReadUInt32(); + Unk1 = br.ReadUInt32(); + ParentSkeletonFileID = br.ReadUInt32(); + Unk2 = br.ReadUInt32(); + } + Console.WriteLine("Finished SKPD"); + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + using (var bw = new BinaryWriter(ms)) + { + return null; + } + } + } +} diff --git a/Warcraft.NET/Files/Skel/Chunks/SKS1.cs b/Warcraft.NET/Files/Skel/Chunks/SKS1.cs new file mode 100644 index 0000000..0982c64 --- /dev/null +++ b/Warcraft.NET/Files/Skel/Chunks/SKS1.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; +using System.IO; +using Warcraft.NET.Extensions; +using Warcraft.NET.Files.Interfaces; +using Warcraft.NET.Files.M2.Entries; + +namespace Warcraft.NET.Files.Skel.Chunks +{ + public class SKS1 : IIFFChunk, IBinarySerializable + { + /// + /// Holds the binary chunk signature. + /// + public const string Signature = "SKS1"; + + /// + /// Gets or Sets the global sequences + /// + public List Sequences { get; set; } + + /// + /// Gets or Sets the animations + /// + public List Animations { get; set; } + + /// + /// Gets or Sets the animation lookups + /// + public List AnimationLookups { get; set; } + + /// + /// Gets or Sets the Unknown field (padding?) + /// + public UInt64 Unk { get; set; } + + /// + /// Initializes a new instance of + /// + public SKS1() { } + + /// + /// Initializes a new instance of + /// + /// ExtendedData. + public SKS1(byte[] inData) => LoadBinaryData(inData); + + /// + public string GetSignature() { return Signature; } + + /// + public uint GetSize() { return (uint)Serialize().Length; } + + /// + public void LoadBinaryData(byte[] inData) + { + using (var ms = new MemoryStream(inData)) + using (var br = new BinaryReader(ms)) + { + var nSequences = br.ReadUInt32(); + var ofsSequences = br.ReadUInt32(); + var nAnimations = br.ReadUInt32(); + var ofsAnimations = br.ReadUInt32(); + var nAnimationLookup = br.ReadUInt32(); + var ofsAnimationLookup = br.ReadUInt32(); + Unk = br.ReadUInt64(); + Sequences = ReadStructList(nSequences, ofsSequences, br); + Animations = ReadStructList(nAnimations, ofsAnimations, br); + AnimationLookups = ReadStructList(nAnimationLookup, ofsAnimationLookup, br); + } + Console.WriteLine("Finished SKS1"); + + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + using (var bw = new BinaryWriter(ms)) + { + return null; + } + } + + private List ReadStructList(uint count, uint offset, BinaryReader br) where T : struct + { + br.BaseStream.Position = offset; + List list = new List(); + + for (var i = 0; i < count; i++) + list.Add(br.ReadStruct()); + + return list; + } + } +} diff --git a/Warcraft.NET/Files/Skel/Skel.cs b/Warcraft.NET/Files/Skel/Skel.cs new file mode 100644 index 0000000..0d64f5b --- /dev/null +++ b/Warcraft.NET/Files/Skel/Skel.cs @@ -0,0 +1,75 @@ +using Warcraft.NET.Attribute; +using Warcraft.NET.Files.Skel.Chunks; +using Warcraft.NET.Files.M2.Chunks.Legion; + +namespace Warcraft.NET.Files.Skel +{ + public class Skel : ChunkedFile + { + /// + /// contains the name and unknown data of the skeleton + /// + [ChunkOrder(1)] + public SKL1 Skeleton { get; set; } + + /// + /// contains the animations of the skeleton + /// + [ChunkOptional] + public SKS1 Animations { get; set; } + + /// + /// contains the attachments of the skeleton + /// + [ChunkOptional] + public SKA1 Attachments { get; set; } + + /// + /// contains the bones of the skeleton + /// + [ChunkOptional] + public SKB1 Bones { get; set; } + + /// + /// contains the animation file ids of the skeleton + /// + [ChunkOptional] + public AFID AnimationFileIDs { get; set; } + + /// + /// contains the animations of the skeleton + /// + [ChunkOptional] + public SKPD ParentSkelFileID { get; set; } + + /// + /// contains the bone file ids of the skeleton + /// + [ChunkOptional] + public BFID BoneFileIDs { get; set; } + + /// + /// Initializes a new instance of the class. + /// + public Skel() + { + + } + + /// + /// Initializes a new instance of the class. + /// + /// The binary data. + public Skel(byte[] inData) : base(inData) + { + + } + public override bool IsReverseSignature() + { + return false; + } + + } +} + + diff --git a/Warcraft.NET/Files/Structures/C3Vector.cs b/Warcraft.NET/Files/Structures/C3Vector.cs new file mode 100644 index 0000000..5f925ec --- /dev/null +++ b/Warcraft.NET/Files/Structures/C3Vector.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +using Warcraft.NET.Files.Interfaces; + +namespace Warcraft.NET.Files.Structures +{ + /// + /// A structure representing a 3D vector of floats. + /// + public struct C3Vector : IFlattenableData + { + public float X { get; set; } + public float Y { get; set; } + public float Z { get; set; } + + public C3Vector(float inX, float inY, float inZ) + { + X = inX; + Y = inY; + Z = inZ; + } + + public Vector3 asVec3(){ + return new Vector3(X,Y,Z); + } + + public byte[] asBytes(){ + return BitConverter.GetBytes(X).Concat(BitConverter.GetBytes(Y)).Concat(BitConverter.GetBytes(Z)).ToArray(); + } + + public C3Vector(byte[] input) + { + if (input.Length == 12) + { + X = BitConverter.ToSingle(input,0); + Y = BitConverter.ToSingle(input,4); + Z = BitConverter.ToSingle(input,8); + } + } + + /// + public override string ToString() + { + return $"{X}, {Y}, {Z}"; + } + + public IReadOnlyCollection Flatten() + { + return new[] { X, Y, Z }; + } + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/Structures/CImVector.cs b/Warcraft.NET/Files/Structures/CImVector.cs new file mode 100644 index 0000000..ad01d56 --- /dev/null +++ b/Warcraft.NET/Files/Structures/CImVector.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +using System.Text; +using Warcraft.NET.Files.Interfaces; + +namespace Warcraft.NET.Files.Structures +{ + public struct CImVector : IFlattenableData + { + public byte r, g, b, a; + + public CImVector(byte _r, byte _g, byte _b, byte _a) + { + r = _r; + g = _g; + b = _b; + a = _a; + } + + public byte[] toBytes() + { + byte[] arr = new byte[4] { r, g, b, a }; + return arr; + } + + public CImVector(byte[] input) + { + if (input.Length == 4) + { + r = input[0]; + g = input[1]; + b = input[2]; + a = input[3]; + } + } + + /// + public override string ToString() + { + return $"{r}, {g}, {b}, {a}"; + } + + public IReadOnlyCollection Flatten() + { + return new[] { r,g,b,a }; + } + } +} diff --git a/Warcraft.NET/Files/Structures/M2Batch.cs b/Warcraft.NET/Files/Structures/M2Batch.cs new file mode 100644 index 0000000..37040e8 --- /dev/null +++ b/Warcraft.NET/Files/Structures/M2Batch.cs @@ -0,0 +1,73 @@ +namespace Warcraft.NET.Files.Structures +{ + public struct M2Batch + { + /// + /// Texture Flags + /// Usually 16 for static textures, and 0 for animated textures. &0x1: materials invert something; &0x2: transform &0x4: projected texture; &0x10: something batch compatible; &0x20: projected texture?; &0x40: possibly don't multiply transparency by texture weight transparency to get final transparency value(?) + /// + public byte Flags; + + /// + /// Priority Plane + /// + public sbyte PriorityPlane; + + /// + /// ShaderID + /// negative = direct selection + /// positive = selection trough a function. See wiki for more information + /// + public ushort ShaderId; + + /// + /// A duplicate entry of a submesh from the list above. + /// + public ushort SkinSectionIndex; + + /// + /// New name: flags2. 0x2 - projected. 0x8 - EDGF chunk in m2 is mandatory and data from is applied to this mesh + /// + public ushort GeosetIndex; + + /// + /// A Color out of the Colors-Block or -1 if none. + /// + public ushort ColorIndex; + + /// + /// The renderflags used on this texture-unit. Index into M2 Materials + /// + public ushort MaterialIndex; + + /// + /// Capped at 7 (CM2Scene::BeginDraw) + /// + public ushort MaterialLayer; + + /// + /// 1 to 4. See below. Also seems to be the number of textures to load, starting at the texture lookup in the next field (0x10). + /// + public ushort TextureCount; + + /// + /// Index into Texture lookup table + /// + public ushort TextureComboIndex; + + /// + /// Index into the texture mapping lookup table. + /// + public ushort TextureCoordComboIndex; + + /// + /// Index into transparency lookup table. + /// + public ushort TextureWeightComboIndex; + + /// + /// Index into uvanimation lookup table. + /// + public ushort TextureTransformComboIndex; + } +} diff --git a/Warcraft.NET/Files/Structures/M2ShadowBatch.cs b/Warcraft.NET/Files/Structures/M2ShadowBatch.cs new file mode 100644 index 0000000..db25b23 --- /dev/null +++ b/Warcraft.NET/Files/Structures/M2ShadowBatch.cs @@ -0,0 +1,41 @@ +namespace Warcraft.NET.Files.Structures +{ + public struct M2ShadowBatch + { + /// + /// if auto-generated: M2Batch.Flags & 0xFF + /// + public byte Flags; + + /// + /// gets auto generated if certain flags in TextureUnit are set + /// See wiki for more information + /// + public byte Flags2; + + /// + /// unknown field + /// + public ushort Unk1; + + /// + /// same as TextureUnit + /// + public ushort SubmeshId; + + /// + /// same as TextureUnit + /// + public ushort TextureId; // already looked-up + + /// + /// same as TextureUnit + /// + public ushort ColorId; + + /// + /// same as TextureUnit + /// + public ushort TransparencyId; // already looked-up + } +} diff --git a/Warcraft.NET/Files/Structures/M2SkinBoneStruct.cs b/Warcraft.NET/Files/Structures/M2SkinBoneStruct.cs new file mode 100644 index 0000000..6f813ee --- /dev/null +++ b/Warcraft.NET/Files/Structures/M2SkinBoneStruct.cs @@ -0,0 +1,25 @@ +namespace Warcraft.NET.Files.Structures +{ + public struct M2SkinBoneStruct + { + /// + /// Bone 1 Index into BoneLookupTable from M2. see wiki for exact calculation + /// + public byte Bone1ID; + + /// + /// Bone 2 Index into BoneLookupTable from M2. see wiki for exact calculation + /// + public byte Bone2ID; + + /// + /// Bone 3 Index into BoneLookupTable from M2. see wiki for exact calculation + /// + public byte Bone3ID; + + /// + /// Bone 4 Index into BoneLookupTable from M2. see wiki for exact calculation + /// + public byte Bone4ID; + } +} diff --git a/Warcraft.NET/Files/Structures/M2SkinSection.cs b/Warcraft.NET/Files/Structures/M2SkinSection.cs new file mode 100644 index 0000000..cbd4b55 --- /dev/null +++ b/Warcraft.NET/Files/Structures/M2SkinSection.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.Numerics; +using System.Text; + +namespace Warcraft.NET.Files.Structures +{ + public struct M2SkinSection + { + /// + /// Mesh part ID, see wiki for exact calculation + /// + public ushort SkinSectionId; + + /// + /// (level << 16) is added (|ed) to startTriangle and alike to avoid having to increase those fields to uint32s. + /// + public ushort Level; + + /// + /// Starting Vertex. Index into local vertex list + /// + public ushort VertexStart; + + /// + /// Number of Vertices taken from local vertex list + /// + public ushort VertexCount; + + /// + /// Starting triangle index. + /// + public ushort IndexStart; + + /// + /// Number of triangle indices. + /// + public ushort IndexCount; + + /// + /// Number of elements in the bone lookup table. Max seems to be 256 in Wrath. Shall be ≠ 0. + /// + public ushort BoneCount; + + /// + /// Starting index in the bone lookup table. + /// + public ushort BoneComboIndex; + + /// + /// <= 4 + /// from <=BC documentation: Highest number of bones needed at one time in this Submesh --Tinyn (wowdev.org) + /// In 2.x this is the amount of of bones up the parent-chain affecting the submesh --NaK + /// Highest number of bones referenced by a vertex of this submesh. 3.3.5a and suspectedly all other client revisions. -- Skarn + /// + public ushort BoneInfluences; + + /// + /// Index of the center bone + /// + public ushort CenterBoneIndex; + + /// + /// Average position of all the vertices in the sub mesh. + /// + public Vector3 CenterPosition; + + //≥BC + /// + /// The center of the box when an axis aligned box is built around the vertices in the submesh. + /// + public Vector3 SortCenterPosition; + + /// + /// Distance of the vertex farthest from CenterBoundingBox. + /// + public float SortRadius; + } +} diff --git a/Warcraft.NET/Files/Structures/M2Triangle.cs b/Warcraft.NET/Files/Structures/M2Triangle.cs new file mode 100644 index 0000000..639055d --- /dev/null +++ b/Warcraft.NET/Files/Structures/M2Triangle.cs @@ -0,0 +1,25 @@ +namespace Warcraft.NET.Files.Structures +{ + /// + /// Triangle read from skin. + /// Default = Right Handed + /// To make it left handed, swap the second and third vertex + /// + public struct M2Triangle + { + /// + /// the first vertex of the Triangle + /// + public ushort Vertex1; + + /// + /// the second vertex of the Triangle + /// + public ushort Vertex2; + + /// + /// the third vertex of the Triangle + /// + public ushort Vertex3; + } +} diff --git a/Warcraft.NET/Files/Structures/Matrix3x4.cs b/Warcraft.NET/Files/Structures/Matrix3x4.cs new file mode 100644 index 0000000..7c6e0d6 --- /dev/null +++ b/Warcraft.NET/Files/Structures/Matrix3x4.cs @@ -0,0 +1,68 @@ +using System.Collections.Generic; +using Warcraft.NET.Files.Interfaces; +using System.Numerics; + +public class Matrix3x4 : IFlattenableData +{ + /// + /// The directional vector 'right' + /// + public Vector3 RotationX { get; set; } + + /// + /// The directional vector 'up' + /// + public Vector3 RotationY { get; set; } + + /// + /// The directional vector 'forward' + /// + public Vector3 RotationZ { get; set; } + + /// + /// The scale of the matrix + /// + public Vector3 Scale { get; set; } + + /// + /// The position of the matrix + /// + public Vector3 Position { get; set; } + + public Matrix3x4 (Vector3 column1, Vector3 column2, Vector3 column3, Vector3 column4) + { + float scaleX = column1.Length(); + float scaleY = column2.Length(); + float scaleZ = column3.Length(); + + RotationX = column1 / scaleX; + RotationY = column2 / scaleY; + RotationZ = column3 / scaleZ; + + Scale = new Vector3(scaleX, scaleY, scaleZ); + Position = column4; + } + + public Vector3 GetForward() + { + return Vector3.Normalize(RotationZ); + } + + public Vector3 GetUp() + { + return Vector3.Normalize(RotationY); + } + + public Vector3 GetRight() + { + return Vector3.Normalize(RotationX); + } + + public IReadOnlyCollection Flatten() + { + return new[] { + GetForward().X,GetForward().Y,GetForward().Z, + Scale.X, Scale.Y, Scale.Z, + Position.X, Position.Y, Position.Z }; + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/phys/Chunks/BDY4.cs b/Warcraft.NET/Files/phys/Chunks/BDY4.cs new file mode 100644 index 0000000..7f90e83 --- /dev/null +++ b/Warcraft.NET/Files/phys/Chunks/BDY4.cs @@ -0,0 +1,68 @@ +using System.Collections.Generic; +using System.IO; +using Warcraft.NET.Attribute; +using Warcraft.NET.Files.Interfaces; +using Warcraft.NET.Files.Phys.Entries; + +namespace Warcraft.NET.Files.Phys.Chunks +{ + [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)] + public class BDY4 : IIFFChunk, IBinarySerializable + { + /// + /// Holds the binary chunk signature. + /// + public const string Signature = "BDY4"; + + /// + /// Gets or Sets the used rigidbodies(V4) + /// + public List BDY4Entries = new(); + + /// + /// Initializes a new instance of + /// + public BDY4() { } + + /// + /// Initializes a new instance of + /// + /// ExtendedData. + public BDY4(byte[] inData) => LoadBinaryData(inData); + + /// + public string GetSignature() { return Signature; } + + /// + public uint GetSize() { return (uint)Serialize().Length; } + + /// + public void LoadBinaryData(byte[] inData) + { + using (var ms = new MemoryStream(inData)) + using (var br = new BinaryReader(ms)) + { + var bdy4count = br.BaseStream.Length / BDY4Entry.GetSize(); + + for (var i = 0; i < bdy4count; ++i) + { + BDY4Entries.Add(new BDY4Entry(br.ReadBytes(BDY4Entry.GetSize()))); + } + } + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + using (var bw = new BinaryWriter(ms)) + { + foreach (BDY4Entry obj in BDY4Entries) + { + bw.Write(obj.Serialize()); + } + return ms.ToArray(); + } + } + } +} diff --git a/Warcraft.NET/Files/phys/Chunks/BOXS.cs b/Warcraft.NET/Files/phys/Chunks/BOXS.cs new file mode 100644 index 0000000..98128a9 --- /dev/null +++ b/Warcraft.NET/Files/phys/Chunks/BOXS.cs @@ -0,0 +1,68 @@ +using System.Collections.Generic; +using System.IO; +using Warcraft.NET.Attribute; +using Warcraft.NET.Files.Interfaces; +using Warcraft.NET.Files.Phys.Entries; + +namespace Warcraft.NET.Files.Phys.Chunks +{ + [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)] + public class BOXS : IIFFChunk, IBinarySerializable + { + /// + /// Holds the binary chunk signature. + /// + public const string Signature = "BOXS"; + + /// + /// sets or gets the box shapes + /// + public List BOXSEntries = new(); + + /// + /// Initializes a new instance of + /// + public BOXS() { } + + /// + /// Initializes a new instance of + /// + /// ExtendedData. + public BOXS(byte[] inData) => LoadBinaryData(inData); + + /// + public string GetSignature() { return Signature; } + + /// + public uint GetSize() { return (uint)Serialize().Length; } + + /// + public void LoadBinaryData(byte[] inData) + { + using (var ms = new MemoryStream(inData)) + using (var br = new BinaryReader(ms)) + { + var boxscount = br.BaseStream.Length / BOXSEntry.GetSize(); + + for (var i = 0; i < boxscount; ++i) + { + BOXSEntries.Add(new BOXSEntry(br.ReadBytes(BOXSEntry.GetSize()))); + } + } + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + using (var bw = new BinaryWriter(ms)) + { + foreach (BOXSEntry obj in BOXSEntries) + { + bw.Write(obj.Serialize()); + } + return ms.ToArray(); + } + } + } +} diff --git a/Warcraft.NET/Files/phys/Chunks/CAPS.cs b/Warcraft.NET/Files/phys/Chunks/CAPS.cs new file mode 100644 index 0000000..26fab82 --- /dev/null +++ b/Warcraft.NET/Files/phys/Chunks/CAPS.cs @@ -0,0 +1,68 @@ +using System.IO; +using Warcraft.NET.Attribute; +using Warcraft.NET.Files.Interfaces; +using System.Collections.Generic; +using Warcraft.NET.Files.Phys.Entries; + +namespace Warcraft.NET.Files.Phys.Chunks +{ + [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)] + public class CAPS : IIFFChunk, IBinarySerializable + { + /// + /// Holds the binary chunk signature. + /// + public const string Signature = "CAPS"; + + /// + /// sets or gets the capsule shapes + /// + public List CAPSEntries = new(); + + /// + /// Initializes a new instance of + /// + public CAPS() { } + + /// + /// Initializes a new instance of + /// + /// ExtendedData. + public CAPS(byte[] inData) => LoadBinaryData(inData); + + /// + public string GetSignature() { return Signature; } + + /// + public uint GetSize() { return (uint)Serialize().Length; } + + /// + public void LoadBinaryData(byte[] inData) + { + using (var ms = new MemoryStream(inData)) + using (var br = new BinaryReader(ms)) + { + var capscount = br.BaseStream.Length / CAPSEntry.GetSize(); + + for (var i = 0; i < capscount; ++i) + { + CAPSEntries.Add(new CAPSEntry(br.ReadBytes(CAPSEntry.GetSize()))); + } + } + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + using (var bw = new BinaryWriter(ms)) + { + foreach (CAPSEntry obj in CAPSEntries) + { + bw.Write(obj.Serialize()); + } + return ms.ToArray(); + } + } + } +} diff --git a/Warcraft.NET/Files/phys/Chunks/DSTJ.cs b/Warcraft.NET/Files/phys/Chunks/DSTJ.cs new file mode 100644 index 0000000..32db762 --- /dev/null +++ b/Warcraft.NET/Files/phys/Chunks/DSTJ.cs @@ -0,0 +1,68 @@ +using System.Collections.Generic; +using System.IO; +using Warcraft.NET.Attribute; +using Warcraft.NET.Files.Interfaces; +using Warcraft.NET.Files.Phys.Entries; + +namespace Warcraft.NET.Files.Phys.Chunks +{ + [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)] + public class DSTJ : IIFFChunk, IBinarySerializable + { + /// + /// Holds the binary chunk signature. + /// + public const string Signature = "DSTJ"; + + /// + /// sets or gets the distance joints + /// + public List DSTJEntries = new(); + + /// + /// Initializes a new instance of + /// + public DSTJ() { } + + /// + /// Initializes a new instance of + /// + /// ExtendedData. + public DSTJ(byte[] inData) => LoadBinaryData(inData); + + /// + public string GetSignature() { return Signature; } + + /// + public uint GetSize() { return (uint)Serialize().Length; } + + /// + public void LoadBinaryData(byte[] inData) + { + using (var ms = new MemoryStream(inData)) + using (var br = new BinaryReader(ms)) + { + var DSTJcount = br.BaseStream.Length / DSTJEntry.GetSize(); + + for (var i = 0; i < DSTJcount; ++i) + { + DSTJEntries.Add(new DSTJEntry(br.ReadBytes(DSTJEntry.GetSize()))); + } + } + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + using (var bw = new BinaryWriter(ms)) + { + foreach (DSTJEntry obj in DSTJEntries) + { + bw.Write(obj.Serialize()); + } + return ms.ToArray(); + } + } + } +} diff --git a/Warcraft.NET/Files/phys/Chunks/JOIN.cs b/Warcraft.NET/Files/phys/Chunks/JOIN.cs new file mode 100644 index 0000000..d378ac3 --- /dev/null +++ b/Warcraft.NET/Files/phys/Chunks/JOIN.cs @@ -0,0 +1,67 @@ +using System.Collections.Generic; +using System.IO; +using Warcraft.NET.Attribute; +using Warcraft.NET.Files.Interfaces; +using Warcraft.NET.Files.Phys.Entries; + +namespace Warcraft.NET.Files.Phys.Chunks +{ + [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)] + public class JOIN : IIFFChunk, IBinarySerializable + { + /// + /// Holds the binary chunk signature. + /// + public const string Signature = "JOIN"; + + /// + /// sets or gets the joints + /// + public List JOINEntries = new(); + + /// + /// Initializes a new instance of + /// + public JOIN() { } + + /// + /// Initializes a new instance of + /// + /// ExtendedData. + public JOIN(byte[] inData) => LoadBinaryData(inData); + + /// + public string GetSignature() { return Signature; } + + /// + public uint GetSize() { return (uint)Serialize().Length; } + + /// + public void LoadBinaryData(byte[] inData) + { + using (var ms = new MemoryStream(inData)) + using (var br = new BinaryReader(ms)) + { + var JOINcount = br.BaseStream.Length / JOINEntry.GetSize(); + for (var i = 0; i < JOINcount; ++i) + { + JOINEntries.Add(new JOINEntry(br.ReadBytes(JOINEntry.GetSize()))); + } + } + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + using (var bw = new BinaryWriter(ms)) + { + foreach (JOINEntry obj in JOINEntries) + { + bw.Write(obj.Serialize()); + } + return ms.ToArray(); + } + } + } +} diff --git a/Warcraft.NET/Files/phys/Chunks/PHYS.cs b/Warcraft.NET/Files/phys/Chunks/PHYS.cs new file mode 100644 index 0000000..7226e29 --- /dev/null +++ b/Warcraft.NET/Files/phys/Chunks/PHYS.cs @@ -0,0 +1,58 @@ +using System.IO; +using Warcraft.NET.Attribute; +using Warcraft.NET.Files.Interfaces; + +namespace Warcraft.NET.Files.Phys.Chunks +{ + [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)] + public class PHYS : IIFFChunk, IBinarySerializable + { + /// + /// Holds the binary chunk signature. + /// + public const string Signature = "PHYS"; + + /// + /// Gets or Sets the version of the physics + /// + public ushort Version; + + /// + /// Initializes a new instance of + /// + public PHYS() { } + + /// + /// Initializes a new instance of + /// + /// ExtendedData. + public PHYS(byte[] inData) => LoadBinaryData(inData); + + /// + public string GetSignature() { return Signature; } + + /// + public uint GetSize() { return (uint)Serialize().Length; } + + /// + public void LoadBinaryData(byte[] inData) + { + using (var ms = new MemoryStream(inData)) + using (var br = new BinaryReader(ms)) + { + Version = br.ReadUInt16(); + } + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + using (var bw = new BinaryWriter(ms)) + { + bw.Write(Version); + return ms.ToArray(); + } + } + } +} diff --git a/Warcraft.NET/Files/phys/Chunks/PHYT.cs b/Warcraft.NET/Files/phys/Chunks/PHYT.cs new file mode 100644 index 0000000..7e2d5c7 --- /dev/null +++ b/Warcraft.NET/Files/phys/Chunks/PHYT.cs @@ -0,0 +1,58 @@ +using System.IO; +using Warcraft.NET.Attribute; +using Warcraft.NET.Files.Interfaces; + +namespace Warcraft.NET.Files.Phys.Chunks +{ + [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)] + public class PHYT : IIFFChunk, IBinarySerializable + { + /// + /// Holds the binary chunk signature. + /// + public const string Signature = "PHYT"; + + /// + /// Gets or Sets PHYT (unknown) + /// + public uint Phyt = 0; + + /// + /// Initializes a new instance of + /// + public PHYT() { } + + /// + /// Initializes a new instance of + /// + /// ExtendedData. + public PHYT(byte[] inData) => LoadBinaryData(inData); + + /// + public string GetSignature() { return Signature; } + + /// + public uint GetSize() { return (uint)Serialize().Length; } + + /// + public void LoadBinaryData(byte[] inData) + { + using (var ms = new MemoryStream(inData)) + using (var br = new BinaryReader(ms)) + { + Phyt = br.ReadUInt32(); + } + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + using (var bw = new BinaryWriter(ms)) + { + bw.Write(Phyt); + return ms.ToArray(); + } + } + } +} diff --git a/Warcraft.NET/Files/phys/Chunks/PHYV.cs b/Warcraft.NET/Files/phys/Chunks/PHYV.cs new file mode 100644 index 0000000..690428a --- /dev/null +++ b/Warcraft.NET/Files/phys/Chunks/PHYV.cs @@ -0,0 +1,71 @@ +using System.IO; +using Warcraft.NET.Attribute; +using Warcraft.NET.Files.Interfaces; + +namespace Warcraft.NET.Files.Phys.Chunks +{ + [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)] + public class PHYV : IIFFChunk, IBinarySerializable + { + /// + /// Holds the binary chunk signature. + /// + public const string Signature = "PHYV"; + + /// + /// Gets or Sets the PHYV (unknown) + /// + public float[] Values; + + /// + /// Initializes a new instance of + /// + public PHYV() { } + + /// + /// Initializes a new instance of + /// + /// ExtendedData. + public PHYV(byte[] inData) => LoadBinaryData(inData); + + /// + public string GetSignature() { return Signature; } + + /// + public uint GetSize() { return (uint)Serialize().Length; } + + /// + public void LoadBinaryData(byte[] inData) + { + using (var ms = new MemoryStream(inData)) + using (var br = new BinaryReader(ms)) + { + var PHYVcount = br.BaseStream.Length / 24; + Values = new float[PHYVcount * 6]; + for (var i = 0; i < PHYVcount; ++i) + { + Values[i] = br.ReadSingle(); + Values[i+1] = br.ReadSingle(); + Values[i+2] = br.ReadSingle(); + Values[i+3] = br.ReadSingle(); + Values[i+4] = br.ReadSingle(); + Values[i+5] = br.ReadSingle(); + } + } + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + using (var bw = new BinaryWriter(ms)) + { + foreach (float f in Values) + { + bw.Write(f); + } + return ms.ToArray(); + } + } + } +} diff --git a/Warcraft.NET/Files/phys/Chunks/PLYT.cs b/Warcraft.NET/Files/phys/Chunks/PLYT.cs new file mode 100644 index 0000000..1316870 --- /dev/null +++ b/Warcraft.NET/Files/phys/Chunks/PLYT.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.IO; +using Warcraft.NET.Attribute; +using Warcraft.NET.Files.Interfaces; +using Warcraft.NET.Files.Phys.Entries; + +namespace Warcraft.NET.Files.Phys.Chunks +{ + [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)] + public class PLYT : IIFFChunk, IBinarySerializable + { + /// + /// Holds the binary chunk signature. + /// + public const string Signature = "PLYT"; + + /// + /// sets or gets the polytope shapes + /// + public List PLYTEntries = new(); + + /// + /// Initializes a new instance of + /// + public PLYT() { } + + /// + /// Initializes a new instance of + /// + /// ExtendedData. + public PLYT(byte[] inData) => LoadBinaryData(inData); + + /// + public string GetSignature() { return Signature; } + + /// + public uint GetSize() { return (uint)Serialize().Length; } + + /// + public void LoadBinaryData(byte[] inData) + { + using (var ms = new MemoryStream(inData)) + using (var br = new BinaryReader(ms)) + { + var plyt_count = br.ReadUInt32(); + for (var i = 0; i < plyt_count; i++) + { + PLYTEntry plyt_entry = new PLYTEntry(br.ReadBytes(80)); + PLYTEntries.Add(plyt_entry); + } + for (var j = 0; j < plyt_count; j++) + { + PLYTEntry plyt_entry = PLYTEntries[j]; + plyt_entry.DeserializeData(br.ReadBytes(plyt_entry.DataSize)); + } + } + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + using (var bw = new BinaryWriter(ms)) + { + bw.Write((uint)PLYTEntries.Count); + foreach (PLYTEntry obj in PLYTEntries) + { + bw.Write(obj.SerializeHeader()); + } + foreach (PLYTEntry obj in PLYTEntries) + { + bw.Write(obj.SerializeData()); + } + return ms.ToArray(); + } + } + } +} diff --git a/Warcraft.NET/Files/phys/Chunks/PRS2.cs b/Warcraft.NET/Files/phys/Chunks/PRS2.cs new file mode 100644 index 0000000..7d1e742 --- /dev/null +++ b/Warcraft.NET/Files/phys/Chunks/PRS2.cs @@ -0,0 +1,68 @@ +using System.Collections.Generic; +using System.IO; +using Warcraft.NET.Attribute; +using Warcraft.NET.Files.Interfaces; +using Warcraft.NET.Files.Phys.Entries; + +namespace Warcraft.NET.Files.Phys.Chunks +{ + [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)] + public class PRS2 : IIFFChunk, IBinarySerializable + { + /// + /// Holds the binary chunk signature. + /// + public const string Signature = "PRS2"; + + /// + /// sets or gets the prismatic(V2) joints + /// + public List PRS2Entries = new(); + + /// + /// Initializes a new instance of + /// + public PRS2() { } + + /// + /// Initializes a new instance of + /// + /// ExtendedData. + public PRS2(byte[] inData) => LoadBinaryData(inData); + + /// + public string GetSignature() { return Signature; } + + /// + public uint GetSize() { return (uint)Serialize().Length; } + + /// + public void LoadBinaryData(byte[] inData) + { + using (var ms = new MemoryStream(inData)) + using (var br = new BinaryReader(ms)) + { + var PRS2count = br.BaseStream.Length / PRS2Entry.GetSize(); + + for (var i = 0; i < PRS2count; ++i) + { + PRS2Entries.Add(new PRS2Entry(br.ReadBytes(PRS2Entry.GetSize()))); + } + } + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + using (var bw = new BinaryWriter(ms)) + { + foreach (PRS2Entry obj in PRS2Entries) + { + bw.Write(obj.Serialize()); + } + return ms.ToArray(); + } + } + } +} diff --git a/Warcraft.NET/Files/phys/Chunks/REV2.cs b/Warcraft.NET/Files/phys/Chunks/REV2.cs new file mode 100644 index 0000000..297898a --- /dev/null +++ b/Warcraft.NET/Files/phys/Chunks/REV2.cs @@ -0,0 +1,68 @@ +using System.Collections.Generic; +using System.IO; +using Warcraft.NET.Attribute; +using Warcraft.NET.Files.Interfaces; +using Warcraft.NET.Files.Phys.Entries; + +namespace Warcraft.NET.Files.Phys.Chunks +{ + [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)] + public class REV2 : IIFFChunk, IBinarySerializable + { + /// + /// Holds the binary chunk signature. + /// + public const string Signature = "REV2"; + + /// + /// sets or gets the revolute(V2) joints + /// + public List REV2Entries = new(); + + /// + /// Initializes a new instance of + /// + public REV2() { } + + /// + /// Initializes a new instance of + /// + /// ExtendedData. + public REV2(byte[] inData) => LoadBinaryData(inData); + + /// + public string GetSignature() { return Signature; } + + /// + public uint GetSize() { return (uint)Serialize().Length; } + + /// + public void LoadBinaryData(byte[] inData) + { + using (var ms = new MemoryStream(inData)) + using (var br = new BinaryReader(ms)) + { + var REV2count = br.BaseStream.Length / REV2Entry.GetSize(); + + for (var i = 0; i < REV2count; ++i) + { + REV2Entries.Add(new REV2Entry(br.ReadBytes(REV2Entry.GetSize()))); + } + } + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + using (var bw = new BinaryWriter(ms)) + { + foreach (REV2Entry obj in REV2Entries) + { + bw.Write(obj.Serialize()); + } + return ms.ToArray(); + } + } + } +} diff --git a/Warcraft.NET/Files/phys/Chunks/SHJ2.cs b/Warcraft.NET/Files/phys/Chunks/SHJ2.cs new file mode 100644 index 0000000..c8ae2e2 --- /dev/null +++ b/Warcraft.NET/Files/phys/Chunks/SHJ2.cs @@ -0,0 +1,68 @@ +using System.Collections.Generic; +using System.IO; +using Warcraft.NET.Attribute; +using Warcraft.NET.Files.Interfaces; +using Warcraft.NET.Files.Phys.Entries; + +namespace Warcraft.NET.Files.Phys.Chunks +{ + [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)] + public class SHJ2 : IIFFChunk, IBinarySerializable + { + /// + /// Holds the binary chunk signature. + /// + public const string Signature = "SHJ2"; + + /// + /// sets or gets the shoulder(V2) joints + /// + public List SHJ2Entries = new(); + + /// + /// Initializes a new instance of + /// + public SHJ2() { } + + /// + /// Initializes a new instance of + /// + /// ExtendedData. + public SHJ2(byte[] inData) => LoadBinaryData(inData); + + /// + public string GetSignature() { return Signature; } + + /// + public uint GetSize() { return (uint)Serialize().Length; } + + /// + public void LoadBinaryData(byte[] inData) + { + using (var ms = new MemoryStream(inData)) + using (var br = new BinaryReader(ms)) + { + var SHJ2count = br.BaseStream.Length / SHJ2Entry.GetSize(); + + for (var i = 0; i < SHJ2count; ++i) + { + SHJ2Entries.Add(new SHJ2Entry(br.ReadBytes(SHJ2Entry.GetSize()))); + } + } + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + using (var bw = new BinaryWriter(ms)) + { + foreach (SHJ2Entry obj in SHJ2Entries) + { + bw.Write(obj.Serialize()); + } + return ms.ToArray(); + } + } + } +} diff --git a/Warcraft.NET/Files/phys/Chunks/SHOJ.cs b/Warcraft.NET/Files/phys/Chunks/SHOJ.cs new file mode 100644 index 0000000..b1149ac --- /dev/null +++ b/Warcraft.NET/Files/phys/Chunks/SHOJ.cs @@ -0,0 +1,68 @@ +using System.Collections.Generic; +using System.IO; +using Warcraft.NET.Attribute; +using Warcraft.NET.Files.Interfaces; +using Warcraft.NET.Files.Phys.Entries; + +namespace Warcraft.NET.Files.Phys.Chunks +{ + [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)] + public class SHOJ : IIFFChunk, IBinarySerializable + { + /// + /// Holds the binary chunk signature. + /// + public const string Signature = "SHOJ"; + + /// + /// sets or gets the shoulder joints + /// + public List SHOJEntries = new(); + + /// + /// Initializes a new instance of + /// + public SHOJ() { } + + /// + /// Initializes a new instance of + /// + /// ExtendedData. + public SHOJ(byte[] inData) => LoadBinaryData(inData); + + /// + public string GetSignature() { return Signature; } + + /// + public uint GetSize() { return (uint)Serialize().Length; } + + /// + public void LoadBinaryData(byte[] inData) + { + using (var ms = new MemoryStream(inData)) + using (var br = new BinaryReader(ms)) + { + var SHOJcount = br.BaseStream.Length / SHOJEntry.GetSize(); + + for (var i = 0; i < SHOJcount; ++i) + { + SHOJEntries.Add(new SHOJEntry(br.ReadBytes(SHOJEntry.GetSize()))); + } + } + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + using (var bw = new BinaryWriter(ms)) + { + foreach (SHOJEntry obj in SHOJEntries) + { + bw.Write(obj.Serialize()); + } + return ms.ToArray(); + } + } + } +} diff --git a/Warcraft.NET/Files/phys/Chunks/SHP2.cs b/Warcraft.NET/Files/phys/Chunks/SHP2.cs new file mode 100644 index 0000000..21f1265 --- /dev/null +++ b/Warcraft.NET/Files/phys/Chunks/SHP2.cs @@ -0,0 +1,68 @@ +using System.Collections.Generic; +using System.IO; +using Warcraft.NET.Attribute; +using Warcraft.NET.Files.Interfaces; +using Warcraft.NET.Files.Phys.Entries; + +namespace Warcraft.NET.Files.Phys.Chunks +{ + [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)] + public class SHP2 : IIFFChunk, IBinarySerializable + { + /// + /// Holds the binary chunk signature. + /// + public const string Signature = "SHP2"; + + /// + /// sets or gets the shapes(V2) + /// + public List SHP2Entries = new(); + + /// + /// Initializes a new instance of + /// + public SHP2() { } + + /// + /// Initializes a new instance of + /// + /// ExtendedData. + public SHP2(byte[] inData) => LoadBinaryData(inData); + + /// + public string GetSignature() { return Signature; } + + /// + public uint GetSize() { return (uint)Serialize().Length; } + + /// + public void LoadBinaryData(byte[] inData) + { + using (var ms = new MemoryStream(inData)) + using (var br = new BinaryReader(ms)) + { + var SHP2count = br.BaseStream.Length / SHP2Entry.GetSize(); + + for (var i = 0; i < SHP2count; ++i) + { + SHP2Entries.Add(new SHP2Entry(br.ReadBytes(SHP2Entry.GetSize()))); + } + } + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + using (var bw = new BinaryWriter(ms)) + { + foreach (SHP2Entry obj in SHP2Entries) + { + bw.Write(obj.Serialize()); + } + return ms.ToArray(); + } + } + } +} diff --git a/Warcraft.NET/Files/phys/Chunks/SPHJ.cs b/Warcraft.NET/Files/phys/Chunks/SPHJ.cs new file mode 100644 index 0000000..4ec195f --- /dev/null +++ b/Warcraft.NET/Files/phys/Chunks/SPHJ.cs @@ -0,0 +1,67 @@ +using System.Collections.Generic; +using System.IO; +using Warcraft.NET.Attribute; +using Warcraft.NET.Files.Interfaces; +using Warcraft.NET.Files.Phys.Entries; + +namespace Warcraft.NET.Files.Phys.Chunks +{ + [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)] + public class SPHJ : IIFFChunk, IBinarySerializable + { + /// + /// Holds the binary chunk signature. + /// + public const string Signature = "SPHJ"; + + /// + /// sets or gets the spherical joints + /// + public List SPHJEntries = new(); + + /// + /// Initializes a new instance of + /// + public SPHJ() { } + + /// + /// Initializes a new instance of + /// + /// ExtendedData. + public SPHJ(byte[] inData) => LoadBinaryData(inData); + + /// + public string GetSignature() { return Signature; } + + /// + public uint GetSize() { return (uint)Serialize().Length; } + + /// + public void LoadBinaryData(byte[] inData) + { + using (var ms = new MemoryStream(inData)) + using (var br = new BinaryReader(ms)) + { + var SPHJcount = br.BaseStream.Length / SPHJEntry.GetSize(); + for (var i = 0; i < SPHJcount; ++i) + { + SPHJEntries.Add(new SPHJEntry(br.ReadBytes(SPHJEntry.GetSize()))); + } + } + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + using (var bw = new BinaryWriter(ms)) + { + foreach (SPHJEntry obj in SPHJEntries) + { + bw.Write(obj.Serialize()); + } + return ms.ToArray(); + } + } + } +} diff --git a/Warcraft.NET/Files/phys/Chunks/SPHS.cs b/Warcraft.NET/Files/phys/Chunks/SPHS.cs new file mode 100644 index 0000000..5b55a64 --- /dev/null +++ b/Warcraft.NET/Files/phys/Chunks/SPHS.cs @@ -0,0 +1,68 @@ +using System.Collections.Generic; +using System.IO; +using Warcraft.NET.Attribute; +using Warcraft.NET.Files.Interfaces; +using Warcraft.NET.Files.Phys.Entries; + +namespace Warcraft.NET.Files.Phys.Chunks +{ + [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)] + public class SPHS : IIFFChunk, IBinarySerializable + { + /// + /// Holds the binary chunk signature. + /// + public const string Signature = "SPHS"; + + /// + /// sets or gets a list of sphere shapes + /// + public List Spheres = new(); + + /// + /// Initializes a new instance of + /// + public SPHS() { } + + /// + /// Initializes a new instance of + /// + /// ExtendedData. + public SPHS(byte[] inData) => LoadBinaryData(inData); + + /// + public string GetSignature() { return Signature; } + + /// + public uint GetSize() { return (uint)Serialize().Length; } + + /// + public void LoadBinaryData(byte[] inData) + { + using (var ms = new MemoryStream(inData)) + using (var br = new BinaryReader(ms)) + { + var SHP2count = br.BaseStream.Length / SHP2Entry.GetSize(); + + for (var i = 0; i < SHP2count; ++i) + { + Spheres.Add(new SPHSEntry(br.ReadBytes(SPHSEntry.GetSize()))); + } + } + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + using (var bw = new BinaryWriter(ms)) + { + foreach (SPHSEntry obj in Spheres) + { + bw.Write(obj.Serialize()); + } + return ms.ToArray(); + } + } + } +} diff --git a/Warcraft.NET/Files/phys/Chunks/WLJ3.cs b/Warcraft.NET/Files/phys/Chunks/WLJ3.cs new file mode 100644 index 0000000..b71e7a7 --- /dev/null +++ b/Warcraft.NET/Files/phys/Chunks/WLJ3.cs @@ -0,0 +1,68 @@ +using System.Collections.Generic; +using System.IO; +using Warcraft.NET.Attribute; +using Warcraft.NET.Files.Interfaces; +using Warcraft.NET.Files.Phys.Entries; + +namespace Warcraft.NET.Files.Phys.Chunks +{ + [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)] + public class WLJ3 : IIFFChunk, IBinarySerializable + { + /// + /// Holds the binary chunk signature. + /// + public const string Signature = "WLJ3"; + + /// + /// sets or gets a list of Weld(V3) Joints + /// + public List WLJ3Entries = new(); + + /// + /// Initializes a new instance of + /// + public WLJ3() { } + + /// + /// Initializes a new instance of + /// + /// ExtendedData. + public WLJ3(byte[] inData) => LoadBinaryData(inData); + + /// + public string GetSignature() { return Signature; } + + /// + public uint GetSize() { return (uint)Serialize().Length; } + + /// + public void LoadBinaryData(byte[] inData) + { + using (var ms = new MemoryStream(inData)) + using (var br = new BinaryReader(ms)) + { + var WLJ3count = br.BaseStream.Length / WLJ3Entry.GetSize(); + + for (var i = 0; i < WLJ3count; ++i) + { + WLJ3Entries.Add(new WLJ3Entry(br.ReadBytes(WLJ3Entry.GetSize()))); + } + } + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + using (var bw = new BinaryWriter(ms)) + { + foreach (WLJ3Entry obj in WLJ3Entries) + { + bw.Write(obj.Serialize()); + } + return ms.ToArray(); + } + } + } +} diff --git a/Warcraft.NET/Files/phys/Entries/BDY4Entry.cs b/Warcraft.NET/Files/phys/Entries/BDY4Entry.cs new file mode 100644 index 0000000..8fc497e --- /dev/null +++ b/Warcraft.NET/Files/phys/Entries/BDY4Entry.cs @@ -0,0 +1,139 @@ +using System.IO; +using System.Numerics; +using Warcraft.NET.Extensions; +using Warcraft.NET.Files.Phys.Enums; +using Warcraft.NET.Files.Structures; + +namespace Warcraft.NET.Files.Phys.Entries +{ + public class BDY4Entry + { + /// + /// Sets or gets the BodyType of the rigidbody + /// 0=static + /// 1=dynamic + /// 2=unknown + /// + public BodyType BodyType { get; set; } // maps to dmBodyDef BodyType enum. 0 -> 1, 1 -> 0 = dm_dynamicBody, * -> 2. Only one should be of BodyType 0 (root). possibly only 0 and 1. + + /// + /// Sets or gets the index of the bone, which is connected to this rigidbody + /// + public ushort BoneIndex { get; set; } + + /// + /// sets or gets the default Position of the rigidbody + /// + public Vector3 Position { get; set; } = new Vector3(0, 0, 0); + + /// + /// sets or gets the index of the shape, which is connected to this rigidbody + /// + public ushort ShapesIndex { get; set; } + + /// + /// sets or gets a currently unknown field. Possibly 'Padding' + /// + public byte[] Unk0 { get; set; } = { 0, 0 }; + + /// + /// sets or gets the amount of shapes this rigidbody has + /// + public int ShapesCount { get; set; } // shapes_count shapes are in this body. + + /// + /// sets or gets a currently unknown field. Possibly 'UpliftFactor' + /// + public float Unk1 { get; set; } = 0f; + + //#if version >= 3 // BDY3 + /// + /// sets or gets a currently unknown field. Possibly 'GravityScale' + /// + public float Unk2 { get; set; } = 1.0f; + + /// + /// sets or gets the Drag value of the rigidbody. + /// + public float Drag { get; set; } = 0f; + + /// + /// sets or gets a currently unknown field. Possibly 'Mass/Weight' + /// + public float Unk3 = 0f; + + /// + /// sets or gets a currently unknown field. + /// + public float Unk4 { get; set; } = 0.89999998f; + + /// + /// sets or gets a currently unknown field. + /// + public byte[] Unk5 { get; set; } = { 0, 0, 0, 0 }; + + /// + /// Initializes a new instance of the class. + /// + public BDY4Entry() { } + + /// + /// Initializes a new instance of the class. + /// + /// ExtendedData. + public BDY4Entry(byte[] data) + { + using (var ms = new MemoryStream(data)) + using (var br = new BinaryReader(ms)) + { + BodyType = (BodyType)br.ReadUInt16(); + BoneIndex = br.ReadUInt16(); + Position = br.ReadVector3(AxisConfiguration.ZUp); + ShapesIndex = br.ReadUInt16(); + Unk0 = br.ReadBytes(2); + ShapesCount = br.ReadInt32(); + Unk1 = br.ReadSingle(); + Unk2 = br.ReadSingle(); + Drag = br.ReadSingle(); + Unk3 = br.ReadSingle(); + Unk4 = br.ReadSingle(); + Unk5 = br.ReadBytes(4); + } + } + + /// + /// Gets the size of a bdy4 entry. + /// + /// The size. + public static int GetSize() + { + return 48; + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + { + using (var bw = new BinaryWriter(ms)) + { + bw.Write((ushort)BodyType); + bw.Write(BoneIndex); + bw.Write(Position.X); + bw.Write(Position.Y); + bw.Write(Position.Z); + bw.Write(ShapesIndex); + bw.Write(Unk0); + bw.Write(ShapesCount); + bw.Write(Unk1); + bw.Write(Unk2); + bw.Write(Drag); + bw.Write(Unk3); + bw.Write(Unk4); + bw.Write(Unk5); + } + return ms.ToArray(); + } + } + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/phys/Entries/BOXSEntry.cs b/Warcraft.NET/Files/phys/Entries/BOXSEntry.cs new file mode 100644 index 0000000..8fffebd --- /dev/null +++ b/Warcraft.NET/Files/phys/Entries/BOXSEntry.cs @@ -0,0 +1,52 @@ +using System.IO; +using System.Numerics; +using Warcraft.NET.Extensions; + +namespace Warcraft.NET.Files.Phys.Entries +{ + public class BOXSEntry + { + /// + /// Gets or Sets the transformation matrix of the box shape + /// + public Matrix3x4 Dimensions; + + /// + /// Gets or Sets the local position of the box shape + /// + public Vector3 Position; + + public BOXSEntry(byte[] data) + { + using (var ms = new MemoryStream(data)) + using (var br = new BinaryReader(ms)) + { + Dimensions = br.ReadMatrix3x4(); + Position = br.ReadVector3(); + } + } + + /// + /// Gets the size of a box entry. + /// + /// The size. + public static int GetSize() + { + return 60; + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + { + using (var bw = new BinaryWriter(ms)) + { + bw.WriteMatrix3x4(Dimensions); + bw.WriteVector3(Position); + } + return ms.ToArray(); + } + } + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/phys/Entries/CAPSEntry.cs b/Warcraft.NET/Files/phys/Entries/CAPSEntry.cs new file mode 100644 index 0000000..dcfde2d --- /dev/null +++ b/Warcraft.NET/Files/phys/Entries/CAPSEntry.cs @@ -0,0 +1,57 @@ +using System.IO; +using System.Numerics; +using Warcraft.NET.Extensions; +using Warcraft.NET.Files.Structures; + +namespace Warcraft.NET.Files.Phys.Entries +{ + public class CAPSEntry + { + /// + /// Gets or Sets the local start position of this capsule shape + /// + public Vector3 LocalPosition1; + + /// + /// Gets or Sets the local end position of this capsule shape + /// + public Vector3 LocalPosition2; + + /// + /// Gets or Sets the Radius of this capsule shape + /// + public float Radius; + + public CAPSEntry(byte[] data) + { + using (var ms = new MemoryStream(data)) + using (var br = new BinaryReader(ms)) + { + LocalPosition1 = br.ReadVector3(AxisConfiguration.ZUp); + LocalPosition2 = br.ReadVector3(AxisConfiguration.ZUp); + Radius = br.ReadSingle(); + } + } + /// + /// Gets the size of a caps entry. + /// + /// The size. + public static int GetSize() + { + return 28; + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + using (var bw = new BinaryWriter(ms)) + { + bw.WriteVector3(LocalPosition1); + bw.WriteVector3(LocalPosition2); + bw.Write(Radius); + return ms.ToArray(); + } + } + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/phys/Entries/DSTJEntry.cs b/Warcraft.NET/Files/phys/Entries/DSTJEntry.cs new file mode 100644 index 0000000..6752e96 --- /dev/null +++ b/Warcraft.NET/Files/phys/Entries/DSTJEntry.cs @@ -0,0 +1,68 @@ +using System.IO; +using System.Numerics; +using Warcraft.NET.Extensions; + +namespace Warcraft.NET.Files.Phys.Entries +{ + public class DSTJEntry + { + /// + /// sets or gets the local Anchor for Bone A from the Joint + /// + public Vector3 LocalAnchorA; + + /// + /// sets or gets the local Anchor for Bone B from the Joint + /// + public Vector3 LocalAnchorB; + + /// + /// sets or gets the currently unknown value for the distance joint calculation + /// + public float UnknownDistanceFactor; + + /// + /// Initializes a new instance of the class. + /// + public DSTJEntry() { } + + /// + /// Initializes a new instance of the class. + /// + /// ExtendedData. + public DSTJEntry(byte[] data) + { + using (var ms = new MemoryStream(data)) + using (var br = new BinaryReader(ms)) + { + LocalAnchorA = br.ReadVector3(); + LocalAnchorB = br.ReadVector3(); + UnknownDistanceFactor = br.ReadSingle(); + } + } + + /// + /// Gets the size of a DSTJ entry. + /// + /// The size. + public static int GetSize() + { + return 28; + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + { + using (var bw = new BinaryWriter(ms)) + { + bw.WriteVector3(LocalAnchorA); + bw.WriteVector3(LocalAnchorB); + bw.Write(UnknownDistanceFactor); + } + return ms.ToArray(); + } + } + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/phys/Entries/JOINEntry.cs b/Warcraft.NET/Files/phys/Entries/JOINEntry.cs new file mode 100644 index 0000000..03aaa3c --- /dev/null +++ b/Warcraft.NET/Files/phys/Entries/JOINEntry.cs @@ -0,0 +1,87 @@ +using System.IO; +using Warcraft.NET.Files.Phys.Enums; + +namespace Warcraft.NET.Files.Phys.Entries +{ + public class JOINEntry + { + /// + /// sets or gets the index of the first connected Rigidbody + /// + public uint BodyAIdx; + + /// + /// sets or gets the index of the second connected Rigidbody + /// + public uint BodyBIdx; + + /// + /// sets or gets a Unknown field. + /// + public byte[] Unk; + + /// + /// sets or gets the JointType + /// 0 = SphericalJoint + /// 1 = ShoulderJoint + /// 2 = WeldJoint + /// 3 = RevoluteJoint + /// 4 = PrismaticJoint + /// 5 = DistanceJoint + /// + public JointType JointType; + + /// + /// sets or gets the index of the joint into the joint list based on the JointType field + /// + public ushort JointID; + + /// + /// Initializes a new instance of the class. + /// + public JOINEntry() { } + + /// + /// Initializes a new instance of the class. + /// + /// ExtendedData. + public JOINEntry(byte[] data) + { + using (var ms = new MemoryStream(data)) + using (var br = new BinaryReader(ms)) + { + BodyAIdx = br.ReadUInt32(); + BodyBIdx = br.ReadUInt32(); + Unk = br.ReadBytes(4); + JointType = (JointType)br.ReadUInt16(); + JointID = br.ReadUInt16(); + } + } + + /// + /// Gets the size of a JOIN entry. + /// + /// The size. + public static int GetSize() + { + return 16; + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + { + using (var bw = new BinaryWriter(ms)) + { + bw.Write(BodyAIdx); + bw.Write(BodyBIdx); + bw.Write(Unk); + bw.Write((ushort)JointType); + bw.Write(JointID); + } + return ms.ToArray(); + } + } + } +} diff --git a/Warcraft.NET/Files/phys/Entries/PLYTEntry.cs b/Warcraft.NET/Files/phys/Entries/PLYTEntry.cs new file mode 100644 index 0000000..5e5ce51 --- /dev/null +++ b/Warcraft.NET/Files/phys/Entries/PLYTEntry.cs @@ -0,0 +1,188 @@ +using System.IO; +using System.Numerics; +using Warcraft.NET.Extensions; +using Warcraft.NET.Files.Phys.Structures; + +namespace Warcraft.NET.Files.Phys.Entries +{ + public class PLYTEntry + { + /// + /// gets or set the Polytope Header + /// + public PlytHeader Header; + + /// + /// gets or set the Polytope Data + /// + public PlytData Data; + + /// + /// gets or set the Polytope Data + /// + public int DataSize { get; } + + /// + /// Initializes a new instance of the class. + /// + public PLYTEntry() { } + + /// + /// Initializes a new instance of the class. + /// + /// Header Data + public PLYTEntry(byte[] header) + { + using (var ms = new MemoryStream(header)) + using (var br = new BinaryReader(ms)) + { + Header = new PlytHeader + { + VertexCount = br.ReadUInt32(), + Unk0 = br.ReadBytes(4), + RUNTIME08ptrData0 = br.ReadUInt64(), + Count10 = br.ReadUInt32(), + Unk1 = br.ReadBytes(4), + RUNTIME18ptrData1 = br.ReadUInt64(), + RUNTIME20ptrData2 = br.ReadUInt64(), + NodeCount = br.ReadUInt32(), + Unk2 = br.ReadBytes(4), + RUNTIME30ptrData3 = br.ReadUInt64(), + Unk3 = [br.ReadSingle(), br.ReadSingle(), br.ReadSingle(), br.ReadSingle(), br.ReadSingle(), br.ReadSingle()] + }; + int size = 0; + size += (int)Header.VertexCount * 12; + size += (int)Header.Count10 * 16; + size += (int)Header.Count10; + size += (int)Header.NodeCount * 4; + DataSize = size; + } + } + + /// + /// Deserialization of the Data Chunks + /// + /// + public void DeserializeData(byte[] data) + { + using (var ms = new MemoryStream(data)) + using (var br = new BinaryReader(ms)) + { + uint vcount = Header.VertexCount; + uint count_10 = Header.Count10; + uint nodeCount = Header.NodeCount; + + Data.Vertices = new Vector3[vcount]; + for (int v = 0; v < vcount; v++) + { + Data.Vertices[v] = br.ReadVector3(); + } + Data.Unk1 = br.ReadBytes((int)count_10 * 16); + Data.Unk2 = br.ReadBytes((int)count_10); + Data.Nodes = new PlytNode[nodeCount]; + for (int n = 0; n < nodeCount; n++) + { + PlytNode node = new(); + node.Unk = br.ReadByte(); + node.VertexIndex = br.ReadByte(); + node.UnkIndex0 = br.ReadByte(); + node.UnkIndex1 = br.ReadByte(); + Data.Nodes[n] = node; + } + } + } + + /// + /// gets the data size of the polytope. + /// + /// The size. + public int GetDataSize() + { + return SerializeData().Length; + } + + /// + /// gets the header size of the polytope. + /// + /// The size. + public int GetHeaderSize() + { + return SerializeHeader().Length; + } + + /// + /// gets the full size of the polytope. + /// + /// The size. + public int GetSize() + { + return SerializeHeader().Length + SerializeData().Length; + } + + /// + /// Serialize the Header + /// + /// + /// + public byte[] SerializeHeader(long offset = 0) + { + using (var ms = new MemoryStream()) + { + using (var bw = new BinaryWriter(ms)) + { + bw.Write(Header.VertexCount); + bw.Write(Header.Unk0); + + bw.Write(Header.RUNTIME08ptrData0); + + bw.Write(Header.Count10); + bw.Write(Header.Unk1); + + bw.Write(Header.RUNTIME18ptrData1); + + bw.Write(Header.RUNTIME20ptrData2); + + bw.Write(Header.NodeCount); + + bw.Write(Header.Unk2); + + bw.Write(Header.RUNTIME30ptrData3); + foreach (float f in Header.Unk3) + { + bw.Write(f); + } + } + return ms.ToArray(); + } + } + + /// + /// Serialize the Data + /// + /// + /// + public byte[] SerializeData(long offset = 0) + { + using (var ms = new MemoryStream()) + { + using (var bw = new BinaryWriter(ms)) + { + foreach (var vertex in Data.Vertices) + { + bw.WriteVector3(vertex); + } + bw.Write(Data.Unk1); + bw.Write(Data.Unk2); + foreach (var node in Data.Nodes) + { + bw.Write(node.Unk); + bw.Write(node.VertexIndex); + bw.Write(node.UnkIndex0); + bw.Write(node.UnkIndex1); + } + } + return ms.ToArray(); + } + } + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/phys/Entries/PRS2Entry.cs b/Warcraft.NET/Files/phys/Entries/PRS2Entry.cs new file mode 100644 index 0000000..fc925a8 --- /dev/null +++ b/Warcraft.NET/Files/phys/Entries/PRS2Entry.cs @@ -0,0 +1,119 @@ +using System.IO; +using Warcraft.NET.Extensions; + +namespace Warcraft.NET.Files.Phys.Entries +{ + public class PRS2Entry + { + /// + /// The Transformation Matrix for Bone A of this Joint + /// + public Matrix3x4 FrameA; + + /// + /// The Transformation Matrix for Bone B of this Joint + /// + public Matrix3x4 FrameB; + + /// + /// The lower limit + /// + public float LowerLimit; + + /// + /// The upper limit + /// + public float UpperLimit; + + /// + /// Unknown value + /// + public float Unk0; + + /// + /// Max motor force if enabled + /// + public float MaxMotorForce; + + /// + /// unknown value + /// + public float Unk1; + + /// + /// The MotorMode + /// 0 = disabled? + /// 1 = motorPositionMode (MotorFrequencyHz>0) + /// 2 = motorVelocityMode + /// + public uint MotorMode; + + /// + /// how often per second the motor damps + /// + public float MotorFrequencyHz; + + /// + /// the ratio how much the motor damps + /// + public float MotorDampingRatio; + + /// + /// Initializes a new instance of the class. + /// + public PRS2Entry() { } + + /// + /// Initializes a new instance of the class. + /// + /// ExtendedData. + public PRS2Entry(byte[] data) + { + using (var ms = new MemoryStream(data)) + using (var br = new BinaryReader(ms)) + { + FrameA = br.ReadMatrix3x4(); + FrameB = br.ReadMatrix3x4(); + LowerLimit = br.ReadSingle(); + UpperLimit = br.ReadSingle(); + Unk0 = br.ReadSingle(); + MaxMotorForce = br.ReadSingle(); + Unk1 = br.ReadSingle(); + MotorMode = br.ReadUInt32(); + MotorFrequencyHz = br.ReadSingle(); + MotorDampingRatio = br.ReadSingle(); + } + } + + /// + /// Gets the size of a PRS2 entry. + /// + /// The size. + public static int GetSize() + { + return 128; + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + { + using (var bw = new BinaryWriter(ms)) + { + bw.WriteMatrix3x4(FrameA); + bw.WriteMatrix3x4(FrameB); + bw.Write(LowerLimit); + bw.Write(UpperLimit); + bw.Write(Unk0); + bw.Write(MaxMotorForce); + bw.Write(Unk1); + bw.Write(MotorMode); + bw.Write(MotorFrequencyHz); + bw.Write(MotorDampingRatio); + } + return ms.ToArray(); + } + } + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/phys/Entries/REV2Entry.cs b/Warcraft.NET/Files/phys/Entries/REV2Entry.cs new file mode 100644 index 0000000..bc747ac --- /dev/null +++ b/Warcraft.NET/Files/phys/Entries/REV2Entry.cs @@ -0,0 +1,101 @@ +using System.IO; +using Warcraft.NET.Extensions; + +namespace Warcraft.NET.Files.Phys.Entries +{ + public class REV2Entry + { + /// + /// The Transformation Matrix for Bone A of this Joint + /// + public Matrix3x4 FrameA; + + /// + /// The Transformation Matrix for Bone B of this Joint + /// + public Matrix3x4 FrameB; + + /// + /// The lower swing angle + /// + public float LowerAngle; + /// + /// The upper swing angle + /// + public float UpperAngle; + + /// + /// The max motor torque + /// + public float MaxMotorTorque; + /// + /// The MotorMode + /// 0 = disabled? + /// 1 = motorPositionMode (MotorFrequencyHz>0) + /// 2 = motorVelocityMode + /// + public uint MotorMode; // 1: motorPositionMode → frequency > 0, 2: motorVelocityMode + /// + /// how often per second the motor damps + /// + public float MotorFrequencyHz; + /// + /// the ratio how much the motor damps + /// + public float MotorDampingRatio; + + /// + /// Initializes a new instance of the class. + /// + public REV2Entry() { } + + /// + /// Initializes a new instance of the class. + /// + /// ExtendedData. + public REV2Entry(byte[] data) + { + using (var ms = new MemoryStream(data)) + using (var br = new BinaryReader(ms)) + { + FrameA = br.ReadMatrix3x4(); + FrameB = br.ReadMatrix3x4(); + LowerAngle = br.ReadSingle(); + UpperAngle = br.ReadSingle(); + MaxMotorTorque = br.ReadSingle(); + MotorMode = br.ReadUInt32(); + MotorFrequencyHz = br.ReadSingle(); + MotorDampingRatio = br.ReadSingle(); + } + } + + /// + /// Gets the size of a REV2 entry. + /// + /// The size. + public static int GetSize() + { + return 120; + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + { + using (var bw = new BinaryWriter(ms)) + { + bw.WriteMatrix3x4(FrameA); + bw.WriteMatrix3x4(FrameB); + bw.Write(LowerAngle); + bw.Write(UpperAngle); + bw.Write(MaxMotorTorque); + bw.Write(MotorMode); + bw.Write(MotorFrequencyHz); + bw.Write(MotorDampingRatio); + } + return ms.ToArray(); + } + } + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/phys/Entries/SHJ2Entry.cs b/Warcraft.NET/Files/phys/Entries/SHJ2Entry.cs new file mode 100644 index 0000000..0586d11 --- /dev/null +++ b/Warcraft.NET/Files/phys/Entries/SHJ2Entry.cs @@ -0,0 +1,112 @@ +using System.IO; +using Warcraft.NET.Extensions; + +namespace Warcraft.NET.Files.Phys.Entries +{ + public class SHJ2Entry + { + /// + /// The Transformation Matrix for Bone A of this Joint + /// + public Matrix3x4 FrameA; + + /// + /// The Transformation Matrix for Bone B of this Joint + /// + public Matrix3x4 FrameB; + + /// + /// The lower twist angle of the angular constraint + /// + public float LowerTwistAngle; + + /// + /// The upper twist angle of the angular constraint + /// + public float UpperTwistAngle; + + /// + /// The cone angle of the angular constraint + /// + public float ConeAngle; + + /// + /// The max motor torque + /// + public float MaxMotorTorque; + + /// + /// The MotorMode + /// 0 = disabled? + /// 1 = motorPositionMode (MotorFrequencyHz>0) + /// 2 = motorVelocityMode + /// + public uint MotorMode; // 1: motorPositionMode → frequency > 0, 2: motorVelocityMode + + /// + /// how often per second the motor damps + /// + public float MotorFrequencyHz; + + /// + /// the ratio how much the motor damps + /// + public float MotorDampingRatio; + + /// + /// Initializes a new instance of the class. + /// + public SHJ2Entry() { } + + /// + /// Initializes a new instance of the class. + /// + /// ExtendedData. + public SHJ2Entry(byte[] data) + { + using (var ms = new MemoryStream(data)) + using (var br = new BinaryReader(ms)) + { + FrameA = br.ReadMatrix3x4(); + FrameB = br.ReadMatrix3x4(); + LowerTwistAngle = br.ReadSingle(); + UpperTwistAngle = br.ReadSingle(); + ConeAngle = br.ReadSingle(); + MaxMotorTorque = br.ReadSingle(); + MotorMode = br.ReadUInt32(); + MotorFrequencyHz = br.ReadSingle(); + MotorDampingRatio = br.ReadSingle(); + } + } + + /// + /// Gets the size of a SHJ2 entry. + /// + /// The size. + public static int GetSize() + { + return 124; + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + { + using (var bw = new BinaryWriter(ms)) + { + bw.WriteMatrix3x4(FrameA); + bw.WriteMatrix3x4(FrameB); + bw.Write(LowerTwistAngle); + bw.Write(UpperTwistAngle); + bw.Write(ConeAngle); + bw.Write(MaxMotorTorque); + bw.Write(MotorMode); + bw.Write(MotorFrequencyHz); + bw.Write(MotorDampingRatio); + } + return ms.ToArray(); + } + } + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/phys/Entries/SHOJEntry.cs b/Warcraft.NET/Files/phys/Entries/SHOJEntry.cs new file mode 100644 index 0000000..1c5bead --- /dev/null +++ b/Warcraft.NET/Files/phys/Entries/SHOJEntry.cs @@ -0,0 +1,98 @@ +using System.IO; +using Warcraft.NET.Extensions; + +namespace Warcraft.NET.Files.Phys.Entries +{ + public class SHOJEntry + { + /// + /// The Transformation Matrix for Bone A of this Joint + /// + public Matrix3x4 FrameA; + + /// + /// The Transformation Matrix for Bone B of this Joint + /// + public Matrix3x4 FrameB; + + /// + /// The lower twist angle for the angular constraint + /// + public float LowerTwistAngle; + + /// + /// The upper twist angle for the angular constraint + /// + public float UpperTwistAngle; + + /// + /// The cone angle for the angular constraint + /// + public float ConeAngle; + + /// + /// The Maximum torque the motor can apply + /// + public float MaxMotorTorque; + + /// + /// The MotorMode + /// 0 = disabled? + /// 1 = motorPositionMode (MotorFrequencyHz>0) + /// 2 = motorVelocityMode + /// + public uint MotorMode; // NO BACKWARDS COMPATIBILITY as of Legion (7.0.1.20979) and Legion (7.3.0.24931)! client always assumes new size! + + /// + /// Initializes a new instance of the class. + /// + public SHOJEntry() { } + + /// + /// Initializes a new instance of the class. + /// + /// ExtendedData. + public SHOJEntry(byte[] data) + { + using (var ms = new MemoryStream(data)) + using (var br = new BinaryReader(ms)) + { + FrameA = br.ReadMatrix3x4(); + FrameB = br.ReadMatrix3x4(); + LowerTwistAngle = br.ReadSingle(); + UpperTwistAngle = br.ReadSingle(); + ConeAngle = br.ReadSingle(); + MaxMotorTorque = br.ReadSingle(); + MotorMode = br.ReadUInt32(); + } + } + + /// + /// Gets the size of a SHOJ entry. + /// + /// The size. + public static int GetSize() + { + return 116; + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + { + using (var bw = new BinaryWriter(ms)) + { + bw.WriteMatrix3x4(FrameA); + bw.WriteMatrix3x4(FrameB); + bw.Write(LowerTwistAngle); + bw.Write(UpperTwistAngle); + bw.Write(ConeAngle); + bw.Write(MaxMotorTorque); + bw.Write(MotorMode); + } + return ms.ToArray(); + } + } + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/phys/Entries/SHP2Entry.cs b/Warcraft.NET/Files/phys/Entries/SHP2Entry.cs new file mode 100644 index 0000000..e179c04 --- /dev/null +++ b/Warcraft.NET/Files/phys/Entries/SHP2Entry.cs @@ -0,0 +1,120 @@ +using System.IO; +using Warcraft.NET.Files.Phys.Enums; + +namespace Warcraft.NET.Files.Phys.Entries +{ + public class SHP2Entry + { + /// + /// The Shape Type + /// 0 = Box + /// 1 = Capsule + /// 2 = Sphere + /// 3 = Polytope + /// + public ShapeType ShapeType; + + /// + /// The index into the corresponding chunk based on ShapeType + /// + public ushort ShapeIndex; + + /// + /// unknown field + /// + public byte[] Unk0; + + /// + /// the friction of the shape + /// + public float Friction; + + /// + /// the restitution of the shape + /// + public float Restitution; + + /// + /// the density of the shape + /// + public float Density; + + /// + /// unknown field + /// + public uint Unk1 = 0; + + /// + /// unknown field + /// + public float Unk2 = 1f; + + /// + /// unknown field + /// + public ushort Unk3 = 0; + + /// + /// unknown field + /// + public ushort Unk4; //no default, padding? + + /// + /// Initializes a new instance of the class. + /// + public SHP2Entry() { } + + /// + /// Initializes a new instance of the class. + /// + /// ExtendedData. + public SHP2Entry(byte[] data) + { + using (var ms = new MemoryStream(data)) + using (var br = new BinaryReader(ms)) + { + ShapeType = (ShapeType)br.ReadUInt16(); + ShapeIndex = br.ReadUInt16(); + Unk0 = br.ReadBytes(4); + Friction = br.ReadSingle(); + Restitution = br.ReadSingle(); + Density = br.ReadSingle(); + Unk1 = br.ReadUInt32(); + Unk2 = br.ReadSingle(); + Unk3 = br.ReadUInt16(); + Unk4 = br.ReadUInt16(); + } + } + + /// + /// Gets the size of a SHP2 entry. + /// + /// The size. + public static int GetSize() + { + return 32; + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + { + using (var bw = new BinaryWriter(ms)) + { + bw.Write((ushort)ShapeType); + bw.Write(ShapeIndex); + bw.Write(Unk0); + bw.Write(Friction); + bw.Write(Restitution); + bw.Write(Density); + bw.Write(Unk1); + bw.Write(Unk2); + bw.Write(Unk3); + bw.Write(Unk4); + } + return ms.ToArray(); + } + } + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/phys/Entries/SPHJEntry.cs b/Warcraft.NET/Files/phys/Entries/SPHJEntry.cs new file mode 100644 index 0000000..1f0d175 --- /dev/null +++ b/Warcraft.NET/Files/phys/Entries/SPHJEntry.cs @@ -0,0 +1,69 @@ +using System.IO; +using System.Numerics; +using Warcraft.NET.Extensions; +using Warcraft.NET.Files.Structures; + +namespace Warcraft.NET.Files.Phys.Entries +{ + public class SPHJEntry + { + /// + /// the local anchor of the Bone A of the joint + /// + public Vector3 AnchorA; + + /// + /// the local anchor of the Bone B of the joint + /// + public Vector3 AnchorB; + + /// + /// the friction torque + /// + public float FrictionTorque; + + /// + /// Initializes a new instance of the class. + /// + public SPHJEntry() { } + + /// + /// Initializes a new instance of the class. + /// + /// ExtendedData. + public SPHJEntry(byte[] data) + { + using (var ms = new MemoryStream(data)) + using (var br = new BinaryReader(ms)) + { + AnchorA = br.ReadVector3(AxisConfiguration.ZUp); + AnchorB = br.ReadVector3(AxisConfiguration.ZUp); + FrictionTorque = br.ReadSingle(); + } + } + + /// + /// Gets the size of a SPHJ entry. + /// + /// The size. + public static int GetSize() + { + return 28; + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + { + using (var bw = new BinaryWriter(ms)) + { + bw.WriteVector3(AnchorA); + bw.WriteVector3(AnchorB); + bw.Write(FrictionTorque); + } + return ms.ToArray(); + } + } + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/phys/Entries/SPHSEntry.cs b/Warcraft.NET/Files/phys/Entries/SPHSEntry.cs new file mode 100644 index 0000000..51ceec7 --- /dev/null +++ b/Warcraft.NET/Files/phys/Entries/SPHSEntry.cs @@ -0,0 +1,52 @@ +using System.IO; +using System.Numerics; +using Warcraft.NET.Extensions; + +namespace Warcraft.NET.Files.Phys.Entries +{ + public class SPHSEntry + { + /// + /// Gets or Sets the local position of the Sphere shape + /// + public Vector3 LocalPosition; + + /// + /// Gets or Sets the radius of the Sphere shape + /// + public float Radius; + + public SPHSEntry(byte[] data) + { + using (var ms = new MemoryStream(data)) + using (var br = new BinaryReader(ms)) + { + LocalPosition = br.ReadVector3(); + Radius = br.ReadSingle(); + } + } + + /// + /// Gets the size of a Sphere entry. + /// + /// The size. + public static int GetSize() + { + return 16; + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + { + using (var bw = new BinaryWriter(ms)) + { + bw.WriteVector3(LocalPosition); + bw.Write(Radius); + } + return ms.ToArray(); + } + } + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/phys/Entries/WLJ3Entry.cs b/Warcraft.NET/Files/phys/Entries/WLJ3Entry.cs new file mode 100644 index 0000000..396083e --- /dev/null +++ b/Warcraft.NET/Files/phys/Entries/WLJ3Entry.cs @@ -0,0 +1,93 @@ +using System.IO; +using Warcraft.NET.Extensions; + +namespace Warcraft.NET.Files.Phys.Entries +{ + public class WLJ3Entry + { + /// + /// The Transformation Matrix for Bone A of this Joint + /// + public Matrix3x4 FrameA; + + /// + /// The Transformation Matrix for Bone B of this Joint + /// + public Matrix3x4 FrameB; + + /// + /// how often the angular dampening is applied per second + /// + public float AngularFrequencyHz; + + /// + /// the ratio how strong the angular dampening is applied + /// + public float AngularDampingRatio; + + /// + /// how often the linear dampening is applied per second + /// + public float LinearFrequencyHz; // default 0 + + /// + /// the ratio how linear the angular dampening is applied + /// + public float LinearDampingRatio; // default 0 + + /// + /// unknown field + /// + public float Unk0; + + /// + /// Initializes a new instance of the class. + /// + public WLJ3Entry() { } + + /// + /// Initializes a new instance of the class. + /// + /// ExtendedData. + public WLJ3Entry(byte[] data) + { + using (var ms = new MemoryStream(data)) + using (var br = new BinaryReader(ms)) + { + FrameA = br.ReadMatrix3x4(); + FrameB = br.ReadMatrix3x4(); + AngularFrequencyHz = br.ReadSingle(); + AngularDampingRatio = br.ReadSingle(); + LinearFrequencyHz = br.ReadSingle(); + LinearDampingRatio = br.ReadSingle(); + Unk0 = br.ReadSingle(); + } + } + + /// + /// Gets the size of a WLJ3 entry. + /// + /// The size. + public static int GetSize() + { + return 116; + } + + /// + public byte[] Serialize(long offset = 0) + { + using (var ms = new MemoryStream()) + using (var bw = new BinaryWriter(ms)) + { + bw.WriteMatrix3x4(FrameA); + bw.WriteMatrix3x4(FrameB); + bw.Write(AngularFrequencyHz); + bw.Write(AngularDampingRatio); + bw.Write(LinearFrequencyHz); + bw.Write(LinearDampingRatio); + bw.Write(Unk0); + return ms.ToArray(); + } + } + } +} diff --git a/Warcraft.NET/Files/phys/Enums/BodyType.cs b/Warcraft.NET/Files/phys/Enums/BodyType.cs new file mode 100644 index 0000000..070e59b --- /dev/null +++ b/Warcraft.NET/Files/phys/Enums/BodyType.cs @@ -0,0 +1,9 @@ +namespace Warcraft.NET.Files.Phys.Enums +{ + public enum BodyType : ushort + { + Root = 0, + Dynamic = 1, + Unk = 2, + } +} diff --git a/Warcraft.NET/Files/phys/Enums/JointType.cs b/Warcraft.NET/Files/phys/Enums/JointType.cs new file mode 100644 index 0000000..0ea6327 --- /dev/null +++ b/Warcraft.NET/Files/phys/Enums/JointType.cs @@ -0,0 +1,12 @@ +namespace Warcraft.NET.Files.Phys.Enums +{ + public enum JointType : ushort + { + SphericalJoint = 0, + ShoulderJoint = 1, + WeldJoint = 2, + RevoluteJoint = 3, + PrismaticJoint = 4, + DistanceJoint = 5, + } +} diff --git a/Warcraft.NET/Files/phys/Enums/ShapeType.cs b/Warcraft.NET/Files/phys/Enums/ShapeType.cs new file mode 100644 index 0000000..1f599e5 --- /dev/null +++ b/Warcraft.NET/Files/phys/Enums/ShapeType.cs @@ -0,0 +1,10 @@ +namespace Warcraft.NET.Files.Phys.Enums +{ + public enum ShapeType : short + { + Box = 0, + Caps = 1, + Sphere = 2, + Polytope = 3, + } +} diff --git a/Warcraft.NET/Files/phys/Physics.cs b/Warcraft.NET/Files/phys/Physics.cs new file mode 100644 index 0000000..45ec5ef --- /dev/null +++ b/Warcraft.NET/Files/phys/Physics.cs @@ -0,0 +1,129 @@ +using Warcraft.NET.Attribute; +using Warcraft.NET.Files.Phys.Chunks; + +namespace Warcraft.NET.Files.Phys +{ + [AutoDocFile("phys")] + public class Physics : ChunkedFile + { + /// + /// contains the version of the physics + /// + [ChunkOrder(1)] + public PHYS Version{get; set;} + + /// + /// contains an unknown uint + /// + [ChunkOrder(2),ChunkOptional] + public PHYT Phyt{get; set; } + + /// + /// contains the used box shapes + /// + [ChunkOrder(3),ChunkOptional] + public BOXS BoxShapes{get;set;} + + /// + /// contains the used sphere shapes + /// + [ChunkOrder(4),ChunkOptional] + public SPHS SphereShapes{get;set;} + + /// + /// contains the used capsule shapes + /// + + [ChunkOrder(5),ChunkOptional] + public CAPS CapsuleShapes{get;set;} + + /// + /// contains the used polytope shapes + /// + [ChunkOrder(6),ChunkOptional] + public PLYT PolytopeShapes{get; set;} + + /// + /// contains the used shapes + /// + [ChunkOrder(7),ChunkOptional] + public SHP2 Shapes2{get; set;} //SHAP nyi + + /// + /// contains the used rigidbodies + /// + [ChunkOrder(8),ChunkOptional] + public BDY4 Rigidbodies4{get; set;} //BODY,BDY2,BDY3 NYI + + /// + /// contains the used shoulder joints + /// + [ChunkOrder(9),ChunkOptional] + public SHOJ ShoulderJoints { get; set; } + + /// + /// contains the used shoulder joints + /// + [ChunkOrder(10),ChunkOptional] + public SHJ2 ShoulderJoints2{get; set;} + + /// + /// contains the used weld joints + /// + [ChunkOrder(11),ChunkOptional] + public WLJ3 WeldJoints3{get; set;} //WELJ,WLJ2 nyi + + /// + /// contains the used spherical joints + /// + [ChunkOrder(12),ChunkOptional] + public SPHJ SphericalJoints{get; set;} + + /// + /// contains the used prismatic joints + /// + [ChunkOrder(13),ChunkOptional] + public PRS2 PrismaticJoints2{get; set;} //PRSJ nyi + + /// + /// contains the used revolute joints + /// + [ChunkOrder(14),ChunkOptional] + public REV2 RevoluteJoints2{get; set;} //REVJ nyi + + /// + /// contains the used distance joints + /// + [ChunkOrder(15),ChunkOptional] + public DSTJ DistanceJoints{get; set;} + + /// + /// contains the used joints + /// + [ChunkOrder(16),ChunkOptional] + public JOIN Joints{get; set;} + + /// + /// contains the used phyv data (unknown) + /// + [ChunkOrder(17),ChunkOptional] + public PHYV Phyv { get; set; } + + /// + /// Initializes a new instance of the class. + /// + public Physics() + { + + } + + /// + /// Initializes a new instance of the class. + /// + /// The binary data. + public Physics(byte[] inData) : base(inData) + { + + } + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/phys/Structures/PlytData.cs b/Warcraft.NET/Files/phys/Structures/PlytData.cs new file mode 100644 index 0000000..65ddf95 --- /dev/null +++ b/Warcraft.NET/Files/phys/Structures/PlytData.cs @@ -0,0 +1,29 @@ +using System; +using System.Numerics; + +namespace Warcraft.NET.Files.Phys.Structures +{ + [Serializable] + public struct PlytData + { + /// + /// gets or sets the vertices. Amount is defined by header.VertexCount + /// + public Vector3[] Vertices; //amount = VertexCount in Header + + /// + /// gets or sets the Unk1 array. Unknown purpose. Amount is defined by header.Count10 + /// + public byte[] Unk1; //multiple of 16 -> amount = count_10 in Header + + /// + /// gets or sets the Unk2 array. Unknown purpose.Amount is defined by header.Count10 + /// + public byte[] Unk2; //amount = count_10 in Header + + /// + /// gets or sets the Unk2 array. Unknown purpose.Amount is defined by header.NodeCount + /// + public PlytNode[] Nodes; + } +} diff --git a/Warcraft.NET/Files/phys/Structures/PlytHeader.cs b/Warcraft.NET/Files/phys/Structures/PlytHeader.cs new file mode 100644 index 0000000..c6b871a --- /dev/null +++ b/Warcraft.NET/Files/phys/Structures/PlytHeader.cs @@ -0,0 +1,62 @@ +using System; + +namespace Warcraft.NET.Files.Phys.Structures +{ + public struct PlytHeader + { + /// + /// gets or sets the amount of vertices for this polytope + /// + public uint VertexCount; + + /// + /// gets or sets unknown data + /// + public byte[] Unk0; + + /// + /// gets or sets certain runtime data. Unknown purpose + /// + public UInt64 RUNTIME08ptrData0; + + /// + /// gets or sets the count10, which defines how many Unk1[] and Unk2[] there are inside the Data. + /// + public uint Count10; + + /// + /// gets or sets the Unk1 array. Unknown purpose + /// + public byte[] Unk1; + + /// + /// gets or sets certain runtime data. Unknown purpose + /// + public UInt64 RUNTIME18ptrData1; + + /// + /// gets or sets certain runtime data. Unknown purpose + /// + public UInt64 RUNTIME20ptrData2; + + /// + /// gets or sets the amount of nodes. Defines how Vertices are connected + /// + public uint NodeCount; + + /// + /// gets or sets the Unk2 array. Unknown purpose + /// + public byte[] Unk2; + + /// + /// gets or sets certain runtime data. Unknown purpose + /// + public UInt64 RUNTIME30ptrData3; + + /// + /// gets or sets the Unk3 array. Unknown purpose + /// + public float[] Unk3; + } +} \ No newline at end of file diff --git a/Warcraft.NET/Files/phys/Structures/PlytNode.cs b/Warcraft.NET/Files/phys/Structures/PlytNode.cs new file mode 100644 index 0000000..c727e69 --- /dev/null +++ b/Warcraft.NET/Files/phys/Structures/PlytNode.cs @@ -0,0 +1,29 @@ +using System; + +namespace Warcraft.NET.Files.Phys.Structures +{ + + [Serializable] + public struct PlytNode + { + /// + /// Unknown byte. Always 1 or -1 + /// + public byte Unk; // 1 or -1 + + /// + /// Index into the data.Vertices + /// + public byte VertexIndex; // index in vertex list + + /// + /// Index into data.Nodes + /// + public byte UnkIndex0; // index into the nodes + + /// + /// Index into data.Nodes + /// + public byte UnkIndex1; // index into the nodes + } +} \ No newline at end of file