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

时间:2017-10-26 12:25:30

标签: javascript three.js

我有一个带有圆圈的three.js画布,可以独立移动。最初这些圆圈通过一条线连接,该线与所有位置保持相同的几何形状。

在这些圈子移动时,我无法更新线条的几何体。

我正在搜索所有场景中的孩子,找到任何一个名为“' item'并更新x&你的位置。当我尝试更新线条的几何图形时,它会消失或保持静止(如下面的代码所示)。

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

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

1 个答案:

答案 0 :(得分:1)

线几何的点已经引用了圆的位置,因此在场景的每次渲染中都不需要为它们指定新的值。

如果你将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>