How can I correctly rotate an object around a specific point using three.js?

Most tutorials/questions about three.js suggest using a parent object to rotate an object around a specific point. This involves creating a parent object at the desired position, attaching the object to it, and then rotating the parent to achieve the desired rotation for the child object.

//Create a pivot
var pivot = new THREE.Object3D();
//Create an object
var object = new THREE.Mesh( new THREE.BoxGeometry(2,2,2), new THREE.MeshBasicMaterial() );
//Attach object to pivot
pivot.add(object);

//Move object away from pivot
object.position.set(new THREE.Vector3(5,0,0));

//Rotate the object 90 degrees around pivot
pivot.rotation.y = Math.PI / 2;

While this method works, it has limitations as an object can only have one parent, restricting the ability to rotate around different points.

Another effective method is applying a rotated matrix to the object's position:

//Create an object
var object = new THREE.Mesh( new THREE.BoxGeometry(2,2,2), new THREE.MeshBasicMaterial() );
//Move the object
object.position.set(new THREE.Vector3(5,0,0));

//Create a matrix
var matrix = new THREE.Matrix4();
//Rotate the matrix
matrix.makeRotationY(Math.PI / 2);

//Apply the matrix to rotate the object
object.position.applyMatrix4(matrix);

However, this approach also lacks the ability to set a specific rotation point, always defaulting to the world origin.

There is an option in sceneUtils to detach and attach objects to different parents, but it is not recommended and rarely utilized in example code.

The ultimate goal is to make a cube follow an S-shaped path by rotating it around various points, a seemingly basic task that proves challenging without proper functionality.

In summary, I am seeking a way to rotate a three.js object around multiple different points. Any suggestions on how to achieve this would be appreciated.

Answer №1

Check out this answer for some guidance: Three JS Pivot point

When approaching this issue, there are various methods you can use. While swapping the pivot point in the parenting approach is one option, it involves a significant amount of work to convert the object position between different coordinate systems.

Alternatively, consider this approach (in pseudo-code):

  1. Move the object to the pivot point

    1.1. Subtract the pivot point from the original position of your object

  2. Apply the rotation

  3. Move the object back by the same position vector

    1.1. Add the pivot point to the new position of your object

Keep in mind that all calculations are done in world coordinates, so make sure to convert as necessary.

Answer №2

An easy fix: shift towards the anchor point, spin, then shift back.

Suppose you need to rotate a viewer around an anchorSpot (where viewer is a type of THREE.Camera and anchorSpot is a type of THREE.Vector3):

/// step 1: determine movement direction and distance:
let moveDirection = new THREE.Vector3(
    anchorSpot.x - viewer.position.x,
    anchorSpot.y - viewer.position.y,
    anchorSpot.z - viewer.position.z
);
moveDirection.normalize();
let moveDistance = viewer.position.distanceTo(anchorSpot);
/// step 2: shift the viewer to the anchor spot
viewer.translateOnAxis(moveDirection, moveDistance);
/// step 3: spin the viewer
viewer.rotateX(rotationX);
viewer.rotateY(rotationY);
viewer.rotateZ(rotationZ);
/// step4: move the viewer in the opposite direction
moveDirection.multiplyScalar(-1);
viewer.translateOnAxis(moveDirection, moveDistance);

Answer №3

This method has its limitations - for instance, rotating an object around a different point can be challenging because objects cannot have multiple parents.

While it is true that having two parents could provide more flexibility, the default behavior of this feature may lead to complications. For example, if a woman is holding a camera in a car, creating a nested hierarchy of parenting relationships, adding a second parent like a man holding the camera simultaneously could present challenges in terms of movement coordination. The concept of parallel parenting raises questions about how objects interact and move within the hierarchy.

To address this issue, you can detach an object from one parent and attach it to another. However, caution is advised when manually detaching objects as it can disrupt the positional relationship between the object and its parent.

Fortunately, there are tools available in SceneUtils specifically designed for transitioning objects between parents using the attach and detach functions. By utilizing these functions, you can transfer objects without experiencing inconsistencies in their positioning.

It's important to note that proper alignment between the new and previous parent locations is crucial during the handoff process to avoid unexpected results. Visit the link provided for further insights: https://i.sstatic.net/ZiS6o.png

Answer №4

To rotate an object around another object, the key is to make the object you want to rotate a child of the object it will revolve around.

Assuming you have set up the basics (scene, camera, and light) with an empty scene, you can create a visible object (such as a cube) and an empty object.

// creating a cube
const geometry = new THREE.BoxGeometry(5,5,5);
const material = new THREE.MeshStandardMaterial({roughness:1});
const cube = new THREE.Mesh(geometry, material);

// creating an empty point
const point = new THREE.Object3D();

Now that we have the cube and the empty point, we need to position the cube at a distance from the point in order for it to rotate around the point.

cube.position.setX(20);

Remember to only add the parent object to the scene since it already includes the child (adding separately will cause issues).

scene.add(point);

Next, make the cube the child of the point so that when the point rotates, the cube rotates along with it.

point.add(cube);

Finally, rotate the point around its axis.

function _render(){
    point.rotation.y += 0.006;
    window.requestAnimationFrame(_render);
    renderer.render(scene, camera);
  }
_render();

Understanding how children and parents interact is crucial - changing the parent's position will also affect the children's positions.

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

Exploring the power of React Hooks with the useState() function and an array filled

When creating new "Todo" items and modifying the fields, everything works fine. However, my problem arises when trying to retrieve the child data after clicking the "show all objects" button. To better understand my issue, here is a code example: const Co ...

Issue with dropdown list removeClass function

I am encountering an issue with the Jquery dropdown list click function. The addClass method is working properly, but the removeClass method is not functioning as expected. When I click on the dropdown list, it does not hide. Here is a live demo: http://j ...

Create personalized styles for each item within a stack with specific spacing using the @mui library

Is there a way to change both the background color and spacing area when hovering over each item in my list? https://i.stack.imgur.com/87TST.png <Stack spacing={4} divider={<Divider variant={`fullWidth`} orientation={`horizontal`} flexItem/>}> ...

Clicking to Load Images - Angular

Implementing a feature to load sets of images on button click instead of loading all at once. Although lazy load plugins are available, I decided to experiment with this approach. Here's the logic: Start with a data array called 'Images' co ...

How can you show a green check mark next to an input field in AngularJS after inputting valid data?

I am diving into the world of AngularJS and Angular Material with my web application. As a beginner in AngularJS and Angular Material, I need some help. My current task is to display a green checkmark next to an input field only when valid data is entere ...

Fill a form with jQuery and ajax data after it has been submitted

I'm working on a simple HTML form and I want to use Ajax to perform a lookup using a PHP file after entering data into the first field. The goal is to fetch information from an external source for the two remaining fields. <form method="post" acti ...

Determining the cursor location within a character in a div that is content editable using AngularJS

I am facing challenges with obtaining the cursor caret position within a contenteditable div. Currently, I am utilizing the following function : onBlurArea (field, ev) { ev.preventDefault() const editable = ev.target.childNodes[1].childNodes[2] ...

Is the ajaxToolkit PopupControlExtender malfunctioning? Could it be due to being outdated?

I recently tried following a tutorial on using ASP.NET Ajax Popup Control to display GridView row details. However, I encountered a runtime error when attempting to perform a mouseover action. The error message reads: Sys.ArgumentUndefinedException: Va ...

Unnecessary PHP code will run on its own in JavaScript

Attempting to initiate a session in PHP and assign a value to a session variable within a Javascript function on a PHP/HTML page is creating an issue. The problem arises when the PHP code inside the if statement runs automatically upon loading the page, ra ...

Newbie struggling with executing JavaScript in Visual Studio Code

Hey there! I'm new to coding and have been struggling for the past couple of hours trying to get a simple JavaScript code to run on VSC. Can anyone lend a hand in helping me set up my sandbox correctly? Here's a snapshot for reference: https://i ...

What are the steps to installing and utilizing the Chart.js package on your local machine?

I thought installing chart.js on my Raspberry Pi would be a simple task, but I seem to be struggling with it. Due to the nature of my project, I need to have it installed locally rather than relying on an online version. Following the usual steps, I navig ...

Failed to retrieve the requested item using fetch, encountering a NetworkError

My API is being accessed to retrieve data using this code snippet. It sends the email and password to the API: onSubmitSignIn = () => { fetch('http://localhost:3001/signin', { method: 'post', headers: {'Content-Type&ap ...

Passport.js does not provide authentication for server-side asynchronous requests

Recently, I configured Passport.js with the local-strategy on my express server. Interestingly, when I am logged in and send an asynchronous request within NextJS's getInitialProps, it allows the GET request through client-side rendering but not serv ...

Using v-bind to dynamically set styles in Vue.js

While utilizing v-bind:style to apply dynamic values, I encountered an issue where v-bind:style did not seem to work. However, in the console, I verified that v-bind:style was receiving the correct value (:style='{ color : red (or any other value) }&a ...

Unusual happenings when adjusting camera settings in three.js

After creating a basic three.js application that displays a cube and includes buttons to set fixed camera positions, I encountered some unexpected behavior. You can view a demo of my code here: https://jsfiddle.net/ph0ropg7/9/ In my application, I have im ...

Modifying text on input buttons using Javascript

Including product names, text forms, and buttons on a webpage is essential for showcasing products effectively. Each product is assigned an ID such as p1, p2, etc., while the input types are identified by i1, i2, etc. When users enter information into the ...

Is there a way to easily identify the error in my Express application that is preventing my hbs template from running properly?

I am facing an issue with my express code where it is not rendering the data properly. Can someone please assist me in resolving this error? Your help will be greatly appreciated! let express=require('express'); let app=express(); ...

Apps hosted on Heroku are restricted from accessing CORS, even within the platform's domain

I've been struggling with this problem for a while now. My Nuxt app and service are both hosted on Heroku. After ditching cors(), I added the following code: app.use(function(req, res, next) { res.header("Access-Control-Allow-Origin", '*&ap ...

How to get an empty object as a response in a NODE.JS request?

For some reason, I am attempting to send an object to my backend. Even though I can retrieve valuable information from my network's payload, my req.body consistently returns an empty object. View my issue ...

The content in ACF appears to be missing when displayed in the fancybox

I have configured ACF to appear in a fancybox. The fields are being pulled in (as I can see the hardcoded header information), but nothing from the ACF appears. I have linked it to call an ID, which is then associated with the section that should be displa ...