diff --git a/Community/StrideExamples.Community.CubeClicker/App.config b/Community/StrideExamples.Community.CubeClicker/App.config new file mode 100644 index 0000000..49cc43e --- /dev/null +++ b/Community/StrideExamples.Community.CubeClicker/App.config @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/Community/StrideExamples.Community.MeshOutlineShader/Program.cs b/Community/StrideExamples.Community.MeshOutlineShader/Program.cs index 29285ff..cfc91a0 100644 --- a/Community/StrideExamples.Community.MeshOutlineShader/Program.cs +++ b/Community/StrideExamples.Community.MeshOutlineShader/Program.cs @@ -39,8 +39,7 @@ void CreateOutlinePrimitive(Scene rootScene, PrimitiveModelType modelType, Color var entity = game.Create3DPrimitive(modelType, options: new() { RenderGroup = RenderGroup.Group5, - } - ); + }); entity.Transform.Position = position; entity.Add( diff --git a/Community/StrideExamples.Community.StrideUI.Grid/Core/ClickData.cs b/Community/StrideExamples.Community.StrideUI.Grid/Core/ClickData.cs index ecec679..9da5249 100644 --- a/Community/StrideExamples.Community.StrideUI.Grid/Core/ClickData.cs +++ b/Community/StrideExamples.Community.StrideUI.Grid/Core/ClickData.cs @@ -1,6 +1,6 @@ using Stride.Core; -namespace StrideExamples.StrideUI.Grid.Core; +namespace StrideExamples.Community.StrideUI.Grid.Core; [DataContract] public sealed class ClickData diff --git a/Community/StrideExamples.Community.StrideUI.Grid/Core/CubeData.cs b/Community/StrideExamples.Community.StrideUI.Grid/Core/CubeData.cs index c01e703..b8c861b 100644 --- a/Community/StrideExamples.Community.StrideUI.Grid/Core/CubeData.cs +++ b/Community/StrideExamples.Community.StrideUI.Grid/Core/CubeData.cs @@ -1,8 +1,7 @@ -using BepuUtilities.Collections; using Stride.Core; using Stride.Core.Mathematics; -namespace StrideExamples.StrideUI.Grid.Core; +namespace StrideExamples.Community.StrideUI.Grid.Core; [DataContract] public sealed class CubeData diff --git a/Community/StrideExamples.Community.StrideUI.Grid/Core/DataSaver.cs b/Community/StrideExamples.Community.StrideUI.Grid/Core/DataSaver.cs index 8b4bd8c..141c6a8 100644 --- a/Community/StrideExamples.Community.StrideUI.Grid/Core/DataSaver.cs +++ b/Community/StrideExamples.Community.StrideUI.Grid/Core/DataSaver.cs @@ -1,7 +1,7 @@ using NexVYaml; using Stride.Core.IO; -namespace StrideExamples.StrideUI.Grid.Core; +namespace StrideExamples.Community.StrideUI.Grid.Core; public class DataSaver { diff --git a/Community/StrideExamples.Community.StrideUI.Grid/Core/IClickable.cs b/Community/StrideExamples.Community.StrideUI.Grid/Core/IClickable.cs index 4cfe28f..f53ef7d 100644 --- a/Community/StrideExamples.Community.StrideUI.Grid/Core/IClickable.cs +++ b/Community/StrideExamples.Community.StrideUI.Grid/Core/IClickable.cs @@ -1,6 +1,6 @@ using Stride.Input; -namespace StrideExamples.StrideUI.Grid.Core; +namespace StrideExamples.Community.StrideUI.Grid.Core; public interface IClickable { diff --git a/Community/StrideExamples.Community.StrideUI.Grid/Core/LeftMouseButtonCounter.cs b/Community/StrideExamples.Community.StrideUI.Grid/Core/LeftMouseButtonCounter.cs index a11d055..1a54e5f 100644 --- a/Community/StrideExamples.Community.StrideUI.Grid/Core/LeftMouseButtonCounter.cs +++ b/Community/StrideExamples.Community.StrideUI.Grid/Core/LeftMouseButtonCounter.cs @@ -1,7 +1,7 @@ using Stride.Core; using Stride.Input; -namespace StrideExamples.StrideUI.Grid.Core; +namespace StrideExamples.Community.StrideUI.Grid.Core; /// /// Has to be directly [DataContract] tagged, else it won't detect it. diff --git a/Community/StrideExamples.Community.StrideUI.Grid/Core/RightMouseButtonCounter.cs b/Community/StrideExamples.Community.StrideUI.Grid/Core/RightMouseButtonCounter.cs index 371ca0a..a14ca54 100644 --- a/Community/StrideExamples.Community.StrideUI.Grid/Core/RightMouseButtonCounter.cs +++ b/Community/StrideExamples.Community.StrideUI.Grid/Core/RightMouseButtonCounter.cs @@ -1,7 +1,7 @@ using Stride.Core; using Stride.Input; -namespace StrideExamples.StrideUI.Grid.Core; +namespace StrideExamples.Community.StrideUI.Grid.Core; [DataContract] diff --git a/Community/StrideExamples.Community.StrideUI.Grid/Core/SimpleVector.cs b/Community/StrideExamples.Community.StrideUI.Grid/Core/SimpleVector.cs index 1a016f9..90a455d 100644 --- a/Community/StrideExamples.Community.StrideUI.Grid/Core/SimpleVector.cs +++ b/Community/StrideExamples.Community.StrideUI.Grid/Core/SimpleVector.cs @@ -1,6 +1,6 @@ using Stride.Core; -namespace StrideExamples.StrideUI.Grid.Core; +namespace StrideExamples.Community.StrideUI.Grid.Core; /// /// Stride.Core.Vector isn't generated as the generator can't reach the core without being in it diff --git a/Community/StrideExamples.Community.StrideUI.Grid/Managers/ClickDataManager.cs b/Community/StrideExamples.Community.StrideUI.Grid/Managers/ClickDataManager.cs index cf3ee34..06b83a4 100644 --- a/Community/StrideExamples.Community.StrideUI.Grid/Managers/ClickDataManager.cs +++ b/Community/StrideExamples.Community.StrideUI.Grid/Managers/ClickDataManager.cs @@ -1,6 +1,6 @@ -using StrideExamples.StrideUI.Grid.Core; +using StrideExamples.Community.StrideUI.Grid.Core; -namespace StrideExamples.StrideUI.Grid.Managers; +namespace StrideExamples.Community.StrideUI.Grid.Managers; public class ClickDataManager { diff --git a/Community/StrideExamples.Community.StrideUI.Grid/Managers/CubeDataManager.cs b/Community/StrideExamples.Community.StrideUI.Grid/Managers/CubeDataManager.cs index f604e36..7596710 100644 --- a/Community/StrideExamples.Community.StrideUI.Grid/Managers/CubeDataManager.cs +++ b/Community/StrideExamples.Community.StrideUI.Grid/Managers/CubeDataManager.cs @@ -1,8 +1,7 @@ using Stride.Core.Mathematics; -using StrideExamples.StrideUI.Grid.Core; -using System.Runtime.Serialization; +using StrideExamples.Community.StrideUI.Grid.Core; -namespace StrideExamples.StrideUI.Grid.Managers; +namespace StrideExamples.Community.StrideUI.Grid.Managers; public class CubeDataManager { diff --git a/Community/StrideExamples.Community.StrideUI.Grid/Managers/GameManager.cs b/Community/StrideExamples.Community.StrideUI.Grid/Managers/GameManager.cs index fb40d68..dfbd0ed 100644 --- a/Community/StrideExamples.Community.StrideUI.Grid/Managers/GameManager.cs +++ b/Community/StrideExamples.Community.StrideUI.Grid/Managers/GameManager.cs @@ -6,7 +6,7 @@ using System.Globalization; using System.Text; -namespace StrideExamples.StrideUI.Grid.Managers; +namespace StrideExamples.Community.StrideUI.Grid.Managers; public class GameManager { diff --git a/Community/StrideExamples.Community.StrideUI.Grid/Managers/UIManager.cs b/Community/StrideExamples.Community.StrideUI.Grid/Managers/UIManager.cs index 46e2772..14412ee 100644 --- a/Community/StrideExamples.Community.StrideUI.Grid/Managers/UIManager.cs +++ b/Community/StrideExamples.Community.StrideUI.Grid/Managers/UIManager.cs @@ -6,10 +6,9 @@ using Stride.UI; using Stride.UI.Controls; using Stride.UI.Events; -using Stride.UI.Panels; -using StrideExamples.StrideUI.Grid.Core; +using StrideExamples.Community.StrideUI.Grid.Core; -namespace StrideExamples.StrideUI.Grid.Managers; +namespace StrideExamples.Community.StrideUI.Grid.Managers; public class UIManager { diff --git a/Community/StrideExamples.Community.StrideUI.Grid/Program.cs b/Community/StrideExamples.Community.StrideUI.Grid/Program.cs index 1057f17..3ddfaf6 100644 --- a/Community/StrideExamples.Community.StrideUI.Grid/Program.cs +++ b/Community/StrideExamples.Community.StrideUI.Grid/Program.cs @@ -1,14 +1,12 @@ -using Stride.CommunityToolkit.Bepu; +using NexVYaml; +using Stride.CommunityToolkit.Bepu; using Stride.CommunityToolkit.Engine; +using Stride.CommunityToolkit.Renderers; using Stride.CommunityToolkit.Skyboxes; using Stride.Engine; using Stride.Graphics; - -using NexVYaml; - -using StrideExamples.StrideUI.Grid.Managers; -using StrideExamples.StrideUI.Grid.Scripts; -using Stride.CommunityToolkit.Renderers; +using StrideExamples.Community.StrideUI.Grid.Managers; +using StrideExamples.Community.StrideUI.Grid.Scripts; using var game = new Game(); diff --git a/Community/StrideExamples.Community.StrideUI.Grid/Scripts/ClickHandlerComponent.cs b/Community/StrideExamples.Community.StrideUI.Grid/Scripts/ClickHandlerComponent.cs index 3cb3aa2..87035d6 100644 --- a/Community/StrideExamples.Community.StrideUI.Grid/Scripts/ClickHandlerComponent.cs +++ b/Community/StrideExamples.Community.StrideUI.Grid/Scripts/ClickHandlerComponent.cs @@ -1,3 +1,4 @@ +using System.Diagnostics; using Stride.CommunityToolkit.Bepu; using Stride.CommunityToolkit.Engine; using Stride.CommunityToolkit.Rendering.ProceduralModels; @@ -5,10 +6,9 @@ using Stride.Engine; using Stride.Input; using Stride.Rendering; -using StrideExamples.StrideUI.Grid.Managers; -using System.Diagnostics; +using StrideExamples.Community.StrideUI.Grid.Managers; -namespace StrideExamples.StrideUI.Grid.Scripts; +namespace StrideExamples.Community.StrideUI.Grid.Scripts; public class ClickHandlerComponent : AsyncScript { diff --git a/Community/StrideExamples.Community.StrideUI.Grid/Scripts/CubeGrower.cs b/Community/StrideExamples.Community.StrideUI.Grid/Scripts/CubeGrower.cs index f77886e..3679009 100644 --- a/Community/StrideExamples.Community.StrideUI.Grid/Scripts/CubeGrower.cs +++ b/Community/StrideExamples.Community.StrideUI.Grid/Scripts/CubeGrower.cs @@ -3,7 +3,7 @@ using Stride.Engine; using Stride.Physics; -namespace StrideExamples.StrideUI.Grid.Scripts; +namespace StrideExamples.Community.StrideUI.Grid.Scripts; public class CubeGrower : AsyncScript { diff --git a/Community/StrideExamples.Community.StrideUI.Grid/Scripts/CubeVanisher.cs b/Community/StrideExamples.Community.StrideUI.Grid/Scripts/CubeVanisher.cs index fed2598..1d1ba60 100644 --- a/Community/StrideExamples.Community.StrideUI.Grid/Scripts/CubeVanisher.cs +++ b/Community/StrideExamples.Community.StrideUI.Grid/Scripts/CubeVanisher.cs @@ -3,7 +3,7 @@ using Stride.Engine; using Stride.Physics; -namespace StrideExamples.StrideUI.Grid.Scripts; +namespace StrideExamples.Community.StrideUI.Grid.Scripts; public class CubeVanisher : AsyncScript { diff --git a/Local/StrideExamples.Local.OcclusionTest/Components/MultiRaycastVisibility.cs b/Local/StrideExamples.Local.OcclusionTest/Components/MultiRaycastVisibility.cs new file mode 100644 index 0000000..cc21238 --- /dev/null +++ b/Local/StrideExamples.Local.OcclusionTest/Components/MultiRaycastVisibility.cs @@ -0,0 +1,113 @@ +using Stride.Core; +using Stride.Core.Mathematics; +using Stride.Engine; + +namespace StrideExamples.Local.OcclusionTest.Components; + +public class MultiRaycastVisibilityComponent : SyncScript +{ + public required Game Game { get; init; } + public required Entity Target { get; init; } + public required CameraComponent Camera { get; init; } + public required Stride.BepuPhysics.BepuSimulation Simulation { get; init; } + + public VisibilityResult LastVisibilityResult { get; private set; } + + [DataMemberIgnore] + private Stride.CommunityToolkit.DebugShapes.Code.ImmediateDebugRenderSystem? _debugDraw; + + public record struct VisibilityResult + { + public bool IsVisible; + public float VisibilityPercentage; // 0.0 to 1.0 + public int RaysHit; + public int TotalRays; + } + + public VisibilityResult CheckVisibility(Game game, Entity target, CameraComponent camera, Stride.BepuPhysics.BepuSimulation simulation) + { + _debugDraw ??= game.Services.GetService(); + if (_debugDraw is not null) + { + _debugDraw.Enabled = true; + _debugDraw.Visible = true; + } + + var cameraPos = camera.Entity.Transform.WorldMatrix.TranslationVector; + + // Get target bounding box points + var targetTransform = target.Transform; + var targetModel = target.Get(); + var worldMatrix = targetTransform.WorldMatrix; + var localBoundingBox = targetModel.Model.BoundingBox; + BoundingBox.Transform(ref localBoundingBox, ref worldMatrix, out var worldBoundingBox); + + var testPoints = GenerateTestPoints(worldBoundingBox); + var visibleRays = 0; + + foreach (var point in testPoints) + { + var direction = point - cameraPos; + + direction.Normalize(); + _debugDraw?.DrawRay(cameraPos, direction*100, Color.Yellow, 0, false); + + // Use Bepu's raycast method + var hit = simulation.RayCast( + cameraPos, + direction, + float.MaxValue, + out var hitInfo + ); + + if (hit && hitInfo.Collidable?.Entity == target) + { + visibleRays++; // Ray hit the target + } + } + + var visibilityPercentage = (float)visibleRays / testPoints.Length; + + return new VisibilityResult + { + IsVisible = visibilityPercentage > 0.0f, + VisibilityPercentage = visibilityPercentage, + RaysHit = visibleRays, + TotalRays = testPoints.Length + }; + } + + private Vector3[] GenerateTestPoints(BoundingBox boundingBox) + { + var min = boundingBox.Minimum; + var max = boundingBox.Maximum; + var center = (min + max) * 0.5f; + + return + [ + // 8 corners of the bounding box + new(min.X, min.Y, min.Z), // 0: min corner + new(max.X, min.Y, min.Z), // 1: +X + new(min.X, max.Y, min.Z), // 2: +Y + new(min.X, min.Y, max.Z), // 3: +Z + new(max.X, max.Y, min.Z), // 4: +XY + new(max.X, min.Y, max.Z), // 5: +XZ + new(min.X, max.Y, max.Z), // 6: +YZ + new(max.X, max.Y, max.Z), // 7: max corner + + // Face centers + center, // Center + new(center.X, center.Y, min.Z), // Front face center + new(center.X, center.Y, max.Z), // Back face center + new(min.X, center.Y, center.Z), // Left face center + new(max.X, center.Y, center.Z), // Right face center + new(center.X, min.Y, center.Z), // Bottom face center + new(center.X, max.Y, center.Z), // Top face center + ]; + } + + public override void Update() + { + LastVisibilityResult = CheckVisibility(Game, Target, Camera, Simulation); + } +} \ No newline at end of file diff --git a/Local/StrideExamples.Local.OcclusionTest/Components/MultiRaycastVisibilityComponent.cs b/Local/StrideExamples.Local.OcclusionTest/Components/MultiRaycastVisibilityComponent.cs new file mode 100644 index 0000000..aa2fbb3 --- /dev/null +++ b/Local/StrideExamples.Local.OcclusionTest/Components/MultiRaycastVisibilityComponent.cs @@ -0,0 +1,86 @@ +using Stride.Core.Mathematics; +using Stride.Engine; + +public class MultiRaycastVisibility +{ + public record struct VisibilityResult + { + public bool IsVisible; + public float VisibilityPercentage; // 0.0 to 1.0 + public int RaysHit; + public int TotalRays; + } + + public VisibilityResult CheckVisibility(Game game, Entity target, CameraComponent camera, Stride.BepuPhysics.BepuSimulation simulation) + { + var cameraPos = camera.Entity.Transform.WorldMatrix.TranslationVector; + + // Get target bounding box points + var targetTransform = target.Transform; + var targetModel = target.Get(); + var worldMatrix = targetTransform.WorldMatrix; + var localBoundingBox = targetModel.Model.BoundingBox; + BoundingBox.Transform(ref localBoundingBox, ref worldMatrix, out var worldBoundingBox); + + var testPoints = GenerateTestPoints(worldBoundingBox); + var visibleRays = 0; + + foreach (var point in testPoints) + { + var direction = point - cameraPos; + direction.Normalize(); + + // Use Bepu's raycast method + var hit = simulation.RayCast( + cameraPos, + direction, + float.MaxValue, + out var hitInfo + ); + + if (hit && hitInfo.Collidable?.Entity == target) + { + visibleRays++; // Ray hit the target + } + } + + var visibilityPercentage = (float)visibleRays / testPoints.Length; + + return new VisibilityResult + { + IsVisible = visibilityPercentage > 0.0f, + VisibilityPercentage = visibilityPercentage, + RaysHit = visibleRays, + TotalRays = testPoints.Length + }; + } + + private Vector3[] GenerateTestPoints(BoundingBox boundingBox) + { + var min = boundingBox.Minimum; + var max = boundingBox.Maximum; + var center = (min + max) * 0.5f; + + return + [ + // 8 corners of the bounding box + new(min.X, min.Y, min.Z), // 0: min corner + new(max.X, min.Y, min.Z), // 1: +X + new(min.X, max.Y, min.Z), // 2: +Y + new(min.X, min.Y, max.Z), // 3: +Z + new(max.X, max.Y, min.Z), // 4: +XY + new(max.X, min.Y, max.Z), // 5: +XZ + new(min.X, max.Y, max.Z), // 6: +YZ + new(max.X, max.Y, max.Z), // 7: max corner + + // Face centers + center, // Center + new(center.X, center.Y, min.Z), // Front face center + new(center.X, center.Y, max.Z), // Back face center + new(min.X, center.Y, center.Z), // Left face center + new(max.X, center.Y, center.Z), // Right face center + new(center.X, min.Y, center.Z), // Bottom face center + new(center.X, max.Y, center.Z), // Top face center + ]; + } +} diff --git a/Local/StrideExamples.Local.OcclusionTest/Managers/GameManager.cs b/Local/StrideExamples.Local.OcclusionTest/Managers/GameManager.cs new file mode 100644 index 0000000..51c9245 --- /dev/null +++ b/Local/StrideExamples.Local.OcclusionTest/Managers/GameManager.cs @@ -0,0 +1,18 @@ +using Stride.Engine; +using Stride.Games; +using Stride.Graphics; + +namespace StrideExamples.Local.OcclusionTest.Managers; + +public class GameManager +{ + private readonly MultiRaycastVisibility _visibility; + + public UIManager UIManager { get; } + + public GameManager(Scene rootScene, SpriteFont font) + { + UIManager = new UIManager(rootScene, font); + _visibility = new MultiRaycastVisibility(); + } +} \ No newline at end of file diff --git a/Local/StrideExamples.Local.OcclusionTest/Managers/UIManager.cs b/Local/StrideExamples.Local.OcclusionTest/Managers/UIManager.cs new file mode 100644 index 0000000..9b285ee --- /dev/null +++ b/Local/StrideExamples.Local.OcclusionTest/Managers/UIManager.cs @@ -0,0 +1,142 @@ +using Stride.Core.Mathematics; +using Stride.Engine; +using Stride.Graphics; +using Stride.Input; +using Stride.Rendering; +using Stride.UI; +using Stride.UI.Controls; +using Stride.UI.Events; +using Stride.UI.Panels; +using StrideExamples.Local.OcclusionTest.Components; + +namespace StrideExamples.Local.OcclusionTest.Managers; + +public class UIManager +{ + private const string EntityName = "GameUI"; + private readonly SpriteFont _font; + private readonly Color _gridBackgroundColor = Color.LightGray; + private readonly Grid _grid; + + private readonly StackPanel _panel; + + private List _monitoredEntities = []; + + public UIManager(Scene rootScene, SpriteFont spriteFont) + { + _font = spriteFont; + _grid = CreateGrid(); + _panel = CreatePanel(_grid); + + var ui = CreateUI(_grid); + ui.Scene = rootScene; + } + + internal Entity CreateUI(Grid grid) => new(EntityName) + { + new UIComponent + { + Page = new UIPage { RootElement = grid }, + RenderGroup = RenderGroup.Group31 + } + }; + + internal void UpdateUI() + { + _panel.Children.Clear(); + foreach (var entity in _monitoredEntities) + { + var visibility = entity.Get(); + + if (visibility is not null) + { + _panel.Children.Add(CreateTextBlock($"Entity: {entity.Name} ({visibility.LastVisibilityResult.VisibilityPercentage:P}% visible, {visibility.LastVisibilityResult.RaysHit} / {visibility.LastVisibilityResult.TotalRays} rays hit)", 12, TextAlignment.Left)); + } + } + } + + public void MonitorEntity(Entity entity) + { + if (!_monitoredEntities.Contains(entity)) + { + _monitoredEntities.Add(entity); + } + } + + private StackPanel CreatePanel(Grid grid) + { + var panel = CreateVisibilityPanel(); + panel.SetGridColumn(2); + panel.SetGridRow(1); + grid.Children.Add(panel); + + return panel; + } + + private static Grid CreateGrid() => new() + { + VerticalAlignment = VerticalAlignment.Center, + HorizontalAlignment = HorizontalAlignment.Stretch, + RowDefinitions = { + new StripDefinition() { Type = StripType.Auto }, + new StripDefinition() { Type = StripType.Auto }, + new StripDefinition() { Type = StripType.Auto }, + new StripDefinition() { Type = StripType.Auto } + }, + ColumnDefinitions = + { + new StripDefinition(StripType.Star, 1), + new StripDefinition(StripType.Star, 1), + new StripDefinition(StripType.Star, 1) + } + }; + + private StackPanel CreateVisibilityPanel() + { + var panel = new StackPanel + { + Orientation = Orientation.Vertical, + HorizontalAlignment = HorizontalAlignment.Center, + VerticalAlignment = VerticalAlignment.Center, + BackgroundColor = _gridBackgroundColor, + Margin = new Thickness(0, 3, 0, 3), + }; + + panel.Children.Add(CreateTextBlock("Visibility:", 14, TextAlignment.Center)); + panel.Children.Add(CreateSlider()); + + return panel; + } + + + private Slider CreateSlider() + { + var slider = new Slider + { + Minimum = 0, + Maximum = 100, + Value = 50, + Width = 200, + Margin = new Thickness(3, 3, 3, 3), + HorizontalAlignment = HorizontalAlignment.Center, + VerticalAlignment = VerticalAlignment.Center, + BackgroundColor = Color.Black, + MinimumWidth = 100, + Name = "VisibilitySlider" + }; + + return slider; + } + + private TextBlock CreateTextBlock(string? text = null, float textSize = 20, TextAlignment textAlignment = TextAlignment.Left) + => new() + { + Text = text, + TextColor = Color.Black, + Margin = new Thickness(3, 0, 3, 0), + TextSize = textSize, + Font = _font, + TextAlignment = textAlignment, + VerticalAlignment = VerticalAlignment.Center + }; +} \ No newline at end of file diff --git a/Local/StrideExamples.Local.OcclusionTest/Program.cs b/Local/StrideExamples.Local.OcclusionTest/Program.cs new file mode 100644 index 0000000..48fe14d --- /dev/null +++ b/Local/StrideExamples.Local.OcclusionTest/Program.cs @@ -0,0 +1,95 @@ +using Stride.CommunityToolkit.Bepu; +using Stride.CommunityToolkit.DebugShapes.Code; +using Stride.CommunityToolkit.Engine; +using Stride.CommunityToolkit.Games; +using Stride.CommunityToolkit.Renderers; +using Stride.CommunityToolkit.Rendering.ProceduralModels; +using Stride.Core.Mathematics; +using Stride.Engine; +using Stride.Games; +using Stride.Graphics; +using Stride.Rendering; +using Stride.Rendering.Materials; +using Stride.Rendering.Materials.ComputeColors; +using StrideExamples.Local.OcclusionTest.Components; +using StrideExamples.Local.OcclusionTest.Managers; + + +Console.WriteLine("Hello, World!"); + +using var game = new Game(); +game.Run(start: Start, update: Update); + +void Start(Scene rootScene) +{ + game.SetupBase3DScene(); + game.AddGroundGizmo(); + game.Add3DGround(); + game.AddProfiler(); + game.AddAllDirectionLighting(); + // game.AddEntityDebugSceneRenderer(); + // game.AddDebugShapes(); + + var font = game.Content.Load("StrideDefaultFont"); + var gameManager = new GameManager(rootScene, font); + game.Services.AddService(gameManager); + + var greenCube = CreateCube(rootScene, game, "GreenCube", new(-5, 1, 0), Color.Green); + gameManager.UIManager.MonitorEntity(greenCube); + + var blueCube = CreateCube(rootScene, game, "BlueCube", new(5, 1, 0), Color.Blue); + gameManager.UIManager.MonitorEntity(blueCube); +} + +void Update(Scene rootScene, GameTime gameTime) +{ + var gameManager = game.Services.GetService(); + gameManager?.UIManager.UpdateUI(); +} + +static Material CreateMaterial(Game game, Color? color = null, float specular = 1.0f, float microSurface = 0.65f) +{ + var lightmapMaterial = new MaterialDescriptor + { + Attributes = + { + Diffuse = new MaterialDiffuseMapFeature(new ComputeColor(color ?? GameDefaults.DefaultMaterialColor)), + // DiffuseModel = new MaterialLightmapModelFeature() + // { + // Intensity = 20, + // LightMap = new ComputeColor(color ?? GameDefaults.DefaultMaterialColor) + // }, + Specular = new MaterialMetalnessMapFeature(new ComputeFloat(specular)), + SpecularModel = new MaterialSpecularMicrofacetModelFeature(), + MicroSurface = new MaterialGlossinessMapFeature(new ComputeFloat(microSurface)) + } + }; + + return Material.New(game.GraphicsDevice, lightmapMaterial); +} + +static Entity CreateCube(Scene rootScene, Game game, string name, Vector3 position, Color color) +{ + var cube = game.Create3DPrimitive( + PrimitiveModelType.Cube, + new Bepu3DPhysicsOptions + { + Material = game.CreateMaterial(color), + Size = new(2) + } + ); + + cube.Name = name; + cube.Transform.Position = position; + cube.Scene = rootScene; + + cube.Add(new MultiRaycastVisibilityComponent + { + Game = game, + Target = cube, + Camera = rootScene.GetCamera() ?? throw new InvalidOperationException("No camera found in scene"), + Simulation = cube.GetSimulation() + }); + + return cube; +} \ No newline at end of file diff --git a/Local/StrideExamples.Local.OcclusionTest/StrideExamples.Local.OcclusionTest.csproj b/Local/StrideExamples.Local.OcclusionTest/StrideExamples.Local.OcclusionTest.csproj new file mode 100644 index 0000000..f5136ef --- /dev/null +++ b/Local/StrideExamples.Local.OcclusionTest/StrideExamples.Local.OcclusionTest.csproj @@ -0,0 +1,21 @@ + + + + Exe + net9.0 + enable + enable + + + + + + + + + + + + + + diff --git a/StrideExamples.slnx b/StrideExamples.slnx index 41f304c..599b5f9 100644 --- a/StrideExamples.slnx +++ b/StrideExamples.slnx @@ -16,4 +16,7 @@ + + + diff --git a/nuget.config b/nuget.config new file mode 100644 index 0000000..3a9f6b3 --- /dev/null +++ b/nuget.config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file