62 lines
2.2 KiB
C#
62 lines
2.2 KiB
C#
using System.Collections.Generic;
|
|
using System.Numerics;
|
|
using DatReaderWriter.DBObjs;
|
|
using DatReaderWriter.Enums;
|
|
using DatReaderWriter.Types;
|
|
|
|
namespace AcDream.Core.Meshing;
|
|
|
|
/// <summary>
|
|
/// Computes retail's rigid per-part frames for attachments and effects.
|
|
/// Visual GfxObj scale is deliberately excluded.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Pose selection matches <see cref="SetupMesh.Flatten"/>: an explicit motion
|
|
/// frame, then Resting, Default, then the first placement frame. Retail
|
|
/// <c>CPartArray::UpdateParts</c> (<c>0x005190F0</c>) scales only the frame
|
|
/// origin by the object's scale. <c>CPartArray::SetScaleInternal</c>
|
|
/// (<c>0x00518A00</c>) stores Setup DefaultScale separately on the visual
|
|
/// <c>CPhysicsPart::gfxobj_scale</c>, so it never enters this rigid frame.
|
|
/// </remarks>
|
|
public static class SetupPartTransforms
|
|
{
|
|
public static IReadOnlyList<Matrix4x4> Compute(
|
|
Setup setup,
|
|
AnimationFrame? motionFrameOverride = null,
|
|
float objectScale = 1.0f)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(setup);
|
|
AnimationFrame? source = motionFrameOverride;
|
|
if (source is null && setup.PlacementFrames.TryGetValue(Placement.Resting, out var resting))
|
|
{
|
|
source = resting;
|
|
}
|
|
else if (source is null && setup.PlacementFrames.TryGetValue(Placement.Default, out var def))
|
|
{
|
|
source = def;
|
|
}
|
|
else if (source is null)
|
|
{
|
|
foreach (var kvp in setup.PlacementFrames)
|
|
{
|
|
source = kvp.Value;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (source is null)
|
|
return Array.Empty<Matrix4x4>();
|
|
|
|
int partCount = setup.Parts.Count;
|
|
var result = new Matrix4x4[partCount];
|
|
for (int i = 0; i < partCount; i++)
|
|
{
|
|
Frame frame = i < source.Frames.Count
|
|
? source.Frames[i]
|
|
: new Frame { Origin = Vector3.Zero, Orientation = Quaternion.Identity };
|
|
result[i] = Matrix4x4.CreateFromQuaternion(frame.Orientation)
|
|
* Matrix4x4.CreateTranslation(frame.Origin * objectScale);
|
|
}
|
|
return result;
|
|
}
|
|
}
|