Search code examples
javascriptthree.jsgeometryring

THREE.js: updating RingGeometry vertices


I want to update a RingGeometry's vertices dynamically. What I do is to create another RingGeometry and replace the first one's vertices with the vertices of the new one.

The problem is it was working fine on version 6.7 of THREE.JS, but on the latest version (8.9) it stopped working.

Snippet with version 6.7:

scene = new THREE.Scene;
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000);
renderer = new THREE.WebGLRenderer;
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

counter = 0;
increase = Math.PI / 100;

render = function() {
  requestAnimationFrame(render);
  angle = Math.PI * (Math.sin(counter) + 1) / 2; // avoid negatives
  counter += increase;
  ring = new THREE.RingGeometry(4, 5, 40, 1, 0, angle);
  mesh.geometry.vertices = ring.vertices;
  mesh.geometry.verticesNeedUpdate = true;
  renderer.render(scene, camera);
};

geometry = new THREE.RingGeometry(4, 5, 40, 1, 0, Math.PI * (Math.sin(counter)+1) / 2);
material = new THREE.MeshBasicMaterial({color: 0xffff00});
mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

camera.position.z = 10;
renderer.render(scene, camera);
render();
<script src="https://threejs-socketio-basic.herokuapp.com/three67.js"></script>

Snippet with version 8.9:

scene = new THREE.Scene;
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000);
renderer = new THREE.WebGLRenderer;
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

counter = 0;
increase = Math.PI / 100;

render = function() {
  requestAnimationFrame(render);
  angle = Math.PI * (Math.sin(counter) + 1) / 2; // avoid negatives
  counter += increase;
  ring = new THREE.RingGeometry(4, 5, 40, 1, 0, angle);
  mesh.geometry.vertices = ring.vertices;
  mesh.geometry.verticesNeedUpdate = true;
  renderer.render(scene, camera);
};

geometry = new THREE.RingGeometry(4, 5, 40, 1, 0, Math.PI * (Math.sin(counter)+1) / 2);
material = new THREE.MeshBasicMaterial({color: 0xffff00});
mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

camera.position.z = 10;
renderer.render(scene, camera);
render();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/89/three.min.js"></script>

Am I missing something?


Solution

  • Well, after several hours of fiddling, I found the problem!

    With the new version of THREE.js it needs the flag "elementsNeedUpdate = true;".

    Working fiddle on version 8.9:

    scene = new THREE.Scene;
    camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000);
    renderer = new THREE.WebGLRenderer;
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);
    
    counter = 0;
    increase = Math.PI / 100;
    
    render = function() {
      requestAnimationFrame(render);
      angle = Math.PI * (Math.sin(counter) + 1.01) / 2; // avoid negatives
      counter += increase;
      ring = new THREE.RingGeometry(4, 5, 40, 1, 0, angle);
      mesh.geometry.vertices = ring.vertices;
      mesh.geometry.verticesNeedUpdate = true;
      mesh.geometry.elementsNeedUpdate = true;
      renderer.render(scene, camera);
    };
    
    geometry = new THREE.RingGeometry(4, 5, 40, 1, 0, Math.PI * (Math.sin(counter)+1) / 2);
    material = new THREE.MeshBasicMaterial({color: 0xffff00});
    mesh = new THREE.Mesh(geometry, material);
    scene.add(mesh);
    
    camera.position.z = 10;
    renderer.render(scene, camera);
    render();
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/89/three.min.js"></script>