Skip to content

Java 2D

Kai Burjack edited this page Apr 27, 2017 · 6 revisions

Java 2D holds the transformation applied to drawn primitives in an instance of the AffineTransform class, which can be manipulated directly or operated on via methods on the Graphics2D class, such as rotate() or translate(). Instead of the AffineTransformation, JOML's matrix classes can be used to build the transformations. When a matrix has been built in JOML, its represented transformation can be copied to an AffineTransform instance like so:

Matrix4f m = ...; // <- any affine 2D transformation built with JOML
AffineTransform t = ...; // <- any Java 2D AffineTransform (e.g. Graphics2D.getTransform())
t.setTransform(m.m00(), m.m01(), m.m10(), m.m11(), m.m30(), m.m31());

The above will copy any affine 2D transformation, represented by the Matrix4f, to the provided AffineTransform instance.

Since Java 2D cannot represent 3D transformations, using a Matrix4f in JOML is not necessary. For 2D transformations JOML provides the Matrix3x2f and Matrix3x2d classes. If those are used, copying the 2D transformation into a Java 2D AffineTransform instance works like this:

Matrix3x2f m = ...; // <- any 2D transformation built with JOML
AffineTransform t = ...; // <- any Java 2D AffineTransform
t.setTransform(m.m00, m.m01, m.m10, m.m11, m.m20, m.m21);

(Note: The AffineTransform class uses a different order for the row and column indices of a matrix element. Here, the row index comes first, and then the column index)

Example

The following example emulates OpenGL's Clip Space, or in 2D equally the Normalized Device Coordinate space, by creating a JOML Matrix3x2f instance which transforms input coordinates within [-1..+1] into Java 2D's default window coordinates/pixel space.

import java.awt.BasicStroke;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.geom.Line2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import org.joml.Matrix3x2f;

public class Java2dExample extends JFrame {
  private static final AffineTransform T = new AffineTransform();

  private static void loadMatrix(Matrix3x2f m, Graphics2D g) {
    T.setTransform(m.m00, m.m01, m.m10, m.m11, m.m20, m.m21);
    g.setTransform(T);
  }

  public Java2dExample() {
    getContentPane().add(new JPanel() {
      {
        setPreferredSize(new Dimension(500, 500));
      }

      public void paint(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        Rectangle b = this.getBounds();
        Matrix3x2f m = new Matrix3x2f()
            .scale(b.width, -b.height) // [0..+1, -1..0] -> [0..w, h..0]
            .scale(0.5f) // [0..+2, -2..0] -> [0..+1, -1..0]
            .translate(1, -1); // [-1..+1] -> [0..+2, -2..0]
        loadMatrix(m, g2); // load matrix in 'g2'
        Line2D line = new Line2D.Float(-1, -1, +1, +1);
        g2.setStroke(new BasicStroke(0.02f)); // width in world units
        g2.draw(line);
      }
    });
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    pack();
    setVisible(true);
  }

  public static void main(String arg[]) {
    new Java2dExample();
  }
}
Clone this wiki locally