Running and animating two Three-JS objects simultaneously: A step-by-step guide

I have created two 3JS objects and scenes for educational purposes. Each one is stored in separate PHP files (not in the jsfiddle). However, I'm facing an issue where adding a second object causes the first object to stop animating. How can I troubleshoot this problem and ensure that multiple threejs items animate simultaneously?

//GRID OBJ represents the first object, while //BALL represents the second. When I remove the script for the 3js ball, the grid animates as expected. But when the ball script is added, only the ball animates while the grid stops.

http://jsfiddle.net/tdqh4jno/

//GRID OBJ
var container = document.getElementById('grid')

var vertexHeight = 90,
  planeDefinition = 25,
  planeSize = 900,
  totalObjects = 1,
  background = "#002135",
  meshColor = "#ff3057";

var camera2 = new THREE.PerspectiveCamera( 110, 1, 5)
camera2.position.y = 500;

var scene2 = new THREE.Scene();
scene2.background = new THREE.Color( 0x08080c);
var renderer = new THREE.WebGLRenderer({alpha: true});
renderer.setClearColor( 0x000000, 0 );

var planeGeo = new THREE.PlaneGeometry(planeSize, planeSize, planeDefinition, planeDefinition);

var plane = new THREE.Mesh(planeGeo, new THREE.MeshBasicMaterial({
  color: meshColor,
  wireframe: true
}));
plane.rotation.x -= Math.PI * .5;

scene2.add(plane);

renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(background, 1);
container.appendChild(renderer.domElement);

function updatePlane() {
  for (var i = 0; i < planeGeo.vertices.length; i++) {
    planeGeo.vertices[i].z += Math.random() * vertexHeight;
    planeGeo.vertices[i]._myZ = planeGeo.vertices[i].z
  }

};

var count = 0

function renderGrid() {
  var gridSpeed = 0.4;
  var gridInterlop = -0.4;
  var gridWaveSpeed = 0.003;  
  var gridWaveHeight = 0.00003;

  requestAnimationFrame(renderGrid);

  for (var i = 0; i < planeGeo.vertices.length; i++) {
    var z = +planeGeo.vertices[i].z;
    planeGeo.vertices[i].z = Math.sin(( i + count * gridWaveHeight)) * (planeGeo.vertices[i]._myZ - (planeGeo.vertices[i]._myZ * gridWaveSpeed))
    plane.geometry.verticesNeedUpdate = true;
    count += gridInterlop
  }

  renderer.render(scene2, camera2);

}

updatePlane();
renderGrid();


//BALL ITEM
var camera2 = new THREE.PerspectiveCamera(100, window.innerWidth/window.innerHeight, 0.1, 1000);
  var renderer = new THREE.WebGLRenderer();
  renderer.autoClear = false;
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);

  var sceneTop = new THREE.Scene(); // initialising the scene
  sceneTop.background = new THREE.Color( 0x08080c);


  var spotLight = new THREE.SpotLight(0xffffff);
  spotLight.position.set(100,100,100);
  spotLight.castShadow = false;
  sceneTop.add(spotLight);

  function Mat(){
    var material = new THREE.MeshPhongMaterial({
      color      : new THREE.Color(0xff3266),
      emissive   : new THREE.Color(0x08080c),
      specular   : new THREE.Color(0x08080c),

      shininess  : 0,
      wireframe  : true,
      transparent: 0.5,
      opacity    : 0.55
    });
    return material;
  }

  var geometry = new THREE.IcosahedronGeometry(45 , 1);
  var obj = new THREE.Mesh(geometry, Mat());


  sceneTop.add(obj);

  camera2.position.z = 90;

  function myrender(){
    renderer.setClearColor( 0x000000, 0 );

    obj.rotation.x += 0.0004;
    obj.rotation.y += 0.0006;
    obj.rotation.z += Math.random() * 0.0005;
    renderer.render(sceneTop, camera2);
    requestAnimationFrame(myrender);
  }



  window.addEventListener('resize', onWindowResize, true);

  function onWindowResize() {
    renderer.setSize(window.innerWidth, window.innerHeight);
    camera2.updateProjectionMatrix();
};


    myrender();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/99/three.min.js"></script>
<div id="grid"></div>

Answer №1

Two instances of THREE.WebGLRenderer are created, but both are assigned to the same variable renderer. This results in disrupting the animation of the first object (grid) in the function renderGrid.

In your code, two different scenes are created and referenced by different variables (sceneTop, scene2). Similarly, create two distinct render objects referenced by separate variables (renderer, renderer2):

var scene2 = new THREE.Scene();
scene2.background = new THREE.Color( 0x08080c);
var renderer2 = new THREE.WebGLRenderer({alpha: true});
renderer2.setClearColor( 0x000000, 0 );

// [...]

renderer2.setSize(window.innerWidth, window.innerHeight);
renderer2.setClearColor(background, 1);
container.appendChild(renderer2.domElement);

function renderGrid() {

    // [...]

    renderer2.render(scene2, camera2);
}

In the following code snippet, make sure that renderer corresponds to camera and sceneTop, while renderer2 corresponds to scene2 and camera2:

var camera = new THREE.PerspectiveCamera(100, window.innerWidth/window.innerHeight, 0.1, 1000);

[...]

camera.position.z = 90;

function myrender(){

    // [...]    

    renderer.render(sceneTop, camera);
    requestAnimationFrame(myrender);
}

Check out the example below where I implemented the recommended changes to your original code:

...(remaining content unchanged)


Alternatively, you can render both scenes to different parts of the viewport.

Create a single THREE.WebGLRenderer with the property .autoClear set to false:

var renderer = new THREE.WebGLRenderer({alpha: true, preserveDrawingBuffer: true});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor( 0x000000, 0 );
renderer.autoClear = false;
document.body.appendChild(renderer.domElement);

Render both scenes on different parts of the viewport. Modify the viewport rectangle using the .setViewport method:

function myrender(){

    // [...]

    renderer.setViewport(0,0,window.innerWidth, window.innerHeight);
    renderer.clear();

    renderer.setViewport(window.innerWidth/2,0,window.innerWidth/2, window.innerHeight);
    renderer.render(sceneTop, camera, 0, false);

    renderer.setViewport(0,0,window.innerWidth/2, window.innerHeight);
    renderer.render(scene2, camera2, 0, false);

    requestAnimationFrame(myrender);
}

Ensure setting the .background property only for the first rendered THREE.Scene.

Refer to the example provided for better clarity:

...(remaining content unchanged)

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

Detecting drag events between connected angular ui-trees is a complex yet achievable task

How can I trigger an action when an item is dragged from tree#1 to tree#2 and dropped? I want to make a specific HTTP call to save the transferred item. I have successfully implemented actions within one tree using the 'dropped' event, but strugg ...

I'm currently facing difficulties trying to implement AJAX with JavaScript and PHP as the desired output is not being

My query is quite straightforward - why isn't the code functioning properly? I am attempting to have the text echoed in PHP displayed inside a div with the ID of "show". Interestingly, this works with a txt file but not with PHP or any other type of f ...

Generating views for individual models in a backbone collection

Currently, I am developing a small backbone.js application that simulates a library where CRUD operations can be performed. The core components of this application are the book model and the library collection (which stores books). var Book = Backbone.Mod ...

The functionality of the OnClientClick event within the ASP.NET platform

While utilizing ASP.NET to pass a value to a JavaScript function, I encountered an issue where it doesn't seem to work when trying to pass a value from another control. It seems to behave as if there is a syntax error and just reverts back to the main ...

Issues with retrieving data from Firestore and storing it into an array in a React

Struggling to fetch data from my firestore and display it on the webpage. Despite trying all possible solutions and searching extensively, I am unable to get it working. When using the code below, nothing appears on the website. However, if I switch to th ...

The statement ""x=x || 4" will result in a `ReferenceError: x is not defined` because the

What is the reason behind receiving a ReferenceError: x is not defined error when using x = x || 4 or even x=(x||5), while var x = x || 4 operates as intended? ...

What is the most efficient way to retrieve a substantial volume of data from Mongodb quickly, especially when the query results require processing before transmitting to the client?

My project involves a large Mongodb database paired with a React front-end and Node back-end, housing around 100000 documents. Indexing has been completed and Redis is already in use. The search feature implemented allows users to find relevant documents b ...

Error in D3: stream_layers function is not defined

Utilizing nvd3.js to construct a basic stacked bar chart as detailed here I inserted the code provided in the link into an Angular directive like this: app.directive('stackBar', function() { return { restrict: 'A', ...

Techniques for retrieving user inputs upon loading the HTML document and detecting changes using JavaScript

I am new to using JS to pass data to Python. I have managed to collect the values when the HTML is loaded, but I am facing an issue where the value does not change when it is updated. Here is the code snippet that I have been working with: <input type= ...

The condition to break when a value is found within a specific range on sheet1 if it is present in the range on

Essentially, the user will input data for a new item on the NovoItem sheet. Upon pressing the Save Button (yet to be added), the code should check the ArquivoItens sheet to see if the item already exists. If it does, the code should halt its operation. Ho ...

Are programmatic clicks distinguishable from manual clicks in JQuery?

Currently, I am in the process of creating selectable and draggable elements for a table. You can test the functionality by following this JsFiddle link (please try vertically selecting). Initially, the selection works well but upon trying to select for th ...

Sending data from events to a textbox and a div

I've set an onClick event for a textbox. Is there a way to have the click event of a different div also execute when clicking on the textbox, even though they are not nested and in separate parts of the document? Any help with this in Javascript would ...

Exposing a factory JS variable globally within an AngularJS environment

I am trying to access a variable created within a factory in another function in my AngularJS controllers. How can I achieve this and make the new calculated value available? The variable I want to use is result.data.bkor_payamount = result.data.bkor_paya ...

Issue with AngularJS: Not able to get second app in template to function properly

I have encountered a puzzling issue with my two nearly identical apps. The first one seems to be running smoothly as expected, while the second one doesn't appear to be executing at all. Here is my code (jsfiddle): <div ng-app="passwdtool" ng-con ...

Bootstrap4 does not support the <button> element

How can I achieve a 'collapse icon' floated to the left followed by Copyright © using Bootstrap 4? I've looked at similar questions on this topic, but none seem to provide a direct answer. Other questions contain different code with ob ...

Retrieve an array from the success function of a jQuery AJAX call

After successfully reading an rss file using the jQuery ajax function, I created the array function mycarousel_itemList in which I stored items by pushing them. However, when I tried to use this array in another function that I had created, I encountered t ...

Incomplete header data in Angular $resource GET request

Currently, I am working with Ionic 1.3 and Angular 1.5. My goal is to retrieve some header properties from my response. The code snippet I am using looks something like this: factory('Service', function($resource, API_SETTINGS, JsonData) { re ...

Is there a way to utilize a cookie in order for the website to recognize that I have already agreed to the terms?

It's common for websites to ask for cookie and privacy acceptance upon loading, especially in the EU. I'm looking for a way to automatically accept these cookies so I don't have to constantly click "accept all" every time I open Chrome. My ...

Ignore the first checkbox selection and increase the original value by .10 with each subsequent checkbox selection

In my scenario, there is a set of checkboxes that are linked to the pricing system. Specifically, I need the base price to remain unchanged when the first checkbox is ticked. Subsequently, for each additional checkbox selected, an increment of $0.10 shou ...

Decoding JavaScript elements embedded in an HTML website

My current HTML site includes the following code: <script type="text/javascript"> jwplayer('player_container').setup( { 'width': '640', ...