Navigate a first person simulation using three.js and control your movements with the keyboard arrow

To access my reference material, please go to http://jsfiddle.net/fYtwf/

Overview

I am working on a basic 3D simulation using three.js where the camera is surrounded by cubes in three dimensions. These cubes serve as a visual guide to where the camera is pointing until the view controls are implemented and tested. The goal is to create a simple 3D application where the camera movement is controlled using the up, down, left, and right keys, similar to moving one's head.

Challenges

Currently, in my simulation, when the camera is facing forward and then tilted upwards, everything works as expected. However, when the camera is turned 90 degrees to the left and the up arrow key is pressed, unexpected behavior occurs. The camera increments the x-axis, but due to the change in direction, modifying the x-axis alone is incorrect.

It seems that trigonometry is needed to calculate the correct values for the z-axis in such scenarios. Unfortunately, my trigonometry skills are not very strong.

Current State

To better understand the issue, please visit my jsfiddle: http://jsfiddle.net/fYtwf/

UP key increments X only

DOWN key decrements X only

LEFT key increments Y only

RIGHT key decrements Y only

Q key increments Z only

W key decrements Z only

(Q and W were added in an attempt to assist in understanding the issue.)

As per my current understanding, pressing the UP key should increment X and modify the Z axis based on the current Y axis. However, I lack the algorithm to achieve this.

Therefore, both X and Z should be adjusted in the KEYUP code (I believe, but open to corrections).

// setRotateX, getRotateX, setRotateY, and getRotateY are custom camera functions
// created to manage degrees. It is not mandatory to use them, but they aided me in the process

switch(key) {
    case KEYUP:
        if (camera.getRotateX() < 90) { // Limit to avoid overhead view
            camera.setRotateX(camera.getRotateX() + VIEW_INCREMENT);
        }
        break;
                
    case KEYDOWN:
        if (camera.getRotateX() > -90) { // Ensure camera doesn't point below
            camera.setRotateX(camera.getRotateX() - VIEW_INCREMENT);
        }
        break;
                
    case KEYLEFT:
        camera.setRotateY(camera.getRotateY() + VIEW_INCREMENT);
        break;
                
    case KEYRIGHT:
        camera.setRotateY(camera.getRotateY() - VIEW_INCREMENT);
        break;
}

Answer №1

When faced with the challenge of rotating the camera in specific directions, the solution is actually quite simple.

All you need to do is adjust the camera's Euler order to "YXZ" as shown below:

camera.rotation.order = "YXZ"; // three.js r.65

By making this adjustment, the process of rotating the camera becomes much more intuitive.

You can test out the updated version here: http://jsfiddle.net/fYtwf/3/ (please note that this demo is based on r.54)

It's important to avoid changing camera.rotation.z from its default setting of zero, as this can lead to confusion. So it's best to stick with the recommended configuration. :-)

three.js r.65

Answer №2

Although this won't directly solve your coding issue, I wanted to bring up the fact that Three.js offers two built-in controllers for navigating in first-person-shooter (FPS) mode. Both of these controllers utilize mouse input for looking and movement, but they can easily be modified to accommodate keyboard input for looking and disable movement if necessary. These controllers are:

I would suggest starting with the latter option as it is more straightforward, while the former can be confusing due to redundant looking code, possibly leftover from previous versions.

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

attempting to fulfil a promise through a resolution

I am currently attempting to use a resolve with a promise in response to an issue with filters that I am currently tackling. However, my resolve function is not yet functioning as expected. I have decided to implement this approach based on advice I recei ...

Developers guide to using Selenium IDE

After downloading the source code of Selenium IDE, I'm eager to make some edits but unfortunately, I can't seem to find any documentation on how to do so. Hey folks, anyone aware of any resources available for developers working on Selenium IDE? ...

Ways to retrieve the baseURL of an axios instance

This question is being posted to provide an easy solution for fellow developers who may be looking for an answer. //Suppose you have an axios instance declared in a module called api.js like this: var axios = require('axios'); var axiosInstance ...

Using jquery to dynamically change audio source on click

Is there a way to dynamically change the audio src using jquery? <audio id="audio" controls="" > <source src="" type="audio/mpeg" /> </audio> <ul id="playlist"> <?php if($lists) { foreach ($lists as $list) { ?> ...

Merging two arrays of objects from the same response in JavaScript

How can I efficiently merge two arrays of objects from the same response? let data = [{ "testLevel":"mid", "testId":"m-001", "majorCourse": [ { "courseName":"C++" ...

After a page reload, Material-UI stops functioning properly

I am currently working with Material UI in a Next.js project. When I run npm run dev, everything looks good. However, whenever I refresh the page, all the styling breaks. Has anyone experienced this issue before? It seems like Material-UI is no longer func ...

The .val() and focus() methods are not functioning correctly

I am having an issue with a simple script: when I input a link to an image in the form's INPUT field, it should automatically display a preview of the image: https://example.com/image.jpg However, when I input the same link not by using ctrl+C/ctr ...

Tips for gently scrolling instead of quickly scrolling all at once

As a novice in HTML, I have a question about navigation to an ID targeted by an anchor tag. For example: When I execute this code, it quickly jumps to the specified ID but I would like to incorporate animations. Is there a way to achieve this? ...

Jquery Plugin fails to generate dynamic elements effectively

I developed a masking jQuery script that dynamically adds elements to an existing input element. var link = $('<a title="show" role="link" href="#" class="masker-value">show</a>'); wrapper: function() { container = $(container) ...

Can you explain the functionality of sinon's stub.yields method?

The explanation given in the documentation for sinon regarding stub.yields is as follows: By using stub.yields([arg1, arg2, ...]), you are essentially performing a function similar to callsArg. This will result in the stub executing the first callback it ...

Are there any JavaScript charting tools that can draw in a clockwise direction with multiple data points?

Can anyone recommend a JavaScript live chart/graph library that can create clockwise graphs with multiple points, similar to the example below? https://i.sstatic.net/dQfK4.png ...

Links have a longer transition delay compared to the content

In a unique JavaScript function I've developed, the my-content-section-visible class is removed and replaced with my-content-section-hidden. This change is being made to hide a particular div using a smooth transition effect. The transition itself is ...

Executing Scripts within the Browser: A Guide to Using Selenium

One of my current objectives involves running a script on my Selenium browser that establishes a variable and then using DevTools to access this variable in the console log. Below is the conflicting script that I am encountering issues with: from selenium ...

What could be causing the change event to be triggered in a v-text-field when I press enter, despite not making any changes?

How come the @change event triggers in a v-text-field when I press enter, even if I haven't made any changes? HTML <div id="app"> <v-app> <v-content> <v-container> <v-text-field @change=" ...

Open a Link in the Default Browser with a Right Click in node-webkit

I'm using an iframe in my node-webkit app. I want users to have the ability to right-click on links within the iframe (a tags) and choose an option like "Open in Browser" to open the link in their default browser. Can this be done? ...

Is your Ajax jQuery live search not functioning properly with JSON data?

My programming code is not functioning properly. Here is the file I am working on. When it does work, it does not display the list and gives an error in the Json file. I am unsure of the reason behind this issue. You will be able to view the error in the C ...

Tips for retrieving the selected option from a dropdown menu

I have a dropdown menu with checkboxes that can be selected using SumoSelect. Here is the markup for the dropdown menu: <select multiple="multiple" name="somename" id="uq" class="select"> <option value="volvo">Volvo</option> <o ...

Ensure there is a sufficient gap between the top and bottom icons within the Material-UI Drawer

I'm having difficulty articulating this, but I'd like to add two different sets of icons to the Drawer component. Set 1 should be displayed at the top in a standard column format, similar to the examples provided by them. Set 2 should go at the b ...

What is the process for executing code on a server by clicking a button?

In my Next.js application, there is a file named dummy.js with the following content: class Dummy extends React.Component{ static async getInitialProps(ctx){ return { dummy : 'abc'}; } displayHelloWorld(params) { cons ...

Trouble with setting up custom static route

Greetings! I am currently working on setting up my project in React and here is my current project structure: -public --w ---dist ----bundle.js ---index.html -server --server.js -src --app.js -webpack.config.js -package.json -.babelrc For my server, I am ...