Three.js tutorial: Rotating items on each axis individually

Looking to create an interactive 3D item that users can rotate with their mouse freely? I experimented with using three quaternions, one for each axis, and then multiplying them together to determine the final position of the item.

// Initializing xQuat, yQuat, zQuat as new instances of THREE.Quaternion()

rotate(e, axis) {
  // e.movement represents mouse movement
  const dy = e.movementY

  switch(axis) {
    case 'x':
      this.xRot += dy / 100
      break;
    case 'y':
      this.yRot += dy / 100
      break;
    case 'z':
      this.zRot += dy / 100
      break;
  }

  this.xQuat.setFromAxisAngle( new THREE.Vector3(1, 0, 0), this.xRot );
  this.yQuat.setFromAxisAngle( new THREE.Vector3(0, 1, 0), this.yRot );
  this.zQuat.setFromAxisAngle( new THREE.Vector3(0, 0, 1), this.zRot );

  // Where target is a THREE.Mesh()
  this.target.quaternion.multiplyQuaternions(this.yQuat, this.xQuat);
  this.target.quaternion.multiply(this.zQuat)
}

Despite these calculations, I encountered a challenge where the rotation wasn't independent on each axis—instead, it affected the orientation of the axes themselves along with the item's rotation. My goal is to maintain the axes in place; for instance, when rotating around the y-axis, I aim to spin the item around the global y-axis rather than its local y-axis.

Answer â„–1

After some trial and error, I finally cracked the code 20 minutes later! Instead of performing quaternion multiplication every time the mouse is moved, I decided to multiply the manipulated axis' quaternion by the item's quaternion.

rotate(e, axis){
        const dy = e.movementY
        
        if(axis != this.lastSelectedAxis){
            this.lastSelectedAxis = axis
            this.lastQuaternion.copy(this.target.quaternion)
            this.xRot = 0
            this.yRot = 0
            this.zRot = 0
        }

        switch(axis){
            case 'x':
                this.xRot += dy / 100
                break;
            case 'y':
                this.yRot += dy / 100
                break;
            case 'z':
                this.zRot += dy / 100
                break;
        }


        this.xQuat.setFromAxisAngle( new THREE.Vector3(1, 0, 0), this.xRot );
        this.yQuat.setFromAxisAngle( new THREE.Vector3(0, 1, 0), this.yRot );
        this.zQuat.setFromAxisAngle( new THREE.Vector3(0, 0, 1), this.zRot );

        switch(axis){
            case 'x':
                this.target.quaternion.multiplyQuaternions(this.xQuat, this.lastQuaternion)
                break;
            case 'y':
                this.target.quaternion.multiplyQuaternions(this.yQuat, this.lastQuaternion)
                break;
            case 'z':
                this.target.quaternion.multiplyQuaternions(this.zQuat, this.lastQuaternion)
                break;
        }

    }

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

Tips for importing font files from the node_module directory (specifically otf files)

We cannot seem to retrieve the fonts file from the node module and are encountering this error message. Can't find 'assets/fonts/roman.woff2' in 'C:\Projects\GIT2\newbusinessapp\projects\newbusinessapp\src ...

Is there a way to extract the content from a dynamic textbox using a dynamic button in HTML and AJAX?

My current task involves fetching data from a database and updating the records individually. I have created a table with a text input field and a button that will be generated dynamically for each record. The text input field is populated with the previou ...

Display/conceal within a jQuery fixed navigation bar (center-aligned)

I am facing challenges with creating a sticky menu that shows/hides with a click button. Considering abandoning the show/hide feature altogether and rebuilding it from scratch in the future. Two major problems I have identified: How can I make the sho ...

streamlined method for accessing page parameters in nested components using the next.js application router

In my next.js application, I have a deep hierarchy of nested components. I currently use the params.lang parameter for translations, but I find myself passing it down to every nested component. Although there are hooks available, I prefer rendering them ...

The slider causing conflicts with widgets and content positioned below it in an HTML layout

When implementing a slider with a fade effect, there seems to be an issue with the placement of widgets on the homepage. The problem arises from the margin-top setting as when images change in the slider, the widgets clash with the slider. During the trans ...

What is the best way to ensure my jQuery plugin is up to date?

I have a question regarding the functionality of this plugin I am using. My goal is to update the timer it provides. To start the countdown timer with 5000 milliseconds remaining, I use the following code: $('#CountdownTimer').countdown({ remai ...

Guide on initiating document-wide events using Jasmine tests in Angular 2/4

As stated in the Angular Testing guidelines, triggering events from tests requires using the triggerEventHandler() method on the debug element. This method accepts the event name and the object. It is effective when adding events with HostListener, such as ...

What is the process for creating a hover linear wipe transition using CSS/JS?

It's worth noting that I can't simply stack one image on top of the other because I'll be dealing with transparent images as well. preview of linear wipe ...

Attempting to switch between classes with the click of a button

I am attempting to create a basic animation that involves changing an image from A to B to C when a button is clicked. However, I am encountering an issue with the error message Cannot read properties of undefined (reading 'classList'). I am puzz ...

Electron Web Workers do not have compatibility with NodeJS modules

I'm currently working on a desktop application using Electron paired with ReactJS. From the initial renderer process, I create a hidden BrowserWindow to launch another renderer process. Within this new renderer process, I set up a web worker that wil ...

Following the build process with the --prod flag in Ionic 3, users may encounter a situation where

Encountering an issue only when using --prod on Android phones. Strangely, touching anywhere triggers the event that should be fired at that specific location, causing the content to suddenly appear. I came across information suggesting a conflict between ...

A custom JavaScript function designed to replicate Excel's functionality of dividing numbers by thousands

I've noticed a unique behavior in Excel where when a cell is in focus and you enter, for example, 1500.32, it displays as 1 500.32. However, once you click enter or move away from the cell, it changes to 1 500.32. I'm intrigued by how this works. ...

Enhance your viewing experience with the Zoom feature that activates when

I recently noticed on that I am able to zoom/enlarge a photo by clicking on it. Is there a way for me to incorporate this feature without purchasing the entire theme? While I understand the theme is designed for purchase, I only need this specific functi ...

Execute asynchronous calls within each iteration and proceed to the next iteration in Node.js

I am currently faced with a dilemma at work and I need advice on the most effective approach to handle it. Below is an example of my code: for(var i =0 ;i < collection.length; i++){ asynCall( collection[i],function(){....})//doing a asynchronous cal ...

Tips for removing duplicate objects from an array

I am utilizing the underscore.js plugin in my code I experimented with it on jsfiddle var basket=[{ "basketitems":[{"items":[]}], "itemdetails":[{ "amountPledged": "100", "bActivity": "Handloom Wo ...

How can you easily reuse an Ajax method in Vue.js by passing a Vue data array name as an argument?

After dedicating 9 hours to learning Vue.js, I have ventured into using it with JQuery Ajax. My challenge lies in making the last argument work as intended. Passing an array name expected to exist in vue data: {... seems to yield no results. Update: I hav ...

Add HTML content to a specific div according to the option selected in a drop-down menu

I am currently working on a project where I need a button to insert HTML content into a div based on the value selected in a select box. However, the functionality is not working as intended. Upon clicking the button, nothing happens. I am unsure of what t ...

Errors in socket.on Listeners Result in Inaccurate Progress and Index Matching for Multiple Video Uploads

Is there a way to make sure that the `socket.on('upload-progress')` listener accurately updates the upload progress for each video as multiple videos are uploaded simultaneously? Currently, it appears that the listener is updating the progress fo ...

Instructions on how to insert the meta tag with the attribute "http-equiv" set to "REFRESH" and the content "0; URL="somedomain"" into a division on a

Trying to send an ajax request to a page that includes the following meta tag: <meta http-equiv="REFRESH" content="0; URL=https://www.ohterDomain.com/help?nodeId=2&view=content-only"> After making a successful ajax call, the correct content is ...

Having trouble updating the icon on my website using FontAwsome

Just a heads up - I'm not familiar with HTML/CSS/JS. This template is pre-made, and I'm simply making some adjustments to it. Hello, I'm currently working on my portfolio website and I want to display my projects based on the programming la ...