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



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • UPDATE: this seems to be an Arch-specific issue. Switching to Ubuntu server fixed EVERYTHING.
    • Yes, Attapoll offers a $20 Sign-up bonus for new users using a code (AOVCQ). Enter the Attapoll Referral Code “AOVCQ” and submit. Yes, Attapoll offers $20 Referral Code {AOVCQ} For New Customers. If you are who wish to join Attapoll, then you should use this exclusive Attapoll referral code $20 Signup Bonus Use this Code (AOVCQ) and get $20 Welcome Bonus. You can get a $20 Signup bonus use this referral code {AOVCQ}. You can get a $20 Attpoll Referral Code {AOVCQ}. This Attapoll $20 Referral code is specifically for existing customers and can be redeemed to receive a $20. Enter $20 Attapoll Referral Code {AOVCQ} at checkout. Enjoy $20Welcome Bonus. Use the best Attapoll referral code $20 (AOVCQ) to get up to $20 first time survey as a new user. Complete the survey and get $20 credited on your Attapoll account. Plus, refer your friend to earn 10% commission on their earning If you're on the hunt for a little extra cash or some cool rewards without too much hassle, you've landed in the right place. Today, we're diving into the world of Attapoll referral codes, a nifty way to boost your earnings while taking surveys. Use this Attapoll Referral Link or code {{AOVCQ}} to get a $20 sign up bonus.
    • Yes, Attapoll offers a $20 Sign-up bonus for new users using a code (AOVCQ). Enter the Attapoll Referral Code “AOVCQ” and submit. Yes, Attapoll offers $20 Referral Code {AOVCQ} For New Customers. If you are who wish to join Attapoll, then you should use this exclusive Attapoll referral code $20 Signup Bonus Use this Code (AOVCQ) and get $20 Welcome Bonus. You can get a $20 Signup bonus use this referral code {AOVCQ}. You can get a $20 Attpoll Referral Code {AOVCQ}. This Attapoll $20 Referral code is specifically for existing customers and can be redeemed to receive a $20. Enter $20 Attapoll Referral Code {AOVCQ} at checkout. Enjoy $20Welcome Bonus. Use the best Attapoll referral code $20 (AOVCQ) to get up to $20 first time survey as a new user. Complete the survey and get $20 credited on your Attapoll account. Plus, refer your friend to earn 10% commission on their earning If you're on the hunt for a little extra cash or some cool rewards without too much hassle, you've landed in the right place. Today, we're diving into the world of Attapoll referral codes, a nifty way to boost your earnings while taking surveys. Use this Attapoll Referral Link or code {{AOVCQ}} to get a $20 sign up bonus.
    • Yes, Attapoll offers a $20 Sign-up bonus for new users using a code (AOVCQ). Enter the Attapoll Referral Code “AOVCQ” and submit. Yes, Attapoll offers $20 Referral Code {AOVCQ} For New Customers. If you are who wish to join Attapoll, then you should use this exclusive Attapoll referral code $20 Signup Bonus Use this Code (AOVCQ) and get $20 Welcome Bonus. You can get a $20 Signup bonus use this referral code {AOVCQ}. You can get a $20 Attpoll Referral Code {AOVCQ}. This Attapoll $20 Referral code is specifically for existing customers and can be redeemed to receive a $20. Enter $20 Attapoll Referral Code {AOVCQ} at checkout. Enjoy $20Welcome Bonus. Use the best Attapoll referral code $20 (AOVCQ) to get up to $20 first time survey as a new user. Complete the survey and get $20 credited on your Attapoll account. Plus, refer your friend to earn 10% commission on their earning If you're on the hunt for a little extra cash or some cool rewards without too much hassle, you've landed in the right place. Today, we're diving into the world of Attapoll referral codes, a nifty way to boost your earnings while taking surveys. Use this Attapoll Referral Link or code {{AOVCQ}} to get a $20 sign up bonus.
    • Yes, Attapoll offers a $20 Sign-up bonus for new users using a code (AOVCQ). Enter the Attapoll Referral Code “AOVCQ” and submit. Yes, Attapoll offers $20 Referral Code {AOVCQ} For New Customers. If you are who wish to join Attapoll, then you should use this exclusive Attapoll referral code $20 Signup Bonus Use this Code (AOVCQ) and get $20 Welcome Bonus. You can get a $20 Signup bonus use this referral code {AOVCQ}. You can get a $20 Attpoll Referral Code {AOVCQ}. This Attapoll $20 Referral code is specifically for existing customers and can be redeemed to receive a $20. Enter $20 Attapoll Referral Code {AOVCQ} at checkout. Enjoy $20Welcome Bonus. Use the best Attapoll referral code $20 (AOVCQ) to get up to $20 first time survey as a new user. Complete the survey and get $20 credited on your Attapoll account. Plus, refer your friend to earn 10% commission on their earning If you're on the hunt for a little extra cash or some cool rewards without too much hassle, you've landed in the right place. Today, we're diving into the world of Attapoll referral codes, a nifty way to boost your earnings while taking surveys. Use this Attapoll Referral Link or code {{AOVCQ}} to get a $20 sign up bonus.
  • Topics

×
×
  • Create New...

Important Information

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