feat(core): UCG Stage 1 — EnvCell.FromDat derivation (mirrors BuildLoadedCell)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
76c9e2f07d
commit
5bc72d5cd1
4 changed files with 109 additions and 4 deletions
|
|
@ -1,7 +1,9 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using AcDream.Core.Physics; // BSPQuery
|
||||
using DatReaderWriter.Types; // CellBSPTree
|
||||
using DatReaderWriter.Enums; // EnvCellFlags
|
||||
using DatReaderWriter.Types; // CellBSPTree, CellStruct
|
||||
|
||||
namespace AcDream.Core.World.Cells;
|
||||
|
||||
|
|
@ -30,4 +32,55 @@ public sealed class EnvCell : ObjCell
|
|||
&& local.Y >= LocalBoundsMin.Y && local.Y <= LocalBoundsMax.Y
|
||||
&& local.Z >= LocalBoundsMin.Z && local.Z <= LocalBoundsMax.Z;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Build an EnvCell from dat data. Mirrors the render derivation in
|
||||
/// BuildLoadedCell (GameWindow.cs:5588-5704) so Core and render stay equivalent.
|
||||
/// <paramref name="worldTransform"/> MUST be the physics-verbatim transform
|
||||
/// (no +2 cm render lift).
|
||||
/// </summary>
|
||||
public static EnvCell FromDat(uint id, DatReaderWriter.DBObjs.EnvCell datCell,
|
||||
CellStruct cellStruct, Matrix4x4 worldTransform)
|
||||
{
|
||||
Matrix4x4.Invert(worldTransform, out var inverse);
|
||||
|
||||
var min = new Vector3(float.MaxValue);
|
||||
var max = new Vector3(float.MinValue);
|
||||
foreach (var kvp in cellStruct.VertexArray.Vertices)
|
||||
{
|
||||
var p = new Vector3(kvp.Value.Origin.X, kvp.Value.Origin.Y, kvp.Value.Origin.Z);
|
||||
min = Vector3.Min(min, p);
|
||||
max = Vector3.Max(max, p);
|
||||
}
|
||||
if (min.X == float.MaxValue) { min = Vector3.Zero; max = Vector3.Zero; }
|
||||
|
||||
var portals = new List<CellPortal>(datCell.CellPortals.Count);
|
||||
foreach (var p in datCell.CellPortals)
|
||||
{
|
||||
portals.Add(new CellPortal(
|
||||
otherCellId: p.OtherCellId,
|
||||
otherPortalId: p.OtherPortalId,
|
||||
polygonId: p.PolygonId,
|
||||
flags: (ushort)p.Flags,
|
||||
polygonLocal: ResolvePortalPolygon(cellStruct, p.PolygonId)));
|
||||
}
|
||||
|
||||
uint lbPrefix = id & 0xFFFF0000u;
|
||||
var stab = new List<uint>(datCell.VisibleCells.Count);
|
||||
foreach (var low in datCell.VisibleCells) stab.Add(lbPrefix | low);
|
||||
bool seenOutside = datCell.Flags.HasFlag(EnvCellFlags.SeenOutside);
|
||||
|
||||
return new EnvCell(id, worldTransform, inverse, min, max, portals, stab,
|
||||
seenOutside, cellStruct.CellBSP);
|
||||
}
|
||||
|
||||
private static IReadOnlyList<Vector3> ResolvePortalPolygon(CellStruct cellStruct, ushort polygonId)
|
||||
{
|
||||
if (!cellStruct.Polygons.TryGetValue(polygonId, out var poly)) return Array.Empty<Vector3>();
|
||||
var verts = new List<Vector3>(poly.VertexIds.Count);
|
||||
foreach (var vid in poly.VertexIds)
|
||||
if (cellStruct.VertexArray.Vertices.TryGetValue((ushort)vid, out var v))
|
||||
verts.Add(new Vector3(v.Origin.X, v.Origin.Y, v.Origin.Z));
|
||||
return verts;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue