refactor(render): delete the packed dispatcher

This commit is contained in:
Erik 2026-08-31 04:44:22 +02:00
parent 8d8aa715ee
commit 73ba1d3c32
7 changed files with 115 additions and 1659 deletions

View file

@ -2,6 +2,7 @@ using System.Numerics;
using AcDream.App.Rendering.Scene;
using AcDream.App.Rendering.Selection;
using AcDream.App.Rendering.Walk;
using AcDream.Core.Lighting;
using AcDream.Core.Meshing;
using AcDream.Core.World;
using DatReaderWriter.Enums;
@ -166,7 +167,7 @@ public sealed partial class WbDrawDispatcher
/// Classifies one static entity for the walk populator: resolves its clip
/// slot / light set / selection lighting exactly as
/// <c>ClassifyPackedEntity</c> does (via the shared
/// <see cref="ResolveSlotForFrame"/> / <c>ResolvePackedLightSet</c>
/// <see cref="ResolveSlotForFrame"/> / <c>ResolveWalkLightSet</c>
/// helpers), walks its Setup parts or single mesh (mirroring
/// <c>ClassifyPackedEntity</c>'s own shape), and appends one
/// <see cref="WalkClassifiedBatch"/> per surviving batch to
@ -204,7 +205,7 @@ public sealed partial class WbDrawDispatcher
if (culled)
return;
ResolvePackedLightSet(in entity, out InstanceLightSet lights, out bool indoor);
ResolveWalkLightSet(in entity, out InstanceLightSet lights, out bool indoor);
Vector2 selectionLighting =
_selectionLighting?.TryGetLighting(
entity.ServerGuid, entity.LocalEntityId, out RetailSelectionLighting lighting) == true
@ -261,7 +262,7 @@ public sealed partial class WbDrawDispatcher
}
float opacity = liveDynamic
? PackedPartOpacity(
? WalkPartOpacity(
entity.ServerGuid,
entity.LocalEntityId,
(uint)setupPartIndex)
@ -298,7 +299,7 @@ public sealed partial class WbDrawDispatcher
else
{
float opacity = liveDynamic
? PackedPartOpacity(
? WalkPartOpacity(
entity.ServerGuid,
entity.LocalEntityId,
(uint)partIndex)
@ -330,6 +331,110 @@ public sealed partial class WbDrawDispatcher
}
}
private float WalkPartOpacity(
uint serverGuid,
uint localEntityId,
uint setupPartIndex)
{
float opacity = EntityOpacity(serverGuid);
if (opacity <= 0f)
return 0f;
if (!_translucencyFades.TryGetCurrentValue(
localEntityId,
setupPartIndex,
out float translucency))
{
return opacity;
}
return translucency >= 1f
? 0f
: opacity * (1f - translucency);
}
private void ResolveWalkLightSet(
in RenderInstanceCandidate entity,
out InstanceLightSet lights,
out bool indoor)
{
indoor = IndoorObjectReceivesTorches(entity.ParentCell);
lights = InstanceLightSet.Disabled;
IReadOnlyList<LightSource>? snapshot = _pointSnapshot;
if (!indoor || snapshot is null || snapshot.Count == 0)
return;
Vector3 center =
(entity.Bounds.Minimum + entity.Bounds.Maximum) * 0.5f;
float radius =
(entity.Bounds.Maximum - entity.Bounds.Minimum)
.Length() * 0.5f;
Span<int> selected =
stackalloc int[LightManager.MaxLightsPerObject];
selected.Fill(-1);
LightManager.SelectForObject(
snapshot,
center,
radius,
selected);
lights = InstanceLightSet.From(selected);
}
private static bool PartVisibleInLookInTurn(
IWalkLookInViewSource? lookInViews,
int routeIndex,
uint cellId,
in RenderInstanceCandidate entity,
int partIndex,
uint gfxObjId,
ObjectRenderData renderData,
Matrix4x4 localToWorld)
{
if (lookInViews is null)
return true;
if (renderData.SelectionSphere is not { Radius: > 0f } sphere)
return true;
return LookInDrawingSphereVisible(
lookInViews,
routeIndex,
sphere,
localToWorld,
out _,
out _);
}
internal static bool LookInDrawingSphereVisible(
IWalkLookInViewSource lookInViews,
int routeIndex,
DatReaderWriter.Types.Sphere sphere,
Matrix4x4 localToWorld,
out Vector3 center,
out float radius)
{
ArgumentNullException.ThrowIfNull(lookInViews);
ArgumentNullException.ThrowIfNull(sphere);
center = Vector3.Transform(sphere.Origin, localToWorld);
float scaleX = new Vector3(
localToWorld.M11,
localToWorld.M12,
localToWorld.M13).Length();
float scaleY = new Vector3(
localToWorld.M21,
localToWorld.M22,
localToWorld.M23).Length();
float scaleZ = new Vector3(
localToWorld.M31,
localToWorld.M32,
localToWorld.M33).Length();
radius = sphere.Radius
* MathF.Max(scaleX, MathF.Max(scaleY, scaleZ));
return lookInViews.SphereVisibleInLookInTurn(
routeIndex,
in center,
radius);
}
/// <summary>
/// Walks one resolved mesh's batches through <see cref="TryClassifyBatch"/>
/// and appends every surviving one to <paramref name="sink"/> at