Skip to content

Commit

Permalink
Simplified how JObj is read by using Schema.
Browse files Browse the repository at this point in the history
  • Loading branch information
MeltyPlayer committed Nov 4, 2023
1 parent 5da018b commit c7f3e7e
Show file tree
Hide file tree
Showing 14 changed files with 87 additions and 113 deletions.
10 changes: 6 additions & 4 deletions FinModelUtility/Fin/Fin Tests/math/matrix/four/Matrix4x4Tests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using fin.math.floats;
using System;

using fin.math.floats;
using fin.util.asserts;

using NUnit.Framework;
Expand All @@ -17,7 +19,7 @@ public void TestFloatArrayConstructor() {
}
}

var mat = new FinMatrix4x4(values);
var mat = new FinMatrix4x4(values.AsSpan());

for (var r = 0; r < FinMatrix4x4.ROW_COUNT; ++r) {
for (var c = 0; c < FinMatrix4x4.COLUMN_COUNT; ++c) {
Expand All @@ -36,7 +38,7 @@ public void TestDoubleArrayConstructor() {
}
}

var mat = new FinMatrix4x4(values);
var mat = new FinMatrix4x4(values.AsSpan());

for (var r = 0; r < FinMatrix4x4.ROW_COUNT; ++r) {
for (var c = 0; c < FinMatrix4x4.COLUMN_COUNT; ++c) {
Expand All @@ -55,7 +57,7 @@ public void TestCopyConstructor() {
}
}

var first = new FinMatrix4x4(values);
var first = new FinMatrix4x4(values.AsSpan());
var second = new FinMatrix4x4(first);

for (var r = 0; r < FinMatrix4x4.ROW_COUNT; ++r) {
Expand Down
14 changes: 14 additions & 0 deletions FinModelUtility/Fin/Fin/src/math/matrix/four/FinMatrix4x4.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,20 @@ public FinMatrix4x4(IReadOnlyList<double> data) {
}
}

public FinMatrix4x4(ReadOnlySpan<float> data) {
Asserts.Equal(CELL_COUNT, data.Length);
for (var i = 0; i < CELL_COUNT; ++i) {
this[i] = data[i];
}
}

public FinMatrix4x4(ReadOnlySpan<double> data) {
Asserts.Equal(CELL_COUNT, data.Length);
for (var i = 0; i < CELL_COUNT; ++i) {
this[i] = (float) data[i];
}
}

public FinMatrix4x4(IReadOnlyFinMatrix4x4 other) => this.CopyFrom(other);
public FinMatrix4x4(SystemMatrix other) => this.CopyFrom(other);

Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
33 changes: 20 additions & 13 deletions FinModelUtility/Formats/Dat/Dat/src/api/DatModelImporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,35 +35,42 @@ public unsafe IModel ImportModel(DatModelFileBundle modelFileBundle) {
var jObjByOffset = dat.JObjByOffset;
var finBoneByJObj = new Dictionary<JObj, IBone>();
var boneWeightsByJObj = new Dictionary<JObj, IBoneWeights>();
var inverseBindMatrixByJObj =
new Dictionary<JObj, IReadOnlyFinMatrix4x4>();
var boneQueue = new Queue<(IBone finParentBone, JObj datBone)>();
foreach (var datRootBone in dat.RootJObjs) {
boneQueue.Enqueue((finModel.Skeleton.Root, datRootBone));
}

Span<float> inverseBindMatrixBuffer = stackalloc float[4 * 4];
while (boneQueue.Count > 0) {
var (finParentBone, jObj) = boneQueue.Dequeue();

var datBoneData = jObj.Data;

var finBone =
finParentBone.AddChild(datBoneData.Position.X,
datBoneData.Position.Y,
datBoneData.Position.Z)
finParentBone.AddChild(jObj.Position.X,
jObj.Position.Y,
jObj.Position.Z)
.SetLocalRotationRadians(
datBoneData.RotationRadians.X,
datBoneData.RotationRadians.Y,
datBoneData.RotationRadians.Z)
jObj.RotationRadians.X,
jObj.RotationRadians.Y,
jObj.RotationRadians.Z)
.SetLocalScale(
datBoneData.Scale.X,
datBoneData.Scale.Y,
datBoneData.Scale.Z);
jObj.Scale.X,
jObj.Scale.Y,
jObj.Scale.Z);
finBone.Name = jObj.Name;

finBoneByJObj[jObj] = finBone;
boneWeightsByJObj[jObj] =
finSkin.GetOrCreateBoneWeights(VertexSpace.BONE, finBone);

foreach (var datChildBone in jObj.Children) {
var inverseBindMatrixValues = jObj.InverseBindMatrixValues;
inverseBindMatrixValues.CopyTo(inverseBindMatrixBuffer);
inverseBindMatrixBuffer[15] = 1;
inverseBindMatrixByJObj[jObj] =
new FinMatrix4x4(inverseBindMatrixBuffer).TransposeInPlace();

foreach (var datChildBone in jObj.GetChildren()) {
boneQueue.Enqueue((finBone, datChildBone));
}
}
Expand Down Expand Up @@ -304,7 +311,7 @@ public unsafe IModel ImportModel(DatModelFileBundle modelFileBundle) {
jObjByOffset[pObjWeight.JObjOffset];
return new BoneWeight(
finBoneByJObj[jObj],
jObj.InverseBindMatrix,
inverseBindMatrixByJObj[jObj],
pObjWeight.Weight
);
})
Expand Down
106 changes: 22 additions & 84 deletions FinModelUtility/Formats/Dat/Dat/src/schema/Dat.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using fin.math.matrix.four;
using fin.data.queues;
using fin.math.matrix.four;
using fin.util.asserts;
using fin.util.enumerables;
using fin.util.hex;
Expand Down Expand Up @@ -31,20 +32,13 @@ public class Dat : IBinaryDeserializable {

public List<JObj> RootJObjs { get; } = new();

private Dictionary<uint, JObj> jObjByOffset_ = new();
private readonly Dictionary<uint, JObj> jObjByOffset_ = new();
public IReadOnlyDictionary<uint, JObj> JObjByOffset => this.jObjByOffset_;

public IEnumerable<JObj> JObjs => this.RootJObjs.SelectMany(
this.EnumerateSelfAndChildrenWithinJObj_);

private IEnumerable<JObj> EnumerateSelfAndChildrenWithinJObj_(JObj jObj)
=> jObj.Yield()
.Concat(jObj.Children.SelectMany(
this.EnumerateSelfAndChildrenWithinJObj_));
DatNodeExtensions.GetSelfAndChildrenAndSiblings);

public void Read(IBinaryReader br) {
this.VertexDescriptorValue = (uint) 0;

var fileHeader = br.ReadNew<FileHeader>();
Asserts.Equal(br.Length, fileHeader.FileSize);

Expand Down Expand Up @@ -94,104 +88,48 @@ public void Read(IBinaryReader br) {
}

this.ReadJObs_(br);
this.ReadDObjs_(br);
this.ReadNames_(br);
}

private bool AssertNullOrValidPointer_(uint pointer) {
if (pointer == 0) {
return false;
}

if (!this.validOffsets_.Contains(pointer)) {
;
}

Asserts.True(this.validOffsets_.Contains(pointer));
return true;
}

public uint VertexDescriptorValue { get; set; }

private void ReadJObs_(IBinaryReader br) {
var jObjQueue =
new Queue<(
RootNode rootNode,
JObj? parentJObj,
uint jObjDataOffset
)>();

foreach (var rootNode in this.rootNodes_.Where(
rootNode => rootNode.Type == RootNodeType.JObj)) {
jObjQueue.Enqueue((rootNode, null, rootNode.Data.DataOffset));
}

br.Position = this.dataBlockOffset_;
br.PushLocalSpace();

this.RootJObjs.Clear();
while (jObjQueue.Count > 0) {
var (rootNode, parentJObj, jObjDataOffset) = jObjQueue.Dequeue();

var jObj = new JObj();
var jObjData = jObj.Data;
var jObjQueue = new FinTuple2Queue<uint, JObj>();

this.jObjByOffset_[jObjDataOffset] = jObj;
jObj.Name = jObjDataOffset.ToHex();

if (parentJObj == null) {
this.RootJObjs.Add(jObj);
} else {
parentJObj.Children.Add(jObj);
}

br.Position = jObjDataOffset;
jObjData.Read(br);

if (jObjData.InverseBindMatrixOffset != 0) {
br.Position = jObjData.InverseBindMatrixOffset;

var inverseBindMatrixValues = new float[4 * 4];
br.ReadSingles(inverseBindMatrixValues.AsSpan(0, 4 * 3));
inverseBindMatrixValues[15] = 1;
jObj.InverseBindMatrix =
new FinMatrix4x4(inverseBindMatrixValues).TransposeInPlace();
}
this.RootJObjs.Clear();
foreach (var rootNode in this.rootNodes_.Where(
rootNode => rootNode.Type == RootNodeType.JObj)) {
var jObjOffset = rootNode.Data.DataOffset;
br.Position = jObjOffset;

var firstChildOffset = jObj.Data.FirstChildBoneOffset;
if (this.AssertNullOrValidPointer_(firstChildOffset)) {
jObjQueue.Enqueue((rootNode, jObj, firstChildOffset));
}
var jObj = br.ReadNew<JObj>();
this.RootJObjs.Add(jObj);

var nextSiblingOffset = jObj.Data.NextSiblingBoneOffset;
if (this.AssertNullOrValidPointer_(nextSiblingOffset)) {
jObjQueue.Enqueue((rootNode, parentJObj, nextSiblingOffset));
}
jObjQueue.Enqueue((jObjOffset, jObj));
}

br.PopLocalSpace();
}

private void ReadDObjs_(IBinaryReader br) {
br.Position = this.dataBlockOffset_;
br.PushLocalSpace();
while (jObjQueue.TryDequeue(out var jObjOffset, out var jObj)) {
this.jObjByOffset_[jObjOffset] = jObj;

foreach (var jObj in this.JObjs) {
if (jObj.Data.FirstDObjOffset != 0) {
br.Position = jObj.Data.FirstDObjOffset;
jObj.FirstDObj = br.ReadNew<DObj>();
if (jObj.FirstChild != null) {
jObjQueue.Enqueue((jObj.FirstChildBoneOffset, jObj.FirstChild));
}
}

br.PopLocalSpace();
if (jObj.NextSibling != null) {
jObjQueue.Enqueue((jObj.NextSiblingBoneOffset, jObj.NextSibling));
}
}
}

private void ReadNames_(IBinaryReader br) {
br.Position = this.stringTableOffset_;
br.PushLocalSpace();

foreach (var jObj in this.JObjs) {
var jObjStringOffset = jObj.Data.StringOffset;
var jObjStringOffset = jObj.StringOffset;
if (jObjStringOffset != 0) {
br.Position = jObjStringOffset;
jObj.Name = br.ReadStringNT();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,9 @@ public static IEnumerable<TNode> GetSelfAndChildrenAndSiblings<TNode>(
}
}
}

public static IEnumerable<TNode> GetChildren<TNode>(this TNode? root)
where TNode : IDatTreeNode<TNode>
=> root?.FirstChild?.GetSelfAndSiblings() ?? Enumerable.Empty<TNode>();
}
}
29 changes: 19 additions & 10 deletions FinModelUtility/Formats/Dat/Dat/src/schema/JObj.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using fin.schema.vector;

using schema.binary;
using schema.binary.attributes;

namespace dat.schema {
[Flags]
Expand Down Expand Up @@ -51,8 +52,11 @@ public enum JObjFlags : uint {
ROOT_TEXEDGE = 1 << 30,
}

/// <summary>
/// Joint object.
/// </summary>
[BinarySchema]
public partial class JObjData : IBinaryConvertible {
public partial class JObj : IDatTreeNode<JObj>, IBinaryDeserializable {
public uint StringOffset { get; set; }
public JObjFlags Flags { get; set; }
public uint FirstChildBoneOffset { get; set; }
Expand All @@ -62,25 +66,30 @@ public partial class JObjData : IBinaryConvertible {
public Vector3f Scale { get; } = new();
public Vector3f Position { get; } = new();
public uint InverseBindMatrixOffset { get; set; }

[Unknown]
public uint UnknownPointer { get; set; }
}

/// <summary>
/// Joint object.
/// </summary>
public class JObj {
public JObjData Data { get; } = new();

[Ignore]
public string? Name { get; set; }

[RAtPositionOrNull(nameof(FirstChildBoneOffset))]
public JObj? FirstChild { get; set; }

[RAtPositionOrNull(nameof(NextSiblingBoneOffset))]
public JObj? NextSibling { get; set; }

[RAtPositionOrNull(nameof(FirstDObjOffset))]
public DObj? FirstDObj { get; set; }

public IEnumerable<DObj> DObjs => this.FirstDObj.GetSelfAndSiblings();
[RAtPositionOrNull(nameof(InverseBindMatrixOffset))]
[SequenceLengthSource(4 * 3)]
public float[]? InverseBindMatrixValues { get; set; }

public List<JObj> Children { get; } = new();

public IFinMatrix4x4? InverseBindMatrix { get; set; }
[Ignore]
public IEnumerable<DObj> DObjs => this.FirstDObj.GetSelfAndSiblings();

public override string? ToString() => this.Name;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ private IDictionary<string, IBwObject> ParseObjectMap_(

isUsefulNode = true;
node ??= new LevelObject { Id = objId };
node.Matrix = new FinMatrix4x4(floats);
node.Matrix = new FinMatrix4x4(floats.AsSpan());
} else if (objectType is "cNodeHierarchyResource" &&
childNameAttribute is "mName") {
isUsefulNode = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,6 @@ private void AddGeoFileToModel_(
}

public IFinMatrix4x4 GetMatrixFromBone_(Matrix4x4f matrix)
=> new FinMatrix4x4(matrix.Values).InvertInPlace();
=> new FinMatrix4x4(matrix.Values.AsSpan()).InvertInPlace();
}
}

0 comments on commit c7f3e7e

Please sign in to comment.