Updating line connections between objects in Three.js while rendering

I am working with a three.js canvas that contains circles moving independently. Initially, these circles are connected by a single line that follows the same geometry as their positions.

However, I am facing difficulty updating the line's geometry when these circles move.

I have tried searching through all the scene's children to find any child named 'item' and updating their x & y positions. Yet, when attempting to update the line's geometry, it either disappears or remains static (as seen in the code below).

How can I effectively update the line's geometry on each frame to match the movements of the circles?

var container;
var camera, scene, renderer;

var numItems = 40;
var xspeed; // Speed of the shape
var yspeed; // Speed of the shape
var lineGeometry;

init();
animate();

function init() {
  container = document.createElement('div');
  document.body.appendChild(container);
  camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 10000);
  scene = new THREE.Scene();
  scene.background = new THREE.Color(0xff3000);
  var geometry = new THREE.CircleBufferGeometry(15, 20);
  lineGeometry = new THREE.Geometry();

  for (var i = 0; i < numItems; i++) {
    var item = new THREE.Mesh(geometry, new THREE.MeshLambertMaterial({ color: Math.random() * 0x000000 }));
    item.position.x = (-180) + (i * Math.random() * (80 - 1) + 1);
    item.position.y = (-50) + (i * Math.random() * (80 - 1) + 1);
    item.xspeed = Math.random() * (2 - 1);
    item.yspeed = Math.random() * (1 - 0.5);
    item.name = "item";
    scene.add(item);
    lineGeometry.vertices.push(item.position);
  }

  var line = new THREE.Line(lineGeometry, new THREE.LineBasicMaterial({ color: 0x000000 }));
  line.name = "line";
  scene.add(line);

  function animate() {
    requestAnimationFrame(animate);
    render();
  }
  
  function render() {
    for (var i = 0; i < scene.children.length; i++) {
      var newPosition;
      if (scene.children[i].name === 'item') {
        scene.children[i].position.x = scene.children[i].position.x + scene.children[i].xspeed;
        scene.children[i].position.y = scene.children[i].position.y + scene.children[i].yspeed;

        newPosition = scene.children[i].position;

        if (scene.children[i].position.x > window.innerWidth/2 || scene.children[i].position.x < -window.innerWidth/2) {
          scene.children[i].xspeed = scene.children[i].xspeed * (-1);
        }
        if (scene.children[i].position.y > window.innerWidth/2 || scene.children[i].position.y < -window.innerWidth/2) {
          scene.children[i].yspeed = scene.children[i].yspeed * (-1);
        }
      }

      if (scene.children[i].name === 'line') {
        scene.children[i].vertices = newPosition;
      }
    }

    camera.position.x = 0;
    camera.position.z = 1000;
    renderer.render(scene, camera);
  }

Answer №1

Your line geometry points are already aligned with circle positions, eliminating the need for constant reassignment during scene rendering.

If you make the line a global variable and create another global array to store circles, you can simplify the process.

var camera, scene, renderer, line, circles = [];

You can then easily add your item to the array:

circles.push(item);
scene.add(item); 

This will streamline your render function as follows:

function render() {
  circles.forEach(circle => {
    circle.position.x += circle.xspeed;
    circle.position.y += circle.yspeed;

    if (circle.position.x > window.innerWidth / 2 || circle.position.x < -window.innerWidth / 2) {
      circle.xspeed *= -1;
    }
    if (circle.position.y > window.innerWidth / 2 || circle.position.y < -window.innerWidth / 2) {
      circle.yspeed *= -1;
    }
  });
  line.geometry.verticesNeedUpdate = true;

  renderer.render(scene, camera);
}

var container;
var camera, scene, renderer, line, circles = [];

var numItems = 40;
var xspeed // Speed of the shape
var yspeed // Speed of the shape
var lineGeometry;

init();
animate();

function init() {
  scene = new THREE.Scene();
  scene.background = new THREE.Color(0xff3000);
  camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 10000);
  camera.position.set(0, 0, 1000);
  renderer = new THREE.WebGLRenderer();
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);

  var geometry = new THREE.CircleBufferGeometry(15, 20);
  lineGeometry = new THREE.Geometry();

  for (var i = 0; i < numItems; i++) {
    var item = new THREE.Mesh(geometry, new THREE.MeshLambertMaterial({
      color: Math.random() * 0x000000
    }));
    item.position.x = (-180) + (i * Math.random() * (80 - 1) + 1);
    item.position.y = (-50) + (i * Math.random() * (80 - 1) + 1);
    item.xspeed = Math.random() * (2 - 1);
    item.yspeed = Math.random() * (1 - 0.5);
    circles.push(item);
    scene.add(item);
    lineGeometry.vertices.push(item.position);
  }

  line = new THREE.Line(lineGeometry, new THREE.LineBasicMaterial({
    color: 0x000000
  }));
  line.name = "line";
  scene.add(line);
}

function animate() {
  requestAnimationFrame(animate);
  render();
}

function render() {
  circles.forEach(circle => {
    circle.position.x += circle.xspeed;
    circle.position.y += circle.yspeed;

    if (circle.position.x > window.innerWidth / 2 || circle.position.x < -window.innerWidth / 2) {
      circle.xspeed *= -1;
    }
    if (circle.position.y > window.innerWidth / 2 || circle.position.y < -window.innerWidth / 2) {
      circle.yspeed *= -1;
    }
  });
  line.geometry.verticesNeedUpdate = true;
  // this flag is crucial for updating vertex coordinates in a geometry

  renderer.render(scene, camera);
}
body {
  overflow: hidden;
  margin: 0;
}
<script src="https://threejs.org/build/three.min.js"></script>

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

Calculate the number of arrays in an object and then substitute them

Currently, I have an object that is returning the following data: Object {1: 0, 2: Array[2], 3: 0, 4: 0, 5: 0, 6: 0, 7: 0, 8: 0, 9: 0, 10: 0, 11: 0, 12: 0} My goal is to replace the "Array[2]" with just the number "2" (indicating how many records are in ...

How to use Angular pipes to format dates as Long Dates in the template

Suppose I have a date input such as 2022-04-02T00:00:00. When I utilize {{data?.dateStarted | date:'MM/dd/YYYY'}}, the result will be 04/02/2022. But how can we transform it into a Long Date format like April 2, 2022? Does anyone have any sugges ...

When a React page is re-rendered using useEffect, it automatically scrolls back to the

Every time I utilize the <Tabs> component, the onChange method triggers the handleTabChange function. This leads to the component being called again and after repainting, the useEffect is triggered causing the page to scroll back to the top. How can ...

Django issue: A Tuple or struct_time argument is necessary

Currently, I am developing a code that deals with 2 variables - showdate and viewtype. Both of these variables are transferred via JavaScript using the POST method. viewtype = send an srt showdate = send a date from javascript Within this code snippet, ...

Ways to alter the color of an icon when hovering over it

Is there a way to change the color of a material icon inside an IconButton material component when hovering over the IconButton? I've tried adding a class directly to the icon, but it only works when hovering over the icon itself and not the IconButto ...

Determining the dimensions of Vue slots

I am struggling with determining the height and width of slots to render images in my Perimeter component. The images should be 105x160 in size, but when I check clientWidth and clientHeight, I get 0x24. My issue seems related to this problem discussed on ...

How to retrieve a nested array element in JavaScript

Here is the Pastebin link of the index.html file for reference: http://pastebin.com/g8WpX6Wn (The file contains broken image links and no CSS styling). If you would like to access the entire project, you can download the zip file. I am currently working ...

Simple requirements for implementing shadows in three.js

Is this configuration enough: renderer.shadowMap.enabled = true; //for object model.castShadow = true; model.receiveShadow = true; //for ground plane.receiveShadow = true; //for light light.castShadow = true; It seems like it's no ...

Node.js: Troubleshooting a forEach Function Error

I am encountering an issue with my nodejs script that is causing a "function not found" error after trying to insert data from json files into Firestore. How can I resolve this? Thank you for your help. Below is my code snippet: var admin = require("f ...

Is there something I'm overlooking, or is this behavior unusual for an "if statement"?

I am facing an issue with returning a value from a function. It seems like a simple task - just looping through my HTMLElements and returning the one I need. This problem is new to me, and I have spent a considerable amount of time debugging the code and ...

Issues with Javascript positioning in Chrome and Safari are causing some functionality to malfunction

My Javascript script is designed to keep an image centered in the window even when the window is smaller than the image. It achieves this by adjusting the left offset of the image so that its center aligns with the center of the screen. If the window is la ...

How can you reset a variable counter while inside a forEach loop?

I am currently working on resetting a counter that is part of a recursive forEach loop within my code. Essentially, the code snippet provided calculates the length of the innermost key-value pair as follows: length = (key length) + (some strings inserted) ...

New Angular Datatables used to create a revitalizing table

In my project, I am utilizing the Angular Datatables library. The data is fetched from a URL that returns a JSON object, which is then stored in an array and used to populate a table. appenditems(){ this.items = []; this.items2 = []; this.items ...

executing the following event in Node.js

Is it feasible to execute only a portion of the code on each iteration of the event loop in an application where requests can take a second or two? Consider the following scenario: function foo() { ...critical code... ...start processing the next ...

Dynamic Checkbox Functionality in REACT

Motivation: My goal is to generate multiple rows with a variable number of checkboxes that will be managed by a useState hook. Challenge: The page freezes or displays constant loading, with no content visible. There are no console logs, and even the debug ...

I have experimented with both POST and GET methods in Node.js, exploring a variety

After creating a login page with a GET form, the server code includes: app.use(express.static(path.join(__dirname, 'public'))); I am facing an issue trying to implement a POST request. When I use "POST", it gives me a "CANNOT / PO ...

Problem encountered when attempting to utilize the spread operator within .vue files in an Elixir Phoenix 1.3 application

I'm facing an issue while building Vue.js components that involve using the spread operator to map states from Vuex within my Phoenix 1.3 application. The JavaScript compile errors I encountered are causing some roadblocks: 26 | }, 27 | compu ...

Notifications will be displayed with Alertifyjs to the individual who activated them

Just diving into the world of nodejs and express framework, so I appreciate your patience as I navigate through this learning process. I've implemented the alertifyjs library to display notifications for different alerts on my site. However, I&apos ...

Advanced Techniques: Leveraging Master Layouts, Partial Rendering, and JavaScript Function

Trying to understand the sequence of events when a master page, partials, and JavaScript code are involved. Imagine having a Master page with scripts: <%@ Master Language="C#" ... %> <head> <asp:ContentPlaceHolder ID="HeadContent" run ...

Enhancing Chat: Updating Chat Messages in Real-Time with Ember.js and Firebase

I recently started working with ember.js and firebase. Right now, I have successfully implemented a feature to post messages and view them in a list format as shown below: //templates/show-messages.hbs {{page-title "ShowMessages"}} <div clas ...