Skip to content

Commit

Permalink
Set up logic for caching Dead Space MTLB file paths by ID.
Browse files Browse the repository at this point in the history
  • Loading branch information
MeltyPlayer committed May 1, 2024
1 parent 08983b7 commit 803303a
Show file tree
Hide file tree
Showing 12 changed files with 179 additions and 88 deletions.
Original file line number Diff line number Diff line change
@@ -1,28 +1,29 @@
using fin.io;
using System.Collections.Generic;
using System.Linq;

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

namespace uni.util.io {
namespace fin.io {
[GenerateReadOnly]
public partial interface IFileIdDictionary {
IReadOnlyTreeFile this[uint id] { get; set; }

[Const]
void Save(IGenericFile file);
void Save(IGenericFile fileIdsFile);
}

public partial class FileIdDictionary : IFileIdDictionary {
private readonly IReadOnlyTreeDirectory baseDirectory_;
private readonly Dictionary<uint, string> impl_;

public FileIdDictionary(IReadOnlyTreeDirectory baseDirectory,
IReadOnlyGenericFile fileIds) {
IReadOnlyGenericFile fileIdsFile) {
this.baseDirectory_ = baseDirectory;
this.impl_ = fileIds.ReadNew<FileIds>()
.Pairs.ToDictionary(pair => pair.Id,
pair => pair.FilePath);
this.impl_ = fileIdsFile.ReadNew<FileIds>()
.Pairs.ToDictionary(pair => pair.Id,
pair => pair.FilePath);
}

public FileIdDictionary(IReadOnlyTreeDirectory baseDirectory) {
Expand All @@ -36,12 +37,14 @@ public IReadOnlyTreeFile this[uint id] {
= value.AssertGetPathRelativeTo(this.baseDirectory_);
}

public void Save(IGenericFile file) => file.Write(new FileIds {
Pairs = this.impl_
.Select(pair => new FileIdPair
{ Id = pair.Key, FilePath = pair.Value })
.ToArray()
});
public void Save(IGenericFile fileIdsFile)
=> fileIdsFile.Write(
new FileIds {
Pairs = this.impl_
.Select(pair => new FileIdPair
{ Id = pair.Key, FilePath = pair.Value })
.ToArray()
});

[BinarySchema]
private partial class FileIds : IBinaryConvertible {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,31 @@
using fin.data.dictionaries;
using fin.io;
using System.Collections.Generic;
using System.Linq;

using fin.data.dictionaries;

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

namespace uni.util.io {
namespace fin.io {
[GenerateReadOnly]
public partial interface IFileIdsDictionary {
IEnumerable<IReadOnlyTreeFile> this[uint id] { get; }

public void AddFile(uint id, IReadOnlyTreeFile file);

[Const]
void Save(IGenericFile file);
void Save(IGenericFile fileIdsFile);
}

public partial class FileIdsDictionary : IFileIdsDictionary {
private readonly IReadOnlyTreeDirectory baseDirectory_;
private readonly SetDictionary<uint, string> impl_ = new();

public FileIdsDictionary(IReadOnlyTreeDirectory baseDirectory,
IReadOnlyGenericFile fileIds) {
IReadOnlyGenericFile fileIdsFile) {
this.baseDirectory_ = baseDirectory;
foreach (var fileIdsPair in fileIds.ReadNew<FileIds>().Pairs) {
foreach (var fileIdsPair in fileIdsFile.ReadNew<FileIds>().Pairs) {
foreach (var filePath in fileIdsPair.FilePaths) {
this.impl_.Add(fileIdsPair.Id, filePath.FilePath);
}
Expand All @@ -41,17 +43,19 @@ public IEnumerable<IReadOnlyTreeFile> this[uint id]
public void AddFile(uint id, IReadOnlyTreeFile file)
=> this.impl_.Add(id, file.AssertGetPathRelativeTo(this.baseDirectory_));

public void Save(IGenericFile file) => file.Write(new FileIds {
Pairs = this.impl_
.Select(pair => new FileIdsPair {
Id = pair.Key,
FilePaths = pair.Value
.Select(v => new NullableString
{ FilePath = v })
.ToArray()
})
.ToArray()
});
public void Save(IGenericFile fileIdsFile)
=> fileIdsFile.Write(
new FileIds {
Pairs = this.impl_
.Select(pair => new FileIdsPair {
Id = pair.Key,
FilePaths = pair.Value
.Select(v => new NullableString
{ FilePath = v })
.ToArray()
})
.ToArray()
});

[BinarySchema]
private partial class FileIds : IBinaryConvertible {
Expand Down
14 changes: 12 additions & 2 deletions FinModelUtility/Fin/Fin/src/io/GenericFileExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,28 @@ public static void Serialize<T>(this IGenericFile file, T instance)
public static StreamReader OpenReadAsText(this IReadOnlyGenericFile file)
=> new(file.OpenRead());

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static IBinaryReader OpenReadAsBinary(this IReadOnlyGenericFile file)
=> new SchemaBinaryReader(file.OpenRead());

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static IBinaryReader OpenReadAsBinary(
this IReadOnlyGenericFile file,
Endianness endianness)
=> new SchemaBinaryReader(file.OpenRead(), endianness);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T ReadNew<T>(this IReadOnlyGenericFile file)
where T : IBinaryDeserializable, new() {
using var br = new SchemaBinaryReader(file.OpenRead());
using var br = file.OpenReadAsBinary();
return br.ReadNew<T>();
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T ReadNew<T>(this IReadOnlyGenericFile file,
Endianness endianness)
where T : IBinaryDeserializable, new() {
using var br = new SchemaBinaryReader(file.OpenRead(), endianness);
using var br = file.OpenReadAsBinary(endianness);
return br.ReadNew<T>();
}

Expand Down
12 changes: 8 additions & 4 deletions FinModelUtility/Formats/Visceral/Visceral/src/010/Geo.bt
Original file line number Diff line number Diff line change
Expand Up @@ -113,20 +113,24 @@ typedef struct {
uint meshNameOffset;
StringAtOffset name(meshNameOffset);

byte unk0[0x1c];
byte unk9[0x8];

uint mtlbId;

byte unk1[0x10];
byte unk2[0x10];

uint polyInfoOffset;

byte unk2[0x4];
byte unk3[0x4];

uint vertOffset;

byte unk3[0x4];
byte unk4[0x4];

uint faceOffset;

byte unk4[0x4];
byte unk5[0x4];


typedef struct {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ public IEnumerable<IReadOnlyGenericFile> Files
public required IReadOnlyList<IReadOnlyTreeFile> BnkFiles { get; init; }
public required IReadOnlyTreeFile? RcbFile { get; init; }

public required MtlbFileIdsDictionary MtlbFileIdsDictionary { get; init; }

public IReadOnlyList<Tg4ImageFileBundle>? Tg4ImageFileBundles { get; init; }
}
}
109 changes: 64 additions & 45 deletions FinModelUtility/Formats/Visceral/Visceral/src/api/GeoModelImporter.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Drawing;

using fin.data.dictionaries;
using fin.data.lazy;
using fin.data.queues;
using fin.io;
using fin.math.matrix.four;
Expand All @@ -11,6 +12,7 @@
using fin.schema.matrix;

using visceral.schema.geo;
using visceral.schema.mtlb;
using visceral.schema.rcb;

namespace visceral.api {
Expand All @@ -20,6 +22,17 @@ public class GeoModelImporter : IModelImporter<GeoModelFileBundle> {
public IModel Import(GeoModelFileBundle modelFileBundle) {
var finModel = new ModelImpl();

// Builds skeletons
IBone[] finBones = Array.Empty<IBone>();
var rcbFile = modelFileBundle.RcbFile;
if (rcbFile != null) {
this.AddRcbFileToModel_(finModel, rcbFile, out finBones);
}

foreach (var bnkFile in modelFileBundle.BnkFiles) {
new BnkReader().ReadBnk(finModel, bnkFile, rcbFile, finBones);
}

// Builds textures
var textureBundles = modelFileBundle.Tg4ImageFileBundles;
var textures = new List<ITexture>();
Expand All @@ -35,16 +48,17 @@ public IModel Import(GeoModelFileBundle modelFileBundle) {
}
}

// Builds skeletons
IBone[] finBones = Array.Empty<IBone>();
var rcbFile = modelFileBundle.RcbFile;
if (rcbFile != null) {
this.AddRcbFileToModel_(finModel, rcbFile, out finBones);
}

foreach (var bnkFile in modelFileBundle.BnkFiles) {
new BnkReader().ReadBnk(finModel, bnkFile, rcbFile, finBones);
}
// Gets materials
var lazyMtlbDictionary = new LazyDictionary<uint, IReadOnlyList<Mtlb>>(
mtlbId =>
modelFileBundle.MtlbFileIdsDictionary[mtlbId]
.Select(mtlbFile => mtlbFile.ReadNew<Mtlb>())
.ToArray());
var lazyMaterialDictionary = new LazyDictionary<uint, IMaterial>(
mtlbId => {
var mtlb = lazyMtlbDictionary[mtlbId].First();
return null!;
});

// Builds meshes
var geoFiles = modelFileBundle.GeoFiles;
Expand Down Expand Up @@ -155,44 +169,49 @@ private void AddGeoFileToModel_(
var finVertices =
geoMesh.Vertices
.Select(geoVertex => {
var vertex = finSkin.AddVertex(geoVertex.Position);

var boneWeights =
geoVertex.Weights
.Select((weight, i)
=> (geoVertex.Bones[i], weight))
.Where(boneWeight => boneWeight.weight > 0)
.Select(boneWeight
=> new BoneWeight(
finBones[
geo.Bones[
boneWeight.Item1].Id],
null,
boneWeight.Item2))
.ToArray();

vertex.SetBoneWeights(
finSkin.GetOrCreateBoneWeights(
VertexSpace.RELATIVE_TO_WORLD,
boneWeights));

vertex.SetLocalNormal(geoVertex.Normal);
vertex.SetLocalTangent(geoVertex.Tangent);
vertex.SetUv(geoVertex.Uv);
return vertex as IReadOnlyVertex;
})
var vertex = finSkin.AddVertex(geoVertex.Position);

var boneWeights =
geoVertex.Weights
.Select((weight, i)
=> (geoVertex.Bones[i],
weight))
.Where(boneWeight
=> boneWeight.weight > 0)
.Select(boneWeight
=> new BoneWeight(
finBones[
geo.Bones[
boneWeight
.Item1]
.Id],
null,
boneWeight.Item2))
.ToArray();

vertex.SetBoneWeights(
finSkin.GetOrCreateBoneWeights(
VertexSpace.RELATIVE_TO_WORLD,
boneWeights));

vertex.SetLocalNormal(geoVertex.Normal);
vertex.SetLocalTangent(geoVertex.Tangent);
vertex.SetUv(geoVertex.Uv);
return vertex as IReadOnlyVertex;
})
.ToArray();

var triangles = geoMesh.Faces.Select(geoFace => {
var indices = geoFace.Indices
.Select(
index => index -
geoMesh.BaseVertexIndex)
.ToArray();
return (finVertices[indices[0]],
finVertices[indices[1]],
finVertices[indices[2]]);
})
var indices = geoFace.Indices
.Select(
index => index -
geoMesh
.BaseVertexIndex)
.ToArray();
return (finVertices[indices[0]],
finVertices[indices[1]],
finVertices[indices[2]]);
})
.ToArray();

finMesh.AddTriangles(triangles)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using fin.io;

using schema.binary;

namespace visceral.api {
public class MtlbFileIdsDictionary : IReadOnlyFileIdsDictionary {
private readonly IReadOnlyFileIdsDictionary impl_;

public MtlbFileIdsDictionary(IReadOnlyTreeDirectory baseDirectory,
ISystemFile fileIdsFile) {


if (fileIdsFile.Exists) {
this.impl_ = new FileIdsDictionary(baseDirectory, fileIdsFile);
} else {
var impl = new FileIdsDictionary(baseDirectory);
this.impl_ = impl;
foreach (var mtlbFile in baseDirectory.GetFilesWithFileType(
".mtlb",
true)) {
using var br = mtlbFile.OpenReadAsBinary(Endianness.LittleEndian);
br.Position = 8;
var id = br.ReadUInt32();
impl.AddFile(id, mtlbFile);
}

this.Save(fileIdsFile);
}
}

public IEnumerable<IReadOnlyTreeFile> this[uint id] => this.impl_[id];

public void Save(IGenericFile fileIdsFile) => this.impl_.Save(fileIdsFile);
}
}
Loading

0 comments on commit 803303a

Please sign in to comment.