javascript - Three.js - 如何在渲染期间更新连接对象的线

标签 javascript three.js

我有一个 Three.js Canvas ,其中的圆圈可以独立移动。最初,这些圆圈通过一条线连接,该线具有与其所有位置相同的几何形状。

当这些圆圈移动时,我无法更新线条自身的几何形状。

我正在搜索场景的所有子项,以查找任何名为“item”的子项并更新 x 和 y 位置。当我尝试更新线条的几何形状时,它要么消失,要么保持静态(如下面的代码所示)。

如何成功更新每一帧上的线条几何形状以匹配移动的圆圈?

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 );
}

最佳答案

线几何体的点已经引用了圆的位置,因此无需在每次渲染场景时为它们分配新值。

如果将line作为全局变量,并添加另一个全局变量来将圆存储在数组中,那么您可以简化事情。

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

然后你可以将你的item推送到数组中:

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

因此你的渲染函数将变成这样:

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 is the most important thing to set this flag to true,
  //when you change coordinates of vertices of a geometry

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

关于javascript - Three.js - 如何在渲染期间更新连接对象的线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46954291/

相关文章:

Three.js 子网格位置总是返回 (0,0,0)

caching - Three.js 中的缓存场景

javascript - 我如何将其从两个硬编码图像更改为图像数组。

javascript - 三个js : computing the bounding box of rotated text

javascript - MongoDB : how to put conditional for multiple optional value

javascript - 长宽比填充 - 正确的方法

javascript - 如何使用 Jest 测试不同的屏幕宽度

javascript - 错误: Automation server can't create object

javascript - moment js中的自定义长日期格式

javascript - 使用three.js,如何将EffectComposer 与OculusRiftEffect、VREffect 或VRRenderer 集成?