Skip to content

Commit

Permalink
Attempt to mitigate overdraws in sprite cutting process (not perfect …
Browse files Browse the repository at this point in the history
…yet)
  • Loading branch information
Stephane-D committed Jan 21, 2025
1 parent 8dcb6f3 commit fa97bd4
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 51 deletions.
Binary file modified bin/rescomp.jar
Binary file not shown.
2 changes: 1 addition & 1 deletion bin/rescomp.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
ResComp 3.90 (November 2024)
ResComp 3.91 (January 2025)
Copyright Stephane Dallongeville
https://github.com/Stephane-D/SGDK

Expand Down
2 changes: 1 addition & 1 deletion tools/rescomp/src/sgdk/rescomp/Launcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ else if (dep && depTarget == null)
depTarget = param;
}

System.out.println("ResComp 3.90 - SGDK Resource Compiler - Copyright 2024 (Stephane Dallongeville)");
System.out.println("ResComp 3.91 - SGDK Resource Compiler - Copyright 2025 (Stephane Dallongeville)");

if (fileName == null)
{
Expand Down
116 changes: 81 additions & 35 deletions tools/rescomp/src/sgdk/rescomp/tool/SpriteCutter.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import sgdk.tool.ImageUtil;
import sgdk.tool.Random;
import sgdk.tool.SystemUtil;
import sgdk.tool.ThreadUtil;

public class SpriteCutter
{
Expand Down Expand Up @@ -63,7 +62,7 @@ private static List<Solution> getFastOptimizedSolutions(byte[] image8bpp, Dimens
// fast optimization
solution.fastOptimize();
// fix positions
solution.fixPos();
// solution.fixPos();

// add the solution
if (!solution.cells.isEmpty())
Expand Down Expand Up @@ -253,6 +252,14 @@ public Solution()
this(new byte[image.length]);
}

public Solution(Solution solution)
{
this();

for (SpriteCell cell : solution.cells)
addCell(new SpriteCell(cell, cell.opt));
}

public Solution(CellGrid grid, OptimizationType opt)
{
this();
Expand Down Expand Up @@ -330,6 +337,24 @@ public boolean isComplete()
return remainingPixToCover <= 0;
}

public int getSpriteOverdraw()
{
int result = 0;

for (SpriteCell curCell : cells)
{
for (SpriteCell otherCell : cells)
{
if (curCell != otherCell)
{
result += curCell.getOverdraw(otherCell);
}
}
}

return result;
}

public double getScore()
{
// not yet complete
Expand All @@ -343,6 +368,8 @@ public double getScore()
for (SpriteCell cell : cells)
result += cell.getScore();

result += getSpriteOverdraw() / 3000d;

// if more than 16 sprites (not allowed) we set a penalty
if (cells.size() > 16)
result *= 2d;
Expand All @@ -363,20 +390,20 @@ public boolean rebuildFrom(List<SpriteCell> sprCells)
return isComplete();
}

private boolean rebuildCoverage(List<SpriteCell> sprcells)
{
// rebuild solution and coverage
reset();
for (SpriteCell sc : sprcells)
addCell(sc);

return isComplete();
}

private boolean rebuildCoverage()
{
return rebuildCoverage(new ArrayList<>(cells));
}
// private boolean rebuildCoverage(List<SpriteCell> sprcells)
// {
// // rebuild solution and coverage
// reset();
// for (SpriteCell sc : sprcells)
// addCell(sc);
//
// return isComplete();
// }

// private boolean rebuildCoverage()
// {
// return rebuildCoverage(new ArrayList<>(cells));
// }

private void rebuildWithout(SpriteCell cell)
{
Expand Down Expand Up @@ -490,7 +517,7 @@ void optimizeMergeForPart(SpriteCell cell)
public void optimizeMerge()
{
// sort cells on their size and coverage
Collections.sort(cells, SpriteCell.sizeAndCoverageComparator);
Collections.sort(cells, SpriteCell.sizeComparator);

final List<SpriteCell> cellsCopy = new ArrayList<>(cells);

Expand All @@ -502,7 +529,7 @@ public void optimizeMerge()
private void optimizePos()
{
// sort cells on their size and coverage
Collections.sort(cells, SpriteCell.sizeAndCoverageComparator);
Collections.sort(cells, SpriteCell.sizeComparator);

final List<SpriteCell> cellsCopy = new ArrayList<>(cells);

Expand All @@ -516,7 +543,7 @@ private void optimizePos()
private void optimizeOverdraw()
{
// sort cells on their size and coverage
Collections.sort(cells, SpriteCell.sizeAndCoverageComparator);
Collections.sort(cells, SpriteCell.sizeComparator);

final List<SpriteCell> cellsCopy = new ArrayList<>(cells);

Expand Down Expand Up @@ -552,7 +579,7 @@ private void optimizeSize(boolean fromOriginalImage)
score = newScore;

// sort cells on their size and coverage
Collections.sort(cells, SpriteCell.sizeAndCoverageComparator);
Collections.sort(cells, SpriteCell.sizeComparator);

// optimize each cell independently (starting from smallest cell)
for (int i = cells.size() - 1; i >= 0; i--)
Expand Down Expand Up @@ -580,33 +607,52 @@ public void fixPos()
public void fastOptimize()
{
double score;
double newScore = getScore();
double conv = 1d;

do
double minScore = getScore();
Solution bestSolution = new Solution(this);
int conv = 0;

while (true)
{
score = newScore;

// first iteration from coverage image
optimizeMerge();
optimizePos();
optimizeSize(false);
fixPos();
optimizeOverdraw();

score = getScore();
if (score < minScore)
{
minScore = score;
bestSolution.rebuildFrom(cells);
conv = 0;
}

// stop if we reached a minimum
if (conv++ >= 3)
break;

// second iteration from origin image
optimizeMerge();
optimizePos();
optimizeSize(true);
fixPos();
optimizeOverdraw();

newScore = getScore();

// compute convergence (to avoid death lock with oscillating score)
conv /= 2;
conv += score - newScore;

score = getScore();
if (score < minScore)
{
minScore = score;
bestSolution.rebuildFrom(cells);
conv = 0;
}

// stop if we reached a minimum
if (conv++ >= 3)
break;
}
while ((newScore != score) && (Math.abs(conv) > 0.05d));

rebuildFrom(bestSolution.cells);
}

public void showInfo()
Expand Down Expand Up @@ -1019,7 +1065,7 @@ private void addNewTask()
synchronized (branches)
{
final int size = branches.size();

// branch mutation
if ((Random.nextInt() & 0xF) != 0)
{
Expand Down Expand Up @@ -1064,7 +1110,7 @@ private void addNewTask()
curBranchId++;
}
}

executor.execute(task);
}
}
Expand Down
43 changes: 29 additions & 14 deletions tools/rescomp/src/sgdk/rescomp/type/SpriteCell.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,27 @@ public static enum OptimizationLevel
FAST, MEDIUM, SLOW, MAX
};

public static final Comparator<SpriteCell> sizeAndCoverageComparator = new Comparator<SpriteCell>()
// public static final Comparator<SpriteCell> sizeAndCoverageComparator = new Comparator<SpriteCell>()
// {
// @Override
// public int compare(SpriteCell o1, SpriteCell o2)
// {
// int result = Integer.compare(o1.numTile, o2.numTile);
//
// if (result == 0)
// result = java.lang.Double.compare(o1.getCoverage(), o2.getCoverage());
//
// // we want ascending order
// return -result;
// }
// };

public static final Comparator<SpriteCell> sizeComparator = new Comparator<SpriteCell>()
{
@Override
public int compare(SpriteCell o1, SpriteCell o2)
{
int result = Integer.compare(o1.numTile, o2.numTile);

if (result == 0)
result = java.lang.Double.compare(o1.getCoverage(), o2.getCoverage());

// we want ascending order
return -result;
return -Integer.compare(o1.numTile, o2.numTile);
}
};

Expand Down Expand Up @@ -236,7 +245,7 @@ private List<SpriteCell> mutateSplit()

public double getScore()
{
return getBaseScore() + (getCoveragePenalty() / 10d);
return getBaseScore(); // + (getCoveragePenalty() / 10d);
}

public double getBaseScore()
Expand All @@ -254,7 +263,13 @@ public double getBaseScore()
return 6d + (numTile * 4d) + (getWidth() / 32d);
}
}


public int getOverdraw(SpriteCell cell)
{
Rectangle r = intersection(cell);
return r.height * r.width;
}

public double getCoverage()
{
if (coveredPix == -1)
Expand All @@ -263,10 +278,10 @@ public double getCoverage()
return (double) coveredPix / (double) (numTile * 64);
}

public double getCoveragePenalty()
{
return 1d - getCoverage();
}
// public double getCoveragePenalty()
// {
// return 1d - getCoverage();
// }

public boolean optimizeOverdraw(Dimension imageDim, List<SpriteCell> allSpr)
{
Expand Down

0 comments on commit fa97bd4

Please sign in to comment.