using AcDream.App.Rendering.Wb; using AcDream.Core.Meshing; namespace AcDream.App.Tests.Rendering.Wb; /// /// Campaign VM VM6: — the pure /// function WbDrawDispatcher.ClassifyBatches (the world receiver) and /// WbDrawDispatcher.AddDirectionalShadowBatches (the directional- /// shadow caster) both call with the same four inputs (entity id, exclusion /// check, subset translucency, mesh-level HasCutoutSubset), which is what /// makes the two agree by construction — see foliage_wind.glsl. /// public sealed class FoliageWindClassificationTests { private const uint ProceduralSceneryEntityId = 0x80010203u; // bit 31 set private const uint OrdinaryEntityId = 0x00010203u; // bit 31 clear [Fact] public void ProceduralSceneryCutoutSubsetGetsTheCutoutFlag() { uint flags = FoliageWindClassification.Classify( ProceduralSceneryEntityId, isExcluded: false, TranslucencyKind.ClipMap, meshHasCutoutSubset: true); Assert.Equal(FoliageWindClassification.CutoutFoliageFlag, flags); } [Fact] public void ProceduralSceneryOpaqueSubsetGetsTheTrunkFlagOnlyWhenTheMeshOwnsACutoutSubset() { uint withCutoutSibling = FoliageWindClassification.Classify( ProceduralSceneryEntityId, isExcluded: false, TranslucencyKind.Opaque, meshHasCutoutSubset: true); uint withoutCutoutSibling = FoliageWindClassification.Classify( ProceduralSceneryEntityId, isExcluded: false, TranslucencyKind.Opaque, meshHasCutoutSubset: false); Assert.Equal(FoliageWindClassification.TrunkFlag, withCutoutSibling); Assert.Equal(0u, withoutCutoutSibling); // a rock, not a tree trunk } [Fact] public void NonProceduralSceneryEntityGetsNeitherBitRegardlessOfMaterial() { uint cutout = FoliageWindClassification.Classify( OrdinaryEntityId, isExcluded: false, TranslucencyKind.ClipMap, meshHasCutoutSubset: true); uint opaqueWithCutoutSibling = FoliageWindClassification.Classify( OrdinaryEntityId, isExcluded: false, TranslucencyKind.Opaque, meshHasCutoutSubset: true); Assert.Equal(0u, cutout); Assert.Equal(0u, opaqueWithCutoutSibling); } [Fact] public void AnExcludedObjectIdGetsNeitherBitEvenWhenOtherwiseQualifying() { uint cutout = FoliageWindClassification.Classify( ProceduralSceneryEntityId, isExcluded: true, TranslucencyKind.ClipMap, meshHasCutoutSubset: true); uint trunk = FoliageWindClassification.Classify( ProceduralSceneryEntityId, isExcluded: true, TranslucencyKind.Opaque, meshHasCutoutSubset: true); Assert.Equal(0u, cutout); Assert.Equal(0u, trunk); } [Theory] [InlineData(TranslucencyKind.AlphaBlend)] [InlineData(TranslucencyKind.Additive)] [InlineData(TranslucencyKind.InvAlpha)] public void OtherMaterialKindsOnProceduralSceneryGetNeitherBit(TranslucencyKind translucency) { uint flags = FoliageWindClassification.Classify( ProceduralSceneryEntityId, isExcluded: false, translucency, meshHasCutoutSubset: true); Assert.Equal(0u, flags); } [Theory] [InlineData(0x80000000u, true)] [InlineData(0x7FFFFFFFu, false)] [InlineData(0x00000000u, false)] [InlineData(0xFFFFFFFFu, true)] public void IsProceduralSceneryDecodesOnlyBit31(uint entityId, bool expected) { Assert.Equal(expected, FoliageWindClassification.IsProceduralScenery(entityId)); } }