feat(rendering): prove packed dispatcher output parity
Build a compare-only dispatcher classifier from RenderFrameView and compare complete opaque, alpha, selection, clip, light, texture, transform, and draw payloads against the accepted path. Preserve retail's stable equal-CYpt ordering with explicit draw-local submission ordinals so material-group history cannot affect alpha ties.
This commit is contained in:
parent
58b712c6ec
commit
29195fb255
11 changed files with 1264 additions and 65 deletions
|
|
@ -1,4 +1,5 @@
|
|||
using System.Numerics;
|
||||
using AcDream.Core.Selection;
|
||||
namespace AcDream.App.Rendering.Selection;
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -14,3 +15,19 @@ internal interface IRetailSelectionRenderSink
|
|||
uint gfxObjId,
|
||||
Matrix4x4 partWorld);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read-only mirror of the exact geometry and drawing-sphere acceptance used
|
||||
/// by the retained selection scene. G2's packed dispatcher referee uses it
|
||||
/// without publishing a second picking frame.
|
||||
/// </summary>
|
||||
internal interface IRetailSelectionRenderOracle
|
||||
{
|
||||
bool TryCreateVisiblePart(
|
||||
uint serverGuid,
|
||||
uint localEntityId,
|
||||
int partIndex,
|
||||
uint gfxObjId,
|
||||
Matrix4x4 partWorld,
|
||||
out RetailSelectionPart part);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ internal interface IWorldSceneSelectionFrame
|
|||
|
||||
internal sealed class RetailSelectionScene :
|
||||
IRetailSelectionRenderSink,
|
||||
IRetailSelectionRenderOracle,
|
||||
IRetailSelectionLightingSource,
|
||||
IWorldSceneSelectionFrame
|
||||
{
|
||||
|
|
@ -128,32 +129,65 @@ internal sealed class RetailSelectionScene :
|
|||
return;
|
||||
if (serverGuid == 0u)
|
||||
return;
|
||||
|
||||
if (!_buildingKeys.Add(new PartKey(
|
||||
localEntityId,
|
||||
partIndex,
|
||||
gfxObjId)))
|
||||
return;
|
||||
RetailSelectionMesh? mesh = _geometry.Resolve(gfxObjId);
|
||||
if (mesh is null)
|
||||
return;
|
||||
if (_viewFrustum is not { } frustum
|
||||
|| !DrawingSphereIntersectsFrustum(mesh, partWorld, frustum))
|
||||
if (!TryCreateVisiblePart(
|
||||
serverGuid,
|
||||
localEntityId,
|
||||
partIndex,
|
||||
gfxObjId,
|
||||
partWorld,
|
||||
out RetailSelectionPart part))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_building.Add(new RetailSelectionPart(
|
||||
serverGuid,
|
||||
localEntityId,
|
||||
partIndex,
|
||||
partWorld,
|
||||
mesh));
|
||||
_building.Add(part);
|
||||
_currentRenderSceneObserver?.ObserveSelectionPart(
|
||||
serverGuid,
|
||||
localEntityId,
|
||||
partIndex,
|
||||
gfxObjId,
|
||||
partWorld,
|
||||
part.Mesh);
|
||||
}
|
||||
|
||||
public bool TryCreateVisiblePart(
|
||||
uint serverGuid,
|
||||
uint localEntityId,
|
||||
int partIndex,
|
||||
uint gfxObjId,
|
||||
Matrix4x4 partWorld,
|
||||
out RetailSelectionPart part)
|
||||
{
|
||||
if (serverGuid == 0u)
|
||||
{
|
||||
part = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
RetailSelectionMesh? mesh = _geometry.Resolve(gfxObjId);
|
||||
if (mesh is null
|
||||
|| _viewFrustum is not { } frustum
|
||||
|| !DrawingSphereIntersectsFrustum(
|
||||
mesh,
|
||||
partWorld,
|
||||
frustum))
|
||||
{
|
||||
part = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
part = new RetailSelectionPart(
|
||||
serverGuid,
|
||||
localEntityId,
|
||||
partIndex,
|
||||
partWorld,
|
||||
mesh);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void CompleteFrame()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue