Rotating a Three.js sphere to a custom position

With the use of Three.js, I have a globe with attached sprites representing volcano points. When I rotate the globe, the sprites remain in their designated positions because they are grouped with the sphere.

Now, I am looking to implement a feature where I can spin the globe to a specific position using a button. For instance, if the desired point is at the back of the globe, how can I rotate it to be at the front?

This is the current code structure I have - a main mesh to which sprites are added:

 <html>
<head></head>
<body>


<script src="three.min.js"></script>

<script>

  var scene, camera, renderer;
  var geometry, material, mesh;

  init();
  animate();

  function init() {

      scene = new THREE.Scene();
      camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 10000 );
      camera.position.z = 1000;

      material = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: false } );

      geometry = new THREE.SphereGeometry( 159, 32, 32 );
      mesh = new THREE.Mesh( geometry, material );
      scene.add( mesh );

      var map = THREE.ImageUtils.loadTexture( "sprite1.png" );
      var material2 = new THREE.SpriteMaterial( { map:map, color:0x00ff00 } );
      var sprite1 = new THREE.Sprite( material2 );
      sprite1.position.set(100,100,100);
      sprite1.scale.set(40,40,40);
      mesh.add(sprite1);

      var sprite2 = new THREE.Sprite( material2);
      sprite2.position.set(-100,-100,-100);
      sprite2.scale.set(30,30,30);
      mesh.add(sprite2);

      var sprite3 = new THREE.Sprite(material2);
      sprite3.position.set(100,-100,100);
      sprite3.scale.set(20,20,20);
      mesh.add(sprite3);

      renderer = new THREE.WebGLRenderer({alpha:true});
      renderer.setSize( window.innerWidth, window.innerHeight );

      document.body.appendChild( renderer.domElement );

  }

  function animate() {
      requestAnimationFrame( animate );
      mesh.rotation.y += 0.01;
      renderer.render( scene, camera );
  }

 </script>
</body>
</html>

Example Diagram

Answer №1

Here is the approach I would take:

// When sprite is a child of mesh, obtain its world position
var spritePos = new THREE.Vector3().setFromMatrixPosition(sprite.matrixWorld);

// Calculate vectors needed to determine angle
var cv3 = new THREE.Vector3().subVectors(camera.position(), mesh.position);
var sv3 = new THREE.Vector3().subVectors(spritePos, mesh.position);

// To rotate around y-axis only, focus on angle in x-z-plane
var cv2 = new THREE.Vector2(cv3.x, cv3.z);
var sv2 = new THREE.Vector2(sv3.x, sv3.z);

// Normalize Vectors
cv2.normalize();
sv2.normalize();

// Dot product calculation
var dot = cv2.dot(sv2);

// Determine angle between sprite and camera in radians
// Cosine ranges from 1 to -1, so normalize, invert, and multiply by PI for correct angle
var angle = (1 - (dot + 1) / 2) * Math.PI;

// Is the sprite positioned left or right of the camera?
if(spritePos.x < 0)
  mesh.rotation += angle;
else
  mesh.rotation -= angle;

I have created a Plunker example.

There may be slight inaccuracies as it always rotates slightly left or right to face the front position, possibly due to specific cosine angles.

Also, note that determining whether the sprite is left or right of the camera becomes more complex if the camera or mesh is located elsewhere in the scene.

Explanation on dot product:

The dot product provides the angle between two vectors as cosine. The result ranges between -1 and 1. For instance, cos(0) = 1, cos(PI/2) = 0, cos(PI) = -1. Currently, 0° equals 1 and 180° equals -1.

We aim to obtain the angle in radians for rotating the mesh in position. First, we normalize it as (dot + 1) / 2, making 0° equal 1 and 180° equal 0.

Then invert it (0° = 0, 180° = 1) and multiply by PI (0° = 0, 180° = PI).

Now, we have the rotation angle, but we need to ascertain whether to rotate left or right, hence the check for the sprite's relative position to the camera.

I hope this explanation suffices and is understandable?

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

Utilize data from API responses to configure settings in angular-datepicker using pickadate.js

I am attempting to configure the options for the angular-datepicker, which is utilizing pickadate, by fetching data from a web-api call. Here is my current code: <label for="datepicker">Date:</label> <input type="text" id="datepicker" pick ...

A guide on utilizing the index column for multiple tables using just one statement in the datatable js library

I've incorporated the datatable js for managing two tables on a single page. HTML <!-- Table#1 --> <table class="dataTable"> <thead> <tr> <td>#</td> <td>col1</td> </tr> &l ...

Increase the spacing between the column label and the x-axis label in a c3 chart

Take a look at the chart below, I'm attempting to create some additional spacing between the column labels and the x-axis label. https://i.sstatic.net/R7zqN.png I experimented with adding this CSS style: text.c3-axis-x-label { margin-top: 10 ...

Watchify fails to detect any modifications in the directories above

I currently have multiple apps stored in a single folder with a shared dependency. /app/app1/src/main.js /app/app2/src/main.js /app/app3/src/main.js /common/tools.js Each of these apps has its own instance of Watchify running, and any changes trigger a r ...

Utilizing div tags for creating backgrounds in HTML

I am currently in the process of developing a website and would like to incorporate particles.js as my background while overlaying the content. However, I'm facing an issue where the content is displaying on top of the page instead of behind it when I ...

How can I create the effect of text changing color automatically after a specified time period has elapsed

I am currently dealing with a timer that is functioning properly, but I have a specific CSS inquiry. Essentially, what I would like to achieve is when the timer hits 30 seconds, I want the numbers to change to red color. $(function () { var $startTimer = ...

Getting the value from a .sh (Shell Script) file in React: How to do it?

There is a .sh file that contains the following code: echo "Hello" This code produces the output: Hello The question at hand is: I am trying to extract the output from the .sh file and integrate it into my React application. After exploring various ...

Need to get an item from a collection at the library?

Is it possible to import and use an object from a library? For instance, suppose we have a file named data.js with the following content: return { "name": "Testing" } In the file index.js, could we do something like this: const data = require('. ...

How can I trigger a click event on a link using JQuery?

One of my links has the unique id: nyhedsklik There is a function associated with this link that activates when it is clicked: $('a.poplight[href^=#]').click(function() { var popID = $(this).attr('rel'); //Fetching Popup ...

Can props.children be given a ref without any existing ref?

Consider this scenario... MainComponent.js <Wrapper> <p ref={React.createRef()}>{state.item1}</p> <p>{state.item2}</p> <p>{state.item3}</p> <p>{state.item4}</p> </Wr ...

Troubleshooting issues with ng-options not correctly updating ng-model in AngularJS when using ajax requests

I have a question regarding my logic that I can't seem to figure out. In this Fiddle example, everything works fine without using AJAX or a timeout. However, when I try to implement the same logic with a timeout/ajax, the expected behavior does not o ...

I'm having trouble with the routing of a Node.js REST API built with Express and Mongoose

I am currently in the process of constructing a RESTful webservice by following a tutorial that can be found at: However, I have encountered an issue where it is returning a CANNOT GET/ reports error. Despite my efforts to troubleshoot and rectify the pro ...

What steps should I take to resolve the error: Uncaught SyntaxError: expected expression, received '<'?

I'm facing an issue with my code. It works perfectly on my computer, but when I move it to the server, I encounter the following error. Error: Uncaught SyntaxError: expected expression, got '<' Here is the code snippet causing the prob ...

What is the method for creating an array of strings in VueJS?

In my VueJS and Vuetify project, I am working on creating a modal that allows users to input strings into a text field. What I aim to achieve is adding the inputted string to an array when the user clicks on create button. For example, if I enter 'inp ...

Make sure to incorporate certain node_modules folders within Babel 7

My issue involves a dependency located in the node_modules directory that requires compilation through Babel. Despite upgrading my stack, I am unable to get Babel to compile the dependency. Current versions: @babel/core 7.5.4 webpack 2.7.0 Here is my w ...

open() the html file containing dojo elements

I have a simple Dojo chart that functions perfectly in a separate document. However, here lies the issue, When I use $('#result').load('dojo.html'); to import the file, nothing occurs - the page does not load the graph. On the other h ...

Is there an issue with invoking Spring controller methods from JavaScript (via ajax) that is causing them

Using JavaScript to send a request to a method in Spring controller, the code looks like this: <script language="javascript" type="text/javascript"> var xmlHttp function show() { if(typeof XMLHttpReques ...

What is the best way to update content without having to refresh the entire page?

I need to update the content of the page without having to reload it using JavaScript. Unfortunately, my current method isn't working. window.location.assign("#/invoice/" + $scope.invoiceId); ...

Leveraging the keyword 'this' within an object method in node's module.exports

My custom module: module.exports = { name: '', email: '', id: '', provider: '', logged_in: false, checkIfLoggedIn: function(req, res, next){ console.log(this); } }; I inclu ...

Efficiently uploading multiple files using AJAX in conjunction with Codeigniter

Greetings! I'm attempting to utilize ajax and codeigniter to upload multiple images. As a beginner in ajax and jquery, I would greatly appreciate any assistance in identifying where I might be going wrong or missing something. Below is my controller ...