mirror of
https://github.com/Ellpeck/MLEM.git
synced 2024-11-22 12:58:33 +01:00
further improve RuntimeTexturePacker performance by only checking against already packed textures
This commit is contained in:
parent
93a82bcf36
commit
61770d59b1
1 changed files with 16 additions and 13 deletions
|
@ -34,7 +34,8 @@ namespace MLEM.Data {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public TimeSpan LastTotalTime => this.LastCalculationTime + this.LastPackTime;
|
public TimeSpan LastTotalTime => this.LastCalculationTime + this.LastPackTime;
|
||||||
|
|
||||||
private readonly List<Request> textures = new List<Request>();
|
private readonly List<Request> texturesToPack = new List<Request>();
|
||||||
|
private readonly List<Request> alreadyPackedTextures = new List<Request>();
|
||||||
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;
|
||||||
|
@ -148,7 +149,7 @@ namespace MLEM.Data {
|
||||||
throw new InvalidOperationException($"Cannot add texture with width {texture.Width} to a texture packer with max width {this.maxWidth}");
|
throw new InvalidOperationException($"Cannot add texture with width {texture.Width} to a texture packer with max width {this.maxWidth}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.textures.Add(new Request(texture, result, padding, padWithPixels));
|
this.texturesToPack.Add(new Request(texture, result, padding, padWithPixels));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -162,19 +163,19 @@ namespace MLEM.Data {
|
||||||
if (this.PackedTexture != null)
|
if (this.PackedTexture != null)
|
||||||
throw new InvalidOperationException("Cannot pack a texture packer that is already packed");
|
throw new InvalidOperationException("Cannot pack a texture packer that is already packed");
|
||||||
|
|
||||||
// we pack larger textures first, so that smaller textures can fit in the gaps that larger ones leave
|
|
||||||
this.textures.Sort((r1, r2) => (r2.Texture.Width * r2.Texture.Height).CompareTo(r1.Texture.Width * r1.Texture.Height));
|
|
||||||
|
|
||||||
// set pack areas for each request
|
// set pack areas for each request
|
||||||
|
// we pack larger textures first, so that smaller textures can fit in the gaps that larger ones leave
|
||||||
var stopwatch = Stopwatch.StartNew();
|
var stopwatch = Stopwatch.StartNew();
|
||||||
foreach (var request in this.textures)
|
foreach (var request in this.texturesToPack.OrderByDescending(t => t.Texture.Width * t.Texture.Height)) {
|
||||||
request.PackedArea = this.FindFreeArea(request);
|
request.PackedArea = this.FindFreeArea(request);
|
||||||
|
this.alreadyPackedTextures.Add(request);
|
||||||
|
}
|
||||||
stopwatch.Stop();
|
stopwatch.Stop();
|
||||||
this.LastCalculationTime = stopwatch.Elapsed;
|
this.LastCalculationTime = stopwatch.Elapsed;
|
||||||
|
|
||||||
// figure out texture size and generate texture
|
// figure out texture size and generate texture
|
||||||
var width = this.textures.Max(t => t.PackedArea.Right);
|
var width = this.alreadyPackedTextures.Max(t => t.PackedArea.Right);
|
||||||
var height = this.textures.Max(t => t.PackedArea.Bottom);
|
var height = this.alreadyPackedTextures.Max(t => t.PackedArea.Bottom);
|
||||||
if (this.forcePowerOfTwo) {
|
if (this.forcePowerOfTwo) {
|
||||||
width = ToPowerOfTwo(width);
|
width = ToPowerOfTwo(width);
|
||||||
height = ToPowerOfTwo(height);
|
height = ToPowerOfTwo(height);
|
||||||
|
@ -186,21 +187,22 @@ namespace MLEM.Data {
|
||||||
// copy texture data onto the packed texture
|
// copy texture data onto the packed texture
|
||||||
stopwatch.Restart();
|
stopwatch.Restart();
|
||||||
using (var data = this.PackedTexture.GetTextureData()) {
|
using (var data = this.PackedTexture.GetTextureData()) {
|
||||||
foreach (var request in this.textures)
|
foreach (var request in this.alreadyPackedTextures)
|
||||||
this.CopyRegion(data, request);
|
this.CopyRegion(data, request);
|
||||||
}
|
}
|
||||||
stopwatch.Stop();
|
stopwatch.Stop();
|
||||||
this.LastPackTime = stopwatch.Elapsed;
|
this.LastPackTime = stopwatch.Elapsed;
|
||||||
|
|
||||||
// invoke callbacks
|
// invoke callbacks
|
||||||
foreach (var request in this.textures) {
|
foreach (var request in this.alreadyPackedTextures) {
|
||||||
var packedArea = request.PackedArea.Shrink(new Point(request.Padding));
|
var packedArea = request.PackedArea.Shrink(new Point(request.Padding));
|
||||||
request.Result.Invoke(new TextureRegion(this.PackedTexture, packedArea));
|
request.Result.Invoke(new TextureRegion(this.PackedTexture, packedArea));
|
||||||
if (this.disposeTextures)
|
if (this.disposeTextures)
|
||||||
request.Texture.Texture.Dispose();
|
request.Texture.Texture.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.textures.Clear();
|
this.texturesToPack.Clear();
|
||||||
|
this.alreadyPackedTextures.Clear();
|
||||||
this.dataCache.Clear();
|
this.dataCache.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,7 +212,8 @@ namespace MLEM.Data {
|
||||||
public void Reset() {
|
public void Reset() {
|
||||||
this.PackedTexture?.Dispose();
|
this.PackedTexture?.Dispose();
|
||||||
this.PackedTexture = null;
|
this.PackedTexture = null;
|
||||||
this.textures.Clear();
|
this.texturesToPack.Clear();
|
||||||
|
this.alreadyPackedTextures.Clear();
|
||||||
this.dataCache.Clear();
|
this.dataCache.Clear();
|
||||||
this.LastCalculationTime = TimeSpan.Zero;
|
this.LastCalculationTime = TimeSpan.Zero;
|
||||||
this.LastPackTime = TimeSpan.Zero;
|
this.LastPackTime = TimeSpan.Zero;
|
||||||
|
@ -231,7 +234,7 @@ namespace MLEM.Data {
|
||||||
while (true) {
|
while (true) {
|
||||||
var intersected = false;
|
var intersected = false;
|
||||||
var area = new Rectangle(pos, size);
|
var area = new Rectangle(pos, size);
|
||||||
foreach (var tex in this.textures) {
|
foreach (var tex in this.alreadyPackedTextures) {
|
||||||
if (tex.PackedArea.Intersects(area)) {
|
if (tex.PackedArea.Intersects(area)) {
|
||||||
pos.X = tex.PackedArea.Right;
|
pos.X = tex.PackedArea.Right;
|
||||||
// when we move down, we want to move down by the smallest intersecting texture's height
|
// when we move down, we want to move down by the smallest intersecting texture's height
|
||||||
|
|
Loading…
Reference in a new issue