Search code examples
javacolorsappletgraphics2dcube

Java graphics2D; switch the paint order around of shape objects I have?


I'm just messing around with polygons and stuff and decided I would try to make my own rotatable cube and I decided to achieve this by generating 6 different sides with 8 vertices on each "polygon". (just a square that can be slanted to fit the perspective of a cube - I haven't found any "quad" methods like in LWJGL or whatever) I know this may not be the best way to do it because I've encountered an issue; the paint order. I understand that there is an "order" of which things are painted as they go down the code line by line, but looking at my code is there any way do you think that I might be able to change the order to not get this effect when I render my "cube":

https://i.sstatic.net/3MdT2.png

I've coloured each side with a different colour and as you can see it's turned out pretty badly. Normally, if I were just going to render a 2D cube that couldn't move I would make the paint order so that this wouldn't happen, but because I want to rotate and move it I'd say doing that would be pretty pointless.

Here's my code, any help would be greatly appreciated, thanks! (Ignore the fact I'm using an applet to do it, I'm only testing around...)

package advanced;

import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;

public class rotatingCube extends Applet implements Runnable {

private static final long serialVersionUID = -5353063756246119245L;

    int[][] vertex = {
            { 50, 50 }, { 100, 50 }, { 100, 100 }, { 50, 100 }, 
            { 75, 75 }, { 125, 75 }, { 125, 125 }, { 75, 125 }
    };

    int[]   Xpoly1={ vertex[0][0], vertex[1][0], vertex[2][0], vertex[3][0] },
            Ypoly1={ vertex[0][1], vertex[1][1], vertex[2][1], vertex[3][1] },

            Xpoly2={ vertex[4][0], vertex[5][0], vertex[6][0], vertex[7][0] },
            Ypoly2={ vertex[4][1], vertex[5][1], vertex[6][1], vertex[7][1] },

            Xpoly3={ vertex[5][0], vertex[1][0], vertex[2][0], vertex[6][0] },
            Ypoly3={ vertex[5][1], vertex[1][1], vertex[2][1], vertex[6][1] },

            Xpoly4={ vertex[4][0], vertex[0][0], vertex[3][0], vertex[7][0] },
            Ypoly4={ vertex[4][1], vertex[0][1], vertex[3][1], vertex[7][1] },

            Xpoly5={ vertex[3][0], vertex[2][0], vertex[6][0], vertex[7][0] },
            Ypoly5={ vertex[3][1], vertex[2][1], vertex[6][1], vertex[7][1] },

            Xpoly6={ vertex[0][0], vertex[1][0], vertex[5][0], vertex[4][0] },
            Ypoly6={ vertex[0][1], vertex[1][1], vertex[5][1], vertex[4][1] };

public void start() {
    setSize(500, 500);
    new Thread(this).start();
}

public void run() {

}

public void paint(Graphics e) {
    Graphics2D g = (Graphics2D) e;

    g.setColor(Color.RED);
    g.fillPolygon(Xpoly1, Ypoly1, 4);
    g.setColor(Color.GREEN);
    g.fillPolygon(Xpoly2, Ypoly2, 4);
    g.setColor(Color.BLUE);
    g.fillPolygon(Xpoly3, Ypoly3, 4);
    g.setColor(Color.YELLOW);
    g.fillPolygon(Xpoly4, Ypoly4, 4);
    g.setColor(Color.ORANGE);
    g.fillPolygon(Xpoly5, Ypoly5, 4);
    g.setColor(Color.PINK);
    g.fillPolygon(Xpoly6, Ypoly6, 4);
}
}

Solution

  • This is how that'd be drawn for analytic reference:

    public void paint(Graphics e) {
        Graphics2D g = (Graphics2D) e;
    
        // red blue and orange are all hidden behind the other faces so you don't draw them
        // but if you did you just need to draw them first and the order doesn't matter
        // since they don't overlap
        //g.setColor(Color.RED);
        //g.fillPolygon(Xpoly1, Ypoly1, 4);
        //g.setColor(Color.BLUE);
        //g.fillPolygon(Xpoly3, Ypoly3, 4);
        //g.setColor(Color.ORANGE);
        //g.fillPolygon(Xpoly5, Ypoly5, 4);
    
        // since these three don't overlap you can draw them in any order as well.
        g.setColor(Color.PINK);
        g.fillPolygon(Xpoly6, Ypoly6, 4);
        g.setColor(Color.YELLOW);
        g.fillPolygon(Xpoly4, Ypoly4, 4);
        g.setColor(Color.GREEN);
        g.fillPolygon(Xpoly2, Ypoly2, 4);
    }
    

    anyway that's what you'd want to happen right?

    the way you are making the vertexes for the cube is not enough to figure out how to do this. you need to provide 3d coordinates.

    so like

    int[][][] vertex = {
                { 0, 0, 0 }, { 100, 0, 0 }, { 100, 100, 0 }, { 0, 100, 0 }, 
                { 100, 100, 100}, { 0, 100, 100}, { 0, 0, 100}, { 100, 0, 100 }
        };
    

    then rotate it using math you know. now if you use an isometric view you can easily find out which faces will show since the three that will be visible will have the largest z value (towards you outwards from the screen) if you can identify which three faces have that same corner then you can draw them.

    one thing you'll come across is that if there are two points (meaning it's only rotating on one axis) two points will have the highest z value. then you just draw the faces shared by those two points.

    and the last case is if 4 points share the same max z value the face that has those four points will be the only face that will need to be drawn.

    edit: forgot to make array 3 dimensional