diff --git a/src/G2DataGUI.Common/Data/Maps/Maps.cs b/src/G2DataGUI.Common/Data/Maps/Maps.cs index ec892bf..6a6adb3 100644 --- a/src/G2DataGUI.Common/Data/Maps/Maps.cs +++ b/src/G2DataGUI.Common/Data/Maps/Maps.cs @@ -3,6 +3,7 @@ using System.IO; using System.Threading.Tasks; using G2DataGUI.Common.Data.Errors; +using G2DataGUI.Common.Data.Models; namespace G2DataGUI.Common.Data.Maps; @@ -36,6 +37,12 @@ private void ReadMaps() } CollectionRefreshed?.Invoke(this, EventArgs.Empty); + + using var modelFile = File.Open( + "F:\\programming\\languages\\c#\\programs\\G2DataGUI\\build\\Debug\\net7.0\\models\\2a00.chr_model_1.nj", + FileMode.Open, + FileAccess.Read); + NJCM model = NJCM.ReadNJCM(modelFile, 0); } catch (Exception ex) { diff --git a/src/G2DataGUI.Common/Data/Models/Model.cs b/src/G2DataGUI.Common/Data/Models/Model.cs new file mode 100644 index 0000000..ffcf941 --- /dev/null +++ b/src/G2DataGUI.Common/Data/Models/Model.cs @@ -0,0 +1,6 @@ +namespace G2DataGUI.Common.Data.Models; + +public class Model +{ + +} diff --git a/src/G2DataGUI.Common/Data/Models/Models.cs b/src/G2DataGUI.Common/Data/Models/Models.cs new file mode 100644 index 0000000..a16beab --- /dev/null +++ b/src/G2DataGUI.Common/Data/Models/Models.cs @@ -0,0 +1,7 @@ +using G2DataGUI.Common.Data.Common; + +namespace G2DataGUI.Common.Data.Models; + +public class Models : BaseContainer +{ +} diff --git a/src/G2DataGUI.Common/Data/Models/NJCM.cs b/src/G2DataGUI.Common/Data/Models/NJCM.cs new file mode 100644 index 0000000..6312169 --- /dev/null +++ b/src/G2DataGUI.Common/Data/Models/NJCM.cs @@ -0,0 +1,38 @@ +using System.IO; +using System.Linq; +using G2DataGUI.IO.Streams; + +namespace G2DataGUI.Common.Data.Models; + +public class NJCM +{ + public uint ByteLength { get; private set; } + public NJSBone BaseBone { get; private set; } = null; + + /// + /// Represents the ASCII string "NJCM" + /// + public static byte[] Identifier => new byte[] { 0x4E, 0x4A, 0x43, 0x4D }; + + /// + /// Offsets do not account for Identifier or ByteLength + /// + public static long DataOffset => 0x08; + + public static NJCM ReadNJCM(Stream reader, long instanceOffset) + { + var identifier = reader.ReadRawByteArray((uint)Identifier.Length); + if (!Identifier.SequenceEqual(identifier)) + { + return null; + } + + NJCM njcm = new() + { + ByteLength = reader.ReadRawUInt(), + BaseBone = NJSBone.ReadNJSObject(reader, instanceOffset + DataOffset), + }; + + return njcm; + } +} diff --git a/src/G2DataGUI.Common/Data/Models/NJSBone.cs b/src/G2DataGUI.Common/Data/Models/NJSBone.cs new file mode 100644 index 0000000..88b3cde --- /dev/null +++ b/src/G2DataGUI.Common/Data/Models/NJSBone.cs @@ -0,0 +1,57 @@ +using System.IO; +using G2DataGUI.Common.Data.Common; +using G2DataGUI.IO.Streams; + +namespace G2DataGUI.Common.Data.Models; + +public class NJSBone +{ + public uint Flags { get; set; } + public NJSMesh Model { get; set; } = null; + public Vector3 Position { get; set; } + public Vector3 Angle { get; set; } + public Vector3 Scale { get; set; } + public NJSBone Child { get; set; } = null; + public NJSBone Sibling { get; set; } = null; + + public static NJSBone ReadNJSObject(Stream reader, long instanceOffset) + { + NJSBone obj = new() + { + Flags = reader.ReadRawUInt(), + }; + + var modelOffset = reader.ReadRawUInt(); + if (modelOffset > 0) + { + long position = reader.Position; + reader.Seek(instanceOffset + modelOffset, SeekOrigin.Begin); + obj.Model = NJSMesh.ReadNJSModel(reader, instanceOffset); + reader.Seek(position, SeekOrigin.Begin); + } + + obj.Position = Vector3.ReadVector3(reader); + obj.Angle = Vector3.ReadVector3(reader); + obj.Scale = Vector3.ReadVector3(reader); + + var childOffset = reader.ReadRawUInt(); + if (childOffset > 0) + { + long position = reader.Position; + reader.Seek(instanceOffset + childOffset, SeekOrigin.Begin); + obj.Child = ReadNJSObject(reader, instanceOffset); + reader.Seek(position, SeekOrigin.Begin); + } + + var siblingOffset = reader.ReadRawUInt(); + if (siblingOffset > 0) + { + long position = reader.Position; + reader.Seek(instanceOffset + siblingOffset, SeekOrigin.Begin); + obj.Sibling = ReadNJSObject(reader, instanceOffset); + reader.Seek(position, SeekOrigin.Begin); + } + + return obj; + } +} diff --git a/src/G2DataGUI.Common/Data/Models/NJSMesh.cs b/src/G2DataGUI.Common/Data/Models/NJSMesh.cs new file mode 100644 index 0000000..a504d85 --- /dev/null +++ b/src/G2DataGUI.Common/Data/Models/NJSMesh.cs @@ -0,0 +1,32 @@ +using System.IO; +using G2DataGUI.Common.Data.Common; +using G2DataGUI.IO.Streams; + +namespace G2DataGUI.Common.Data.Models; + +public class NJSMesh +{ + public NJSVertexList VertexList { get; set; } = null; + // indices + public Vector3 Center { get; set; } + public float Radius { get; set; } + + public static NJSMesh ReadNJSModel(Stream reader, long instanceOffset) + { + NJSMesh model = new(); + + var vertexOffset = reader.ReadRawUInt(); + if (vertexOffset > 0) + { + var position = reader.Position; + reader.Seek(instanceOffset + vertexOffset, SeekOrigin.Begin); + model.VertexList = NJSVertexList.ReadNJSVertexList(reader); + reader.Seek(position, SeekOrigin.Begin); + } + + model.Center = Vector3.ReadVector3(reader); + model.Radius = reader.ReadRawFloat(); + + return model; + } +} diff --git a/src/G2DataGUI.Common/Data/Models/NJSVertexList.cs b/src/G2DataGUI.Common/Data/Models/NJSVertexList.cs new file mode 100644 index 0000000..b573772 --- /dev/null +++ b/src/G2DataGUI.Common/Data/Models/NJSVertexList.cs @@ -0,0 +1,52 @@ +using System.Collections.Generic; +using System.IO; +using G2DataGUI.Common.Data.Common; +using G2DataGUI.IO.Streams; + +namespace G2DataGUI.Common.Data.Models; + +public class NJSVertexList +{ + /// + /// Always 0x2900? + /// + public short Format { get; set; } + + /// + /// No idea + /// + public short Unknown1 { get; set; } + + /// + /// Always 0x0000? + /// + public short Flags { get; set; } + + /// + /// Number of Vertices + /// + public short Count { get; set; } + + /// + /// Should end with a 0xFF000000? + /// + public List VertexList { get; set; } = new List(); + + public static NJSVertexList ReadNJSVertexList(Stream reader) + { + NJSVertexList list = new() + { + Format = reader.ReadRawShort(), + Unknown1 = reader.ReadRawShort(), + Flags = reader.ReadRawShort(), + Count = reader.ReadRawShort(), + }; + + for (int index = 0; index < list.Count; index++) + { + list.VertexList.Add(Vector3.ReadVector3(reader)); + } + + return list; + } +} diff --git a/src/G2DataGUI.Common/Data/Models/NJTL.cs b/src/G2DataGUI.Common/Data/Models/NJTL.cs new file mode 100644 index 0000000..834b4e6 --- /dev/null +++ b/src/G2DataGUI.Common/Data/Models/NJTL.cs @@ -0,0 +1,6 @@ +namespace G2DataGUI.Common.Data.Models; + +public class NJTL +{ + +} diff --git a/src/G2DataGUI.Common/Data/Models/NMDM.cs b/src/G2DataGUI.Common/Data/Models/NMDM.cs new file mode 100644 index 0000000..e1225cf --- /dev/null +++ b/src/G2DataGUI.Common/Data/Models/NMDM.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace G2DataGUI.Common.Data.Models; +internal class NMDM +{ +}