diff --git a/FinModelUtility/Fin/Fin/src/schema/matrix/Matrix3x3f.cs b/FinModelUtility/Fin/Fin/src/schema/matrix/Matrix3x3f.cs new file mode 100644 index 000000000..aa6c4a4b3 --- /dev/null +++ b/FinModelUtility/Fin/Fin/src/schema/matrix/Matrix3x3f.cs @@ -0,0 +1,13 @@ +using schema.binary; + +namespace fin.schema.matrix { + [BinarySchema] + public partial class Matrix3x3f : IBinaryConvertible { + public float[] Values { get; } = new float[3 * 3]; + + public float this[int row, int column] { + get => this.Values[3 * row + column]; + set => this.Values[3 * row + column] = value; + } + } +} diff --git a/FinModelUtility/Fin/Fin/src/schema/vector/Vector3.cs b/FinModelUtility/Fin/Fin/src/schema/vector/Vector3.cs index 88b5e54e6..ea0bcd478 100644 --- a/FinModelUtility/Fin/Fin/src/schema/vector/Vector3.cs +++ b/FinModelUtility/Fin/Fin/src/schema/vector/Vector3.cs @@ -78,4 +78,7 @@ public sealed partial class Vector3i : BVector3, IBinaryConvertible { } [BinarySchema] public sealed partial class Vector3s : BVector3, IBinaryConvertible { } + + [BinarySchema] + public sealed partial class Vector3d : BVector3, IBinaryConvertible { } } \ No newline at end of file diff --git a/FinModelUtility/Formats/Nitro/Nitro/Class1.cs b/FinModelUtility/Formats/Nitro/Nitro/Class1.cs deleted file mode 100644 index e9673e8bc..000000000 --- a/FinModelUtility/Formats/Nitro/Nitro/Class1.cs +++ /dev/null @@ -1,5 +0,0 @@ -namespace nitro { - public class Class1 { - - } -} \ No newline at end of file diff --git a/FinModelUtility/Formats/Nitro/Nitro/Nitro.csproj b/FinModelUtility/Formats/Nitro/Nitro/Nitro.csproj index 8d0421d21..d938d31da 100644 --- a/FinModelUtility/Formats/Nitro/Nitro/Nitro.csproj +++ b/FinModelUtility/Formats/Nitro/Nitro/Nitro.csproj @@ -7,4 +7,12 @@ nitro + + + + + + + + diff --git a/FinModelUtility/Formats/Nitro/Nitro/src/schema/nsbmd/Object.cs b/FinModelUtility/Formats/Nitro/Nitro/src/schema/nsbmd/Object.cs new file mode 100644 index 000000000..3e904f72c --- /dev/null +++ b/FinModelUtility/Formats/Nitro/Nitro/src/schema/nsbmd/Object.cs @@ -0,0 +1,67 @@ +using fin.schema.matrix; +using fin.schema.vector; +using fin.util.enums; + +using schema.binary; +using schema.binary.attributes; + +namespace nitro.schema.nsbmd { + [Flags] + public enum ObjectFlags : ushort { + NO_TRANSLATION = 1 << 0, + NO_ROTATION = 1 << 1, + NO_SCALE = 1 << 2, + USE_PIVOT_MATRIX = 1 << 3, + } + + /// + /// Shamelessly copied from: + /// https://github.com/scurest/apicula/blob/07c4d8facdcb015d118bf26a29d37c8b41021bfd/src/nitro/model.rs#L329 + /// + [BinarySchema] + public partial class Object : IBinaryDeserializable { + public ObjectFlags Flags { get; set; } + + [NumberFormat(SchemaNumberType.UN16)] + public float M0 { get; set; } + + + [RIfBoolean(nameof(HasTranslation))] + public Vector3f? Translation { get; set; } + + [ReadLogic] + public void ReadRotation_(IBinaryReader br) { + if (this.Flags.CheckFlag(ObjectFlags.USE_PIVOT_MATRIX)) { + // TODO: Implement + } else if (!this.Flags.CheckFlag(ObjectFlags.NO_ROTATION)) { + this.Rotation ??= new Matrix3x3f(); + + Span m1To9 = stackalloc float[8]; + br.ReadUn16s(m1To9); + + this.Rotation[0, 0] = this.M0; + for (var i = 1; i < 9; i++) { + this.Rotation[i % 3, i / 3] = m1To9[i - 1]; + } + } else { + this.Rotation = null; + } + } + + [RIfBoolean(nameof(HasScale))] + public Vector3f? Scale { get; set; } + + + [Ignore] + public Matrix3x3f? Rotation { get; set; } + + + [Ignore] + public bool HasTranslation + => !this.Flags.CheckFlag(ObjectFlags.NO_TRANSLATION); + + [Ignore] + public bool HasScale + => !this.Flags.CheckFlag(ObjectFlags.NO_SCALE); + } +} \ No newline at end of file diff --git a/FinModelUtility/Formats/Nitro/Nitro/src/schema/nsbmd/mesh/Opcode.cs b/FinModelUtility/Formats/Nitro/Nitro/src/schema/nsbmd/mesh/Opcode.cs new file mode 100644 index 000000000..e230b60bb --- /dev/null +++ b/FinModelUtility/Formats/Nitro/Nitro/src/schema/nsbmd/mesh/Opcode.cs @@ -0,0 +1,106 @@ +namespace nitro.schema.nsbmd.mesh { + public enum Opcode : byte { + // 0x_0 + NOP = 0x00, + UNKNOWN_0x40 = 0x40, + UNKNOWN_0x80 = 0x80, + + // 0x01 + END = 0x01, + + // 0x02 + UNKNOWN_0x02 = 0x02, + + // 0x03 + LOAD_MATRIX = 0x03, + + // 0x_4 + BIND_MATERIAL_1 = 0x04, + BIND_MATERIAL_2 = 0x24, + BIND_MATERIAL_3 = 0x44, + + // 0x05 + DRAW = 0x05, + + // 0x_6 + MULT_MATRIX_1 = 0x06, + MULT_MATRIX_2 = 0x26, // w/ store position + MULT_MATRIX_3 = 0x46, // w/ load position + MULT_MATRIX_4 = 0x66, // w/ both store and load position + + // 0x_7 + UNKNOWN_0x07 = 0x07, + UNKNOWN_0x47 = 0x47, + + // 0x08 + UNKNOWN_0x08 = 0x08, + + // 0x09 + STORE_MATRIX = 0x09, + + // 0x_b + SCALE_UP = 0x0b, + SCALE_DOWN = 0x2b, + + // 0x0c + UNKNOWN_0x0c = 0x0c, + + // 0x0d + UNKNOWN_0x0d = 0x0d, + } + + public static class OpcodeExtensions { + /// + /// Shamelessly copied from: + /// https://github.com/scurest/apicula/blob/07c4d8facdcb015d118bf26a29d37c8b41021bfd/src/nitro/render_cmds.rs#L164 + /// + public static int GetLength(this Opcode opcode) + => opcode switch { + // 0x00 + Opcode.NOP or Opcode.UNKNOWN_0x40 or Opcode.UNKNOWN_0x80 => 0, + + // 0x01 + Opcode.END => 0, + + // 0x02 + Opcode.UNKNOWN_0x02 => 2, + + // 0x03 + Opcode.LOAD_MATRIX => 1, + + // 0x_4 + Opcode.BIND_MATERIAL_1 + or Opcode.BIND_MATERIAL_2 + or Opcode.BIND_MATERIAL_3 => 1, + + // 0x05 + Opcode.DRAW => 1, + + // 0x_6 + Opcode.MULT_MATRIX_1 => 3, + Opcode.MULT_MATRIX_2 => 4, + Opcode.MULT_MATRIX_3 => 4, + Opcode.MULT_MATRIX_4 => 5, + + // 0x_7 + Opcode.UNKNOWN_0x07 => 1, + Opcode.UNKNOWN_0x47 => 2, + + // 0x08 + Opcode.UNKNOWN_0x08 => 1, + + // 0x09 + // (not here because it is variable-length) + + // 0x_b + Opcode.SCALE_UP + or Opcode.SCALE_DOWN => 0, + + // 0x0c + Opcode.UNKNOWN_0x0c => 2, + + // 0x0d + Opcode.UNKNOWN_0x0d => 2, + }; + } +} \ No newline at end of file