Transforming a 3D perspective scene into a 2D orthographic HUD scene using THREE.js

I am working on a 3D scene with objects positioned very far away, utilizing a perspective camera for the main view and an orthographic camera for a 2D Heads-Up Display (HUD):

this.scene = new THREE.Scene();
this.hud = new THREE.Scene();

this.camera = new THREE.PerspectiveCamera( 30, aspect, front, back );
this.camera.position.set(0,0,0);

this.hudCamera = new THREE.OrthographicCamera (-this.windowHalfX,this.windowHalfX, this.windowHalfY, -this.windowHalfY, 1, 10);
this.hudCamera.position.set(0,0,10);

Below is the code for my rendering loop:

  updateFrame : function () {
    this.renderer.clear();
    this.renderer.render( this.scene, this.camera );
    this.renderer.clearDepth();
    this.renderer.render( this.hud, this.hudCamera );
  },

I am looking for a way to determine the position of objects in the HUD by referencing their position in the 3D scene. Any suggestions on how to achieve this?

Answer №1

If you're looking to determine the 2D HUD position of a 3D object using three.js version r71, you can achieve this by following these steps, which have been adapted from this reference post:

  findHUDPosition : function (obj) {
      var vector = new THREE.Vector3();

      obj.updateMatrixWorld();
      vector.setFromMatrixPosition(obj.matrixWorld);
      vector.project(this.camera);

      vector.x = ( vector.x * this.windowHalfX );
      vector.y = ( vector.y * this.windowHalfY );

      return {
          x: vector.x,
          y: vector.y,
          z: vector.z
      }
  }

The input obj refers to the object for which you are seeking the HUD position.

vector.project(this.camera); generates a vector from the object to the this.camera position, passing through the camera's near plane.

The updated values of vector's components represent the intersection of the projected vector and the this.camera's near plane.

Although the coordinates are within three.js' world coordinate system, a conversion to pixel coordinates is necessary to match the canvas size.

  vector.x = ( vector.x * this.windowHalfX );
  vector.y = ( vector.y * this.windowHalfY );

The mentioned conversion assumes a HUD coordinate system with an origin at the screen's center (0,0) and a maximum value of half the canvas resolution. For instance, on a 1024 x 768 pixel canvas, the upper right corner would be located at (512, 384).

In a conventional screen coordinate system, the bottom right corner would be at (1024, 768), and the screen center at (512, 384). To acquire this setup, utilize the conversion provided in this reference post.

    vector.x = ( vector.x * widthHalf ) + widthHalf;
    vector.y = - ( vector.y * heightHalf ) + heightHalf;

At this point in 2D space, the z coordinate is inconsequential.

Lastly, ensure that the object being displayed in 2D is visible to the perspective camera by checking if it falls within the frustum of this.camera. Refer to this source for the code snippet below:

checkFrustrum : function (obj) {
    var frustum = new THREE.Frustum();
    var projScreenMatrix = new THREE.Matrix4();

    this.camera.updateMatrix();
    this.camera.updateMatrixWorld();

    projScreenMatrix.multiplyMatrices( this.camera.projectionMatrix, this.camera.matrixWorldInverse );

    frustum.setFromMatrix( new THREE.Matrix4().multiplyMatrices( this.camera.projectionMatrix,
                                                     this.camera.matrixWorldInverse ) );
    return frustum.containsPoint ( obj.position );
}

Failing to perform this check may result in an object located behind the camera being mistakenly recognized as visible in the 2D scene, leading to issues with object tracking. It's also recommended to update the matrices and matrix world of the obj.

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

Is There a Workaround for XMLHttpRequest Cannot Load When Using jQuery .load() with Relative Path?

My current project is stored locally, with a specific directory structure that I've simplified for clarity. What I'm aiming to do is include an external HTML file as the contents of a <header> element in my index.html file without manually ...

Unable to Trigger onClick Event with react-bootstrap Navbar Dropdown in Combination with react-router-dom

In my React application with react-bootstrap, I have a Navbar component that displays a dropdown menu for different brands. However, I noticed that the second brand option (Tommy Hilfiger) is always the one active by default, as if it is automatically cl ...

What is the proper way to include jQuery script in HTML document?

I am facing an issue with the banners on my website. When viewed on mobile devices, the SWF banner does not show up. In this situation, I want to display an <img> tag instead, but the jQuery code is not functioning correctly. My template structure l ...

Managing waste: AngularJS service variable cleanup

I am a beginner in angularjs. Recently, I created an angularJS service based on the following diagram: https://i.sstatic.net/NifC5.png The Global Service acts as a way for controllers to communicate with each other. It holds data shared between parent an ...

How can Node.js developers properly utilize PM2 for their projects?

I'm currently contemplating a switch from forever to PM2 as a way to ensure my node application stays up and running. I find myself puzzled by the various recommended methods for initiating a process: $ pm2 start app.js -i 4 # Daemonize pm2 and Star ...

Discover the method of obtaining the post id within an Ajax callback in the Wordpress

Currently, I am using the Add to cart Ajax callback, but I am facing difficulty in retrieving the post Id from it. MY OBJECTIVE: My intention is to apply the add_filter only on a specific page. Here is the PHP code in functions.php file: add_filter( &apos ...

Is it possible to transfer state to the getServerSideProps function in any way?

As a newcomer to next.js, I have a question about passing page state to getServerSideProps - is it achievable? const Discover = (props) => { const [page, setPage] = useState(1); const [discoverResults, setDiscoverResults] = useState(props.data. ...

SyntaxError: Encountered an unexpected token that is not jsonp, could it be trying to parse json instead?

As a newcomer to AJAX and Javascript, I am attempting to integrate them with an API following this structure: http://localhost:8088/JobPositionForDd: { "data": [{ "_id": "529dc2dfd0bf07a41b000048", "name": "Junior Android" }, { ...

Troubleshooting: Why isn't my Ajax post functioning correctly with PHP variables?

After researching similar questions, I have discovered that in order to send a JavaScript value to a PHP variable, AJAX must be used. Here is what I have tried: function onCursorChanged(e, data) { $.post('familytree.php', {id: data.context.i ...

Displaying an alert on a webpage that shows a label input using JavaScript and

I'm currently working with HTML5 and JavaScript and I'm facing a challenge. I want to create a feature where users can input any word into a label, and when they click on a button, an alert is triggered with the given text. However, despite my ...

Navigating between two table components in React JS

I am a beginner in the world of React and I am struggling with switching between these two tables. Despite consulting the documentation for inline conditional statements, I still couldn't figure it out. My goal is to have the tables switch after click ...

What is the most effective way to implement Promises within a For loop?

const wiki = require('wikijs').default; const { writeFileSync } = require("fs") const dates = require("./getDates") //December_23 for (let i = 0; i < dates.length; i++){ wiki() .page(dates[i]) .then(page => p ...

The successful loading of tab favicons in the DOM of an angular chrome extension is a triumph, however, explicit XHR requests are unfortunately

I've been immersed in developing a Chrome extension with Angular 5. Successfully, I managed to extract favIconUrls from the tabs API and link them to my popup.html's DOM. The icons are retrieved and displayed without any hiccups. See an example ...

Sharing information among v-for divisions - Vue.js

I am currently delving into the world of VueJS. While my code may not be the most elegant, it does the job almost as intended. The issue I am facing is that the API provides the title and href separately in different v-for loops, even though each loop only ...

What is the process for registering a click using a class in jQuery and retrieving the ID of the clicked element?

Currently, I am working on developing a webpage where I need to use jQuery to register a click using the items class and then extract the ID of that particular object. For example: HTML: <div class="exampleclass" id="exampleid1"></div> <d ...

React-dropzone experiencing delays in loading new files for readers

Is there a way to handle conditional responses from an API and assign the desired value to errorMessageUploaded? I'm looking for a solution to receive error messages from the API, but currently, the errormessageupload variable is not being set withou ...

Tips for correctly formatting a string to use with the setValue() method

I am facing an issue with adding the value US punctuation + alphanumeric lowercase:[a-z0-9,.?;:!&()_'"]+ to a cell in my spreadsheet. The error message I receive is: Missing ) after argument list. I am unsure how to correct the string that inc ...

Troubleshooting Problems with jQuery's .remove() Function

I attempted to create a simple game using JS and jQuery, keeping in mind that I am new to both languages. My goal was to create a function that allows users to delete their save within the game. However, despite my efforts, I faced issues with the function ...

The interactive form fields are not functioning as intended due to a dynamic association issue

Issue with Adding Two Dynamic Form Fields Together I need to add two fields at once by clicking a single button, and each field should have a two-dimensional name structure like [0][0] and [0][1] for saving dual values Although I used jQuery to dyn ...

Arrange the array in chronological order based on the month and year

I'm looking for assistance with sorting an array by month and year to display on a chart in the correct order. Array1: ['Mar19','Apr18','Jun18','Jul18','May18','Jan19'....]; Desired Output: ...