1
0
Fork 0
mirror of https://github.com/Ellpeck/MLEM.git synced 2024-11-22 12:58:33 +01:00

additional runtime texture packer improvements

This commit is contained in:
Ell 2023-05-15 18:36:23 +02:00
parent 4863b5504b
commit e71450366b
3 changed files with 13 additions and 3 deletions

View file

@ -50,6 +50,7 @@ Fixes
### MLEM.Data ### MLEM.Data
Improvements Improvements
- Improved RuntimeTexturePacker performance for differently sized textures - Improved RuntimeTexturePacker performance for differently sized textures
- Allow querying the amount of RuntimeTexturePacker regions
## 6.1.0 ## 6.1.0

View file

@ -33,10 +33,15 @@ namespace MLEM.Data {
/// The time that <see cref="Pack"/> took the last time it was called /// The time that <see cref="Pack"/> took the last time it was called
/// </summary> /// </summary>
public TimeSpan LastTotalTime => this.LastCalculationTime + this.LastPackTime; public TimeSpan LastTotalTime => this.LastCalculationTime + this.LastPackTime;
/// <summary>
/// The amount of currently packed texture regions.
/// </summary>
public int PackedTextures => this.packedTextures.Count;
private readonly List<Request> texturesToPack = new List<Request>(); private readonly List<Request> texturesToPack = new List<Request>();
private readonly List<Request> packedTextures = new List<Request>(); private readonly List<Request> packedTextures = new List<Request>();
private readonly Dictionary<Point, Request> occupiedPositions = new Dictionary<Point, Request>(); private readonly Dictionary<Point, Request> occupiedPositions = new Dictionary<Point, Request>();
private readonly Dictionary<Point, Point> initialPositions = new Dictionary<Point, Point>();
private readonly Dictionary<Texture2D, TextureData> dataCache = new Dictionary<Texture2D, TextureData>(); private readonly Dictionary<Texture2D, TextureData> dataCache = new Dictionary<Texture2D, TextureData>();
private readonly bool autoIncreaseMaxWidth; private readonly bool autoIncreaseMaxWidth;
private readonly bool forcePowerOfTwo; private readonly bool forcePowerOfTwo;
@ -222,6 +227,7 @@ namespace MLEM.Data {
this.LastPackTime = TimeSpan.Zero; this.LastPackTime = TimeSpan.Zero;
this.texturesToPack.Clear(); this.texturesToPack.Clear();
this.packedTextures.Clear(); this.packedTextures.Clear();
this.initialPositions.Clear();
this.occupiedPositions.Clear(); this.occupiedPositions.Clear();
this.dataCache.Clear(); this.dataCache.Clear();
} }
@ -240,14 +246,17 @@ namespace MLEM.Data {
if (size.X <= 0 || size.Y <= 0) if (size.X <= 0 || size.Y <= 0)
return Rectangle.Empty; return Rectangle.Empty;
var area = new Rectangle(0, 0, size.X, size.Y); var pos = this.initialPositions.TryGetValue(size, out var first) ? first : Point.Zero;
var area = new Rectangle(pos.X, pos.Y, size.X, size.Y);
var lowestY = int.MaxValue; var lowestY = int.MaxValue;
while (true) { while (true) {
// check if the current area is already occupied // check if the current area is already occupied
if (!this.occupiedPositions.TryGetValue(area.Location, out var existing)) { if (!this.occupiedPositions.TryGetValue(area.Location, out var existing)) {
existing = this.packedTextures.FirstOrDefault(t => t.PackedArea.Intersects(area)); existing = this.packedTextures.FirstOrDefault(t => t.PackedArea.Intersects(area));
if (existing == null) {
// if no texture is occupying this space, we have found a free area // if no texture is occupying this space, we have found a free area
if (existing == null) {
// if this is the first position that this request fit in, no other requests of the same size will find a position before it
this.initialPositions[area.Size] = area.Location;
this.occupiedPositions.Add(area.Location, request); this.occupiedPositions.Add(area.Location, request);
return area; return area;
} }

View file

@ -126,7 +126,7 @@ public class TexturePackerTests {
[Test] [Test]
public void TestPackTimes() { public void TestPackTimes() {
for (var total = 1; total <= 1001; total += 100) { for (var total = 1; total <= 10001; total += 1000) {
using var sameSizePacker = new RuntimeTexturePacker(); using var sameSizePacker = new RuntimeTexturePacker();
using var diffSizePacker = new RuntimeTexturePacker(); using var diffSizePacker = new RuntimeTexturePacker();
for (var i = 0; i < total; i++) { for (var i = 0; i < total; i++) {