Remove the other goto from TexAtlas.PackAtlas

This commit is contained in:
YoshiRulz 2021-03-25 19:18:04 +10:00
parent 997df16487
commit e9ce42bfe0
No known key found for this signature in database
GPG Key ID: C4DE31C245353FB7
1 changed files with 51 additions and 52 deletions

View File

@ -43,72 +43,71 @@ namespace BizHawk.Bizware.BizwareGL
List<RectItem> currentItems = new(initItems); List<RectItem> currentItems = new(initItems);
List<RectItem> remainItems = new(); List<RectItem> remainItems = new();
RETRY: TryFitParam tfpFinal;
while (true)
// this is where the texture size range is determined.
// we run this every time we make an atlas, in case we want to variably control the maximum texture output size.
// ALSO - we accumulate data in there, so we need to refresh it each time. ... lame.
var todoSizes = new List<TryFitParam>();
for (int i = 3; i <= MaxSizeBits; i++)
{ {
for (int j = 3; j <= MaxSizeBits; j++) // this is where the texture size range is determined.
// we run this every time we make an atlas, in case we want to variably control the maximum texture output size.
// ALSO - we accumulate data in there, so we need to refresh it each time. ... lame.
var todoSizes = new List<TryFitParam>();
for (int i = 3; i <= MaxSizeBits; i++)
{ {
int w = 1 << i; for (int j = 3; j <= MaxSizeBits; j++)
int h = 1 << j;
TryFitParam tfp = new TryFitParam(w, h);
todoSizes.Add(tfp);
}
}
//run the packing algorithm on each potential size
Parallel.ForEach(todoSizes, (param) =>
{
var rbp = new RectangleBinPack();
rbp.Init(16384, 16384);
param.rbp.Init(param.w, param.h);
foreach (var ri in currentItems)
{
RectangleBinPack.Node node = param.rbp.Insert(ri.Width, ri.Height);
if (node == null)
{ {
param.ok = false; int w = 1 << i;
} int h = 1 << j;
else TryFitParam tfp = new TryFitParam(w, h);
{ todoSizes.Add(tfp);
node.ri = ri;
param.nodes.Add(node);
} }
} }
});
//find the best fit among the potential sizes that worked //run the packing algorithm on each potential size
var best = long.MaxValue; Parallel.ForEach(todoSizes, (param) =>
var tfpFinal = todoSizes[0];
foreach (var tfp in todoSizes)
{
if (!tfp.ok) continue;
var area = tfp.w * (long) tfp.h;
if (area > best) continue; // larger than best, not interested
if (area == best) // same area, compare perimeter as tie-breaker (to create squares, which are nicer to look at)
{ {
if (tfp.w + tfp.h >= tfpFinal.w + tfpFinal.h) continue; var rbp = new RectangleBinPack();
} rbp.Init(16384, 16384);
best = area; param.rbp.Init(param.w, param.h);
tfpFinal = tfp;
}
//did we find any fit? foreach (var ri in currentItems)
if (best == long.MaxValue) {
{ RectangleBinPack.Node node = param.rbp.Insert(ri.Width, ri.Height);
if (node == null)
{
param.ok = false;
}
else
{
node.ri = ri;
param.nodes.Add(node);
}
}
});
//find the best fit among the potential sizes that worked
var best = long.MaxValue;
tfpFinal = todoSizes[0];
foreach (var tfp in todoSizes)
{
if (!tfp.ok) continue;
var area = tfp.w * (long) tfp.h;
if (area > best) continue; // larger than best, not interested
if (area == best) // same area, compare perimeter as tie-breaker (to create squares, which are nicer to look at)
{
if (tfp.w + tfp.h >= tfpFinal.w + tfpFinal.h) continue;
}
best = area;
tfpFinal = tfp;
}
//did we find any fit?
if (best < long.MaxValue) break;
//nope - move an item to the remaining list and try again //nope - move an item to the remaining list and try again
remainItems.Add(currentItems[currentItems.Count - 1]); remainItems.Add(currentItems[currentItems.Count - 1]);
currentItems.RemoveAt(currentItems.Count - 1); currentItems.RemoveAt(currentItems.Count - 1);
goto RETRY;
} }
//we found a fit. setup this atlas in the result and drop the items into it //we found a fit. setup this atlas in the result and drop the items into it
atlases.Add((new Size(tfpFinal.w, tfpFinal.h), new List<RectItem>(currentItems))); atlases.Add((new Size(tfpFinal.w, tfpFinal.h), new List<RectItem>(currentItems)));
foreach (var item in currentItems) foreach (var item in currentItems)
{ {
object o = item.Item; object o = item.Item;