user2626652
user2626652

Reputation: 23

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);
}
}

Upvotes: 1

Views: 815

Answers (2)

SteveKB
SteveKB

Reputation: 190

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

Upvotes: 1

Ernest Friedman-Hill
Ernest Friedman-Hill

Reputation: 81694

Without giving you all the code, the general algorithm for this sort of thing is

  1. Represent each polygon (best if it's a triangle, but can be a quad) as an object of some kind, which includes coordinate indices and color
  2. Store the all the polygons in an array
  3. Sort the array according to their z-ordering (i.e., distance from the camera plane) in back-to-front order. Typically you use either the centroid of each polygon (in transformed 3-dimensional coordinates) or merely by the location of the nearest z-value vertex.
  4. Write a simple loop that draws each polygon from the array, in order.

This is called the "painter's algorithm" and it works pretty well for solids built of nearly-equilateral triangles. As soon as you get into highly acute triangles (long pointy ones) it becomes impossible to do a meaningful z-order sort, and you get visual artifacts because the overlapping is wrong. But for a cube, if you represent each quad by two 45-45-90 triangles, it works quite well.

Upvotes: 1

Related Questions