Tips on rotating a 3D shape using axis in three.js

Help needed with rotation in three.js I am facing a challenge when trying to rotate a 3D cube in one of my games.

//initialize
geometry = new THREE.CubeGeometry grid, grid, grid
material = new THREE.MeshLambertMaterial {color:0xFFFFFF * Math.random(), shading:THREE.FlatShading, overdraw:true, transparent: true, opacity:0.8}
for i in [<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b0819e9e9ef0c3d8d1c0d59edcd5ded7c4d8">[email protected]</a>]
    othergeo = new THREE.Mesh new THREE.CubeGeometry(grid, grid, grid)
    othergeo.position.x = grid * @shape[i][0]
    othergeo.position.y = grid * @shape[i][1]
    THREE.GeometryUtils.merge geometry, othergeo
@mesh = new THREE.Mesh geometry, material

//rotate
@mesh.rotation.y += y * Math.PI / 180
@mesh.rotation.x += x * Math.PI / 180
@mesh.rotation.z += z * Math.PI / 180

When using values (1, 0, 0) for (x, y, z), the cube is able to rotate. However, the issue arises as the cube rotates on its own axis, preventing it from rotating as intended.

I came across a page How to rotate a Three.js Vector3 around an axis?, which explains rotating a Vector3 point around the world axis.

I attempted using matrixRotationWorld like this:

@mesh.matrixRotationWorld.x += x * Math.PI / 180
@mesh.matrixRotationWorld.y += y * Math.PI / 180
@mesh.matrixRotationWorld.z += z * Math.PI / 180

Unfortunately, this approach did not yield the desired results. I am unsure if I am using it incorrectly or if there are alternative methods...

Therefore, how can I make the 3D cube rotate around the world's axis?

Answer №1

Starting from version r59, three.js has introduced three handy methods for rotating an object around its axis.

object.rotateX(angle);
object.rotateY(angle);
object.rotateZ(angle);

Answer №2

Here are two essential functions that I utilize for matrix rotations. These functions have the capability to rotate around arbitrary axes. If you wish to rotate an object using the world's axes, it is recommended to make use of the second function, rotateAroundWorldAxis().

// Function to rotate an object around an arbitrary axis in object space
var rotObjectMatrix;
function rotateAroundObjectAxis(object, axis, radians) {
    rotObjectMatrix = new THREE.Matrix4();
    rotObjectMatrix.makeRotationAxis(axis.normalize(), radians);

    object.matrix.multiply(rotObjectMatrix);

    object.rotation.setFromRotationMatrix(object.matrix);
}

var rotWorldMatrix;
// Function to rotate an object around an arbitrary axis in world space       
function rotateAroundWorldAxis(object, axis, radians) {
    rotWorldMatrix = new THREE.Matrix4();
    rotWorldMatrix.makeRotationAxis(axis.normalize(), radians);

    rotWorldMatrix.multiply(object.matrix); 

    object.matrix = rotWorldMatrix;

    object.rotation.setFromRotationMatrix(object.matrix);
}

To achieve a rotation of 90 degrees on the x-axis, ensure that you call these functions within your anim function (requestAnimFrame callback) like so:

var xAxis = new THREE.Vector3(1,0,0);
rotateAroundWorldAxis(mesh, xAxis, Math.PI / 180);

Answer №3

After updating to the latest release (r52), I found that I needed to make some adjustments to the rotateAroundWorldAxis function. It seems that the previous code was no longer compatible, as getRotationFromMatrix() has been replaced with setEulerFromRotationMatrix()

function rotateAroundWorldAxis( object, axis, radians ) {

    var rotationMatrix = new THREE.Matrix4();

    rotationMatrix.makeRotationAxis( axis.normalize(), radians );
    rotationMatrix.multiplySelf( object.matrix );                       // pre-multiply
    object.matrix = rotationMatrix;
    object.rotation.setEulerFromRotationMatrix( object.matrix );
}

Answer №4

When using R55, make sure to update
rotationMatrix.multiplySelf( object.matrix );
with
rotationMatrix.multiply( object.matrix );

Answer №5

There was an update in Three.js R59 where the syntax

object.rotation.setEulerFromRotationMatrix(object.matrix);
was modified to
object.rotation.setFromRotationMatrix(object.matrix);

It's amazing how quickly Three.js is evolving!

Answer №6

In the event that you encounter r52, remember that the function is labeled as setEulerFromRotationMatrix as opposed to getRotationFromMatrix

Answer №7

By the time you reach level 59, manipulating rotation becomes more manageable (specifically rotating around the x-axis):

bb.GraphicsEngine.prototype.adjustRotation = function ( object, xRotation)
{
    var euler = new THREE.Euler( xRotation, 0, 0, 'XYZ' );
    object.position.applyEuler(euler);
}

Answer №8

Here is a snippet of code in CoffeeScript for Three.js R66:

THREE.Object3D.prototype.rotateAroundWorldAxis = (axis, radians) ->
  worldMatrix = new THREE.Matrix4()
  worldMatrix.makeRotationAxis axis.normalize(), radians
  worldMatrix.multiply this.matrix
  this.matrix = worldMatrix
  this.rotation.setFromRotationMatrix this.matrix

Answer №9

This is the method I used:

I developed the 'ObjectControls' module specifically for ThreeJS, allowing users to rotate a single OBJECT or a Group, rather than the entire SCENE.

First, include the library:

<script src="ObjectControls.js"></script>

To use it, simply add the following code:

var controls = new ObjectControls(camera, renderer.domElement, yourMesh);

For a live demonstration, please visit:

Feel free to check out the repository here: https://github.com/albertopiras/threeJS-object-controls.

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

Node.js Request Encoding Using Google Translate

I have developed a node.js module to use the Google Translate API. module.exports = function(sourceText, sourceLang, targetLang, callback) { var qst = qs.stringify({ client: 'gtx', sl: sourceLang, tl: targetLang, ...

Countdown with precision! This timer will begin at the one-hour mark

Having an issue with my JavaScript stopwatch. When I hit the start button, the stopwatch immediately shows one hour (01:00:00) before counting normally. Any solutions to prevent this instant start at one hour would be highly appreciated. Thank you in adv ...

The latest images are now visible in the table alongside the existing images that were previously added

When inserting images here, previously added images are displaying. Any solutions? Here is my view page <div class="col-md-2"> <form enctype="multipart/form-data" method="post" action="<?php echo base_url();?>admin_control/upl ...

Having trouble with Next Js and Typescript, specifically receiving the error TS2304: Unable to locate name 'AppProps'?

I encountered the error message "TS2304: Cannot find name 'AppProps' when trying to launch a basic Next Js project using TypeScript. After searching on Stack Overflow for similar issues, I haven't found any solutions that work for me. imp ...

What could be the reason why PhantomJS is not able to catch the <script> tags in the opened HTML using webpage.onConsoleMessage function?

In this particular query, I have defined the const contents to be the content of my HTML file for the sake of convenience. var webPage = require('webpage'); var page = webPage.create(); const contents = ` <!DOCTYPE html> <html lang=&quo ...

What is the best way to display the angular bootstrap modal only upon the initial page load?

Even though I am only intending to show the bootstrap modal on page load, it is triggering every time the route changes. For example, if I return to the same page from another page using the browser's back or forward buttons, the modal is shown again. ...

Utilizing Node.js and express to promptly address client requests while proceeding with tasks in the nextTick

I am looking to optimize server performance by separating high CPU consuming tasks from the user experience: ./main.js: var express = require('express'); var Test = require('./resources/test'); var http = require('http'); va ...

Ways to conceal a parameter in Angularjs while functioning within the ng-bind directive

I am using Angular to create the final URL by inputting offer information. Below is the code snippet: <!DOCTYPE html> <html> <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script> <body> ...

Exploring the functionality of textareas within iframes on iPad

There is a known issue where textareas and inputs do not function properly on iPad Safari when placed inside an iframe. For more information, visit: This bug can easily be reproduced on iOS 7, but seems to work fine on iOS 8. Despite this issue, I am in ...

Encountering issues in transmitting form data to a Node server from Angular

In my Angular application, I am working on creating a registration page with validation. Once the user fills out the form and submits it, the data is sent to the server and saved in MongoDB. This is the approach I have taken: register_user() { const ...

show button after the page has finished loading

I have a button similar to this: <input type="submit" id="product_197_submit_button" class="wpsc_buy_button" name="Buy" value="Add To Cart"> However, I am encountering an issue where if the user clicks the button before all scripts are loaded, an e ...

Having trouble getting @vercel/ncc to work, keeps throwing a "Module not found" error

Recently, I have been attempting to follow a tutorial on creating custom GitHub actions using JavaScript from here. The tutorial suggests using the @vercel/ncc package to compile code into a single file if you prefer not to check in your node_modules folde ...

Explore all potentialities within an array of objects by examining and contrasting their key values

Looking to run a specific math formula with three parameters using an array of objects in JavaScript. The scenario involves sports, where there are three possibilities: Team A (win), Team B (win), or Draw. There are three different bet websites offering o ...

What is the best way to display an image path and add it to the Ajax success function in a CodeIgniter application?

I am struggling to display my image path correctly using append and a variable to store the value. However, whenever I try, it results in an error. Let me provide you with the code snippet: <script type="text/javascript"> $(document).ready(funct ...

An error was encountered when attempting to reference an external JavaScript script in the document

Could someone please provide guidance on how to utilize the document method in an external .js file within Visual Studio Code? This is what I have tried so far: I have created an index.html file: <!DOCTYPE html> <html lang="en"> <head> ...

Struggling to deal with conditionals in Express

Just starting with Express and I've come across the following code: const { response } = require("express"); const express = require("express"); const app = express(); app.get("/api/products/:id", function (req, res) { ...

Is there a way to incorporate hyperlinks into the Application column of my v-data-table component?

When loading data table from the database, I have included links along with the names of the Applications. However, I only want to display the Application name and open the corresponding link when clicked. headers: [ { text: 'Name&a ...

Unexpected behavior encountered when looping through a list in Vue <template> markup

I am currently using my app.js to dynamically generate tabs like the code snippet below: Input: <tabs> <div> <a slot="header">Tab 1</a> <article slot="content"> <h2>Tab 1 Content</h2& ...

Expanding and collapsing a single item in a ListView with React Native

I am currently encountering an issue with my list of Messages, where clicking on any message expands or collapses all messages instead of just the individual message clicked. See the code snippet below for more details on how each Tab Component is populate ...

The value is currently unset in the TypeScript language

The variable `this.engenes_comparte` is showing up as undefined inside the subscribe function, but it works fine outside of it. baja(){ this._restService.getEngines(this._globalService.currentFisherMan.nid).subscribe((data : any[]) => { le ...