Files
parkan-playground/NResUI/Rendering/Viewport/ViewportScene.cs
T

126 lines
3.5 KiB
C#
Raw Normal View History

2026-06-05 20:47:57 +03:00
using System.Numerics;
2026-06-05 20:33:21 +03:00
using NResUI.Rendering.Viewport.Meshes;
namespace NResUI.Rendering.Viewport;
public sealed class ViewportScene
{
private readonly List<ViewportPiece> _pieces = new();
public IReadOnlyList<ViewportPiece> Pieces => _pieces;
public ViewportGrid? Grid { get; set; }
2026-06-05 20:47:57 +03:00
public ViewportDebugSettings Debug { get; } = new();
2026-06-05 20:33:21 +03:00
public int SelectedPieceId { get; set; } = -1;
public ViewportPiece? SelectedPiece
{
get
{
if (SelectedPieceId < 0)
return null;
foreach (var piece in _pieces)
{
if (piece.Id == SelectedPieceId)
return piece;
}
return null;
}
}
public void AddPiece(ViewportPiece piece)
{
_pieces.Add(piece);
}
public void ClearSelection()
{
SelectedPieceId = -1;
}
2026-06-05 20:47:57 +03:00
public bool TryGetPieceWorldBounds(ViewportPiece piece, out ViewportBounds bounds)
{
return TryTransformBounds(piece.BoundsMin, piece.BoundsMax, piece.LocalTransform, out bounds);
}
public bool TryGetSelectedPieceWorldBounds(out ViewportBounds bounds)
{
var selectedPiece = SelectedPiece;
if (selectedPiece == null)
{
bounds = default;
return false;
}
return TryGetPieceWorldBounds(selectedPiece, out bounds);
}
public bool TryGetSceneWorldBounds(out ViewportBounds bounds)
{
var hasBounds = false;
var min = new Vector3(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity);
var max = new Vector3(float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity);
foreach (var piece in _pieces)
{
if (!TryGetPieceWorldBounds(piece, out var pieceBounds))
continue;
min = Vector3.Min(min, pieceBounds.Min);
max = Vector3.Max(max, pieceBounds.Max);
hasBounds = true;
}
bounds = hasBounds ? new ViewportBounds(min, max) : default;
return hasBounds;
}
2026-06-05 20:33:21 +03:00
public static ViewportScene CreateDefaultCubeScene(GpuMesh cubeMesh, GpuMesh gridMesh)
{
var scene = new ViewportScene
{
Grid = new ViewportGrid(gridMesh)
};
scene.AddPiece(ViewportPiece.CreateUnitCube(0, "Cube", cubeMesh));
return scene;
}
2026-06-05 20:47:57 +03:00
private static bool TryTransformBounds(
Vector3 localMin,
Vector3 localMax,
Matrix4x4 transform,
out ViewportBounds bounds)
{
var corners = new[]
{
new Vector3(localMin.X, localMin.Y, localMin.Z),
new Vector3(localMax.X, localMin.Y, localMin.Z),
new Vector3(localMin.X, localMax.Y, localMin.Z),
new Vector3(localMax.X, localMax.Y, localMin.Z),
new Vector3(localMin.X, localMin.Y, localMax.Z),
new Vector3(localMax.X, localMin.Y, localMax.Z),
new Vector3(localMin.X, localMax.Y, localMax.Z),
new Vector3(localMax.X, localMax.Y, localMax.Z),
};
var min = new Vector3(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity);
var max = new Vector3(float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity);
foreach (var corner in corners)
{
var world = Vector3.Transform(corner, transform);
min = Vector3.Min(min, world);
max = Vector3.Max(max, world);
}
bounds = new ViewportBounds(min, max);
return true;
}
2026-06-05 20:33:21 +03:00
}