Jump to content

Recommended Posts

Posted

Hi,

I've recently started modding and was looking for a tool to properly generate a texture map for mobs.

Fortunately notch already wrote such a tool (http://pastebin.com/0AcY6YV2).

However this does not work with forge so I changed the necessary variables to make it work.

 

To use it simply pass a "new ModelMob().parts" in the main class and wait for the results.

You will need to put all of your boxes into a list called parts (protected ArrayList<ModelRenderer> parts = new ArrayList<ModelRenderer>(); ).

 

Here's an example mob (only the constructor and the list):

protected ArrayList<ModelRenderer> parts = new ArrayList<ModelRenderer>();
ModelMob()
{
textureWidth = 128; //change this to the same size as in ImageGenerator (WIDTH)
textureHeight = 64;

setTextureOffset("null.part1", 0, 0); // important (needs to be called with any offset for the first time, otherwise you will get a NullPtr exception)
setTextureOffset("null.part2", 0, 0); // change it to the output of ImageGenerator afterwards

ModelRenderer part1 = new ModelRenderer(this, 0, 0);
parts.add(part1);
part1.addBox("part1",-8F, -8F, 0F, 16, 16, 32);
//some other code

ModelRenderer part2 = new ModelRenderer(this, 0, 0);
parts.add(part2);
part2.addBox("part2",-0.5F, 0F, 0F, 1, 8, ;
//some other code
}

 

Finally here is the actual code:

 

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.*;
import java.util.List;

import javax.imageio.ImageIO;

import net.minecraft.client.model.ModelBase;
import net.minecraft.client.model.ModelBox;
import net.minecraft.client.model.ModelRenderer;


/*
* Generates a texture map for a specified model 
* modified from: http://pastebin.com/0AcY6YV2
*/

public class ImageGenerator {
    private static final int WIDTH = 256;
    private static final int HEIGHT = 256;

    private class Region {
        public int x1, y1, x2, y2;

        public Region(int x1, int y1, int x2, int y2) {
            this.x1 = x1;
            this.y1 = y1;
            this.x2 = x2;
            this.y2 = y2;
        }

        public void move(int xo, int yo) {
            x1 += xo;
            y1 += yo;
            x2 += xo;
            y2 += yo;
        }

        public boolean overlaps(Region r2, int xo, int yo) {
            if (r2.x2 + xo <= x1) return false;
            if (r2.y2 + yo <= y1) return false;
            if (r2.x1 + xo >= x2) return false;
            if (r2.y1 + yo >= y2) return false;
            return true;
        }

        public void render(Graphics g) {
            g.fillRect(x1, y1, x2 - x1, y2 - y1);
        }
    }

    private class UnfoldedCube {
        public int x, y;
        public Region[] cubeRegions = new Region[6];
        public String id;
        public int width, height;

        public UnfoldedCube(ModelBox cube) {
            int xs = (int) Math.ceil(cube.posX2 - cube.posX1);
            int ys = (int) Math.ceil(cube.posY2 - cube.posY1);
            int zs = (int) Math.ceil(cube.posZ2 - cube.posZ1);

            width = xs * 2 + zs * 2;
            height = zs + ys;

            id = cube.field_78247_g;

            cubeRegions[0] = new Region(0, zs, zs, zs + ys);
            cubeRegions[1] = new Region(zs, zs, zs + xs, zs + ys);
            cubeRegions[2] = new Region(zs + xs, zs, zs + xs + zs, zs + ys);
            cubeRegions[3] = new Region(zs + xs + zs, zs, zs + xs + zs + xs, zs + ys);
            cubeRegions[4] = new Region(zs, 0, zs + xs, zs);
            cubeRegions[5] = new Region(zs + xs, 0, zs + xs * 2, zs);
        }

        public boolean fits(int x, int y) {
            for (int i = 0; i < 6; i++) {
                if (!isFree(cubeRegions[i], x, y)) return false;
            }
            return true;
        }

        public void place(int x, int y) {
            this.x = x;
            this.y = y;
            for (int i = 0; i < 6; i++) {
                cubeRegions[i].move(x, y);
                occupiedRegions.add(cubeRegions[i]);
            }
        }

        public void render(Graphics g) {
            float hue = (float) Math.random();
            g.setColor(new Color(Color.HSBtoRGB(hue, 1, 0.7f)));
            cubeRegions[5].render(g);
            g.setColor(new Color(Color.HSBtoRGB(hue, 1, 1.0f)));
            cubeRegions[4].render(g);
            g.setColor(new Color(Color.HSBtoRGB(hue, 1, 0.9f)));
            cubeRegions[1].render(g);
            cubeRegions[3].render(g);
            g.setColor(new Color(Color.HSBtoRGB(hue, 1, 0.8f)));
            cubeRegions[0].render(g);
            cubeRegions[2].render(g);
        }
    }

    private List<Region> occupiedRegions = new ArrayList<Region>();

    private boolean isFree(Region region, int xo, int yo) {
        if (region.x1 + xo < 0) return false;
        if (region.y1 + yo < 0) return false;
        if (region.x2 + xo > WIDTH) return false;
        if (region.y2 + yo > HEIGHT) return false;

        for (int i = 0; i < occupiedRegions.size(); i++) {
            if (occupiedRegions.get(i).overlaps(region, xo, yo)) return false;
        }

        return true;
    }

    public void generateImage(List<ModelRenderer> parts) {

        List<ModelBox> cubes = new ArrayList<ModelBox>();
        for (ModelRenderer mp : parts) {
            getCubes(mp, cubes);
        }

        Collections.sort(cubes, new Comparator<ModelBox>() {
            @Override
            public int compare(ModelBox c0, ModelBox c1) {
                int xs = (int) Math.ceil(c0.posX2 - c0.posX1);
                int ys = (int) Math.ceil(c0.posY2 - c0.posY1);
                int zs = (int) Math.ceil(c0.posZ2 - c0.posZ1);

                int ww0 = xs * 2 + zs * 2;
                int hh0 = zs + ys;

                xs = (int) Math.ceil(c1.posX2 - c1.posX1);
                ys = (int) Math.ceil(c1.posY2 - c1.posY1);
                zs = (int) Math.ceil(c1.posZ2 - c1.posZ1);

                int ww1 = xs * 2 + zs * 2;
                int hh1 = zs + ys;

                if (ww0 * hh0 < ww1 * hh1) {
                    return 1;
                } else if (ww0 * hh0 > ww1 * hh1) {
                    return -1;
                }

                return 0;
            }
        });

        List<UnfoldedCube> unfolded = new ArrayList<UnfoldedCube>();
        for (ModelBox cube : cubes) {
            UnfoldedCube uc = new UnfoldedCube(cube);

            boolean placed = false;
            positionLoop: for (int y = 0; y < HEIGHT - uc.height; y++) {
                for (int x = 0; x < WIDTH - uc.width; x++) {
                    if (uc.fits(x, y)) {
                        uc.place(x, y);
                        placed = true;
                        break positionLoop;
                    }
                }
            }
            if (!placed) {
                System.out.println("Failed to place " + uc.id);
            } else {
                unfolded.add(uc);
            }
        }

        BufferedImage img = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB);
        Graphics g = img.getGraphics();
        System.out.println("----------------");
        for (UnfoldedCube uc : unfolded) {
            System.out.println("setTextureOffset(\"" + uc.id + "\", " + uc.x + ", " + uc.y + ");");
            uc.render(g);
        }
        try {
            ImageIO.write(img, "png", new File("output.png"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void getCubes(ModelRenderer mp, List<ModelBox> cubeList) {
        addLoop: for (ModelBox cube : (List<ModelBox>)mp.cubeList) {
            if (cube.field_78247_g != null) {
                for (ModelBox otherCube : cubeList) {
                    if (otherCube.field_78247_g != null) {
                        if (otherCube.field_78247_g.equals(cube.field_78247_g)) {
                            System.out.println("Duplicate " + cube.field_78247_g);
                            continue addLoop;
                        }
                    }
                }
            }
            cubeList.add(cube);
        }
    }

    public static void main(String[] args) {
        new ImageGenerator().generateImage(new ModelMob().parts );
    }
}

 

I hope it helps.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.