Skip to content
Merged
32 changes: 30 additions & 2 deletions src/main/java/labs/introtoprogramming/lab5/Main.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,39 @@
package labs.introtoprogramming.lab5;

import labs.introtoprogramming.lab5.exception.NotImplementedException;
import labs.introtoprogramming.lab5.controllers.KeyAndMouseMovementController;
import labs.introtoprogramming.lab5.geometry.Vector3;
import labs.introtoprogramming.lab5.graphics.BufferedImageRaster;
import labs.introtoprogramming.lab5.graphics.Raster;
import labs.introtoprogramming.lab5.gui.SceneRendererWindow;
import labs.introtoprogramming.lab5.scene.Scene;
import labs.introtoprogramming.lab5.scene.Camera;
import labs.introtoprogramming.lab5.scene.Transform;
import labs.introtoprogramming.lab5.scenes.DemoScene;

public class Main {

private static final String APP_TILE = "ray tracing demo";
private static final int SCREEN_WIDTH = 640;
private static final int SCREEN_HEIGHT = 640;

public static void main(String[] args) {
throw new NotImplementedException();
new Main().run();
}

private void run() {
Scene demoScene = new DemoScene();
Camera camera = createCamera();
demoScene.addSceneObjects(camera);
demoScene.addController(new KeyAndMouseMovementController(camera));

SceneRendererWindow window = new SceneRendererWindow(demoScene);
window.setTitle(APP_TILE);
window.setDisplayFPS(true);
window.show();
}

private Camera createCamera() {
Raster raster = new BufferedImageRaster(SCREEN_WIDTH, SCREEN_HEIGHT);
return new Camera(raster, new Transform(Vector3.ZERO));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package labs.introtoprogramming.lab5.controllers;

import labs.introtoprogramming.lab5.gui.Input;

public abstract class Controller {

public abstract void update(int delta, Input input);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package labs.introtoprogramming.lab5.controllers;

import labs.introtoprogramming.lab5.gui.Input;
import labs.introtoprogramming.lab5.scene.SceneObject;

public class KeyAndMouseMovementController extends Controller {

private static double DEFAULT_MOVEMENT_SPEED = 0.0015;
private static double DEFAULT_MOUSE_SENSITIVITY = 0.006;
private double movementSpeed = DEFAULT_MOVEMENT_SPEED;
private double mouseSensitivity = DEFAULT_MOUSE_SENSITIVITY;

private SceneObject controllableObject;

public KeyAndMouseMovementController(SceneObject controllableObject) {
this.controllableObject = controllableObject;
}

@Override
public void update(int delta, Input input) {
controllableObject.getTransform().setPosition(controllableObject.getTransform().position().add(
input.movementVector().multiply(movementSpeed * delta)
));
controllableObject.getTransform().setRotation(controllableObject.getTransform().rotation().add(
input.mouseMovement().multiply(mouseSensitivity * delta)
));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.awt.Color;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Transparency;
import java.awt.image.BufferedImage;

public class BufferedImageRaster implements Raster {
Expand All @@ -14,9 +15,9 @@ public BufferedImageRaster(int width, int height) {
if (!GraphicsEnvironment.isHeadless()) {
image = GraphicsEnvironment.getLocalGraphicsEnvironment()
.getDefaultScreenDevice()
.getDefaultConfiguration().createCompatibleImage(width, height);
.getDefaultConfiguration().createCompatibleImage(width, height, Transparency.BITMASK);
} else {
image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
}
}

Expand Down
59 changes: 59 additions & 0 deletions src/main/java/labs/introtoprogramming/lab5/gui/Input.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package labs.introtoprogramming.lab5.gui;

import labs.introtoprogramming.lab5.geometry.Vector3;

public class Input {

private boolean forwardKeyDown = false;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assignment is redundant. Is it made for clarity?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, to make it clear that my default all keys are not down.

private boolean backwardKeyDown = false;
private boolean leftKeyDown = false;
private boolean rightKeyDown = false;
private boolean upKeyDown = false;
private boolean downKeyDown = false;

private double mouseDeltaX = 0;
private double mouseDeltaY = 0;

public Vector3 movementVector() {
return new Vector3((leftKeyDown ? -1 : 0) + (rightKeyDown ? 1 : 0),
(upKeyDown ? 1 : 0) + (downKeyDown ? -1 : 0),
(forwardKeyDown ? -1 : 0) + (backwardKeyDown ? 1 : 0));
}

public Vector3 mouseMovement() {
//noinspection SuspiciousNameCombination
return new Vector3(mouseDeltaY, mouseDeltaX, 0);
}

public void setMouseDeltaX(double mouseDeltaX) {
this.mouseDeltaX = mouseDeltaX;
}

public void setMouseDeltaY(double mouseDeltaY) {
this.mouseDeltaY = mouseDeltaY;
}

public void setForwardKeyDown(boolean forwardKeyDown) {
this.forwardKeyDown = forwardKeyDown;
}

public void setBackwardKeyDown(boolean backwardKeyDown) {
this.backwardKeyDown = backwardKeyDown;
}

public void setLeftKeyDown(boolean leftKeyDown) {
this.leftKeyDown = leftKeyDown;
}

public void setRightKeyDown(boolean rightKeyDown) {
this.rightKeyDown = rightKeyDown;
}

public void setUpKeyDown(boolean upKeyDown) {
this.upKeyDown = upKeyDown;
}

public void setDownKeyDown(boolean downKeyDown) {
this.downKeyDown = downKeyDown;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package labs.introtoprogramming.lab5.gui;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

class InputKeyListener implements KeyListener {

private Input input;

InputKeyListener(Input input) {
this.input = input;
}

@Override
public void keyTyped(KeyEvent e) {
// ignore
}

@Override
public void keyPressed(KeyEvent e) {
keyCodeUpdate(e.getKeyCode(), true);
}

@Override
public void keyReleased(KeyEvent e) {
keyCodeUpdate(e.getKeyCode(), false);
}

private void keyCodeUpdate(int keyCode, boolean isDown) {
if (keyCode == KeyEvent.VK_W || keyCode == KeyEvent.VK_UP) {
input.setForwardKeyDown(isDown);
}
if (keyCode == KeyEvent.VK_S || keyCode == KeyEvent.VK_DOWN) {
input.setBackwardKeyDown(isDown);
}
if (keyCode == KeyEvent.VK_A || keyCode == KeyEvent.VK_LEFT) {
input.setLeftKeyDown(isDown);
}
if (keyCode == KeyEvent.VK_D || keyCode == KeyEvent.VK_RIGHT) {
input.setRightKeyDown(isDown);
}
if (keyCode == KeyEvent.VK_Q) {
input.setUpKeyDown(isDown);
}
if (keyCode == KeyEvent.VK_Z) {
input.setDownKeyDown(isDown);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package labs.introtoprogramming.lab5.gui;

import java.awt.AWTException;
import java.awt.Cursor;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;

class MouseController {

private static final String BLANK_CURSOR_NAME = "blank cursor";

private Input input;
private JFrame frame;

private Robot robot;
private Point prevLocation;

MouseController(Input input, JFrame frame) {
this.input = input;
this.frame = frame;
try {
this.robot = new Robot();
} catch(AWTException e) {
throw new AssertionError(e);
}
}

void hideCursor() {
BufferedImage cursorImg = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB);
Cursor blankCursor = Toolkit.getDefaultToolkit().createCustomCursor(
cursorImg, new Point(0, 0), BLANK_CURSOR_NAME);
frame.setCursor(blankCursor);
}

void update() {
if (!frame.isFocused()) {
return;
}

int centerX = frame.getX() + frame.getWidth() / 2;
int centerY = frame.getY() + frame.getHeight() / 2;
Point mouseLocation = MouseInfo.getPointerInfo().getLocation();

if (prevLocation != null) {
input.setMouseDeltaX(mouseLocation.getX() - centerX);
input.setMouseDeltaY(mouseLocation.getY() - centerY);
}

prevLocation = mouseLocation;
robot.mouseMove(centerX, centerY);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package labs.introtoprogramming.lab5.gui;

import java.util.Timer;
import java.util.TimerTask;
import labs.introtoprogramming.lab5.exception.NoCameraException;
import labs.introtoprogramming.lab5.scene.BasicRaytracingRender;
import labs.introtoprogramming.lab5.scene.Scene;
import labs.introtoprogramming.lab5.scene.SceneRender;

public class SceneRendererWindow extends Window {

private static final String UPDATE_LOOP_TIMER_NAME = "UpdateLoop";
private static final int UPDATE_LOOP_DELAY = 100; // ms
private static final int TARGET_FPS = 60;
private static final int UPDATE_RATE = 1000/TARGET_FPS;

private SceneRender render;
private Scene scene;
private MouseController mouseController;
private Input input;

public SceneRendererWindow(Scene scene) {
this(new BasicRaytracingRender(scene), scene);
}

public SceneRendererWindow(SceneRender render, Scene scene) {
this.render = render;
this.scene = scene;
input = new Input();
scene.getCamera().ifPresent(camera -> setRaster(camera.raster()));
mouseController = new MouseController(input, frame);
}

public void show() {
super.show();
startUpdateLoop();
setupKeyboardListener();
mouseController.hideCursor();
}

private void setupKeyboardListener() {
frame.addKeyListener(new InputKeyListener(input));
}

private void startUpdateLoop() {
new Timer(UPDATE_LOOP_TIMER_NAME, true).scheduleAtFixedRate(new TimerTask() {
long previousTime = System.currentTimeMillis();

@Override
public void run() {
long currentTime = System.currentTimeMillis();
updateIteration((int) (currentTime - previousTime));
previousTime = currentTime;
}
}, UPDATE_LOOP_DELAY, UPDATE_RATE);
}

private void updateIteration(int delta) {
this.mouseController.update();
scene.update(delta, input);
render.render(scene);
this.update();
}

private void setScene(Scene scene) {
this.scene = scene;
}
}
3 changes: 2 additions & 1 deletion src/main/java/labs/introtoprogramming/lab5/gui/Window.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ public class Window {

private static final int FPS_UPDATE_RATE = 100;

private JFrame frame;
protected JFrame frame;
private RasterRendererComponent renderer;
private Toolkit toolkit;
private String title;
Expand Down Expand Up @@ -74,6 +74,7 @@ public void setTitle(String text) {
}

public void setRaster(Raster raster) {
setDimensions(raster.getWidth(), raster.getHeight());
this.renderer.setRaster(raster);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@
public class BasicRaytracingRender implements SceneRender {
private Raster raster;

public BasicRaytracingRender(Scene scene) {
this(scene.getCamera().orElseThrow(NoCameraException::new));
}

public BasicRaytracingRender(Camera camera) {
this(camera.raster());
}

public BasicRaytracingRender(Raster raster) {
this.raster = raster;
}
Expand Down
Loading