Manipulating the rotation of a group in three.js smoothly transitions between angles, but upon clicking the mouse, it reverts back to

Seeking assistance in tweening the rotation of a group in three.js. While I can successfully rotate it, the issue arises when attempting to rotate the group again - it resets back to its original position. I believe there is a simple solution to this problem, but I am struggling to pinpoint it. Any guidance or suggestions would be greatly appreciated.

Please refer to my fiddle for reference: https://jsfiddle.net/jacob_truax/bw3pmLk1/59/

This is the code snippet I have used for the tweening effect:

  let isMouseDown = false
  let startX = 0
  let startY = 0

  document.addEventListener("mousedown", function () {
    isMouseDown = true
    startX = event.pageX
    startY = event.pageY
    document.body.style.cursor = 'grabbing';
  })

  document.addEventListener("mouseup", function () {
    isMouseDown = false
    document.body.style.cursor = 'grab';
  })

  document.addEventListener("mousemove", function (event) {
    if (isMouseDown) {
      document.body.style.cursor = 'grabbing'
    }

    aimX = ((window.innerWidth / 2) - event.pageX) * 0.35
    aimY = ((window.innerHeight / 2) - event.pageY) * 0.5


    if(isMouseDown) {
      aimX = aimX + (event.pageX - startX)
      aimY = aimY + (event.pageY - startY)
      group.rotation.set(0, ((aimX + (event.pageX - startX)) + (aimY 
+ (event.pageY - startY))) / 900, 0)
    }
  })

Answer №1

When the mouse is dragged, the group is already rotated and the .rotation is set to a specific value. Using THREE.Euler.set() will reset the current rotation and apply an entirely new one, bringing back the rotation to its original orientation.
To combine the new rotation with the existing rotation, a common method involves calculating a rotation matrix for the new rotation, applying it to the current matrix, and then setting the result as the new rotation for the group.

rotation = new_rotation * current_rotation

In THREE.js, the .rotation property represents a THREE.Euler object - for more information on Euler angles see here.
The method Matrix4.makeRotationFromEuler can convert Euler angles into a 4x4 rotation matrix.
Using Matrix4.multiplyMatrices, two matrices can be concatenated together.
Lastly, Euler.setFromRotationMatrix helps in converting a 4x4 rotation matrix back to euler angles.

To retrieve the current rotation matrix from the group:

let currentRotation = new THREE.Matrix4();
currentRotation.makeRotationFromEuler(group.rotation);

Next, define the rotation matrix with the new rotation component using Euler angles:

let newEuler = new THREE.Euler(0, (event.pageX - startX) / 900, 0);
let newRotation = new THREE.Matrix4();
newRotation.makeRotationFromEuler(newEuler);

Applying the new rotation to the current rotation:

let finalRotation = new THREE.Matrix4();
finalRotation.multiplyMatrices(newRotation, currentRotation);

Set the final combined rotation to the group:

group.rotation.setFromRotationMatrix(finalRotation); 

Since the rotation is now applied to the group, remember to update the values of startX and startY to match the current mouse position:

startX = event.pageX;
startY = event.pageY;

Here's the revised code based on the suggestions. You can refer to the example below:

// Your modified code goes here...

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

Innovative react route

Currently, I am in the process of learning about dynamic react routes. In the code example I am working on, there are different buttons for each task. The goal is to render the WorkDetails component when a button is clicked. However, it seems to not be fun ...

Editing an XML file on the browser and saving it in its original location on the local file system

Seeking assistance with editing an XML file directly from the browser on a local file system and saving it back to its original location. I have conducted extensive research using Google, but have not been able to find a suitable solution. Any help or gu ...

Save the output of a function in node.js

I have created a function that utilizes the nodejs module recursive-readdir to read all files within a folder recursively. The function is functioning correctly, but I am facing an issue with exporting the 'routes' array using 'module.export ...

Retrieve the value of an object without relying on hardcoded index values in TypeScript

I am working with an object structure retrieved from an API response. I need to extract various attributes from the data, which is nested within another object. Can someone assist me in achieving this in a cleaner way without relying on hardcoded indices? ...

What is the method to deactivate the date field by using an attribute?

In an attempt to disable a field using an attribute without utilizing the directive scope property, I am seeking a way to disable my field with the type 'date'. Check out my code snippet below: http://plnkr.co/edit/eJDRocLYkr8Krh84vFKY?p=previe ...

How AngularFire automatically adds back a removed item in a Firebase array

I have been working on a way to remove an item from my $firebaseArray called "boxes". Here is the "remove" function: function remove(boxJson) { return boxes.$remove(boxJson); } Although it gets removed, I noticed that it immediately reappea ...

Error: undefined property causing inability to convert to lowercase

I am encountering an error that seems to be stemming from the jQuery framework. When I attempt to load a select list on document ready, I keep getting this error without being able to identify the root cause. Interestingly, it works perfectly fine for the ...

Managing time in an Angular application using Typescript

I am facing an issue with formatting the time obtained from an API in my FormArray. The time is received in the format: 14.21.00 My goal is to convert this time to the following format: 2:21 PM I have attempted to format it using Angular's DatePip ...

Choose an input field using jQuery that is specified by its name

I am currently using jquery form validator to validate all the fields within my form. Within the form validator, I have implemented the following code snippet to determine if an input field is labeled with the name minExperience. errorPlacement: function ...

How can I assign a distinct background color to individual sections in Chart.js?

Wanting to Customize Grid Background Colors in Line Chart using react-chartjs-2 I am looking to have different background colors for each grid in my Line chart. Is this functionality possible with the react-chartjs-2 library? This is the desired appearan ...

PHP question about maintaining data continuously

So, I've created this interesting JavaScript 'thing' with the help of jQuery and AJAX. The main concept behind it is that a div can be edited (contenteditable=true), which sparked the idea to develop a chatroom-like feature. It's pretty ...

Is there a benefit to storing DOM elements in a variable instead of directly adding them to the DOM with jQuery?

I am currently developing a plug-in that retrieves a section of a remote webpage and saves it for use in a jQuery UI dialog widget. Initially, I was adding the HTML to the DOM and hiding it using display:none until it was needed with $.dialog. However, I r ...

Activate radio button exclusively for admin user

My current application includes an admin panel with functions to manage users. I use a while loop in the form creation to display 3 user types: Admin, Manager, and User, which are pulled from a database. Admin Manager User This is how my HTML Form look ...

What is the process for submitting data using AJAX in Django?

I am facing an issue with my dynamically updating form. When I submit the form, I want to post the data to a views function and receive a response. Below is the code from my template file: $("#myForm").submit(function(){ event.preventDefault(); va ...

Transferring user inputs to the server through jQuery-AJAX

I've encountered some issues when trying to send form data inputs to the server. Despite alerting each form input, I keep getting empty alerts. Here's my code snippet: With my current code, it only alerts 0. However, posting normally seems to wor ...

Tutorial on creating a subset of a series using jqplot

I am looking to display three series on the same canvas. The series are defined as follows: rec1 = [0, 0, 150, 200, 0 ]; rec2 = [60, 120, 179, 240, 300]; rec3 = [50, 100, 150, 200, 250]; Below are the source codes I am using to draw these series. $ ...

Expanding - THREE.MeshBasicMaterial

I am interested in duplicating THREE.MeshBasicMaterial and developing my own customized material from it by making some modifications to the shader and adding new uniforms. I believe I can handle the uniform additions without any issues. Initially, I woul ...

Is there a way to retrieve the href value from a modal window upon clicking the link?

When clicking on the a href, I am attempting to retrieve a value in my pop-up window. I am using magnificPopup JavaScript Below is the code for my a href tag and I want to fetch the "data-stream" value in the pop-up window. <a class="popup-with-zoom ...

What is the best way to send and utilize a variable from app.js in index.ejs?

Why are my attempts to pass variables from app.js to index.ejs not working? I am using Mongoose and EJS, and I want to display database data on my web-page instead of just using console.log(). How can I do this correctly? (app.js snippet followed by inde ...

Validating Forms in AngularJS: Ensuring At Least One Input Field is Not Empty

Consider the following basic HTML form: <form name="myForm" action="#sent" method="post" ng-app> <input name="userPreference1" type="text" ng-model="shipment.userPreference" /> <input name="userPreference2" type="text" ng-model="shipm ...