feat(render): Phase A8 Wave 1 — WB scaffolding extraction + stencil low-level method
Five tasks shipped together (interdependent at build time): Task 1: WbRenderPass enum — verbatim port of WB RenderPass.cs:1-22 Task 2: WbFrustum + WbBoundingBox + FrustumTestResult — verbatim port of WB Frustum.cs (98 LOC) with namespace + BoundingBox-type adaptations. +7 unit tests. Task 3: EnvCellSceneryInstance + EnvCellLandblock — verbatim port of WB SceneryInstance.cs:1-161, renamed scope-narrow. Dropped editor-only fields (DisqualificationReason, ParticleEmitters, IsQueuedForUpload, InstanceBufferOffset, InstanceCount, MdiCommands, IsTransformOnlyUpdate) + InstanceId narrowed uint (we don't use ObjectId's editor methods). +5 unit tests. Task 4: EnvCellVisibilitySnapshot — direct port of WB VisibilitySnapshot narrowed to BatchedByCell + VisibleLandblocks only. Task 7: IndoorCellStencilPipeline.RenderBuildingStencilMask — new low-level WB-faithful entry mirroring PortalRenderManager:471-484. No surrounding GL state setup (caller's responsibility). Probe fields LastStencilVertexCount / LastStencilWasFarPunch / LastStencilBuildingId for the [stencil] probe emitter in Task 9. Build green, 18 tests pass (7 new Frustum + 5 new SceneryInstance + 6 existing stencil pipeline). Ready for Wave 2 (EnvCellRenderer port). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
95f0d5267b
commit
fc68d6d01f
7 changed files with 595 additions and 0 deletions
|
|
@ -0,0 +1,78 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using AcDream.App.Rendering.Wb;
|
||||
using Xunit;
|
||||
|
||||
namespace AcDream.App.Tests.Rendering.Wb;
|
||||
|
||||
public class EnvCellSceneryInstanceTests
|
||||
{
|
||||
[Fact]
|
||||
public void Instance_DefaultConstruct_HasZeroFields()
|
||||
{
|
||||
var s = new EnvCellSceneryInstance();
|
||||
Assert.Equal(0UL, s.ObjectId);
|
||||
Assert.False(s.IsBuilding);
|
||||
Assert.False(s.IsSetup);
|
||||
Assert.False(s.IsEntryCell);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Instance_AssignFields_RoundTrip()
|
||||
{
|
||||
var t = Matrix4x4.CreateTranslation(1, 2, 3);
|
||||
var s = new EnvCellSceneryInstance
|
||||
{
|
||||
ObjectId = 0x01000123,
|
||||
IsBuilding = true,
|
||||
IsSetup = false,
|
||||
IsEntryCell = true,
|
||||
WorldPosition = new Vector3(1, 2, 3),
|
||||
Rotation = Quaternion.Identity,
|
||||
Scale = Vector3.One,
|
||||
Transform = t,
|
||||
};
|
||||
Assert.Equal(0x01000123UL, s.ObjectId);
|
||||
Assert.True(s.IsBuilding);
|
||||
Assert.True(s.IsEntryCell);
|
||||
Assert.Equal(new Vector3(1, 2, 3), s.WorldPosition);
|
||||
Assert.Equal(t, s.Transform);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Landblock_Construct_StartsEmpty()
|
||||
{
|
||||
var lb = new EnvCellLandblock { GridX = 0xA9, GridY = 0xB4 };
|
||||
Assert.Empty(lb.StaticPartGroups);
|
||||
Assert.Empty(lb.BuildingPartGroups);
|
||||
Assert.Empty(lb.Instances);
|
||||
Assert.Empty(lb.EnvCellBounds);
|
||||
Assert.False(lb.InstancesReady);
|
||||
Assert.False(lb.GpuReady);
|
||||
Assert.False(lb.MeshDataReady);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Landblock_AddInstanceToBuildingPartGroups_PreservesOrder()
|
||||
{
|
||||
var lb = new EnvCellLandblock();
|
||||
if (!lb.BuildingPartGroups.TryGetValue(0x01000001UL, out var list))
|
||||
{
|
||||
list = new List<InstanceData>();
|
||||
lb.BuildingPartGroups[0x01000001UL] = list;
|
||||
}
|
||||
list.Add(default);
|
||||
list.Add(default);
|
||||
Assert.Single(lb.BuildingPartGroups);
|
||||
Assert.Equal(2, lb.BuildingPartGroups[0x01000001UL].Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Landblock_PendingInstancesNullByDefault()
|
||||
{
|
||||
var lb = new EnvCellLandblock();
|
||||
Assert.Null(lb.PendingInstances);
|
||||
Assert.Null(lb.PendingEnvCellBounds);
|
||||
Assert.Null(lb.PendingSeenOutsideCells);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue