diff options
[WGL/P] Finished movement controller
1 files changed, 77 insertions, 43 deletions
| -rw-r--r-- | Year 2/Computer Graphics with WebGL/Project/spaceship.js | 120 |
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()); } |
