package work;
import java.awt.AWTException;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.media.opengl.GL4;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.awt.GLCanvas;
public class Modelview implements KeyListener, MouseMotionListener, GLEventListener {
private static final int forward = KeyEvent.VK_W;
private static final int backward = KeyEvent.VK_S;
private static final int leftward = KeyEvent.VK_A;
private static final int rightward = KeyEvent.VK_D;
private static final int mouseSpeed = 2;
private static final int keySpeed = 1;
private static final int rotVMax = 1;
private static final int rotVMin = -1;
private final Map<Integer, Boolean> keys = new ConcurrentHashMap<Integer, Boolean>();
private final float[] mv = new float[16];
private final float[] nm = new float[9];
private final GLCanvas canvas;
private final Robot robot;
private float rotX, rotY, rotZ, rotV;
private float posX, posY, posZ;
private int centerX, centerY;
private long lastTime = -1;
private GL4 gl = null;
public Modelview(final GLCanvas canvas) {
Robot robot = null;
try {
robot = new Robot();
} catch (final AWTException e) {
e.printStackTrace();
}
if (robot != null) {
final BufferedImage cursorImg = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB);
final Graphics2D gfx = cursorImg.createGraphics();
gfx.setColor(new Color(0, 0, 0, 0));
gfx.fillRect(0, 0, 16, 16);
gfx.dispose();
canvas.setCursor(canvas.getToolkit().createCustomCursor(cursorImg, new Point(), ""));
}
for (int i = 0; i < 4; i++)
mv[i * 5] = 1.0f;
for (int i = 0; i < 3; i++)
nm[i * 4] = 1.0f;
this.canvas = canvas;
this.robot = robot;
this.posZ = -10;
this.posX = 0;
canvas.addKeyListener(this);
canvas.addMouseMotionListener(this);
canvas.addGLEventListener(this);
}
public void bind() {
calculatePosition();
calculateModelview();
final int hmv = gl.glGetUniformLocation(Shader.getCurrentShaderID(), "mv");
final int hnm = gl.glGetUniformLocation(Shader.getCurrentShaderID(), "nm");
gl.glUniformMatrix4fv(hmv, 1, false, mv, 0);
gl.glUniformMatrix3fv(hnm, 1, false, nm, 0);
// oder eben gl.glLoadMatrix...
}
private void calculatePosition() {
if (lastTime == -1)
lastTime = System.nanoTime();
final double step = keySpeed * -((lastTime - (lastTime = System.nanoTime())) / 10E7);
Boolean value = null;
if ((value = keys.get(forward)) != null && value == true) {
posX -= Math.sin(rotY) * step;
posZ += Math.cos(rotY) * step;
}
if ((value = keys.get(backward)) != null && value == true) {
posX += Math.sin(rotY) * step;
posZ -= Math.cos(rotY) * step;
}
if ((value = keys.get(leftward)) != null && value == true) {
posX += Math.cos(rotY) * step;
posZ += Math.sin(rotY) * step;
}
if ((value = keys.get(rightward)) != null && value == true) {
posX -= Math.cos(rotY) * step;
posZ -= Math.sin(rotY) * step;
}
}
private void calculateModelview() {
final float sinX = (float) Math.sin(rotX);
final float sinY = (float) Math.sin(rotY);
final float sinZ = (float) Math.sin(rotZ);
final float cosX = (float) Math.cos(rotX);
final float cosY = (float) Math.cos(rotY);
final float cosZ = (float) Math.cos(rotZ);
mv[0] = nm[0] = cosY * cosZ + sinY * sinX * sinZ;
mv[1] = nm[1] = cosX * sinZ;
mv[2] = nm[2] = -sinY * cosZ + cosY * sinX * sinZ;
mv[4] = nm[3] = -cosY * sinZ + sinY * sinX * cosZ;
mv[5] = nm[4] = cosX * cosZ;
mv[6] = nm[5] = sinY * sinZ + cosY * sinX * cosZ;
mv[8] = nm[6] = sinY * cosX;
mv[9] = nm[7] = -sinX;
mv[10] = nm[8] = cosY * cosX;
mv[12] = mv[0] * posX + mv[4] * posY + mv[8] * posZ;
mv[13] = mv[1] * posX + mv[5] * posY + mv[9] * posZ;
mv[14] = mv[2] * posX + mv[6] * posY + mv[10] * posZ;
}
@Override
public void init(final GLAutoDrawable drawable) {
gl = (GL4) drawable.getGL();
}
@Override
public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
rotV = 0;
final Rectangle r = canvas.getParent().getBounds();
centerX = r.x + r.width / 2;
centerY = r.y + r.height / 2;
if (robot != null)
robot.mouseMove(centerX, centerY);
}
@Override
public void mouseMoved(final MouseEvent e) {
rotY -= (centerX - e.getXOnScreen()) / 1000.0 * mouseSpeed;
rotV -= (centerY - e.getYOnScreen()) / 1000.0 * mouseSpeed;
if (rotV > rotVMax)
rotV = rotVMax;
if (rotV < rotVMin)
rotV = rotVMin;
rotX = (float) Math.cos(rotY) * rotV;
rotZ = (float) Math.sin(rotY) * rotV;
if (robot != null)
robot.mouseMove(centerX, centerY);
}
@Override
public void mouseDragged(final MouseEvent e) {
mouseMoved(e);
}
@Override
public void keyPressed(final KeyEvent e) {
keys.put(e.getKeyCode(), true);
}
@Override
public void keyReleased(final KeyEvent e) {
keys.put(e.getKeyCode(), false);
}
@Override public void keyTyped(final KeyEvent e) { }
@Override public void display(final GLAutoDrawable drawable) { }
@Override public void dispose(final GLAutoDrawable drawable) { }
}