Rotating a rectangular sprite around a sphere in three.js while keeping a minimum distance

In a three.js environment, featuring a static camera, and a sphere positioned at 0,0,0, along with a rectangular sprite (such as a text label) of varying dimensions, I am seeking a 'threejs method' or formula to enable the rotation of the sprite around the sphere without any clipping, while maintaining the minimal radius possible.

My current approach involves calculating the polar coordinates of the sphere's position and then adjusting the sprite by a multiple of its active dimension as it gets closer to the sphere's center. This has been slightly modified as follows:

const xPolar = Math.sin(phi) * Math.sin(theta);
const yPolar = Math.cos(phi);
const zPolar = Math.sin(phi) * Math.cos(theta);
const x = xPolar + sprite.radius * xPolar;
const y = yPolar + sprite.radius * yPolar;
const z = zPolar + (theta < 0 ? -sprite.radius : sprite.radius) * xPolar // ahem;

View a functional demonstration here: https://codepen.io/theprojectsomething/full/xadQvK/

Please take note of the potential clipping issue when phi approaches the poles. While not severe in the example, I am optimistic that there might exist a more refined solution from an individual who comprehends the dynamics involved on a deeper level!

Additional Information:

  • Aware of the three.js Spherical class; manual computations are utilized for clarity.
  • The default coordinate space in three.js is employed in this illustration. Any adaptable resolutions will be welcomed!

Answer №1

Let's formalize our approach starting with the assumption that we are situated in a coordinate system where the sphere resides at the origin and the z-axis represents the view direction. If we find ourselves outside of this coordinate system, converting the input data to align with it is relatively straightforward. After performing the necessary calculations, we can effortlessly revert back to the original coordinate system.

We possess a directional vector d that indicates the desired center point of the sprite (referred to as xyzPolar in your code snippet). Additionally, we have information regarding the width w and height h of the sprite, understanding that the width extends along the x-axis while the height extends along the y-axis (due to the nature of the view-aligned coordinate system).

For any arbitrary scalar offset t, we can define the center of the sprite as t * d. Subsequently, the points on the sprite are determined by the following set:

{ t * d + x * (w/2, 0, 0) + y * (0, h/2, 0) | -1 <= x <= 1, -1 <= y <= 1 }

The parameters x and y represent the positional coordinates on the sprite, where (-1, -1) signifies the bottom left corner and (0, 0) represents the center. Our specific interest lies in determining the point closest to the center of the sphere, featuring a distance of r (equivalent to the sphere's radius). Hence:

     min          (t * dx + x * w/2)^2 + (t * dy + y * h/2)^2 + (t * dz)^2 = r^2
x, y in [-1, 1]

If we possess knowledge of the parameters x and

y</code) pertaining to this closest point, we can effectively solve for <code>t</code, thereby obtaining the final position of the sprite's center.</p>

<p>However, in the absence of these parameters, let's dissect this formula:</p>

<pre><code>(    min     (t * dx + x * w/2)^2 ) + (    min     (t * dy + y * h/2)^2 ) + (t * dz)^2 = r^2
 x in [-1, 1]                          y in [-1, 1]

The first two terms are minimized if we set

x = -2 dx t / w
y = -2 dy t / h

In such instances, both terms would equate to zero, allowing us to derive t = r / abs(dz). Essentially, this will position the sprite on the xy-aligned plane where z = +- r. This scenario holds true when dealing with an infinite sprite, without imposing restrictions on x and y.

Regrettably, we are not working with an infinite sprite. It becomes imperative to confine x and

y</code) within the permissible range. Therefore, upon identifying a potential <code>t
, it is crucial to verify its validity by computing x and
y</code using the aforementioned formulas and ensuring their compliance with the allowable boundaries. Validation occurs if the nearest point exists within the sprite's central region as opposed to residing on an edge or corner.</p>

<p>Fortunately, the number of viable values for <code>x
and y that necessitate examination is limited. The algorithm orchestrates the calculation of t across all prospective values, validates the solution, and retains only the substantiated outcome. What possible values exist for x and y?

We are already familiar with scenarios under -1 <= x <= 1 and -1 <= y <= 1. All values within this bracket remain equivalent since they nullify the initial two terms (thus having no bearing on the eventual result). Furthermore, alternative cases emerge for each variable, wherein either x = -1 or

x = 1</code) (likewise for <code>y</code). This gives rise to a compilation of nine permutations requiring resolution. Yet, optimization abounds. Given that <code>t
, w</code), and <code>h assume positive values, x</code) and <code>y exhibit an inverse association with
dx</code) and <code>dy</code) respectively. For instance, if <code>dx
proves positive, scrutinizing instances where x = -1 suffices or leads to the vanishing of the initial term (effectively precluding the possibility of the sprite's right boundary serving as the closest point provided the direction vector extends rightward). Similarly, when
dx</code) or <code>dy</code) emulate exact zeroes, immediate deduction involves the erasure of the corresponding term, obviating the need to consider the counter case. In addition, should <code>dz = 0</code), bypass evaluation of situations where the inaugural pair of terms diminishes.</p>

<p>As a result, the process condenses down to four circumstances. A brief recap entails highlighting the quadratic equations attributable to the three distinct cases for each variable:</p>

<pre><code>            first term
-1 = x      dx^2 * t^2 - dx * t * w + w^2 / 4
-1 < x < 1  0
     x = 1  dx^2 * t^2 + dx * t * w + w^2 / 4

            second term
-1 = y      dy^2 * t^2 - dy * t * h + h^2 / 4
-1 < y < 1  0
     y = 1  dy^2 * t^2 + dy * t * h + h^2 / 4

Upon adjudicating the four cases warranting evaluation, expedite solving for

t</code), subsequently determine <code>x
and
y</code before confirming whether they align with the specific circumstance (e.g., if presented with <code>x = 1
, cross-check against x >= 1 et cetera). Finally, compute the sprite center via t * d.

In essence, although not necessarily more elegant than existing methods, the elaborated approach ensures enhanced accuracy.

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

Preventing jQuery from removing child elements while inserting data through ajax

When I try to insert data into an HTML structure using the code below, only one of the elements displays at a time. It seems like when I use Ajax to insert data, the child elements are being removed. How can I prevent this without having to change the stru ...

How to retrieve the latest value from a nested object using JavaScript in JSON

I am attempting to access the most recent element in the Time Series (5 min) object without specifying the date/time after running this JavaScript code: var getStock = new XMLHttpRequest(); getStock.open("GET","https://www.alphavantage.co/qu ...

The range input in HTML does not respond when attempting to adjust it

I am having an issue where the thumb on the slider does not move when I try to. This problem occurred after I inserted an img element inside the slider-cntnr div. View the code at http://codepen.io/danielyaa5/pen/xVEXvB HTML <div id="slider-cntnr"&g ...

Tips for transferring variable values from HTML to Angular

I am attempting to pass a variable value from HTML to Angular. Here is an example of what I am trying to achieve: <span (click)="toggle()" toggled="true" class="glyphicon glyphicon-unchecked"></span>> And in the controller: @Input() toggl ...

When attempting to add a variable using the next() function, I encountered an error with the BehaviorSubject. The error message displayed was "this.count.next is not a function"

In my Angular service, there is a variable called count that I need to monitor for updates. Whenever this count variable is updated, I want to assign its new value to another variable in a separate component. import {BehaviorSubject} from "rxjs/BehaviorSu ...

Getting the response from Google Cloud Translate API using Node JS

Recently, I've been experimenting with the Google Cloud Translate API in NodeJS. While I am able to successfully console.log the value returned from a promise, I am facing challenges passing that value into an EJS template file. Whenever I try to disp ...

Issues reported with Adobe Air and Canvas functionality not functioning as expected

I am attempting to create a simple Air App using Dreamweaver CS5.5, but I am running into an issue with loading an image onto the Canvas element through a function. While I can successfully load the image onLoad, my goal is to draw the image on the canva ...

AWS Cognito - ECS Task Fails to Start

I'm facing an issue with using JavaScript to execute a task in ECS Fargate. AWS suggested utilizing Cognito Identity Credentials for this task. However, when I provide the IdentityPoolId as shown below: const aws = require("aws-sdk"); aws.co ...

Troubleshooting problem with Angular4's HTTP requests

While working on my Angular 4 application, I am creating an oath guard service to check the validity of tokens. If the token is not valid, I want the user to log in again. Below are the functions I have implemented for this purpose: isLogedIn(){ ret ...

Is it possible to blend Bootstrap 3.3 with Bootstrap 4.1? I attempted to do so, but unfortunately, it resulted in website

I am currently facing an issue while attempting to integrate both bootstrap and twitter bootstrap simultaneously. Unfortunately, I have been unable to make them work together effectively. Is it even possible for them to be used in conjunction? You can find ...

Choose the initial element that has a unique label

Looking to create a custom CSS class that will apply a background color only to the first element with a specific tag... This is what I have so far: .blue p:first-of-type { background-color:#2E9AFE; } It works in this scenario: <div class="blue" ...

The options in the dropdown list contain a specific phrase or pattern: "Disable element"

In my dropdown list, I have various options available. If I attempt to click on "POICaption-XX423366 [DONOT ALLOW SELECT FOR THIS]", I can successfully prevent this value from being selected. <select multiple="multiple" size=20 id="caption_collecti ...

Executing the Angular 2 foreach loop before the array is modified by another function

Currently, I am facing some difficulties with an array that requires alteration and re-use within a foreach loop. Below is a snippet of the code: this.selectedDepartementen.forEach(element => { this.DepID = element.ID; if (this.USERSDepIDs. ...

What steps can I take to stop an AJAX request from causing the page to reload

I am facing an issue with my AJAX code where it reloads after a successful upload on the server side. Below is my HTML code that I have included. Any help or suggestions would be greatly appreciated. Thank you. function UploadVid(){ var file = $("#in ...

Include an HTML attribute within a given string

Using jQuery, I am adding HTML content to a div. The variables rowString and inputString have been defined beforehand: $("#filterContainer").append( rowString + `<label class='filterLabel' for=${filter}>${filter}< ...

Creating Three-Dimensional Shapes using 2D Elements with ThreeJS

Being a newcomer to Three.js, I have been attempting to achieve the following: Imagine having an array of x and y coordinates representing a shape in the browser viewport. My goal is to use Three.js to render these shapes with an added height in the z-dir ...

What is the best approach for sending a binary image post request to an API using nodejs?

I am receiving the image binary in this manner: axios.get("image-url.jpg") Now, I want to utilize the response to create a new POST request to another server const form = new FormData(); const url = "post-url-here.com"; form.appe ...

It seems that the Bootstrap 4 Modal Pop up window is having difficulty closing

I recently completed a project on creating a matching game. After all the cards are successfully matched and the game finishes, a congratulatory modal pops up. However, I encountered an issue where the modal would not close after clicking the "Play Again" ...

The Firebase Function consistently ends due to timeout restrictions

I have been utilizing Firebase functions to create notifications through cloud messaging, however, I consistently encounter the following error: Function execution took 60006 ms, finished with status: 'timeout' Despite the error, the notificati ...

Updating the image source using JQuery dynamically

Within my index.php file: <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> <script type="text/javascript"> $(document).ready(function () { $('.on').click(function ...