diff --git a/project/code/TMV/Mission.cs b/project/code/TMV/Mission.cs index f755e73..e769caa 100644 --- a/project/code/TMV/Mission.cs +++ b/project/code/TMV/Mission.cs @@ -265,14 +265,12 @@ public partial class Mission : Node3D var meshDetails = Timing.TimeStage("Get Models", () => Context.Instance.ModelLoader.Load(modelName)); if (meshDetails.Length != 0) { - var model = new Node3D(); + var joints = jointPosProp != null ? jointPosProp.Positions : [0, 0, 0, 0, 0, 0]; + var model = ModelLoader.TransformMeshes(joints, meshDetails); model.Position = pos; model.RotationDegrees = rot; model.Scale = scale; - var joints = jointPosProp != null ? jointPosProp.Positions : [0, 0, 0, 0, 0, 0]; - var meshes = ModelLoader.TransformMeshes(joints, meshDetails); - bool GetTextReplPath(PropString prop, out string path) { path = ""; @@ -301,26 +299,29 @@ public partial class Mission : Node3D } var repls = new PropString[] { txtRepl0, txtRepl1, txtRepl2, txtRepl3 }; - foreach (var meshInstance in meshes) + foreach (var child in model.FindChildren("*", "MeshInstance3D", true, false)) { + var meshInstance = child as MeshInstance3D; for (var i = 0; i < 4; i++) { - if (GetTextReplPath(repls[i], out var path)) + if (!GetTextReplPath(repls[i], out var path)) { - var overrideMat = new StandardMaterial3D - { - AlbedoTexture = TextureLoader.LoadTexture(path), - Transparency = BaseMaterial3D.TransparencyEnum.AlphaDepthPrePass, - }; + continue; + } + + var overrideMat = new StandardMaterial3D + { + AlbedoTexture = TextureLoader.LoadTexture(path), + Transparency = BaseMaterial3D.TransparencyEnum.AlphaDepthPrePass, + }; - var surfaceCount = meshInstance.Mesh.GetSurfaceCount(); - for (var idx = 0; idx < surfaceCount; idx++) + var surfaceCount = meshInstance.Mesh.GetSurfaceCount(); + for (var idx = 0; idx < surfaceCount; idx++) + { + var surfaceMat = meshInstance.Mesh.SurfaceGetMaterial(idx); + if (surfaceMat.HasMeta($"TxtRepl{i}")) { - var surfaceMat = meshInstance.Mesh.SurfaceGetMaterial(idx); - if (surfaceMat.HasMeta($"TxtRepl{i}")) - { - meshInstance.SetSurfaceOverrideMaterial(idx, overrideMat); - } + meshInstance.SetSurfaceOverrideMaterial(idx, overrideMat); } } } @@ -329,8 +330,6 @@ public partial class Mission : Node3D { meshInstance.Transparency = 1.0f - renderAlpha.value; } - - model.AddChild(meshInstance); } model.AddToGroup(OBJECT_MODELS_GROUP); diff --git a/project/code/TMV/Model.cs b/project/code/TMV/Model.cs index b6ddfa7..391fd39 100644 --- a/project/code/TMV/Model.cs +++ b/project/code/TMV/Model.cs @@ -19,13 +19,8 @@ public partial class Model : Node3D } Context.Instance.SetCampaign(campaignName); - var model = new Node3D(); var meshDetails = Context.Instance.ModelLoader.Load(modelPath); - var meshes = ModelLoader.TransformMeshes([0, 0, 0, 0, 0, 0], meshDetails); - foreach (var meshInstance in meshes) - { - model.AddChild(meshInstance); - } + var model = ModelLoader.TransformMeshes([0, 0, 0, 0, 0, 0], meshDetails); AddChild(model); } } diff --git a/project/code/TMV/ModelLoader.cs b/project/code/TMV/ModelLoader.cs index ee2cc74..8895305 100644 --- a/project/code/TMV/ModelLoader.cs +++ b/project/code/TMV/ModelLoader.cs @@ -8,11 +8,12 @@ namespace KeepersCompound.TMV; // TODO: Work out a way to share base game models again in the cache public class ModelLoader { - public struct MeshDetails(int jointIdx, Transform3D transform, MeshInstance3D mesh) + public struct MeshDetails(int jointIdx, Transform3D transform, MeshInstance3D mesh, int parentIdx) { public readonly int JointIdx = jointIdx; public readonly Transform3D Transform = transform; public readonly MeshInstance3D Mesh = mesh; + public int ParentIdx = parentIdx; } private readonly Dictionary<(string, string), MeshDetails[]> _cache = new(); @@ -40,15 +41,20 @@ public class ModelLoader return details; } - public static MeshInstance3D[] TransformMeshes(float[] joints, MeshDetails[] meshDetails) + public static Node3D TransformMeshes(float[] joints, MeshDetails[] meshDetails) { + for (var i = 0; i < joints.Length; i++) + { + joints[i] = float.DegreesToRadians(joints[i]); + } + var meshes = new List(); foreach (var details in meshDetails) { var mesh = details.Mesh.Duplicate() as MeshInstance3D; if (details.JointIdx != -1) { - var ang = float.DegreesToRadians(joints[details.JointIdx]); + var ang = joints[details.JointIdx]; var r1 = new Quaternion(new Vector3(0, 0, 1), ang); var r2 = details.Transform.Basis.GetRotationQuaternion(); var basis = new Basis(r2 * r1); @@ -61,8 +67,23 @@ public class ModelLoader meshes.Add(mesh); } + + var root = new Node3D(); + for (var i = 0; i < meshes.Count; i++) + { + var details = meshDetails[i]; + var parentId = details.ParentIdx; + if (parentId == -1) + { + root.AddChild(meshes[i]); + } + else + { + meshes[parentId].AddChild(meshes[i]); + } + } - return [..meshes]; + return root; } public static MeshDetails[] LoadModel(string modelName) @@ -186,7 +207,19 @@ public class ModelLoader var pos = -modelFile.Header.Center.ToGodotVec3(); var meshInstance = new MeshInstance3D { Mesh = mesh, Position = pos }; - meshDetails[i] = new MeshDetails(jointIdx, transform, meshInstance); + meshDetails[i] = new MeshDetails(jointIdx, transform, meshInstance, -1); + } + + // Build parentage + for (var i = 0; i < objCount; i++) + { + var subObj = modelFile.Objects[i]; + var childIdx = subObj.Child; + while (childIdx != -1) + { + meshDetails[childIdx].ParentIdx = i; + childIdx = modelFile.Objects[childIdx].Next; + } } return meshDetails;