Rotation of objects around a sphere in Three.js

Recently, I've been delving into threejs and encountered some challenges while attempting to rotate a globe with miniature spheres on its surface.

If you're interested, you can find my code here: https://github.com/rohanbhangui/globe-webgl

For a sneak peek at my work, check out this temporary link:

Here's what I'm aiming for:

  • Users should be able to rotate the globe using their mouse, causing the entire scene to rotate accordingly.
  • Upon clicking on a green blob, a specific part of the mouseup event should trigger, resulting in the globe (along with the green blobs) rotating to position the clicked blob at the center of the screen.

I've experimented with various approaches (except, of course, the actual solution!), but haven't found success yet.

Your assistance would be greatly appreciated. (Please excuse the messiness of my code)

Answer №1

Working with latitude and attitude points involves calculating phi and theta in the following manner:

var phi = (90 - varible1) * Math.PI / 180;
    var theta = (-variable2) * Math.PI / 180;
    var RandomHeightOfLine = 1.5 // Choose a value greater than the distance of your point to the origin

For Vector calculations:

new THREE.Vector3(RandomHeightOfLine * Math.sin(phi) * Math.cos(theta), RandomHeightOfLine * Math.cos(phi), RandomHeightOfLine * Math.sin(phi) * Math.sin(theta)));

For Point calculations:

var x = RandomHeightOfLine * Math.sin(phi) * Math.cos(theta);
var y = RandomHeightOfLine * Math.cos(phi);
var z = RandomHeightOfLine * Math.sin(phi) * Math.sin(theta);
controls.target.set( x, y, z );

To move the camera as well, consider calculating x2, y2, z2 with a greater RandomHeightOfLine.

For smooth movements, it's recommended to use TWEEN:

                var t;
                var t2;
                var t3; // Make them Global or use Array to prevent GC from removing Tween objects.
                function tweenCamera(position, target, time){
                    console.log("tween");
                    updateTween = true;
                    beforeTweenPos = camera.position.clone();
                    beforeTweenTarg = controls.target.clone();
                    t = new TWEEN.Tween( camera.position ).to( {
                        x: position.x,
                        y: position.y,
                        z: position.z}, time )
                    .easing( TWEEN.Easing.Quadratic.In).start();
                    t2 = new TWEEN.Tween( camera.up ).to( {
                        x: 0,
                        y: 1,
                        z: 0}, time )
                    .easing( TWEEN.Easing.Quadratic.In).start();
                    t3 = new TWEEN.Tween( controls.target ).to( {
                        x: target.x,
                        y: target.y,
                        z: target.z}, time )
                    .easing( TWEEN.Easing.Quadratic.In)
                    .onComplete(function () {
                        updateTween = false;
                        console.log("Turning off Update Tween");
                        t = null;
                        t2 = null;
                        t3 = null;
                    }, this).start();

                    //camera.up = new THREE.Vector3(0,0,1); // Turn off animation for camera.up if not needed and remove t3. 
                }

Ensure to update your animation as follows:

...
                            lastTimeMsec    = lastTimeMsec || nowMsec-1000/60;
                            deltaMsec   = Math.min(200, nowMsec - lastTimeMsec);
                            lastTimeMsec    = nowMsec;
                                if(updateTween)
                                {
                                    TWEEN.update(lastTimeMsec); //Comment
                                } else {
                                    TWEEN.removeAll();
                                }
...

For Tween JS library, visit:

Answer №2

You've already implemented this in your code, I simply copied it from your original creation. You can refer back to your example here:

if(intersects.length >= 3)
    {
      for(var i = 0; i < vlist.length; i++)
      {
        if(vlist[i][0].position === intersects[0].object.position)
        {
          console.log("that point exists! Add code below to rotate to the green blob");
             targetRotationY = targetRotationYOnMouseDown + ( mouse.y - mouseYOnMouseDown ) * 0.01 *75/targetDistance;
             targetRotationX = targetRotationXOnMouseDown + ( mouse.x - mouseXOnMouseDown ) * 0.01 *75/targetDistance;
          break;
        }
      }
    }

Answer №3

After 8 long years, I have found myself back at the same problem but on a different project. I wanted to share a solution that worked for me in hopes that it may help others.

Ultimately, I decided to utilize the three-globe package as I am working on coding it in react with react-three-fiber. I came across this code that helped me achieve the rotation I needed once the scene loaded. I'm still trying to wrap my head around how it all works, but I am incredibly grateful for that package. Be sure to check it out!

I also want to extend my gratitude to those who offered solutions in the comments below. Your contributions were greatly appreciated!

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

A Vue.js component modifies one store state variable but leaves another unchanged

Currently developing a Vue 3 application that utilizes Vuex and the Composition API. Encountered an issue while working on it. A component is supposed to display elements based on the state of two store variables. One is an array, and the other is a bool ...

Step-by-step guide on utilizing the material-ui AutoComplete feature to filter a table by selecting a key from a list and manually entering

I'm working on developing a filtering system similar to the AWS Dashboard, where users can select a filter key like instance state, which then displays the key in the input field and allows the user to enter a value to search for. I'm attempting ...

Issues arise when using res.send() with ExpressJS and Mongoose

Initially, I have multiple callbacks that need to be executed before sending a res.send() to construct a JSON API: app.get('/api', function (req, res){ ... function logPagesId() { console.log("load: " +pagesId); c ...

Exploring the possibilities of DOM events within nodeJS and express

Does anyone have experience catching a DOM event with NodeJS and Express? I've been looking into the "socket.io" module but am having trouble using it properly. My goal is to run some code whenever the content of a "file input" changes in the DOM. & ...

The Jquery append function is limited to the initial ajax request, necessitating a page refresh in order to populate another div with the desired

When making an AJAX request to retrieve a JSON array, upon successful completion another AJAX request is triggered. The retrieved data is then populated into the div of a bootstrap modal using the jQuery append function. Everything functions as expected ...

Paginating content without the need for a database

Seeking assistance on implementing pagination for displaying trading history API responses, without utilizing a database. Can anyone provide guidance and help with the necessary logic? Here is an excerpt of my code: <?php error_reporting(E_ALL) ...

Tips on skipping the need to repeatedly use `@ApiProperty()` for every dto in NestJs-swagger

I'm currently exploring ways to streamline the process of specifying @ApiProperty() for each DTO. I've heard about a method involving the creation of a nest-cli.json file, where if you define Promise<DTO> in your controller within nest-swa ...

straightforward multiple second timer

I have multiple <span class="timer">342</span> elements with different values (in seconds). I am trying to create a countdown timer for all of them by using the following code: $('.timer').ready(function() { ...

Locate and eliminate the item containing specific content

There are many <p> &nbsp </p> tags scattered throughout the description. I need to locate and delete any tags that contain only &nbsp. The description is enclosed in a container with the class name of desc_container. Below is an exampl ...

Interact with the button through Swipe Left and Right gestures

Is it possible to trigger a button click using JQuery or JavaScript when swiping left or right on two buttons like these? <button id="right" type="button">SWIPE RIGHT</button> <button id="left" type="button">SWIPE LEFT</button> If ...

Looking for a JavaScript function that will enable the acceptance of commas and spaces

How can I modify this integer validation function to allow for commas and spaces to be entered during the keydown event? function intValidate(event) { if (event.keyCode == 46 || event.keyCode == 8 || event.keyCode == 9 || event.keyCode == 27 || even ...

Dragging elements using the jQuery UI Draggable feature onto a designated droppable area

Struggling to implement a Draggable element on Droppable element using jQuery UI? I almost got it working, but the elements on the droppable area keep changing their positions when moved slightly. I want them to stay put, but return to their original place ...

Having trouble with Node.js GET request functionality not functioning properly

I've been encountering difficulties with loading a page using Node.js. While my Node.js Application code functions properly when attempting to load other resources such as www.google.com, it seems to encounter issues specific to the domain name www.eg ...

Issue: Unhandled ReferenceError - onChangeAssignedGroup function is not declared within scope at HTMLSelectElement.onchange

Having difficulty calling a PHP script via JavaScript when the user changes the value in the "Assigned To Group" selection. The goal is to modify the option list of a yet-to-be-created "Assign to User" selection. An error message pops up stating that it d ...

Where should I place the .filter method within my jQuery AJAX call?

I'm currently utilizing a "GET" request to fetch data from this API While the "GET" request works properly, I'm facing an issue where some objects don't have image thumbnails to use as my source. I want to filter these out, but I'm uns ...

A Great Option for Easy Drag and Drop Functionality

Currently researching options for Drag and Drop functionality with items such as images and textareas. Need a solution that provides coordinates of where the item is dropped on screen, saves it, and allows placement in the exact same location later. Desir ...

The JavaScript function Date().timeIntervalSince1970 allows you to retrieve the time

For my React Native app, I currently set the date like this: new Date().getTime() For my Swift App, I use: Date().timeIntervalSince1970 Is there a JavaScript equivalent to Date().timeIntervalSince1970, or vice versa (as the data is stored in Firebase clo ...

Ways to identify when a file download has finished with the help of javascript

let pageUrl = "GPGeneration_Credit.ashx?UniqueID=" + __uniqueId + "&supplierID=" + supplierID + "&CreditID=" + OrderIds; window.open(pageUrl); // Want to check if the file download is complete and then refresh the page location.r ...

"Using Vue 3 to teleport content to a specific element and swap out existing

I've successfully implemented the use of Vue 3 teleport to display elements within a div. Although teleport adds items to the specified element, it doesn't replace existing elements in the div. Is there a way to configure teleport to replace th ...

The modification of HTML styles

How can I change the style (width, color etc) of all 8 functions like this? function my(){document.getElementById("question1").innerHTML="THIS QUESTION"+ "<br>" +"<button onclick=answer1() id=ques1 >first answer</button>" +"<button ...