Move the camera left and right, up and down using the arrow keys in WebGL

I am currently working on implementing a basic camera movement system in WebGL using JavaScript and the keyboard to control the camera's movement along the X and Y axes. However, I am facing an issue where the camera moves in world coordinates rather than relative to its own X and Y axes, resulting in a lack of realistic movement and inconsistencies based on the camera's orientation.

Below is some code snippet I have been using (I am unsure if the "updateprojectionmatrix" line is necessary in this context):

var arrow = { left: 37, up: 38, right: 39, down: 40 };
    var delta = 100;
    switch (event.which) {
        case arrow.left:
            camera.position.x = camera.position.x - delta;
            camera.updateProjectionMatrix();
            break;
        case arrow.up:
            camera.position.y = camera.position.y + delta;
            camera.updateProjectionMatrix();
            break;
        case arrow.right:
            camera.position.x = camera.position.x + delta;
            camera.updateProjectionMatrix();
            break;
        case arrow.down:
            camera.position.y = camera.position.y - delta;
            camera.updateProjectionMatrix();
            break;
    }

Answer №1

Explore this informative piece on cameras in WebGL

The article explains how a camera, represented by a look at matrix, is computed as shown below:

+----+----+----+----+
| Xx | Xy | Xz |  0 |  <- x axis
+----+----+----+----+
| Yx | Yy | Yz |  0 |  <- y axis
+----+----+----+----+
| Zx | Zy | Zz |  0 |  <- z axis
+----+----+----+----+
| Tx | Ty | Tz |  1 |  <- camera position
+----+----+----+----+

This enables moving the camera along its current view plane by adding the camera's world x-axis and/or y-axis to its position.

In three.js, the following code snippet can achieve this:

  var arrow = { left: 37, up: 38, right: 39, down: 40 };
  var delta = 0.05;
  var xAxis = new THREE.Vector3(
      camera.matrixWorld.elements[0], 
      camera.matrixWorld.elements[1], 
      camera.matrixWorld.elements[2]);
  var yAxis = new THREE.Vector3(
      camera.matrixWorld.elements[4], 
      camera.matrixWorld.elements[5], 
      camera.matrixWorld.elements[6]);

  switch (event.keyCode) {
    case arrow.left:
      camera.position.addScaledVector(xAxis, -delta);
      break;
    case arrow.up:
      camera.position.addScaledVector(yAxis, delta);
      break;
    case arrow.right:
      camera.position.addScaledVector(xAxis, delta);
      break;
    case arrow.down:
      camera.position.addScaledVector(yAxis, -delta);
      break;
  }

Below is a working example:

var renderer = new THREE.WebGLRenderer();
document.body.appendChild(renderer.domElement);

// Rest of the Three.js scene setup and camera movement functionality...

Furthermore, Three.js provides a translateOnAxis function for camera movement along specific axes. The code snippet below demonstrates this:

var arrow = { left: 37, up: 38, right: 39, down: 40 };
var delta = 0.05;
var xAxis = new THREE.Vector3(1,0,0);
var yAxis = new THREE.Vector3(0,1,0);

window.addEventListener('keydown', function(event) {
  event.preventDefault();
  switch (event.keyCode) {
    case arrow.left:
      camera.translateOnAxis(xAxis, -delta);
      break;
    case arrow.up:
      camera.translateOnAxis(yAxis, delta);
      break;
    case arrow.right:
      camera.translateOnAxis(xAxis, delta);
      break;
    case arrow.down:
      camera.translateOnAxis(yAxis, -delta);
      break;
  }
});       

Here is a working example with the provided code:

var renderer = new THREE.WebGLRenderer();
document.body.appendChild(renderer.domElement);

// Rest of the Three.js scene setup and camera movement functionality...

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Calling functions in AngularJS/HTML can help you execute specific

Just started with angularjs and facing some major issues haha... I have something that seems to be working fine, but I can't figure out what's wrong with this code... can someone please help me? Here it is: Basically, the scope.create function ...

Implementing React selectors to manage the state changes on page load and when a user

I'm currently delving into React selectors with ReSelect, and while things seem to be going well, I have a feeling that there may be an issue in my logic. 1 - Upon receiving an AJAX response, I obtain a list of "categories" consisting of id, name, an ...

Tips for successfully passing an array containing multiple values within the jsPDF body

I'm experimenting with jsPDF to showcase a list of products that users have ordered. I've managed to set up my columns and generate the PDF for download, but I'm facing some challenges with populating the body section. When attempting to sen ...

Tips on updating the $authProvider.loginUrl for Satellizer from an Angular controller

Consider this hypothetical situation: A user attempts to access a /settings page without being logged in. The Settings controller detects based on $auth.isAuthenticated() != true that the user is not logged in, and directs them to the /login page. The us ...

Looking for a character that includes both lowercase and uppercase letters

Here is the JSON data I have: [ {"lastName":"Noyce","gender":"Male","patientID":19389,"firstName":"Scott","age":"53Y,"}, {"lastName":"noyce724","gender":"Male","patientID":24607,"firstName":"rita","age":"0Y,"} ] var searchBarInput = TextInput.value; var ...

Tips for rearranging objects within a jsPDF document to prevent vertical overlap when a table grows in size

I am new to React and Javascript. I have been struggling to find a solution to my issue while trying to create a .pdf document for a customer invoice using "jsPdf" along with its plugin "jspdf-autoTable". So far, everything is being generated correctly by ...

Unlocking two features with just a single tap

I am currently working on a website for a kiosk, where the site transitions like a photoslide between each section. To achieve this effect, I have added a layover/mask on the initial page. The layover/mask is removed using a mouse click function. This is ...

AngularJS: The power of dynamic HTTP POST parameter names

Utilizing an API to update profile information allows for the addition of a nickname, email, phone number, or password in the request parameters, which will then be updated in the database. When updating a specific field, such as Nickname: { "nickname": ...

What is the best way to display an international phone number using Angular Material V6?

I've been working on a project that utilizes Angular Material V6. My goal is to display international phone numbers with flags in a Material component text box. After some research online, I came across an npm module that achieved this but it was tail ...

Node.js captures the Promise and provides detailed feedback

As I embark on my journey with Node.js + Express, currently in the process of structuring my HTTP APIs, I have a controller that utilizes a specific pattern: my_controller.js 'use strict'; var AppApiFactory = function (express, appService) { ...

Add an input element to a form fieldset by employing vue

In my form, I have a staged approach with 3 fieldsets that only appear when the "Next" button is clicked. Now, in the third fieldset, I need to add input elements based on keys extracted from an external json object. Data: data: () => ({ c ...

Steps for choosing an image and embedding it within a div element

Upon loading the site, an image is displayed with the following code: <img id="some_Image" src="some_source"> However, I am looking to avoid requesting this image again from "some_source". This is because calculating the image can be resource-inten ...

The data input from the HTML is not being correctly transferred to the modal

I am trying to transfer the reservation id from an HTML element to a modal window. When I click "cancel" next to a reservation, a modal should appear showing the reservation id. However, the modal pops up without displaying the reservation id. Can anyone h ...

Angular 2 template format standard

Every Angular 2 example I encounter seems to place the template within the component decorator. import { Component } from '@angular/core'; @Component({ selector: 'my-app', template: '<h1>Hello world</h1>' }) e ...

Is the functionality of this.value compatible with Firefox but not with Internet Explorer?

I am facing an issue with the onChange event on a select element. When I use alert(this.value), it works fine on Firefox, but not on Internet Explorer. What could be causing this discrepancy? Below is the code snippet in question: <select onchange="n ...

Rails - implementing ajax in partials causing an error: 'cannot find method render'

I am encountering an issue with my form partial located within a div that has the id "chapcomments". The form includes a submit button: <%= f.submit "Post", remote: true %> Within the correct view folder, I have a file named create.js.erb which con ...

The JavaScript and CSS properties are not functioning properly with the HTML text field

I came across this CodePen example by dsholmes and made some modifications: Here Furthermore, I have developed my own form on another CodePen pen: Link The issue I'm facing is related to the placeholders/labels not disappearing when typing in text f ...

Is there a quick way to use AJAX in Rails?

By using the remote:true attribute on a form and responding from the controller with :js, Rails is instructed to run a specific javascript file. For instance, when deleting a user, you would have the User controller with the Destroy action. Then, you woul ...

Implementing a blur effect on a CSS loader

I have successfully implemented a loader feature where a loading animation is displayed upon clicking the submit button, indicating that the form submission is in progress. However, I am encountering an issue when trying to apply a blur effect to the entir ...

Guide on importing CDN Vue into a vanilla Typescript file without using Vue CLI?

In the midst of a large project that is mostly developed, I find myself needing to integrate Vue.js for specific small sections of the application. To achieve this, I have opted to import Vue.js using a CDN version and a <script> </script> tag ...