Summary Files Commits Branches @commit @diff @stats
path: root / Year 2 / Computer Graphics with WebGL / Project
diff options
context:
space:
mode:
Commit4d1070d418e1a145d54d927440e500ba307e2431 (patch)
Author
 Syndamia <kamen@syndamia.com>
2023-08-24 19:01:35 +0300
Committer
 Syndamia <kamen@syndamia.com>
2023-08-24 19:01:35 +0300
Files589eb77ce9ca8992a6a11f39284f60ac8e195b4e /Year 2/Computer Graphics with WebGL/Project
uni-projects-4d1070d418e1a145d54d927440e500ba307e2431.tar
uni-projects-4d1070d418e1a145d54d927440e500ba307e2431.tar.gz
uni-projects-4d1070d418e1a145d54d927440e500ba307e2431.zip
Parent517cd733258ce53b3d96bf04d427451278bc546e (diff)
[WGL/P] Finished movement controller
1 files changed, 77 insertions, 43 deletions
-rw-r--r--Year 2/Computer Graphics with WebGL/Project/spaceship.js120
diff --git a/Year 2/Computer Graphics with WebGL/Project/spaceship.js b/Year 2/Computer Graphics with WebGL/Project/spaceship.js
index 3cf7315..ca7de7f 100644
--- a/Year 2/Computer Graphics with WebGL/Project/spaceship.js
+++ b/Year 2/Computer Graphics with WebGL/Project/spaceship.js
@@ -2,16 +2,49 @@
* Helpers
*/
-const MOVE_SPEED = 1.5;
-const ROTATION_SPEED = 3;
+SphericalCoord = function(theta, phi) {
+ this.fulltheta = this.theta = theta;
+ this.phi = phi;
+ this.recalculateCartesian();
+}
+SphericalCoord.prototype.recalculateCartesian = function() {
+ return this.cartesian = [Math.sin(this.theta) * Math.sin(this.phi),
+ Math.cos(this.theta),
+ Math.sin(this.theta) * Math.cos(this.phi)];
+}
+SphericalCoord.prototype.addAngles = function(theta, phi) {
+ // Theta is in the range [0, pi), however in a sphere we have 2pi degrees.
+ // We keep a "full" theta, which is in the range [0, 2pi), and then adjust normal theta
+ // accordingly. With just normal theta, after a positive value is passed (for example)
+ // we wouldn't know in which direction to rotate (or more accurately, we would always
+ // increase theta so it goes the the "south" pole, which is bad, since increasing the
+ // value should just continue rotating the point, like with phi).
+ // When you "overextend" past pi, so when you need to reach the other hemisphere, between
+ // pi and 2pi, you need to rotate phi by 180 degrees (2pi), so theta is acting on the other
+ // hemisphere, and then we need to remove from 2pi the "leftover" amount, since our theta
+ // would signify the "reverse" angle than the one we want.
+ // Special thanks for interactive applet: https://mathinsight.org/spherical_coordinates
-var pos = [1000, 0, 30];
+ var before = this.fulltheta <= Math.PI;
+ this.fulltheta = (this.fulltheta + theta) % (2 * Math.PI);
+ this.theta = (this.fulltheta <= Math.PI) ? this.fulltheta : -this.fulltheta;
-var phi = 0;
-var theta1 = Math.PI / 2;
-var forward = [0,0,1];
+ // We check if fulltheta passed through the 180 degree/pi border
+ if (before && this.fulltheta > Math.PI) {
+ this.phi = (this.phi + Math.PI) % (2 * Math.PI);
+ }
+ else if (!before && this.fulltheta <= Math.PI) {
+ this.phi = (this.phi - Math.PI) % (2 * Math.PI);
+ }
+
+ this.phi = (this.phi + phi) % (2 * Math.PI);
-var up = [0,1,0];
+ this.recalculateCartesian();
+ return this;
+}
+SphericalCoord.prototype.toCartesian = function() {
+ return this.cartesian;
+}
function vecSum(a, b) {
return [a[0]+b[0], a[1]+b[1], a[2]+b[2]];
@@ -19,9 +52,20 @@ function vecSum(a, b) {
function vecSub(a, b) {
return [a[0]-b[0], a[1]-b[1], a[2]-b[2]];
}
-function vecScale(a, scale) {
- return [a[0] * scale, a[1] * scale, a[2] * scale];
-}
+
+/*
+ * Variables
+ */
+
+const MOVE_SPEED = 1.5;
+const ROTATION_SPEED = 3;
+
+var pos = [1000, 0, 30];
+
+var forward = new SphericalCoord(Math.PI / 2, 0);
+var up = new SphericalCoord(0, 0);
+ // this vector can be calculated from forward and up, but this way we improve speed
+var left = new SphericalCoord(Math.PI / 2, Math.PI / 2);
/*
* Navigation keys
@@ -29,54 +73,44 @@ function vecScale(a, scale) {
var pressedKeys = [ false, false, false, false, false, false ];
var keyAction = [
- () => { pos = vecSum(pos, up); }, // ' '
- () => { pos = vecSub(pos, up); }, // 'Shift'
- () => { pos = vecSum(pos, forward); }, // 'w'
- () => { pos = vecSub(pos, forward); }, // 's'
- () => { }, // 'a'
- () => { }, // 'd'
+ () => { pos = vecSum(pos, up.toCartesian()); }, // ' '
+ () => { pos = vecSub(pos, up.toCartesian()); }, // 'Shift'
+ () => { pos = vecSum(pos, forward.toCartesian()); }, // 'w'
+ () => { pos = vecSub(pos, forward.toCartesian()); }, // 's'
+ () => { pos = vecSum(pos, left.toCartesian()); }, // 'a'
+ () => { pos = vecSub(pos, left.toCartesian()); }, // 'd'
];
addEventListener("keydown", (event) => {
switch (event.key) {
- case ' ': pressedKeys[0] = true; break;
+ case ' ' : pressedKeys[0] = true; break;
case 'Shift': pressedKeys[1] = true; break;
- case 'w': pressedKeys[2] = true; break;
- case 's': pressedKeys[3] = true; break;
- case 'a': pressedKeys[4] = true; break;
- case 'd': pressedKeys[5] = true; break;
+ case 'w' : pressedKeys[2] = true; break;
+ case 's' : pressedKeys[3] = true; break;
+ case 'a' : pressedKeys[4] = true; break;
+ case 'd' : pressedKeys[5] = true; break;
}
});
addEventListener("keyup", (event) => {
switch (event.key) {
- case ' ': pressedKeys[0] = false; break;
+ case ' ' : pressedKeys[0] = false; break;
case 'Shift': pressedKeys[1] = false; break;
- case 'w': pressedKeys[2] = false; break;
- case 's': pressedKeys[3] = false; break;
- case 'a': pressedKeys[4] = false; break;
- case 'd': pressedKeys[5] = false; break;
+ case 'w' : pressedKeys[2] = false; break;
+ case 's' : pressedKeys[3] = false; break;
+ case 'a' : pressedKeys[4] = false; break;
+ case 'd' : pressedKeys[5] = false; break;
}
});
/*
* Mouse movement
*/
-function updateForward(e) {
+function updateLookingDirection(e) {
var vertical = (e.movementY / canvas.offsetHeight) * ROTATION_SPEED;
var horizontal = (-e.movementX / canvas.offsetWidth) * ROTATION_SPEED;
- // forward = vecSum(forward, vecScale(up, vertical));
- // forward = vecSum(forward, vecScale(left, horizontal));
- var before = theta1 <= Math.PI;
- theta1 = (theta1 + vertical) % (2 * Math.PI);
- var theta = (theta1 <= Math.PI) ? theta1 : 2*Math.PI - theta1;
- if (before && theta1 > Math.PI) phi = (phi + Math.PI) % (2 * Math.PI);
- else if (!before && theta1 <= Math.PI) phi = (phi - Math.PI) % (2 * Math.PI);
- // if (theta > Math.PI) {
- // }
- phi = (phi + horizontal) % (2 * Math.PI);
- forward = [Math.sin(theta) * Math.sin(phi), Math.cos(theta), Math.sin(theta) * Math.cos(phi)];
- up = [forward[0], forward[2], forward[1]];
- console.log(forward);
+ forward.addAngles(vertical, horizontal);
+ up.addAngles(vertical, horizontal);
+ left.addAngles(vertical, horizontal);
}
function mouseInit() {
@@ -85,9 +119,9 @@ function mouseInit() {
});
document.addEventListener('pointerlockchange', () => {
if (document.pointerLockElement === canvas) {
- document.addEventListener("mousemove", updateForward);
+ document.addEventListener("mousemove", updateLookingDirection);
} else {
- document.removeEventListener("mousemove", updateForward);
+ document.removeEventListener("mousemove", updateLookingDirection);
}
});
}
@@ -98,5 +132,5 @@ function mouseInit() {
function lookUpdate() {
for (var i = 0; i < pressedKeys.length; i++)
if (pressedKeys[i]) keyAction[i]();
- lookAt(pos, vecSum(pos, forward), up);
+ lookAt(pos, vecSum(pos, forward.toCartesian()), up.toCartesian());
}