refactor(content): share EnvCell geometry identity
This commit is contained in:
parent
05a22dee99
commit
86fadf8661
3 changed files with 73 additions and 8 deletions
|
|
@ -1,5 +1,6 @@
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
using AcDream.Core.Rendering.Wb;
|
||||||
using DatReaderWriter.DBObjs;
|
using DatReaderWriter.DBObjs;
|
||||||
using DatReaderWriter.Enums;
|
using DatReaderWriter.Enums;
|
||||||
using DatReaderWriter.Types;
|
using DatReaderWriter.Types;
|
||||||
|
|
@ -125,14 +126,7 @@ public sealed class EnvCellLandblockBuildBuilder
|
||||||
uint environmentId,
|
uint environmentId,
|
||||||
ushort cellStructure,
|
ushort cellStructure,
|
||||||
IReadOnlyList<ushort> surfaces)
|
IReadOnlyList<ushort> surfaces)
|
||||||
{
|
=> EnvCellGeometryIdentity.Compute(environmentId, cellStructure, surfaces);
|
||||||
var hash = 17L;
|
|
||||||
hash = hash * 31 + (int)environmentId;
|
|
||||||
hash = hash * 31 + cellStructure;
|
|
||||||
foreach (var surface in surfaces)
|
|
||||||
hash = hash * 31 + surface;
|
|
||||||
return (ulong)hash | 0x2_0000_0000UL;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static WbBoundingBox ComputeLocalBounds(CellStruct cellStruct)
|
private static WbBoundingBox ComputeLocalBounds(CellStruct cellStruct)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
29
src/AcDream.Core/Rendering/Wb/EnvCellGeometryIdentity.cs
Normal file
29
src/AcDream.Core/Rendering/Wb/EnvCellGeometryIdentity.cs
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace AcDream.Core.Rendering.Wb;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Computes WorldBuilder's content identity for an EnvCell shell.
|
||||||
|
/// Equal environment, cell-structure, and ordered surface tuples share one
|
||||||
|
/// prepared geometry payload even when they occur under different cell IDs.
|
||||||
|
/// </summary>
|
||||||
|
public static class EnvCellGeometryIdentity
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Source: WorldBuilder <c>EnvCellRenderManager.GetEnvCellGeomId</c>,
|
||||||
|
/// lines 94-103. Bit 33 separates content identities from per-cell IDs,
|
||||||
|
/// whose synthetic geometry requests use bit 32.
|
||||||
|
/// </summary>
|
||||||
|
public static ulong Compute(
|
||||||
|
uint environmentId,
|
||||||
|
ushort cellStructure,
|
||||||
|
IReadOnlyList<ushort> surfaces)
|
||||||
|
{
|
||||||
|
long hash = 17;
|
||||||
|
hash = unchecked(hash * 31 + environmentId);
|
||||||
|
hash = unchecked(hash * 31 + cellStructure);
|
||||||
|
for (int i = 0; i < surfaces.Count; i++)
|
||||||
|
hash = unchecked(hash * 31 + surfaces[i]);
|
||||||
|
return (ulong)hash | 0x2_0000_0000UL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
using AcDream.Core.Rendering.Wb;
|
||||||
|
|
||||||
|
namespace AcDream.Core.Tests.Rendering.Wb;
|
||||||
|
|
||||||
|
public sealed class EnvCellGeometryIdentityTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Compute_EmptySurfaces_MatchesExtractedWorldBuilderValue()
|
||||||
|
{
|
||||||
|
Assert.Equal(
|
||||||
|
0x2_0000_47D6UL,
|
||||||
|
EnvCellGeometryIdentity.Compute(0x42, 7, Array.Empty<ushort>()));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Compute_OrderedSurfaces_MatchesExtractedWorldBuilderValue()
|
||||||
|
{
|
||||||
|
Assert.Equal(
|
||||||
|
0x2_20A7_A46CUL,
|
||||||
|
EnvCellGeometryIdentity.Compute(0x42, 7, new ushort[] { 1, 2, 3 }));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Compute_SurfaceOrderIsPartOfIdentity()
|
||||||
|
{
|
||||||
|
var forward = EnvCellGeometryIdentity.Compute(1, 1, new ushort[] { 10, 20 });
|
||||||
|
var reverse = EnvCellGeometryIdentity.Compute(1, 1, new ushort[] { 20, 10 });
|
||||||
|
|
||||||
|
Assert.NotEqual(forward, reverse);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Compute_AlwaysUsesDeduplicatedGeometryNamespace()
|
||||||
|
{
|
||||||
|
var id = EnvCellGeometryIdentity.Compute(
|
||||||
|
uint.MaxValue,
|
||||||
|
ushort.MaxValue,
|
||||||
|
new ushort[] { ushort.MaxValue, ushort.MaxValue });
|
||||||
|
|
||||||
|
Assert.NotEqual(0UL, id & 0x2_0000_0000UL);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue