Skip to content

Commit

Permalink
Texture packer optimization from libGDX PR
Browse files Browse the repository at this point in the history
  • Loading branch information
Anuken committed Sep 8, 2024
1 parent 29c4199 commit 8073823
Showing 1 changed file with 36 additions and 21 deletions.
57 changes: 36 additions & 21 deletions extensions/packer/src/arc/packer/MaxRectsPacker.java
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ private Page packPage(Seq<Rect> inputRects){
throw new RuntimeException("Image does not fit with max page width " + settings.maxWidth + paddingMessage + ": "
+ rect.name + "[" + width + "," + height + "]");
}
if(height > maxHeight && (!settings.rotation || width > maxHeight)){
if(height > maxHeight){
String paddingMessage = edgePadY ? (" and Y edge padding " + paddingY + "*2") : "";
throw new RuntimeException("Image does not fit in max page height " + settings.maxHeight + paddingMessage + ": "
+ rect.name + "[" + width + "," + height + "]");
Expand Down Expand Up @@ -190,16 +190,16 @@ private Page packPage(Seq<Rect> inputRects){
*/
private Page packAtSize(boolean fully, int width, int height, Seq<Rect> inputRects){
Page bestResult = null;
for(int i = 0, n = methods.length; i < n; i++){
for(FreeRectChoiceHeuristic method : methods){
maxRects.init(width, height);
Page result;
if(!settings.fast){
result = maxRects.pack(inputRects, methods[i]);
result = maxRects.pack(inputRects, method);
}else{
Seq<Rect> remaining = new Seq();
for(int ii = 0, nn = inputRects.size; ii < nn; ii++){
Rect rect = inputRects.get(ii);
if(maxRects.insert(rect, methods[i]) == null){
if(maxRects.insert(rect, method) == null){
while(ii < nn)
remaining.add(inputRects.get(ii++));
}
Expand Down Expand Up @@ -272,8 +272,9 @@ public int next(boolean result){
*/
class MaxRects{
private int binWidth, binHeight;
private final Seq<Rect> usedRectangles = new Seq();
private final Seq<Rect> freeRectangles = new Seq();
private final Seq<Rect> usedRectangles = new Seq<>();
private final Seq<Rect> freeRectangles = new Seq<>();
private final Seq<Rect> rectanglesToCheckWhenPruning = new Seq<>();

public void init(int width, int height){
binWidth = width;
Expand Down Expand Up @@ -670,6 +671,7 @@ private boolean splitFreeNode(Rect freeNode, Rect usedNode){
Rect newNode = new Rect(freeNode);
newNode.height = usedNode.y - newNode.y;
freeRectangles.add(newNode);
rectanglesToCheckWhenPruning.add(newNode);
}

// New node at the bottom side of the used node.
Expand All @@ -678,6 +680,7 @@ private boolean splitFreeNode(Rect freeNode, Rect usedNode){
newNode.y = usedNode.y + usedNode.height;
newNode.height = freeNode.y + freeNode.height - (usedNode.y + usedNode.height);
freeRectangles.add(newNode);
rectanglesToCheckWhenPruning.add(newNode);
}
}

Expand All @@ -687,6 +690,7 @@ private boolean splitFreeNode(Rect freeNode, Rect usedNode){
Rect newNode = new Rect(freeNode);
newNode.width = usedNode.x - newNode.x;
freeRectangles.add(newNode);
rectanglesToCheckWhenPruning.add(newNode);
}

// New node at the right side of the used node.
Expand All @@ -695,31 +699,42 @@ private boolean splitFreeNode(Rect freeNode, Rect usedNode){
newNode.x = usedNode.x + usedNode.width;
newNode.width = freeNode.x + freeNode.width - (usedNode.x + usedNode.width);
freeRectangles.add(newNode);
rectanglesToCheckWhenPruning.add(newNode);
}
}

return true;
}

private void pruneFreeList(){
// Go through each pair and remove any rectangle that is redundant.
Seq<Rect> freeRectangles = this.freeRectangles;
for(int i = 0, n = freeRectangles.size; i < n; i++)
for(int j = i + 1; j < n; ++j){
Rect rect1 = freeRectangles.get(i);
Rect rect2 = freeRectangles.get(j);
if(isContainedIn(rect1, rect2)){
freeRectangles.remove(i);
--i;
--n;
break;
IntSet freeRectanglesToRemove = new IntSet();

for(Rect checkingRectangle : rectanglesToCheckWhenPruning){
for(int i = 0; i < freeRectangles.size; i++){
Rect rect = freeRectangles.get(i);
if(rect == checkingRectangle){
continue;
}
if(isContainedIn(rect2, rect1)){
freeRectangles.remove(j);
--j;
--n;
if(isContainedIn(rect, checkingRectangle)){
freeRectanglesToRemove.add(i);
}
}
}

rectanglesToCheckWhenPruning.clear();

if(freeRectanglesToRemove.isEmpty()){
return;
}

Seq<Rect> temporaryFreeRectangles = new Seq<>(freeRectangles);

freeRectangles.clear();
for(int i = 0; i < temporaryFreeRectangles.size; i++){
if(!freeRectanglesToRemove.contains(i)){
freeRectangles.add(temporaryFreeRectangles.get(i));
}
}
}

private boolean isContainedIn(Rect a, Rect b){
Expand Down

0 comments on commit 8073823

Please sign in to comment.