feat(render): implement Campaign AR and terrain fidelity
This commit is contained in:
parent
99cf26e00c
commit
7a5f96ede5
368 changed files with 50611 additions and 950 deletions
|
|
@ -38,6 +38,14 @@ public sealed class SkyObjectData
|
|||
public uint PesObjectId;
|
||||
public uint Properties;
|
||||
|
||||
/// <summary>
|
||||
/// Source GfxObj sort centre. Celestial billboards are authored at their
|
||||
/// apparent direction from the camera, so transforming and normalizing
|
||||
/// this point yields the exact direction rendered by the sky pass. Zero
|
||||
/// means the optional DAT lookup was unavailable.
|
||||
/// </summary>
|
||||
public Vector3 AuthoredSortCenter;
|
||||
|
||||
/// <summary>
|
||||
/// True when this SkyObject is gated on the weather system (Properties
|
||||
/// bit <c>0x04</c>). Per the named retail decomp,
|
||||
|
|
@ -140,6 +148,9 @@ public sealed class SkyObjectReplaceData
|
|||
public float Transparent;
|
||||
public float Luminosity;
|
||||
public float MaxBright;
|
||||
|
||||
/// <summary>Sort centre for a replacement <see cref="GfxObjId"/>.</summary>
|
||||
public Vector3 AuthoredSortCenter;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -334,7 +345,7 @@ public static class SkyDescLoader
|
|||
ArgumentNullException.ThrowIfNull(dats);
|
||||
var region = dats.Get<Region>(RegionDatId);
|
||||
if (region is null) return null;
|
||||
return LoadFromRegion(region);
|
||||
return LoadFromRegion(region, dats);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -352,7 +363,9 @@ public static class SkyDescLoader
|
|||
/// GfxObjReplace swap pattern.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public static LoadedSkyDesc? LoadFromRegion(Region region)
|
||||
public static LoadedSkyDesc? LoadFromRegion(
|
||||
Region region,
|
||||
IDatObjectSource? dats = null)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(region);
|
||||
if (!region.PartsMask.HasFlag(PartsMask.HasSkyInfo) || region.SkyInfo is null)
|
||||
|
|
@ -367,8 +380,12 @@ public static class SkyDescLoader
|
|||
|
||||
foreach (var dg in sky.DayGroups)
|
||||
{
|
||||
var objs = dg.SkyObjects.Select(ConvertSkyObject).ToList();
|
||||
var times = dg.SkyTime.Select(ConvertTimeOfDay).ToList();
|
||||
var objs = dg.SkyObjects
|
||||
.Select(value => ConvertSkyObject(value, dats))
|
||||
.ToList();
|
||||
var times = dg.SkyTime
|
||||
.Select(value => ConvertTimeOfDay(value, dats))
|
||||
.ToList();
|
||||
|
||||
dayGroups.Add(new DayGroupData
|
||||
{
|
||||
|
|
@ -495,7 +512,9 @@ public static class SkyDescLoader
|
|||
Console.WriteLine("[sky-dump] ======== END SkyDesc dump ========");
|
||||
}
|
||||
|
||||
private static SkyObjectData ConvertSkyObject(SkyObject s) => new()
|
||||
private static SkyObjectData ConvertSkyObject(
|
||||
SkyObject s,
|
||||
IDatObjectSource? dats) => new()
|
||||
{
|
||||
BeginTime = s.BeginTime,
|
||||
EndTime = s.EndTime,
|
||||
|
|
@ -506,9 +525,14 @@ public static class SkyDescLoader
|
|||
GfxObjId = s.DefaultGfxObjectId?.DataId ?? 0u,
|
||||
PesObjectId = s.DefaultPesObjectId?.DataId ?? 0u,
|
||||
Properties = s.Properties,
|
||||
AuthoredSortCenter = ResolveSortCenter(
|
||||
s.DefaultGfxObjectId?.DataId ?? 0u,
|
||||
dats),
|
||||
};
|
||||
|
||||
private static DatSkyKeyframeData ConvertTimeOfDay(SkyTimeOfDay s)
|
||||
private static DatSkyKeyframeData ConvertTimeOfDay(
|
||||
SkyTimeOfDay s,
|
||||
IDatObjectSource? dats)
|
||||
{
|
||||
// Transparent / Luminosity / MaxBright are stored in the retail
|
||||
// Region dat as PERCENTAGES (0..100), not fractions (0..1). Our
|
||||
|
|
@ -537,6 +561,9 @@ public static class SkyDescLoader
|
|||
Transparent = r.Transparent / 100f,
|
||||
Luminosity = r.Luminosity / 100f,
|
||||
MaxBright = r.MaxBright / 100f,
|
||||
AuthoredSortCenter = ResolveSortCenter(
|
||||
r.GfxObjId?.DataId ?? 0u,
|
||||
dats),
|
||||
}).ToList();
|
||||
|
||||
var fogMode = s.WorldFog switch
|
||||
|
|
@ -577,6 +604,26 @@ public static class SkyDescLoader
|
|||
};
|
||||
}
|
||||
|
||||
private static Vector3 ResolveSortCenter(
|
||||
uint gfxObjId,
|
||||
IDatObjectSource? dats)
|
||||
{
|
||||
if (dats is null || (gfxObjId & 0xFF000000u) != 0x01000000u)
|
||||
return Vector3.Zero;
|
||||
|
||||
try
|
||||
{
|
||||
return dats.TryGet<GfxObj>(gfxObjId, out var gfx) && gfx is not null
|
||||
? gfx.SortCenter
|
||||
: Vector3.Zero;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Enhancement metadata cannot make authoritative sky loading fail.
|
||||
return Vector3.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="ColorARGB"/> stores bytes as B,G,R,A — but the logical
|
||||
/// channel mapping is just "R/G/B in 0..255". Convert to linear
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue