Three.js - implementing a billboard effect that preserves orientation through camera pans

My situation involves a plane geometry that always faces the camera using the following line of code in the update loop:

plane.lookAt(camera.position);

While I am utilizing OrbitControls to manipulate the camera, the plane successfully maintains its orientation towards the camera when rotating or zooming in the scene.

However, whenever I pan the scene, the plane still faces the camera but rotating the camera causes the plane to also rotate, resulting in situations where text on the plane may appear upside down or rotated to the viewer.

Is there a way to ensure that the plane stays aligned with the camera regardless of camera movements?

Check out an example on jsFiddle: http://jsfiddle.net/Stemkoski/ptVLD/

Answer №1

If you're looking for a quick fix, just insert the following line into your animation cycle:

plane.quaternion.copy( camera.quaternion );

Or, you might consider utilizing a THREE.Sprite

Version r.143 of three.js

Answer №2

Whenever I reach out to StackOverflow, my thoughts just magically fall into place :)

After some contemplation, a more solid approach (for enhanced billboarding) appears to be:

plane.rotation.setFromRotationMatrix( camera.matrix );

Although I have updated the jsFiddle code link in the original post accordingly, I am noticing some slight "shuddering" of the camera/plane when rotating the camera post panning. It seems like there is still room for improvement, so any suggestions to refine this solution would be wholeheartedly welcomed and acknowledged.

Answer №3

The sensation of "shuddering" occurs when the camera position is not utilized for the new frame. Instead, the plane is updated based on the previous camera position, and then the camera is updated based on the controls.

function animate() {
    // plane.lookAt( camera.position ); // rotation messed up after camera pan
    plane.rotation.setFromRotationMatrix( camera.matrix );

    controls.update();
    renderer.render(scene, camera);
    requestAnimationFrame(animate);
}

To eliminate the "shudder," simply swap the order of these two operations.

function animate() {
    controls.update();

    // plane.lookAt( camera.position ); // rotation messed up after camera pan
    plane.rotation.setFromRotationMatrix( camera.matrix );

    renderer.render(scene, camera);
    requestAnimationFrame(animate);
}

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

Chrome Developer Tools - Array Length Discrepancies

While exploring Chrome DevTools, I came across an inconsistency that caught my attention. The screenshot above shows the issue I encountered. Initially, it indicated that the object contained a Body and a Head, with the head being an array of length 1. Ho ...

Control the options of the Select menu using ajax

Consider having two dropdown menus <select id=first> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</opti ...

How can we combine refs in React to work together?

Let's consider this scenario: I need a user to pass a ref to a component, but I also have to access that same ref internally. import React, { useRef, forwardRef } from 'react'; import useId from 'hooks/useId'; interface Props ext ...

Populating a clickable list and form with a complex JavaScript object

I have a code snippet that takes an unstructured String and parses it into a JavaScript object. My next step is to integrate it into a web form. You can check out the demo here. The demo displays the structured object hierarchy and showcases an example of ...

The Angular 9 custom directive is malfunctioning on mobile devices

I recently created a custom directive in Angular 9 that allows users to input only digits and one decimal point. While the directive works perfectly on desktop, it seems not to function at all on mobile devices - almost as if it doesn't exist within t ...

Creating a Node.JS environment with Express and Socket.IO: A beginner's guide

Trying to set up a Node.JS server on port 3800 of my CentOS server and encountering difficulties: var app = require('express')(); var http = require('http').Server(app); app.get('/', function(req, res){ res.send('&l ...

Using ng-mouseover along with ng-if and an animated class causes issues

Whenever I hover over a link, it triggers a change in a variable value which then displays a <p> tag using ng-if. The code snippet looks like this: <div class="position text-center" ng-mouseover="social=1" ng-mouseleave="social=-1"> &l ...

It is imperative that the 'Access-Control-Allow-Origin' header value in the response is not set to '*' when the request's credentials mode is 'include'

I am currently working on establishing a connection using socket.io between Angular and a Node.js Server Within Angular, I have set up a new socket by importing socket.io-client and connecting it as follows: import * as io from 'socket.io-client& ...

Error message: "Unable to find a windows instance" encountered while conducting tests on Paho MQTT Client using mocha and typescript

After spending countless days searching online, I have yet to find any resources on testing the Paho MQTT Client. My approach so far has been somewhat naive, as shown below: import { suite, test, slow, timeout, skip, only } from 'mocha-typescript&apo ...

Stop the print dialog box from causing the page to refresh

I have implemented a print button for an invoice: </script> <!--Function for printing invoice--> <script> function printpage() { window.print() } </script> <button id="print" name="print" class="btn btn-info" onClick="pri ...

Is NextJS on-demand revalidation compatible with Next/link?

https://nextjs.org/docs/basic-features/data-fetching/incremental-static-regeneration#on-demand-revalidation According to the NextJS documentation, it appears that on-demand cache revalidation should function properly with regular <a> tags and when t ...

Server-side props become inaccessible on the client side due to middleware usage

I'm attempting to implement a redirect on each page based on a specific condition using Next.js middleware. Strange enough, when the matcher in middleware.ts matches a page, all props retrieved from getServerSideProps for that page end up being undef ...

What is the best way to perform an action in the database using JavaScript without needing to refresh the page

I have written a code that retrieves data from a table, with each row containing two buttons for updating the database with a fixed value and deleting the row. I am looking to perform these actions without reloading the page. Below is the table code: &l ...

NextJS is throwing an error stating that the function file.endsWith is not recognized as a valid

After upgrading from nextJS version 9.x.x to 12.x.x, I encountered the following error. Any assistance would be greatly appreciated. TypeError: file.endsWith is not a function at eval (webpack-internal:///./node_modules/next/dist/pages/_document.js ...

What is the best way to add bold formatting to text enclosed in parentheses using javascript/jquery?

How can I use jQuery or JavaScript to make the text inside parentheses bold? For example: "what is your Age (in Year)." I need assistance in making the text within parentheses bold using either jQuery or JavaScript. Can someone help me with this task? ...

Using jQuery to scroll a div element

Having some trouble trying to manipulate the scroll of a div using jQuery. Can't seem to figure out where I'm going wrong. This is the code snippet I am currently working with: $("#CategoryList").animate({ scrollLeft: "=-5" }, "slow"); The ID ...

Using a for loop in JavaScript to fetch and display a specified number of results from an API

Recently, I delved into the world of Javascript and API arrays to grasp the concept of retrieving and manipulating various APIs. The topic of Javascript loops and arrays has been discussed numerous times, both here on StackOverflow and on other platforms. ...

I have been dynamically inserting div elements into the DOM using JavaScript, using the appendChild method to add them and later removing them with removeChild. Strangely, when trying to append a div

There seems to be an issue in the code snippet below. The function create() works fine the first time, but encounters a problem on the second run at the line boxWrapper.appendChild(box);. It appears that the removeChild method is causing some disruption in ...

What could be causing my ul list to not be populated by ajax?

To populate the ul list with data from PHP code on page load, you can use the following ajax function. I appreciate any help in advance, and please forgive me if my explanation is not precise as I'm new here. This post contains mostly code snippets. ...

Utilizing 'Ng-If' causes a glitch in the program during the execution of a $( '#x' ).change event or when adding a new item with AngularFire $add

After implementing ng-if in my code, I observed two specific instances where it caused unexpected behavior. The first instance involves using ng-if="isOwnProfile" for an image-upload toolbar. However, the use of ng-if resulted in the event listener ceasin ...