Apply subobj hierarchy to model

This commit is contained in:
Jarrod Doyle 2024-12-23 11:44:13 +00:00
parent 202edd424b
commit 1177474fd6
Signed by: Jayrude
GPG Key ID: 38B57B16E7C0ADF7
3 changed files with 58 additions and 31 deletions

View File

@ -265,14 +265,12 @@ public partial class Mission : Node3D
var meshDetails = Timing.TimeStage("Get Models", () => Context.Instance.ModelLoader.Load(modelName)); var meshDetails = Timing.TimeStage("Get Models", () => Context.Instance.ModelLoader.Load(modelName));
if (meshDetails.Length != 0) 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.Position = pos;
model.RotationDegrees = rot; model.RotationDegrees = rot;
model.Scale = scale; 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) bool GetTextReplPath(PropString prop, out string path)
{ {
path = ""; path = "";
@ -301,12 +299,16 @@ public partial class Mission : Node3D
} }
var repls = new PropString[] { txtRepl0, txtRepl1, txtRepl2, txtRepl3 }; 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++) for (var i = 0; i < 4; i++)
{ {
if (GetTextReplPath(repls[i], out var path)) if (!GetTextReplPath(repls[i], out var path))
{ {
continue;
}
var overrideMat = new StandardMaterial3D var overrideMat = new StandardMaterial3D
{ {
AlbedoTexture = TextureLoader.LoadTexture(path), AlbedoTexture = TextureLoader.LoadTexture(path),
@ -323,14 +325,11 @@ public partial class Mission : Node3D
} }
} }
} }
}
if (renderAlpha != null) if (renderAlpha != null)
{ {
meshInstance.Transparency = 1.0f - renderAlpha.value; meshInstance.Transparency = 1.0f - renderAlpha.value;
} }
model.AddChild(meshInstance);
} }
model.AddToGroup(OBJECT_MODELS_GROUP); model.AddToGroup(OBJECT_MODELS_GROUP);

View File

@ -19,13 +19,8 @@ public partial class Model : Node3D
} }
Context.Instance.SetCampaign(campaignName); Context.Instance.SetCampaign(campaignName);
var model = new Node3D();
var meshDetails = Context.Instance.ModelLoader.Load(modelPath); var meshDetails = Context.Instance.ModelLoader.Load(modelPath);
var meshes = ModelLoader.TransformMeshes([0, 0, 0, 0, 0, 0], meshDetails); var model = ModelLoader.TransformMeshes([0, 0, 0, 0, 0, 0], meshDetails);
foreach (var meshInstance in meshes)
{
model.AddChild(meshInstance);
}
AddChild(model); AddChild(model);
} }
} }

View File

@ -8,11 +8,12 @@ namespace KeepersCompound.TMV;
// TODO: Work out a way to share base game models again in the cache // TODO: Work out a way to share base game models again in the cache
public class ModelLoader 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 int JointIdx = jointIdx;
public readonly Transform3D Transform = transform; public readonly Transform3D Transform = transform;
public readonly MeshInstance3D Mesh = mesh; public readonly MeshInstance3D Mesh = mesh;
public int ParentIdx = parentIdx;
} }
private readonly Dictionary<(string, string), MeshDetails[]> _cache = new(); private readonly Dictionary<(string, string), MeshDetails[]> _cache = new();
@ -40,15 +41,20 @@ public class ModelLoader
return details; 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<MeshInstance3D>(); var meshes = new List<MeshInstance3D>();
foreach (var details in meshDetails) foreach (var details in meshDetails)
{ {
var mesh = details.Mesh.Duplicate() as MeshInstance3D; var mesh = details.Mesh.Duplicate() as MeshInstance3D;
if (details.JointIdx != -1) 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 r1 = new Quaternion(new Vector3(0, 0, 1), ang);
var r2 = details.Transform.Basis.GetRotationQuaternion(); var r2 = details.Transform.Basis.GetRotationQuaternion();
var basis = new Basis(r2 * r1); var basis = new Basis(r2 * r1);
@ -62,7 +68,22 @@ public class ModelLoader
meshes.Add(mesh); meshes.Add(mesh);
} }
return [..meshes]; 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 root;
} }
public static MeshDetails[] LoadModel(string modelName) public static MeshDetails[] LoadModel(string modelName)
@ -186,7 +207,19 @@ public class ModelLoader
var pos = -modelFile.Header.Center.ToGodotVec3(); var pos = -modelFile.Header.Center.ToGodotVec3();
var meshInstance = new MeshInstance3D { Mesh = mesh, Position = pos }; 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; return meshDetails;