SHARE
TWEET

Minecraft Textue Packing Tool

a guest Oct 9th, 2011 75,645 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. package net.minecraft.client.model.geom;
  2.  
  3. import java.awt.*;
  4. import java.awt.image.BufferedImage;
  5. import java.io.*;
  6. import java.util.*;
  7. import java.util.List;
  8.  
  9. import javax.imageio.ImageIO;
  10.  
  11. import net.minecraft.client.model.dragon.DragonModel;
  12. import util.Mth;
  13.  
  14. public class ImageGenerator {
  15.     private static final int WIDTH = 256;
  16.     private static final int HEIGHT = 256;
  17.  
  18.     private class Region {
  19.         public int x1, y1, x2, y2;
  20.  
  21.         public Region(int x1, int y1, int x2, int y2) {
  22.             this.x1 = x1;
  23.             this.y1 = y1;
  24.             this.x2 = x2;
  25.             this.y2 = y2;
  26.         }
  27.  
  28.         public void move(int xo, int yo) {
  29.             x1 += xo;
  30.             y1 += yo;
  31.             x2 += xo;
  32.             y2 += yo;
  33.         }
  34.  
  35.         public boolean overlaps(Region r2, int xo, int yo) {
  36.             if (r2.x2 + xo <= x1) return false;
  37.             if (r2.y2 + yo <= y1) return false;
  38.             if (r2.x1 + xo >= x2) return false;
  39.             if (r2.y1 + yo >= y2) return false;
  40.             return true;
  41.         }
  42.  
  43.         public void render(Graphics g) {
  44.             g.fillRect(x1, y1, x2 - x1, y2 - y1);
  45.         }
  46.     }
  47.  
  48.     private class UnfoldedCube {
  49.         public int x, y;
  50.         public Region[] cubeRegions = new Region[6];
  51.         public String id;
  52.         public int width, height;
  53.  
  54.         public UnfoldedCube(Cube cube) {
  55.             int xs = Mth.ceil(cube.x1 - cube.x0);
  56.             int ys = Mth.ceil(cube.y1 - cube.y0);
  57.             int zs = Mth.ceil(cube.z1 - cube.z0);
  58.  
  59.             width = xs * 2 + zs * 2;
  60.             height = zs + ys;
  61.  
  62.             id = cube.id;
  63.  
  64.             cubeRegions[0] = new Region(0, zs, zs, zs + ys);
  65.             cubeRegions[1] = new Region(zs, zs, zs + xs, zs + ys);
  66.             cubeRegions[2] = new Region(zs + xs, zs, zs + xs + zs, zs + ys);
  67.             cubeRegions[3] = new Region(zs + xs + zs, zs, zs + xs + zs + xs, zs + ys);
  68.             cubeRegions[4] = new Region(zs, 0, zs + xs, zs);
  69.             cubeRegions[5] = new Region(zs + xs, 0, zs + xs * 2, zs);
  70.         }
  71.  
  72.         public boolean fits(int x, int y) {
  73.             for (int i = 0; i < 6; i++) {
  74.                 if (!isFree(cubeRegions[i], x, y)) return false;
  75.             }
  76.             return true;
  77.         }
  78.  
  79.         public void place(int x, int y) {
  80.             this.x = x;
  81.             this.y = y;
  82.             for (int i = 0; i < 6; i++) {
  83.                 cubeRegions[i].move(x, y);
  84.                 occupiedRegions.add(cubeRegions[i]);
  85.             }
  86.         }
  87.  
  88.         public void render(Graphics g) {
  89.             float hue = (float) Math.random();
  90.             g.setColor(new Color(Color.HSBtoRGB(hue, 1, 0.7f)));
  91.             cubeRegions[5].render(g);
  92.             g.setColor(new Color(Color.HSBtoRGB(hue, 1, 1.0f)));
  93.             cubeRegions[4].render(g);
  94.             g.setColor(new Color(Color.HSBtoRGB(hue, 1, 0.9f)));
  95.             cubeRegions[1].render(g);
  96.             cubeRegions[3].render(g);
  97.             g.setColor(new Color(Color.HSBtoRGB(hue, 1, 0.8f)));
  98.             cubeRegions[0].render(g);
  99.             cubeRegions[2].render(g);
  100.         }
  101.     }
  102.  
  103.     private List<Region> occupiedRegions = new ArrayList<Region>();
  104.  
  105.     private boolean isFree(Region region, int xo, int yo) {
  106.         if (region.x1 + xo < 0) return false;
  107.         if (region.y1 + yo < 0) return false;
  108.         if (region.x2 + xo > WIDTH) return false;
  109.         if (region.y2 + yo > HEIGHT) return false;
  110.  
  111.         for (int i = 0; i < occupiedRegions.size(); i++) {
  112.             if (occupiedRegions.get(i).overlaps(region, xo, yo)) return false;
  113.         }
  114.  
  115.         return true;
  116.     }
  117.  
  118.     public void generateImage(List<ModelPart> parts) {
  119.  
  120.         List<Cube> cubes = new ArrayList<Cube>();
  121.         for (ModelPart mp : parts) {
  122.             getCubes(mp, cubes);
  123.         }
  124.  
  125.         Collections.sort(cubes, new Comparator<Cube>() {
  126.             @Override
  127.             public int compare(Cube c0, Cube c1) {
  128.                 int xs = Mth.ceil(c0.x1 - c0.x0);
  129.                 int ys = Mth.ceil(c0.y1 - c0.y0);
  130.                 int zs = Mth.ceil(c0.z1 - c0.z0);
  131.  
  132.                 int ww0 = xs * 2 + zs * 2;
  133.                 int hh0 = zs + ys;
  134.  
  135.                 xs = Mth.ceil(c1.x1 - c1.x0);
  136.                 ys = Mth.ceil(c1.y1 - c1.y0);
  137.                 zs = Mth.ceil(c1.z1 - c1.z0);
  138.  
  139.                 int ww1 = xs * 2 + zs * 2;
  140.                 int hh1 = zs + ys;
  141.  
  142.                 if (ww0 * hh0 < ww1 * hh1) {
  143.                     return 1;
  144.                 } else if (ww0 * hh0 > ww1 * hh1) {
  145.                     return -1;
  146.                 }
  147.  
  148.                 return 0;
  149.             }
  150.         });
  151.  
  152.         List<UnfoldedCube> unfolded = new ArrayList<UnfoldedCube>();
  153.         for (Cube cube : cubes) {
  154.             UnfoldedCube uc = new UnfoldedCube(cube);
  155.  
  156.             boolean placed = false;
  157.             positionLoop: for (int y = 0; y < HEIGHT - uc.height; y++) {
  158.                 for (int x = 0; x < WIDTH - uc.width; x++) {
  159.                     if (uc.fits(x, y)) {
  160.                         uc.place(x, y);
  161.                         placed = true;
  162.                         break positionLoop;
  163.                     }
  164.                 }
  165.             }
  166.             if (!placed) {
  167.                 System.out.println("Failed to place " + uc.id);
  168.             } else {
  169.                 unfolded.add(uc);
  170.             }
  171.         }
  172.  
  173.         BufferedImage img = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB);
  174.         Graphics g = img.getGraphics();
  175.         System.out.println("----------------");
  176.         for (UnfoldedCube uc : unfolded) {
  177.             System.out.println("setMapTex(\"" + uc.id + "\", " + uc.x + ", " + uc.y + ");");
  178.             uc.render(g);
  179.         }
  180.         try {
  181.             ImageIO.write(img, "png", new File("output.png"));
  182.         } catch (IOException e) {
  183.             e.printStackTrace();
  184.         }
  185.     }
  186.  
  187.     public void getCubes(ModelPart mp, List<Cube> cubeList) {
  188.         addLoop: for (Cube cube : mp.cubes) {
  189.             if (cube.id != null) {
  190.                 for (Cube otherCube : cubeList) {
  191.                     if (otherCube.id != null) {
  192.                         if (otherCube.id.equals(cube.id)) {
  193.                             System.out.println("Duplicate " + cube.id);
  194.                             continue addLoop;
  195.                         }
  196.                     }
  197.                 }
  198.             }
  199.             cubeList.add(cube);
  200.         }
  201.     }
  202.  
  203.     public static void main(String[] args) {
  204.         new ImageGenerator().generateImage(new DragonModel(0).cubes);
  205.     }
  206. }
  207.  
  208.  
RAW Paste Data
Top