JavaFX: How to Give Shapes Perspective

By Doug Lowe

The PerspectiveTransform class lets you distort a shape so that it appears to have a three-dimensional effect.

This is not the same thing as creating actual three-dimensional shapes in your scene graph; it simply distorts the geometry of a node to create a perspective effect.

The PerspectiveTransform class works by mapping the corners of the original shape’s bounding rectangle to an arbitrary quadrilateral. (The bounding rectangle is a rectangle that fully contains a shape, and a quadrilateral is any four-cornered shape.) All you have to supply is the x- and y-coordinates of each corner of the quadrilateral, using the methods listed in this table.

The PerspectiveTransform Class
Constructor Explanation
PerspectiveTransform() Creates a new PerspectiveTransform effect with default
parameters.
Methods Explanation
void setUlx(double value) Sets the upper-left corner x-coordinate.
void setUly(double value) Sets the upper-left corner y-coordinate.
void setUrx(double value) Sets the upper-right corner x-coordinate.
void setUry(double value) Sets the upper-right corner y-coordinate.
void setLlx(double value) Sets the lower-left corner x-coordinate.
void setLly(double value) Sets the lower-left corner y-coordinate.
void setLrx(double value) Sets the lower-right corner x-coordinate.
void setLry(double value) Sets the lower-right corner y-coordinate.

To illustrate how the perspective transform works, here it is applied to a chessboard created with the following bit of code:

Group board = new Group();
boolean isLight = true;
int size = 50;
for (int rank = 0; rank < 8; rank++)
{
    for (int file = 0; file < 8; file++)
    {
        Rectangle r = new Rectangle(size, size);
        r.setX(file * size);
        r.setY(rank * size);
        if (isLight)
            r.setFill(Color.LIGHTGRAY);
        else
            r.setFill(Color.DARKGRAY);
        isLight = !isLight;
        board.getChildren().add(r);
    }
    isLight = !isLight;
}

This code uses a set of nested for loops to draw the ranks (rows) and files (columns) of the chessboard using 50×50 rectangles of alternating color. The isLight Boolean variable is used to keep track of the color of each square; this value is inverted after each rectangle is drawn.

The isLight value is inverted after each file is drawn so that the subsequent file starts with the opposite color. The figure shows how the chessboard appears when displayed in a scene.

image0.jpg

The entire chessboard occupies a 400×400 square. To add perspective, PerspectiveTransform effect was created that maps the 400×400 square chessboard to a quadrilateral with the following corner coordinates:

Corner Original x, y New x, y
Upper Left 0, 0 100, 100
Upper Right 400, 0 450, 100
Lower Left 0, 400 0, 300
Lower Right 400, 400 400, 300

The code to accomplish this transformation looks like this:

PerspectiveTransform e = new PerspectiveTransform();
e.setUlx(100);    // Upper left
e.setUly(100);
e.setUrx(450);    // Upper right
e.setUry(100);
e.setLlx(0);      // Lower left
e.setLly(300);
e.setLrx(400);    // Lower right
e.setLry(300);
board.setEffect(e);

This figure shows how the chessboard looks when this perspective transform is applied.

image1.jpg