Utilizing Threejs to Unproject Vector3 from Camera

I'm currently working on a project using three-js where I am attempting to project 2D coordinates onto a sphere within the virtual world.

The code snippet below functions perfectly when bound to the mousedown event:

function project(point){
  var x = 2 * (point[0] - width/2) / width;
  var y = 2 * (point[1] - height/2) / height;
  var l = new THREE.Vector3(x, y, 0.5);
  l.unproject(camera);
  l.sub(camera.position).normalize(); // represents ray or direction of click in world coordinates

  // Code for Ray Sphere Intersection provided below (which is assumed to be correct)
  var omc = camera.position.clone().sub(sphere.position);
  var ldomc = l.dot(omc);
  var d = -ldomc - Math.sqrt(ldomc*ldomc - omc.lengthSq() + radius*radius);
  if (d == d){ // indicates an intersection was found
    return camera.position.clone().add(l.multiplyScalar(d));
  }
  return null; // No intersection found
}

However, upon trying to utilize this function in the following piece of code, the function consistently returned null (indicating no intersections were detected).

get_random_point(scale){ // scale denotes the projected radius (in pixels) of the sphere
  while (true){ // keep iterating until a valid point is obtained
    var a = Math.random();
    var b = Math.sqrt(Math.random());
    var x = width/2 + scale * b * Math.cos(2 * Math.PI * a);
    var y = height/2 + scale * b * Math.sin(2 * Math.PI * a);
    if (width > x && x >= 0 && height > y && y >= 0){
      var projp = project([x,y]);
      if (projp != null){
        return toSpherical(projp); // Return spherical coordinates of obtained point
      }
    }
  }
}

This above code snippet is executed approximately 100 times each animation cycle to select a random visible point on the sphere's surface based on the camera view.

The issue arises once the camera position has been altered. The method I use to control the camera involves orbiting it around the sphere using the mouse.

At one point, I managed to output all variables declared inside the project function to the JavaScript console during such occurrences. Upon testing the same function with identical camera positioning and coordinates in another tab, I discovered that the calculated ray was inaccurate.

Following are the functions related to controlling the camera:

d3.select("body").on("mousedown", function(event){
  m0 = d3.mouse(this);
});

d3.select("body").on("mousemove", function(event){
  if (m0 != null){
    var m1 = d3.mouse(this);
    var mv = [m1[0] - m0[0], m1[1] - m0[1]];
    theta -= mv[0]*0.25/180.0*Math.PI;
    phi += mv[1]*0.25/180.0*Math.PI*camera.up.y;
    if (phi > Math.PI/2){ phi = Math.PI - phi; camera.up.y *= -1; theta += Math.PI}
    if (-Math.PI/2 > phi){ phi = -Math.PI -phi; camera.up.y *= -1; theta += Math.PI}
    while (theta >= 2 * Math.PI){ theta -= 2 * Math.PI; }
    while ( 0 > theta){ theta += 2 * Math.PI; }
    camera.position.x = r * Math.sin(theta) * Math.cos(phi);
    camera.position.y = r * Math.sin(phi);
    camera.position.z = r * Math.cos(theta) * Math.cos(phi);
    camera.lookAt(new THREE.Vector3(0, 0, 0));
    m0 = m1;
  }
});

d3.select("body").on("mouseup", function(event){
  m0 = null;
}).on("mouseleave", function(event){ m0 = null; });

function Zoom(event){
  var movement;
  if (event.wheelDelta){
    movement = event.wheelDelta/120; // wheelDelta increments by 120 units
  } else {
    movement = event.deltaY/-3; // DeltaY increments by 3 units
  }
  r -= 0.05 * movement;
  if (0.9 > r){
    r = 0.9;
  } else if (r > 2.5){
    r = 2.5;
  }
  camera.position.x = r * Math.sin(theta) * Math.cos(phi);
  camera.position.y = r * Math.sin(phi);
  camera.position.z = r * Math.cos(theta) * Math.cos(phi);
  camera.lookAt(new THREE.Vector3(0, 0, 0));
}

I have been unable to determine why the project function behaves differently when called from the animation loop compared to outside of it.

My assumption is that alterations to the camera during mouse movements may result in the insufficient update of the camera matrices, leading to discrepancies in the output of Three.Vector3.unproject() function.

UPDATE: The problem was resolved by rearranging the animation immediately after the render call. This strongly suggests that the issue stemmed from outdated camera matrices. While I understand how to update the camera projection matrix, I am unsure of how to enforce updating the camera's matrix world. Any guidance on this matter would be greatly appreciated.

Answer №1

In the world of three.js, it's important to note that the renderer takes care of calling camera.updateMatrixWorld() during each render loop.

If you happen to make changes to the camera's position, rotation, or quaternion, and then utilize a method that depends on camera.matrixWorld, but that method fails to update camera.matrixWorld itself, you'll need to manually update the matrix.

camera.updateMatrixWorld();

This implementation is specific to version r.71 of three.js.

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

Issue with Ember Select not updating selection binding when populated by another Ember Select

New to Ember.js and grappling with the binding of selection in Select views to the controller. The template I am working with is as follows: {{view Ember.Select contentBinding="content" selectionBinding="selectedCompany" optionLabelPath="content.nam ...

ExpressJS exhibits unique behavior based on whether the API is requested with or without the specified PORT number

I have encountered an issue with my 2 flutter web apps. One of them is functioning flawlessly when I request the URL, but the other one only works when I include the port xxxxx:4000/nexus-vote. However, when I remove the port, I receive a status code of 20 ...

Sending data to SOAP API using AngularJS

I've been struggling to send data to a SOAP API but have hit a roadblock. I've attempted various methods but continue to encounter errors when making the API call. The API URL is - and it requires data in XML format like <?xml version="1.0" ...

What is the best way to transmit a specific property from an array of objects within a child component to its parent component?

In my project, I have a main component called App and a child component named Child: The Child component receives a prop called items to allow for reuse based on different data sets. In this example, we have data, data1, and data2. The issue arises when ...

What is the best way to access the parent document of a Firestore collectionGroup query?

I'm currently working on accessing the parent documents of all subcollection queries in my database structure. The setup I am aiming for is something like this: /production/id/position/id/positionhistory While I have successfully retrieved all the d ...

Possible Inconsistencies with the LookAt Feature in Three.js

Attempting to use the lookAt function to make zombies move towards the character has been a challenge. The problem lies in the fact that they are not turning correctly but at odd angles. Here is the code snippet I tried: var pos = new THREE.Vector3(self ...

Utilize jQuery to automatically assign numbers to <h1-h6> headings

Looking to develop a JavaScript function that can automatically number headings (h1- h6) for multiple projects without relying on CSS. Currently achieving this with CSS: body { counter-reset: h1; } h1 { counter-reset: h2; } h2 { counter-reset: h3; } ... T ...

When the div is refreshed, the input box should retain the text instead of clearing it

I am facing an issue with a div that refreshes every 3 seconds. There is an input box inside the div, but whatever I type gets cleared out in 3 seconds. Is there a way to prevent the text from being cleared out and keep it inside the input box? index.js ...

MongoDB: Issue updating the 'role' field of a document

Recently, I've run into an issue where I am unable to update the 'role' of a specific document. The document in question is a 'user' object within the MEANjs User schema, and it has a pre-defined property for roles. Here is the sec ...

Axios is causing my Pokemon state elements to render in a jumbled order

Forgive me if this sounds like a silly question - I am currently working on a small Pokedex application using React and TypeScript. I'm facing an issue where after the initial page load, some items appear out of order after a few refreshes. This make ...

How can you locate the position of a selector within a parent or set using jQuery

Could someone please help me determine the position of the current selector within its parent using jQuery? I need this information in order to effectively use the .insertAfter() and .insertBefore() methods to rearrange elements within their nested structu ...

Create a custom BoxGeometry with curved edges using Three.JS

Looking to create a curved BoxGeometry in Three.Js, but unsure of how to achieve it. The end result should resemble the image shown here: enter image description here My current code is as follows, however, it does not produce the desired curved effect. ...

What are some techniques for incorporating lazy loading into a div element containing a card?

While exploring different resources, I came across numerous tutorials on implementing lazy loading with images and iframes. But surprisingly, I couldn't find any guide on how to achieve the same effect with a div containing other types of content. Sp ...

Display information from a .js file onto an HTML webpage

I'm completely new to the world of server-side development and I'm attempting to navigate it on my own. Currently, I have a server written in JavaScript using Express and I'm trying to display some content on my HTML page that was sent from ...

modify the color of text in a row within a jquery ajax table

Is it possible to change the font color of values in a row based on a condition inside a function? Specifically, if the TotalStudent count exceeds the room capacity, can we add student information to the table with red font color? Below is my attempt using ...

Spotlight the content of the file obtained from GitHub

I'm having trouble with syntax highlighting for code fetched from GitHub. fetch("https://raw.githubusercontent.com/Ayanmullick/test/master/AutomationAcc/test1.ps1") .then(response => response.text()) .then(data => document.getElem ...

developing a stand-alone job listings feature

Our website features a job postings page that our clients are interested in incorporating into their own websites. This would allow applicants to easily apply for jobs directly on the client's site, with the information being saved in our system. One ...

Is there a way to store JSON data in a constant variable using Node Fetch without encountering the error TypeError [ERR_INVALID_URL]: Invalid URL?

In my current NodeJS project, I am working on extracting data from a JSON file and then sending it to a constant variable in my app2.mjs. The goal is to organize this data into an array of objects and eventually save it into a database. However, when tryin ...

Is it possible to generate an array of objects, where each object includes an observable retrieved through forkJoin?

let food = { id: 1, isTasty: false } Imagine I have a custom function that takes the ID of a food item and returns an observable which resolves to a boolean indicating whether the food is tasty or not. I wish to loop through an array of food items an ...

How to efficiently load 3000 objects in Openlayers using IE8

One of my clients exclusively uses IE8 and is working with an openlayers map. He is trying to load 3000 polygons onto the map, which Chrome and IE9 can handle without any issues. However, IE8 freezes when attempting to load the objects. These objects are c ...