using System;
using AcDream.Core.Meshing;
using DatReaderWriter.DBObjs;
namespace AcDream.App.Rendering;
///
/// Retail particle geometry selection from CPhysicsPart::Always2D
/// (named retail 0x0050D8A0). A GfxObj with no degrade entry, or whose first
/// degrade has mode 1, is drawn as its authored 3D mesh. Every other first
/// degrade mode uses the camera-facing 2D presentation.
///
public static class RetailParticleGeometryClassifier
{
public static RetailParticleGeometryKind Classify(uint? firstDegradeMode)
=> firstDegradeMode is uint mode && mode != 1u
? RetailParticleGeometryKind.Billboard
: RetailParticleGeometryKind.FullMesh;
}
public enum RetailParticleGeometryKind
{
FullMesh,
Billboard,
}
///
/// Resolves authored particle-surface blending without allowing one malformed
/// Surface entry to abort the render frame. The fallback remains the batch's
/// already-decoded additive bit; it never fabricates geometry or a material.
///
internal static class RetailParticleBlendResolver
{
public static TranslucencyKind Resolve(
uint surfaceId,
bool batchIsAdditive,
Func? loadSurface,
Action? diagnostic = null)
{
TranslucencyKind fallback = batchIsAdditive
? TranslucencyKind.Additive
: TranslucencyKind.AlphaBlend;
if (surfaceId == 0 || loadSurface is null)
return fallback;
try
{
Surface? surface = loadSurface(surfaceId);
return surface is null
? fallback
: TranslucencyKindExtensions.FromSurfaceType(surface.Type);
}
catch (Exception ex)
{
diagnostic?.Invoke(
$"[particle-material] Failed to decode Surface 0x{surfaceId:X8}: {ex.Message}");
return fallback;
}
}
}