Improperly aligned rotation using tween.js and three.js

Utilizing three.js and tween.js, my goal is to develop a Rubik's cube made up of 27 small cubes grouped together for rotation by +Math.PI/2 or -Math.PI/2. To ensure smooth rotation, I am implementing the tween library.

The specific issue I encounter is that if a face undergoes multiple rotations (more than 10), it becomes noticeably misaligned. Despite numerous attempts, I am unable to identify the solution for fixing this problem (view visual image of the issue).

Below is the function responsible for rotating the objects in the sample provided:

function rotate( ii ) {
    // Create a temporary object to group multiple objects together for rotation
    var rotationGroup = new THREE.Object3D();
    scene.add(rotationGroup);
    THREE.SceneUtils.attach( box[ ii ], scene, rotationGroup );
    rotationGroup.updateMatrixWorld();

    // Check for any active animations, and stop the function if so
    if( TWEEN.getAll().length > 0 )
        return;

    // Create the animation tween object
    var tween;
    var duration = 300;
    var radiants = Math.PI/2;
    tween = new TWEEN.Tween( rotationGroup.rotation ).to( { z: radiants }, duration );
    tween.easing( TWEEN.Easing.Quadratic.InOut );
    tween.onComplete(
        function() {
            THREE.SceneUtils.detach( box[ ii ], rotationGroup, scene );
            box[ii].updateMatrixWorld();
            scene.remove(rotationGroup);
        }
    );

    // Start the animation
    tween.start();
}

I am currently unable to create a functioning snippet on Stack Overflow, so I have included some code below replicating the issue within the example scenario provided:

var camera, scene, renderer;
var canvas;

var cameraControls;
var clock = new THREE.Clock();

var box = [];

// Additional functions and setup omitted for brevity

function rotate( ii ) {

    var rotationGroup = new THREE.Object3D();
    scene.add(rotationGroup);
    THREE.SceneUtils.attach( box[ ii ], scene, rotationGroup );
    rotationGroup.updateMatrixWorld();

    if( TWEEN.getAll().length > 0 )
        return;
    var tween;
    var duration = 300;
    var radiants = Math.PI/2;

    tween = new TWEEN.Tween( rotationGroup.rotation ).to( { z: radiants }, duration );

    tween.easing( TWEEN.Easing.Quadratic.InOut );
    tween.onComplete(
        function() {
            THREE.SceneUtils.detach( box[ ii ], rotationGroup, scene );
            box[ii].updateMatrixWorld();
            scene.remove(rotationGroup);
        }
    );

    tween.start();
}

// Additional scene setup and cube creation code

Logging the rotation values of rotationGroup and box[ii] to the console reveals a slight discrepancy in their rotations, with the Object3D rotation introducing a minor error on the fourth decimal digit.

Answer №1

I made some alterations to the anonymous function that runs after the tween finishes, incorporating code to verify the rotation and set the correct rotation value (credit to @WestLangley for identifying the solution).

 function() {
     THREE.SceneUtils.detach( box[ ii ], rotationGroup, scene );
     box[ii].updateMatrixWorld();
     scene.remove(rotationGroup);

     // Verify the rotation value and adjust accordingly
     var check = Math.floor( box[ii].rotation.z );
     if( check==1 )
         box[ii].rotation.z = Math.PI/2;
     else if( check==3 )
         box[ii].rotation.z = Math.PI;
     else if( check==-2 )
         box[ii].rotation.z = -Math.PI/2;
     else
         box[ii].rotation.z = 0;
 }

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

Issues encountered when trying to modify the Content-Type of POST requests using ngResource versions 1.0.6 and 1.1.4

Despite numerous attempts and trying various solutions found online, I am still unable to solve this issue. Similar questions have been asked in the following places: How to specify headers parameter for custom Angular $resource action How can I post da ...

Discovering a specific element using jQuery

I am trying to work with a div structure like this: <div class="country"> <div class="cty_popover"> <p>TITLE</p> <ul> <li>NAME 1</li> <li>NAME 2</li> ...

What is preventing the listener from activating?

I came across some HTML code that looks like this: <form id="robokassa" action="//test.robokassa.ru/Index.aspx" method="post"> <input type="text" id="OutSum" name="OutSum" value="" placeholder="Сумма пополнения"> ...

I'm encountering CORS issues while attempting to log in using guacamole from my React app. Can anyone advise on what might be causing this problem

Having trouble logging into the Guacamole form through a React JS web application. The Guacamole server is hosted on Tomcat server, while the React app is on Node.js; both operating on separate domains. Despite using Nginx proxy on the server, encounteri ...

Angular 2: Encounter with 504 Error (Gateway Timeout)

I am struggling with handling errors in my Angular 2 application. Whenever the backend server is offline, an uncaught error appears in the console: GET http://localhost:4200/api/public/index.php/data 504 (Gateway Timeout) This is how my http.get me ...

What causes the parent element's click event to trigger on its own when a child textbox is clicked or focused in Safari?

Describing my HTML setup [Checkbox] [Text] [Input element (Display if check-box is marked)] <span class='spGrpContainer'> <label id='stepGH_Group1' class='lblStep GHSteps lblGroupheader' stepid='1' st ...

Can an event be initiated on dynamically loaded iframe content within a document using the jQuery "on" method?

Is there a way to include mousemove and keypress events for iframes? The code provided seems to work well with existing iframes on the page, but it doesn't seem to work for dynamically created frames in the document using JavaScript. $('iframe&a ...

What is the correct location for the webpack.config.js file within a React project?

I recently inherited a React project that I need to continue working on, but I have never used React before. I've been advised to use a web worker in the project and have found a tool that seems suitable for my needs: Worker Loader The suggested meth ...

Zero-length in Nightmare.js screenshot buffer: an eerie sight

I'm currently working on a nightmare.js script that aims to capture screenshots of multiple elements on a given web page. The initial element is successfully captured, but any subsequent elements below the visible viewport are being captured with a l ...

Saving the AJAX response object in a global variable - Important fields are not being retrieved

Currently, I am developing an asynchronous webpage in Grails wherein I invoke a controller and display the response as a D3.js network. To ensure further usability, I saved the object as a global variable. Despite the successful execution of the function u ...

I'm curious about the meaning of "!" in pseudo-code. I understand that it represents factorial, but I'm unsure of how to properly interpret it

Can someone explain the meaning of ! in pseudo-code to me? I understand that it represents factorial, but for some reason I am having trouble translating it. For example: I came across this code snippet: if (operation!= ’B’ OR operation != ’D’ O ...

Error: The `queries` property is undefined and cannot be read (react.js)

Here is the code snippet I am currently working with: import { useState } from 'react' import { QueryClientProvider, QueryClient } from 'react-query' import { ReactQueryDevtools } from 'react-query-devtools' import Navba ...

I'm curious, what is the exact function of ...state?

Just dipping my toes into NgRx (redux) within Angular and I'm a bit puzzled by the use of ...state in the code snippet below. My understanding is that it functions as spread operator, but I can't grasp why the data attributes from the Interface S ...

Is it possible to replace JavaScript files that are included in my index page if I am utilizing conditional comments specifically for IE9?

My website works perfectly in all browsers, except for IE9. After some investigation, I discovered that the issue lies with a jQuery plugin called multilevelpush.js. While it works great on other browsers, it simply won't cooperate with IE9. Upon fur ...

Triggering event within the componentDidUpdate lifecycle method

Here is the code snippet that I am working with: handleValidate = (value: string, e: React.ChangeEvent<HTMLTextAreaElement>) => { const { onValueChange } = this.props; const errorMessage = this.validateJsonSchema(value); if (errorMessage == null ...

Tips for overlaying text onto a canvas background image

I'm curious about how to overlay text on top of an image that is within a canvas element. The image is a crucial part of my game (Breakout), so it must remain in the canvas. I've tried adding text, but it always ends up behind the image, which is ...

Verifying that a parameter is sent to a function triggering an event in VueJS

One of the components in my codebase is designed to render buttons based on an array of objects as a prop. When these buttons are clicked, an object with specific values is passed to the event handler. Here's an example of how the object looks: { boxe ...

Populate a database with information collected from a dynamic form submission

I recently created a dynamic form where users can add multiple fields as needed. However, I'm facing a challenge when it comes to saving this data into the database. You can view a similar code snippet for my form here. <form id="addFields" me ...

The generation of React Native Jest coverage results may vary depending on how an ES6 module is exported

I am working with a React Native button component that consists of its own index.js and styles.js files. The content of styles.js is as follows: import { StyleSheet } from "react-native"; export default StyleSheet.create({ container: { borderRadius ...

The Enigma of AngularJS Coding

Check out this code snippet. $scope.$watch('year', reloadData); $scope.$watch('month', reloadData); $scope.year = 2017; $scope.month = 1; var reloadData = function() { /* Refresh Data */ } var init = function() { $scope.year ...