Unexpected Rotation Issue in Three.js Mesh (Global Rotation vs. Local Rotation)

While working with Three.js, I encountered an issue where the mesh I was trying to rotate using keyboard controls was not behaving as expected. Regardless of the axis I rotated around, the mesh did not rotate in the intended direction.

Specifically, when rotating the mesh around one axis (Y), it did not rotate around another axis (X) as anticipated.

The code snippet used for rotating the cube is shown below: mesh.rotation.x += 0.03;

var camera, scene, renderer, mesh;

init();
animate();

function init() {
        // Setting up the camera
    camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 10 );
    camera.position.set( 1, 2, - 2 );
    
    // Setting up the scene
    scene = new THREE.Scene();
    camera.lookAt( scene.position );

        // Cube Setup
    var geometry = new THREE.BoxBufferGeometry( 0.5, 0.5, 0.5 );
    var material = new THREE.MeshNormalMaterial();
    mesh = new THREE.Mesh( geometry, material );
    mesh.position.set(0.5,0.5,0.5);
    mesh.rotation.y = 0.5;
    scene.add( mesh );
    
    // Adding grid and axes
    scene.add( new THREE.GridHelper( 4, 10 ) );
    scene.add( new THREE.AxesHelper() );

        // Adding renderer
    renderer = new THREE.WebGLRenderer( { antialias: true } );
    renderer.setSize( window.innerWidth, window.innerHeight );
    document.body.appendChild( renderer.domElement );
}

function animate() {

    requestAnimationFrame( animate );
    
    // The cube does not rotate around its local x-axis
    mesh.rotation.x += 0.03;
    
    renderer.render( scene, camera );

}
body {
      margin: 0;
}
<script src="//cdn.rawgit.com/mrdoob/three.js/master/build/three.min.js"></script>

To troubleshoot the issue, I attempted the following:

  • I came across this question discussing global rotation versus local rotation, but the solutions involved using THREE.Group(), which I wasn't utilizing.
  • I found this question about combining global and local rotation, but the suggestions relied on rotation matrices, which I was not employing.
  • I read through this question on using the Object3D.rotateOnAxis() method. Unfortunately, this approach didn't work for my scenario as it always created an axis from the origin to the position of my mesh. I needed to both rotate and translate my mesh to different positions.

Answer №1

The problem arose when I realized that the code used to rotate the cube (mesh.rotation.x += 0.03;) was modifying the global rotation instead of the local rotation.

To address this issue, I needed to utilize the Object3D.rotateX() method for rotating an object locally

You can find the updated code snippet with the corrected rotation code and a link to a JS Fiddle. Feel free to click the button in the top left corner to compare local versus global rotation.

var camera, scene, renderer, mesh;
var local = false;

init();
animate();

function init() {
        // Camera setup
    camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 10 );
    camera.position.set( 1, 2, - 2 );
    
    // Scene setup
    scene = new THREE.Scene();
    camera.lookAt( scene.position );

        // Cube Setup
    var geometry = new THREE.BoxBufferGeometry( 0.5, 0.5, 0.5 );
    var material = new THREE.MeshNormalMaterial();
    mesh = new THREE.Mesh( geometry, material );
    mesh.position.set(0.5,0.5,0.5);
    // Note: Until the mesh is rotated, global and local rotation are the same
    mesh.rotation.y = 0.5;
    scene.add( mesh );
    
    // Add grid and axes
    scene.add( new THREE.GridHelper( 4, 10 ) );
    scene.add( new THREE.AxesHelper() );

        // Add renderer
    renderer = new THREE.WebGLRenderer( { antialias: true } );
    renderer.setSize( window.innerWidth, window.innerHeight );
    document.body.appendChild( renderer.domElement );
    
    // Create rotation toggle button
    var button = document.createElement("button");
    button.innerText = "Local Rotation Off";
    button.onclick = () => {
      local = !local
      if (local) button.innerText = "Local Rotation On";
      else button.innerText = "Local Rotation Off";
    };
    document.body.appendChild(button);
    

}

function animate() {

    requestAnimationFrame( animate );
    
    // This is GLOBAL
    if (!local) mesh.rotation.x += 0.03;
    // This is LOCAL
    else mesh.rotateX(0.03);
    
    renderer.render( scene, camera );

}
body {
      margin: 0;
}

button {
  position: absolute;
  top: 10px;
  left: 10px;
  
}
<script src="//cdn.rawgit.com/mrdoob/three.js/master/build/three.min.js"></script>

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

Unlock the powers of Express, Passport, and Redis sessions!

Lately, I have been utilizing the default MemoryStore for my Express sessions and everything has been running smoothly. However, I encountered a setback where all session data was lost between restarts. To address this issue, I am now attempting to configu ...

Sorting nested JSON by property with NodeJS

If we consider a directory structure like the following: root |_ .git |_ .sass-cache |_ css | |_ scss | | |_ modules | | | |_ a-module.scss | | | |_ ... | | |_ partials | | | |_ a-partial.scss | | | |_ ... | | |_ main.scss | |_ main.cs ...

Click the edit button to access the options in the material table

https://i.stack.imgur.com/Inyow.png Currently, I am utilizing Material Table within Reactjs to display the table Data. However, I have encountered a hurdle where I need to alter state upon clicking on the edit option/icon. My objective is not to modify th ...

Struggling with retrieving data from multiple models in backbone.js

I'm currently developing a node.js app using backbone but I'm facing some challenges in understanding how to fetch data from two related models. Specifically, I have models for Users and Comments, and on the user view, I need to display user info ...

When using React, the componentDidUpdate() method may have trouble locating DOM objects that were originally rendered by the render() method

Update: I made some changes to the code by adding and utilizing refs instead of document.getElementById. Unfortunately, this did not solve the issue. Update 2: After experimenting with mutationObserver, it became apparent that componentDidUpdate() starts ...

Retrieve the rowid from the first column of a jqGrid row

I want the first column of my jqGrid to display the rowid number number | name | class 1 | A | acceptable 2 | B | good 3 | C | bad Alternatively, I would like to add a column like this (image) https://docs.google.com/file/d/0Bxi6bFcYZ_MgYTI1dUJCMWEtd0E/ ...

"Receive your share of the catch in a pop-up notification

Is there a way to determine if a user shared a result without using the social network's Javascript SDK? All sharing aspects (authorization, sharing, etc.) are done through popups on my domain. var popup = window.open('/api/share/' + servic ...

What's the deal with this error message saying val.slice isn't a function?

In the process of developing a web application using express with a three-tier architecture, I have chosen to use a mysql database to store blogposts as a resource. Here is an illustration of how the table is structured: CREATE TABLE IF NOT EXISTS blogpos ...

CSS- Strategically placing and centering images above specific keywords in (any) HTML content without disrupting the flow of text

My main objective involves dynamically inserting images above text on any given page using a content script. The challenge lies in maintaining the proper alignment of the text after adding the images. To achieve this, I surround the words where the image i ...

Using Fullcalendar Moment to retrieve the current time plus an additional 2 hours

Trying to tackle this seemingly simple task using moment.js in conjunction with Fullcalendar. My goal is to retrieve the current time and then add two hours to it. Within the select method (or whatever terminology you prefer), I currently have: select: f ...

Arranging a dictionary by its keys using Ramda

My task involves manipulating an array of items (specifically, rooms) in a program. I need to filter the array based on a certain property (rooms with more than 10 seats), group them by another property (the area the room is in), store them in a dictionary ...

The Angular Date Pipe is displaying an incorrect date after processing the initial date value

Utilizing Angular's date pipe within my Angular 2 application has been beneficial for formatting dates in a user-friendly manner. I have successfully integrated API dates, edited them, and saved the changes back to the API with ease. However, an issue ...

Implementing a Jquery check based on a checkbox

Hey, I'm having an issue with a condition. When I uncheck the checkbox, it doesn't uncheck. I've tried to make a block display, but the JavaScript isn't working. I attempted to add: document.getElementById("Reload").style.display = "b ...

Can TypeScript be used to dynamically render elements with props?

After extensive research on SO and the wider web, I'm struggling to find a solution. I have devised two components, Link and Button. In short, these act as wrappers for <a> and <button> elements with additional features like chevrons on t ...

Disable Jquery toolstrip while the menu is open

Currently, I am utilizing the jQuery toolstrip plugin in my project. I have a requirement to disable it whenever the sidebar menu is opened. Below are the HTML codes for my menu with li tags: <div class="sidebar-wrapper" id="sidebar-wrapper"> <ul ...

What steps can we take to perform queries within the context of a specific element in a Jest test?

Currently, I am in the process of writing Jest tests for a React application. Imagine that there is a webpage with multiple instances of a specific element present. For instance, let's consider a scenario where there are two buttons on the page. My ob ...

Resetting several sticky titles after displaying and hiding elements

Inspired by a popular codepen example, I have successfully implemented sticky titles in my sidebar. However, when integrating these sticky titles with the functionality to show/hide related items on click, I encountered some unexpected issues. The code sni ...

Using vanilla JavaScript with AJAX, the second asynchronous post will only be sent once the first post has been successfully sent

I am in the process of creating a HotSpot that offers internet access once users input their email addresses. To make this function properly, I need to execute two separate AJAX posts: The first one sends hidden username and password details to the rout ...

Discover the power of EJS embedded within HTML attributes!

There are two cases in which I am attempting to use an EJS tag within an HTML attribute. SITUATION 1: <input style="background-image: url(<%= img.URL %>)" /> SITUATION 2: <input onchange="handleCheckboxChange(<%= i ...

The proper way to cancel useEffect's Async in TypeScript

I'm facing an issue with this straightforward example: useEffect(() => { axios.get(...).then(...).catch(...) }, [props.foo]) warning: can't perform a react state update on an unmounted component After some investigation, I found this ...