Panning is not compatible with shared camera OrbitControls

I am attempting to set up two renderers on separate div containers. Each renderer should have its own OrbitControls to update the camera associated with it. However, the camera is shared between the two renderers.

The objective is to synchronize the camera for OrbitControl so that both containers display the same camera view and render between the two render loops.

I have noticed that the overall rotation can be shared automatically. Yet, there seems to be a strange behavior when panning. You can see the issue in this video:

Below is the minimum reproducible code:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
</head>
<body>

    <div id="rend1" style="height: 400px; width: 400px;"></div>
    <div id="rend2" style="height: 400px; width: 400px;"></div>

<script type="module">
import { OrbitControls } from 'https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="058e848e8e9fa0a0bea1bca1bca1bca0">[email protected]</a>'s/controls/OrbitControls.js';

const rend1 = document.getElementById("rend1")
const rend2 = document.getElementById("rend2")

const camera = new THREE.PerspectiveCamera(40, 1, 0.01, 1000);
camera.position.copy(new THREE.Vector3(0, 1, 2));
camera.lookAt(new THREE.Vector3(0, 0, 0));

const r1 = new THREE.WebGLRenderer({
    antialias: true,
    preserveDrawingBuffer: true,
    precision: "highp",
    alpha: true,
  });
r1.setPixelRatio(window.devicePixelRatio);
const s1 = new THREE.Scene();
rend1.append(r1.domElement);

const c1 =  new OrbitControls(camera, r1.domElement)
s1.add(new THREE.AxesHelper(1));
s1.add(camera);
const g1 = new THREE.BoxGeometry( 0.5, 0.5, 0.5 );
const m1 = new THREE.MeshBasicMaterial( {color: 0x0080ff} );
const cube1 = new THREE.Mesh(g1, m1);
s1.add(cube1)

const r2 = new THREE.WebGLRenderer({
    antialias: true,
    preserveDrawingBuffer: true,
    precision: "highp",
    alpha: true,
  });
r2.setPixelRatio(window.devicePixelRatio);
const s2 = new THREE.Scene();
rend2.append(r2.domElement);
const c2 =  new OrbitControls(camera, r2.domElement)
s2.add(new THREE.AxesHelper(1));
s2.add(camera);
const g2 = new THREE.BoxGeometry( 0.5, 0.5, 0.5 );
const m2 = new THREE.MeshBasicMaterial( {color: 0x0080ff} );
const cube2 = new THREE.Mesh(g2, m2);
s2.add(cube2)



const render1 = () => {
    r1.setSize(400, 400);
    c1.update();
    r1.render(s1, camera);
    window.requestAnimationFrame(() => render1());
};
const render2 = () => {
    r2.setSize(400, 400);
    c2.update();
    r2.render(s2, camera);
    window.requestAnimationFrame(() => render2());
};
render1 ();
render2 ();
</script>
</body>
</html>

What could be causing this issue and what steps can be taken to achieve the desired behavior?

Thank you!

Answer №1

It's not necessary to include your camera in every scene. The camera can function independently. Keep in mind, an Object3D can only have one parent. So, if you do

s1.add(camera);
s2.add(camera);

...the camera will only be added to s2, as it automatically gets removed from s1 when a new parent is assigned.

Consider eliminating all instances of .add(camera) from your code.

Correction:

In addition, you're attaching two CameraControls to the same camera, and then calling c1.update() and c2.update(). This results in conflicting instructions for the camera, with one control directing it to move and the other to remain stationary. It's best to use just one control if you intend to manipulate a single camera.

Answer №2

To resolve this issue effectively, it is crucial to synchronize the cameras and explicitly set the orbit control's target when they change. Refer to the following code snippets:

c1.addEventListener("change", () => { ... }}
and
c2.addEventListener("change", () => { ... }}
.

Below is a comprehensive code snippet to address the problem:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Document</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
  </head>
  <body>

    <div id="rend1" style="height: 400px; width: 400px;"></div>
    <div id="rend2" style="height: 400px; width: 400px;"></div>

    <script type="module">
      import { OrbitControls } from 'https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/controls/OrbitControls.js';

      const rend1 = document.getElementById("rend1")
      const rend2 = document.getElementById("rend2")
      
      // Code continues...
    </script>
  </body>
</html>

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

Using JavaScript with React to invoke an asynchronous action within a component

Within my class, I have implemented some asynchronous actions in the ComponentDidMount method. The code snippet looks like this: componentDidMount(){ // var my_call = new APICall() Promise.resolve(new APICall()).then(console.log(FB)) } class API ...

What is the most effective method for parsing a JSON object with a dynamic object name?

Is it possible to access specific object keys and perform actions based on the object name retrieved from a JSON object? If so, how can I achieve this? The JSON object 'x' will be fetched through an AJAX call from the server. Depending on the ob ...

How can I utilize a service for monitoring user data and ensuring that $watch() functions properly?

I'm a beginner when it comes to AngularJS and currently working on building a website that has a navigation bar dependent on the user's login status. My approach involves using a state model design with the Nav controller as the parent state for ...

Is there an animation triggered by hovering the mouse over?

I've implemented a bounce animation that is triggered by mouseover on an image. Currently, the animation only happens once, but I want it to bounce every time the mouse hovers over it. Here is the HTML code: <div class="hair"> <img src= ...

Whenever my code is used within Google Sites, it triggers the opening of a new and empty tab

When using this code inside an HTML box in Google Sites, a problem arises. It seems to work perfectly fine in Internet Explorer and Chrome when saved to an HTML file. However, within Google Sites, it unexpectedly opens a new tab with no data. The code st ...

Transfer the script from package.json to an npm package

In each of our plugins' root directories, there is a file named tools.js. This file contains a build function that assists in creating builds for the plugin. The package.json file references it like this: "scripts": { "build:node&qu ...

What is the manual way to activate Ratchet's push feature?

I am facing an issue with a link that triggers a search function. Currently, the link is working as expected. However, I am having trouble getting the search to be executed by pressing the 'enter' button. Here is my code snippet: $('#sea ...

Tips for preventing JavaScript errors when making cross-domain requests using AJAX

Is there a way to prevent or handle JavaScript errors without causing the script to crash? Error message: No data returned $.ajax({ type : 'GET', dataType : 'jsonp', url : '//cvrapi.dk/api?search=dsfsdfsd&country= ...

Hash functionality does not cooperate with the back button, requiring the use of JavaScript to trigger a function when the URL changes

Hi everyone, I have a code snippet that is designed to read the value after the hash in the URL and display a specific div based on that value. It works as expected, except for when the hash is changed while already on the site or when navigating back with ...

Store the output of the function in a variable

Here is a script that was provided to me: <div id="container1"> <script> var script = document.createElement("script"); script.type = "text/javascript"; script.text = 'document.write(xmlDoc.getElementsByTagName("INFO") ...

Making multiple Node.js requests using the request module: A comprehensive guide

Purpose: My goal is to extract data from approximately 10,000 web pages using Node.js. Issue: The scraping process speeds through the first 500~1000 pages but then significantly slows down beyond that point, sometimes halting completely. To initiate the ...

Utilize the power of Nuxt and Vue 3 to create sortable columns in a table, with the ability to only change the icons on the sorted column

I am facing a challenge with my sortable table icons. Whenever I click on an icon to sort a column, all the other icons also change direction. I understand that this is happening because I am toggling the visibility of icons based on the currentSortDir sta ...

Utilizing Material-UI components for a seamless navigation button experience

After reviewing the example on https://material-ui.com/guides/composition/#button, I have implemented a button in my main page: <BrowserRouter> <Box m={2}> <Button size="large" variant="cont ...

Exploring the power of promise chaining within AWS Lambda

I'm feeling a bit confused about how Promise chaining works in AWS Lambda. exports.handler = async(event) => { firstMethod = () => { return new Promise(function(resolve, reject){ setTimeout(function() { ...

Tips for updating property values when calling a TypeScript function

Hello everyone, I am looking to convert a snippet of JavaScript code into TypeScript. JavaScript function newState(name){ var state ={ name : name, age : 0 } return state } function initStates() { this.JamesStat ...

Retrieving variables from JavaScript files in TypeScript

Greetings, I am in the process of upgrading an existing Angular application from version 2 to 9. My approach involves first moving it to angular 4 and then continuing with the upgrades. I have successfully updated the necessary packages, but now I'm e ...

What is the best way to darken the background when an alert is displayed and disable the dimming effect when the alert is closed?

Here's the JavaScript snippet I'm using: reset.addEventListener("click", function(){ document.querySelector("#body").classList.add("darkenPage"); myReset(); alert("Reset Successful!!"); document.querySelector("#body").classList.re ...

React-Bootstrap Popup encounters overlay failure

While using the Tooltip without an OverlayTrigger, I encountered the following error: webpack-internal:///133:33 Warning: Failed prop type: The prop overlay is marked as required in Tooltip, but its value is undefined. The code snippet causing the issu ...

Save Scope in JSON format

Currently, I am developing a web application that dynamically displays specific prompts based on the field in focus. There are several different texts stored as scripts that I want to showcase at these different points. My goal is to incorporate scope dat ...

What is the best way to retrieve the state value in react once it has been changed?

How can I ensure that the react state 'country' is immediately accessible after setting it in the code below? Currently, I am only able to access the previous state value in the 'country' variable. Is there a method such as a callback o ...