-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCamera.java
More file actions
102 lines (85 loc) · 3.83 KB
/
Camera.java
File metadata and controls
102 lines (85 loc) · 3.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
public class Camera {
private Vector3 position;
private Vector3 centreVector;
private Vector3 verticalVector;
private Vector3 horizontalVector;
private double verticalRotation;
private double horizontalRotation;
private double horizontalFieldOfView;
private Plane screen;
public Camera(Vector3 position, double verticalRotation, double horizontalRotation, double aspectRatio,
double horizontalFieldOfView) {
this.position = position;
this.verticalRotation = verticalRotation;
this.horizontalRotation = horizontalRotation;
this.horizontalFieldOfView = horizontalFieldOfView;
setVectors();
}
public Camera(Vector3 position, double aspectRatio) {
this(position, 0, 0, aspectRatio, Math.PI / 2);
}
public void setPosition(Vector3 position) {
this.position = position;
}
private void setVectors() {
this.centreVector = new Vector3(
Math.cos(verticalRotation) * Math.cos(horizontalRotation),
Math.sin(horizontalRotation),
Math.sin(verticalRotation) * Math.cos(horizontalRotation));
this.verticalVector = new Vector3(
Math.cos(verticalRotation) * -Math.sin(horizontalRotation),
Math.cos(horizontalRotation),
Math.sin(verticalRotation) * -Math.sin(horizontalRotation));
this.horizontalVector = centreVector.cross(verticalVector);
setScreen();
}
private void setScreen() {
Vector3 screenCentre = centreVector.multiply(1 / Math.tan(horizontalFieldOfView / 2));
screen = new Plane(centreVector, screenCentre);
}
public void setRotation(double verticalRotation, double horizontalRotation) {
this.verticalRotation = verticalRotation % (2 * Math.PI);
if (this.verticalRotation < 0) {
this.verticalRotation += 2 * Math.PI;
}
this.horizontalRotation = Math.max(Math.min(horizontalRotation, Math.PI / 2), -Math.PI / 2);
setVectors();
}
public boolean isInFOV(Vector3 point) {
// this is not the right way to do it, but it is good enough for now
// TODO: do that properly
return centreVector.dot(point.subtract(position).normalise()) > Math.cos(horizontalFieldOfView / 2);
}
public Vector2 getPointProjectionOnScreen(Vector3 point, double screenWidth, double screenHeight) {
// If the point is behind the camera, return null
if (centreVector.dot(point.subtract(position)) <= 0) {
return null;
}
Vector3 positionOnScreen = screen.intersection(point.subtract(position), new Vector3(0, 0, 0));
Vector3 horizontalProjection = positionOnScreen.projection(horizontalVector);
Vector3 verticalProjection = positionOnScreen.projection(verticalVector);
// Accounts for points that could be just outside the screen
double x = horizontalProjection.magnitude() * Math.signum(horizontalProjection.dot(horizontalVector));
double y = verticalProjection.magnitude() * Math.signum(verticalProjection.dot(verticalVector));
return new Vector2(-x * screenWidth / 2 + screenWidth / 2,
// screenWidth because that is by how much we have to scale the coordinates
// (both x and y) to fit the screen
-y * screenWidth / 2 + screenHeight / 2);
}
public Vector3 getPoint3D(Vector2 point, Plane plane, double screenWidth, double screenHeight) {
Vector3 positionOnScreen = horizontalVector.multiply(-(screenWidth / 2 - point.getX()) / (screenWidth / 2))
.add(verticalVector.multiply(-(screenHeight / 2 - point.getY()) / (screenWidth / 2)))
.add(position.subtract(centreVector.multiply(1 / Math.tan(horizontalFieldOfView / 2))));
Vector3 positionOnFace = plane.intersection(positionOnScreen.subtract(position), position);
return positionOnFace;
}
public Vector3 getPosition() {
return position;
}
public double getVerticalRotation() {
return verticalRotation;
}
public double getHorizontalRotation() {
return horizontalRotation;
}
}