Candidate fix for Windows 10 HiDPI - to be tested on macOS/Linux

This commit is contained in:
Martin Pernollet 2022-02-15 13:13:27 +01:00
parent ef99b379fd
commit 49ac8a5f3a
13 changed files with 501 additions and 16 deletions

View File

@ -0,0 +1,41 @@
package org.jzy3d.awt;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.Component;
import org.jzy3d.maths.Coord2d;
public class AWTHelper {
public static Coord2d getPixelScale(Component component) {
return getPixelScale((Graphics2D)component.getGraphics());
}
public static Coord2d getPixelScale(Graphics2D g2d) {
AffineTransform globalTransform = g2d.getTransform();
return new Coord2d(globalTransform.getScaleX(), globalTransform.getScaleY());
}
public static double getPixelScaleX(Component component) {
return getPixelScaleX((Graphics2D)component.getGraphics());
}
public static double getPixelScaleX(Graphics2D g2d) {
if(g2d==null)
return 1;
AffineTransform globalTransform = g2d.getTransform();
return globalTransform.getScaleX();
}
public static double getPixelScaleY(Component component) {
return getPixelScaleY((Graphics2D)component.getGraphics());
}
public static double getPixelScaleY(Graphics2D g2d) {
if(g2d==null)
return 1;
AffineTransform globalTransform = g2d.getTransform();
return globalTransform.getScaleY();
}
}

View File

@ -105,6 +105,12 @@ public interface ICanvas {
*/
public Coord2d getPixelScale();
/**
* Provide pixel scale as considered feasible by the JVM.
*/
public Coord2d getPixelScaleJVM();
public double getLastRenderingTimeMs();
public static final double LAST_RENDER_TIME_UNDEFINED = -1;

View File

@ -1,9 +1,11 @@
package org.jzy3d.plot3d.rendering.view;
import org.jzy3d.maths.Coord2d;
import org.jzy3d.maths.Rectangle;
import org.jzy3d.painters.IPainter;
import org.jzy3d.plot3d.rendering.canvas.ICanvas;
import org.jzy3d.plot3d.rendering.canvas.IScreenCanvas;
/**
* An {@link AbstractViewportManager} describes an element that occupies the whole rendering
@ -82,12 +84,24 @@ public abstract class AbstractViewportManager {
* </ul>
*/
public ViewportConfiguration applyViewport(IPainter painter) {
// We here scale the viewport by either 1 or by the ratio indicated by the JVM
// if only the JVM is able to detect the pixel ratio and if JOGL
// can't guess it (which is the case for Windows 10).
Coord2d scaleHardware = painter.getCanvas().getPixelScale();
Coord2d scaleJVM = painter.getCanvas().getPixelScaleJVM();
Coord2d scale = scaleJVM.div(scaleHardware);
screenWidth = (int)(screenWidth*scale.x);
screenHeight = (int)(screenHeight*scale.y);
// Stretch projection on the whole viewport
if (ViewportMode.STRETCH_TO_FILL.equals(mode)
|| ViewportMode.RECTANGLE_NO_STRETCH.equals(mode)) {
screenXOffset = screenLeft;
screenYOffset = 0;
painter.glViewport(screenXOffset, screenYOffset, screenWidth, screenHeight);
lastViewPort =
@ -100,7 +114,7 @@ public abstract class AbstractViewportManager {
screenSquaredDim = Math.min(screenWidth, screenHeight);
screenXOffset = screenLeft + screenWidth / 2 - screenSquaredDim / 2;
screenYOffset = screenBottom + screenHeight / 2 - screenSquaredDim / 2;
painter.glViewport(screenXOffset, screenYOffset, screenSquaredDim, screenSquaredDim);
lastViewPort = new ViewportConfiguration(screenSquaredDim, screenSquaredDim, screenXOffset, screenYOffset);

View File

@ -19,6 +19,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
import javax.imageio.ImageIO;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jzy3d.awt.AWTHelper;
import org.jzy3d.chart.IAnimator;
import org.jzy3d.chart.factories.IChartFactory;
import org.jzy3d.colors.AWTColor;
@ -499,10 +500,14 @@ public class EmulGLCanvas extends GLCanvas implements IScreenCanvas, IMonitorabl
@Override
public Coord2d getPixelScale() {
Graphics2D g2d = (Graphics2D) getGraphics();
AffineTransform globalTransform = g2d.getTransform();
return new Coord2d(globalTransform.getScaleX(), globalTransform.getScaleY());
return new Coord2d(AWTHelper.getPixelScaleX(this), AWTHelper.getPixelScaleY(this));
}
@Override
public Coord2d getPixelScaleJVM() {
return new Coord2d(AWTHelper.getPixelScaleX(this), AWTHelper.getPixelScaleY(this));
}
@Override
public IAnimator getAnimation() {

View File

@ -3,3 +3,4 @@
/.settings/
/target/
/test-output/
/bin/

View File

@ -9,6 +9,8 @@ import java.util.List;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.jzy3d.awt.AWTHelper;
import org.jzy3d.chart.IAnimator;
import org.jzy3d.chart.factories.IChartFactory;
import org.jzy3d.chart.factories.NativePainterFactory;
@ -76,6 +78,8 @@ public class CanvasAWT extends GLCanvas implements IScreenCanvas, INativeCanvas
if (quality.isPreserveViewportSize())
setPixelScale(newPixelScaleIdentity());
else
setPixelScale(getPixelScale());
}
protected void watchPixelScale() {
@ -121,6 +125,10 @@ public class CanvasAWT extends GLCanvas implements IScreenCanvas, INativeCanvas
setSurfaceScale(new float[] {1f, 1f});
}
public void setPixelScale(Coord2d scale) {
setPixelScale(scale.toArray());
}
/**
* Pixel scale is used to model the pixel ratio thay may be introduced by HiDPI or Retina
* displays.
@ -129,14 +137,24 @@ public class CanvasAWT extends GLCanvas implements IScreenCanvas, INativeCanvas
public Coord2d getPixelScale() {
return new Coord2d(getPixelScaleX(), getPixelScaleY());
}
@Override
public Coord2d getPixelScaleJVM() {
return new Coord2d(AWTHelper.getPixelScaleX(this), AWTHelper.getPixelScaleY(this));
}
public double getPixelScaleX() {
return getSurfaceWidth() / (double) getWidth();
double scale = getSurfaceWidth() / (double) getWidth();
return scale;
//double scale2 = AWTHelper.getPixelScaleX(this);
//return Math.max(scale, scale2);
}
public double getPixelScaleY() {
return getSurfaceHeight() / (double) getHeight();
double scale = getSurfaceHeight() / (double) getHeight();
return scale;
//double scale2 = AWTHelper.getPixelScaleY(this);
//return Math.max(scale, scale2);
}

View File

@ -0,0 +1,345 @@
package issues.jzy3d;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.AffineTransform;
import javax.swing.*;
import com.jogamp.newt.awt.NewtCanvasAWT;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.*;
import com.jogamp.opengl.awt.*;
/**
* A 2D OpenGL animation that demonstrates the use of glPushMatrix and
* glPopMatrix to implement hierarchical modeling. This program is almost a port
* of HierarchicalModeling2D.java, which did more or less the same thing using
* Java Graphics2D.
*/
public class CartAndWindmillJogl2D extends JPanel implements GLEventListener {
public static void main(String[] args) {
JFrame window = new JFrame("Hierarchical Modeling in 2D With Jogl");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setContentPane(new CartAndWindmillJogl2D());
window.pack();
window.setVisible(true);
}
private NewtCanvasAWT drawable; // The OpenGL display panel.
private int frameNumber; // Current frame number, increases by 1 in each frame.
/**
* Constructor creates the GLJPanel that will be used for drawing and adds it to
* the main panel. It also starts a timer to draw the animation. And it sets the
* preferred size to be 700-by-500.
*/
public CartAndWindmillJogl2D() {
GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL2));
// create a NEWT window
GLWindow glWindow = GLWindow.create(caps);
glWindow.setUndecorated(true);
// window.addGLEventListener(this);
drawable = new Canvas(glWindow);
drawable.setPreferredSize(new Dimension(700, 500));
glWindow.addGLEventListener(this);
this.setLayout(new BorderLayout());
/**
* //The following code verifies that layout is not honoring pixel Scale
setLayout(null);
this.setPreferredSize(new Dimension(700, 500));
drawable.setBounds(0, 0, 2*700, 2*500);
*/
add(drawable);
Timer timer = new Timer(30, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
frameNumber++;
drawable.repaint();
}
});
timer.setInitialDelay(1000);
timer.start();
}
/**
* This method is called when the GLJPanel is created. It initializes the GL
* context. Here, it sets the clear color to be sky blue and it sets the
* xy-limits for drawing so that x ranges from 0 to 7 and y ranges from -1 to 4.
*/
public void init(GLAutoDrawable drawable) {
GL2 gl2 = drawable.getGL().getGL2();
gl2.glClearColor(0.5f, 0.5f, 1, 1);
// The next three lines set up the coordinates system.
gl2.glMatrixMode(GL2.GL_PROJECTION);
gl2.glLoadIdentity();
gl2.glOrtho(0, 7, -1, 4, -1, 1);
gl2.glMatrixMode(GL2.GL_MODELVIEW);
}
/**
* This method is called when the GLJPanel needs to be redrawn. It draws the
* current frame of the animation.
*/
public void display(GLAutoDrawable drawable) {
GL2 gl2 = drawable.getGL().getGL2();
gl2.glClear(GL2.GL_COLOR_BUFFER_BIT); // Fills the scene with blue.
gl2.glLoadIdentity();
/* Draw three green triangles to form a ridge of hills in the background */
gl2.glColor3f(0, 0.6f, 0.2f);
gl2.glBegin(GL2.GL_POLYGON);
gl2.glVertex2f(-3, -1);
gl2.glVertex2f(1.5f, 1.65f);
gl2.glVertex2f(5, -1);
gl2.glEnd();
gl2.glBegin(GL2.GL_POLYGON);
gl2.glVertex2f(-3, -1);
gl2.glVertex2f(3, 2.1f);
gl2.glVertex2f(7, -1);
gl2.glEnd();
gl2.glBegin(GL2.GL_POLYGON);
gl2.glVertex2f(0, -1);
gl2.glVertex2f(6, 1.2f);
gl2.glVertex2f(20, -1);
gl2.glEnd();
/* Draw a bluish-gray rectangle to represent the road. */
gl2.glColor3f(0.4f, 0.4f, 0.5f);
gl2.glBegin(GL2.GL_POLYGON);
gl2.glVertex2f(0, -0.4f);
gl2.glVertex2f(7, -0.4f);
gl2.glVertex2f(7, 0.4f);
gl2.glVertex2f(0, 0.4f);
gl2.glEnd();
/*
* Draw a white line to represent the stripe down the middle of the road.
*/
gl2.glLineWidth(6); // Set the line width to be 6 pixels.
gl2.glColor3f(1, 1, 1);
gl2.glBegin(GL2.GL_LINES);
gl2.glVertex2f(0, 0);
gl2.glVertex2f(7, 0);
gl2.glEnd();
gl2.glLineWidth(1); // Reset the line width to be 1 pixel.
/*
* Draw the sun. The drawSun method draws the sun centered at (0,0). A 2D
* translation is applied to move the center of the sun to (5,3.3). A rotation
* makes it rotate
*/
gl2.glPushMatrix();
gl2.glTranslated(5.8, 3, 0);
gl2.glRotated(-frameNumber * 0.7, 0, 0, 1);
drawSun(gl2);
gl2.glPopMatrix();
/*
* Draw three windmills. The drawWindmill method draws the windmill with its
* base at (0,0), and the top of the pole at (0,3). Each windmill is first
* scaled to change its size and then translated to move its base to a different
* paint. In the animation, the vanes of the windmill rotate. That rotation is
* done with a transform inside the drawWindmill method.
*/
gl2.glPushMatrix();
gl2.glTranslated(0.75, 1, 0);
gl2.glScaled(0.6, 0.6, 1);
drawWindmill(gl2);
gl2.glPopMatrix();
gl2.glPushMatrix();
gl2.glTranslated(2.2, 1.6, 0);
gl2.glScaled(0.4, 0.4, 1);
drawWindmill(gl2);
gl2.glPopMatrix();
gl2.glPushMatrix();
gl2.glTranslated(3.7, 0.8, 0);
gl2.glScaled(0.7, 0.7, 1);
drawWindmill(gl2);
gl2.glPopMatrix();
/*
* Draw the cart. The drawCart method draws the cart with the center of its base
* at (0,0). The body of the cart is 5 units long and 2 units high. A scale is
* first applied to the cart to make its size more reasonable for the picture.
* Then a translation is applied to move the cart horizontally. The amount of
* the translation depends on the frame number, which makes the cart move from
* left to right across the screen as the animation progresses. The cart
* animation repeats every 300 frames. At the beginning of the animation, the
* cart is off the left edge of the screen.
*/
gl2.glPushMatrix();
gl2.glTranslated(-3 + 13 * (frameNumber % 300) / 300.0, 0, 0);
gl2.glScaled(0.3, 0.3, 1);
drawCart(gl2);
gl2.glPopMatrix();
}
/**
* Draw a sun with radius 0.5 centered at (0,0). There are also 13 rays which
* extend outside from the sun for another 0.25 units.
*/
private void drawSun(GL2 gl2) {
gl2.glColor3f(1, 1, 0);
for (int i = 0; i < 13; i++) { // Draw 13 rays, with different rotations.
gl2.glRotatef(360f / 13, 0, 0, 1); // Note that the rotations accumulate!
gl2.glBegin(GL2.GL_LINES);
gl2.glVertex2f(0, 0);
gl2.glVertex2f(0.75f, 0);
gl2.glEnd();
}
drawDisk(gl2, 0.5);
gl2.glColor3f(0, 0, 0);
}
/**
* Draw a 32-sided regular polygon as an approximation for a circular disk.
* (This is necessary since OpenGL has no commands for drawing ovals, circles,
* or curves.) The disk is centered at (0,0) with a radius given by the
* parameter.
*/
private void drawDisk(GL2 gl2, double radius) {
gl2.glBegin(GL2.GL_POLYGON);
for (int d = 0; d < 32; d++) {
double angle = 2 * Math.PI / 32 * d;
gl2.glVertex2d(radius * Math.cos(angle), radius * Math.sin(angle));
}
gl2.glEnd();
}
/**
* Draw a windmill, consisting of a pole and three vanes. The pole extends from
* the point (0,0) to (0,3). The vanes radiate out from (0,3). A rotation that
* depends on the frame number is applied to the whole set of vanes, which
* causes the windmill to rotate as the animation proceeds. Note that this
* method changes the current transform in the GL context gl! The caller of this
* subroutine should take care to save and restore the original transform, if
* necessary.
*/
private void drawWindmill(GL2 gl2) {
gl2.glColor3f(0.8f, 0.8f, 0.9f);
gl2.glBegin(GL2.GL_POLYGON);
gl2.glVertex2f(-0.05f, 0);
gl2.glVertex2f(0.05f, 0);
gl2.glVertex2f(0.05f, 3);
gl2.glVertex2f(-0.05f, 3);
gl2.glEnd();
gl2.glTranslatef(0, 3, 0);
gl2.glRotated(frameNumber * (180.0 / 46), 0, 0, 1);
gl2.glColor3f(0.4f, 0.4f, 0.8f);
for (int i = 0; i < 3; i++) {
gl2.glRotated(120, 0, 0, 1); // Note: These rotations accumulate.
gl2.glBegin(GL2.GL_POLYGON);
gl2.glVertex2f(0, 0);
gl2.glVertex2f(0.5f, 0.1f);
gl2.glVertex2f(1.5f, 0);
gl2.glVertex2f(0.5f, -0.1f);
gl2.glEnd();
}
}
/**
* Draw a cart consisting of a rectangular body and two wheels. The wheels are
* drawn by the drawWheel() method; a different translation is applied to each
* wheel to move them into position under the body. The body of the cart is a
* red rectangle with corner at (0,-2.5), width 5, and height 2. The center of
* the bottom of the rectangle is at (0,0).
*/
private void drawCart(GL2 gl2) {
gl2.glPushMatrix();
gl2.glTranslatef(-1.5f, -0.1f, 0);
gl2.glScalef(0.8f, 0.8f, 1);
drawWheel(gl2);
gl2.glPopMatrix();
gl2.glPushMatrix();
gl2.glTranslatef(1.5f, -0.1f, 0);
gl2.glScalef(0.8f, 0.8f, 1);
drawWheel(gl2);
gl2.glPopMatrix();
gl2.glColor3f(1, 0, 0);
gl2.glBegin(GL2.GL_POLYGON);
gl2.glVertex2f(-2.5f, 0);
gl2.glVertex2f(2.5f, 0);
gl2.glVertex2f(2.5f, 2);
gl2.glVertex2f(-2.5f, 2);
gl2.glEnd();
}
/**
* Draw a wheel, centered at (0,0) and with radius 1. The wheel has 15 spokes
* that rotate in a clockwise direction as the animation proceeds.
*/
private void drawWheel(GL2 gl2) {
gl2.glColor3f(0, 0, 0);
drawDisk(gl2, 1);
gl2.glColor3f(0.75f, 0.75f, 0.75f);
drawDisk(gl2, 0.8);
gl2.glColor3f(0, 0, 0);
drawDisk(gl2, 0.2);
gl2.glRotatef(frameNumber * 20, 0, 0, 1);
gl2.glBegin(GL2.GL_LINES);
for (int i = 0; i < 15; i++) {
gl2.glVertex2f(0, 0);
gl2.glVertex2d(Math.cos(i * 2 * Math.PI / 15), Math.sin(i * 2 * Math.PI / 15));
}
gl2.glEnd();
}
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
GL2 gl2 = drawable.getGL().getGL2();
gl2.glViewport(0,0,drawable.getSurfaceWidth(),drawable.getSurfaceHeight());
}
public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {
}
public void dispose(GLAutoDrawable arg0) {
}
public class Canvas extends NewtCanvasAWT {
public Canvas(GLWindow glWindow) {
super(glWindow);
}
@Override
public Dimension getPreferredSize() {
Dimension d=super.getPreferredSize();
return new Dimension(d.width,d.height);
}
@Override
public int getWidth() {
double scale = getPixelScaleX();
return (int)(super.getWidth() * scale);
}
@Override
public int getHeight() {
double scale = getPixelScaleY();
return (int)(super.getHeight() * scale);
}
protected double getPixelScaleX() {
Graphics2D g2d = (Graphics2D)getGraphics();
AffineTransform globalTransform = g2d.getTransform();
return globalTransform.getScaleX();
}
protected double getPixelScaleY() {
Graphics2D g2d = (Graphics2D)getGraphics();
AffineTransform globalTransform = g2d.getTransform();
return globalTransform.getScaleY();
}
}
}

View File

@ -1,31 +1,63 @@
package issues.jzy3d;
import org.jzy3d.analysis.AWTAbstractAnalysis;
import org.jzy3d.analysis.AnalysisLauncher;
import org.jzy3d.bridge.awt.FrameAWT;
import org.jzy3d.chart.factories.AWTChartFactory;
import org.jzy3d.chart.factories.AWTPainterFactory;
import org.jzy3d.chart.factories.IChartFactory;
import org.jzy3d.chart.factories.IPainterFactory;
import org.jzy3d.chart.factories.IFrame;
import org.jzy3d.colors.Color;
import org.jzy3d.colors.ColorMapper;
import org.jzy3d.colors.colormaps.ColorMapRainbow;
import org.jzy3d.maths.Array;
import org.jzy3d.maths.Range;
import org.jzy3d.plot3d.builder.Func3D;
import org.jzy3d.plot3d.builder.SurfaceBuilder;
import org.jzy3d.plot3d.builder.concrete.OrthonormalGrid;
import org.jzy3d.plot3d.primitives.Shape;
import org.jzy3d.plot3d.rendering.canvas.CanvasAWT;
import org.jzy3d.plot3d.rendering.canvas.Quality;
import com.jogamp.opengl.GLCapabilities;
import com.jogamp.opengl.GLProfile;
import com.jogamp.opengl.awt.GLCanvas;
import java.awt.Rectangle;
/**
* This reproduce the HiDPI issue on Windows.
*
* This should be ran with a JDK > 8.
*
* https://github.com/jzy3d/jzy3d-api/issues/101
*/
public class Issue101_Windows10_HiDPI extends AWTAbstractAnalysis {
public static void main(String[] args) throws Exception {
Issue101_Windows10_HiDPI d = new Issue101_Windows10_HiDPI();
AnalysisLauncher.open(d);
d.init();
IFrame frame = d.getChart().open(600, 600);
d.getChart().addMouse();
//AnalysisLauncher.open(d);
FrameAWT f = ((FrameAWT)frame);
CanvasAWT canvas = (CanvasAWT)d.getChart().getCanvas();
float[] result = new float[2];
canvas.getCurrentSurfaceScale(result);
Array.print(result);
float[] test = {2.0f, 2.0f};
canvas.setPixelScale(test);
canvas.getCurrentSurfaceScale(result);
Array.print(result);
System.out.println(canvas.getPixelScale());
canvas.setPixelScale(canvas.getPixelScale());
Rectangle r = f.getBounds();
System.out.println(r);
}
@Override

View File

@ -124,7 +124,11 @@ public class OffscreenCanvas implements ICanvas, INativeCanvas {
.info("getPixelScale() not implemented. Will return {1,1}");
return new Coord2d(1, 1);
}
@Override
public Coord2d getPixelScaleJVM() {
return getPixelScale();
}
@Override
public GLOffscreenAutoDrawable getDrawable() {

View File

@ -11,6 +11,7 @@ import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jzy3d.awt.AWTHelper;
import org.jzy3d.chart.IAnimator;
import org.jzy3d.chart.NativeAnimator;
import org.jzy3d.chart.factories.IChartFactory;
@ -153,6 +154,12 @@ public class CanvasNewtAwt extends Panel implements IScreenCanvas, INativeCanvas
public double getPixelScaleY() {
return window.getSurfaceHeight() / (double) getHeight();
}
@Override
public Coord2d getPixelScaleJVM() {
return new Coord2d(AWTHelper.getPixelScaleX(this), AWTHelper.getPixelScaleY(this));
}
public GLWindow getWindow() {
return window;

View File

@ -11,6 +11,7 @@ import java.util.List;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.jzy3d.awt.AWTHelper;
import org.jzy3d.chart.IAnimator;
import org.jzy3d.chart.factories.IChartFactory;
import org.jzy3d.chart.factories.NativePainterFactory;
@ -124,6 +125,10 @@ public class CanvasSwing extends GLJPanel implements IScreenCanvas, INativeCanva
return new Coord2d(getPixelScaleX(), getPixelScaleY());
}
@Override
public Coord2d getPixelScaleJVM() {
return new Coord2d(AWTHelper.getPixelScaleX(this), AWTHelper.getPixelScaleY(this));
}
public double getPixelScaleX() {
return getSurfaceWidth() / (double) getWidth();

View File

@ -10,6 +10,7 @@ import java.util.concurrent.TimeUnit;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.jzy3d.awt.AWTHelper;
import org.jzy3d.chart.IAnimator;
import org.jzy3d.maths.Coord2d;
import org.jzy3d.painters.NativeDesktopPainter;
@ -149,6 +150,11 @@ public class CanvasNewtSWT extends Composite implements IScreenCanvas, INativeCa
return new Coord2d(getPixelScaleX(), getPixelScaleY());
}
@Override
public Coord2d getPixelScaleJVM() {
return getPixelScale();
}
public double getPixelScaleX() {
return window.getSurfaceWidth() / (double) getSize().x;

View File

@ -8,3 +8,4 @@ data/lizard.mat
.classpath
.project
.settings
/bin/