【问题标题】:How can I make three.js update a scene after adding an object or group of objects?添加对象或对象组后如何让three.js更新场景?
【发布时间】:2015-11-21 04:24:46
【问题描述】:

我对 three.js 还很陌生,遇到了一个我无法轻易找到答案的问题。

这是一个应该总结情况的codepen:http://codepen.io/anon/pen/PPYPzO

var container, stats;
var camera, controls, scene, renderer, raycaster, mouse;

init();
animate();
add_world();

var indie_render = true;
for(var j = 0; j < 20; j++){
  add_objects(20);
  indie_render = !indie_render;
  console.log("adding more objects...");
  if(!indie_render){render();}
}


function add_world(){
  var geometry = new THREE.BoxGeometry( 1000, 1000, 1000);
  var mesh = new THREE.MeshBasicMaterial( {color: 0xf5f5dc, wireframe: false, opacity: 0.2, transparent:true } );
  var world = new THREE.Mesh( geometry, mesh );
  scene.add( world );
  render();
}

function add_objects(num, indiv){
  var geometry = new THREE.SphereGeometry( 5, 32,32 );
  var material = new THREE.MeshBasicMaterial( { shading: THREE.FlatShading } );
  material.color.setRGB( Math.random(), Math.random(), Math.random() );
  for ( var i = 0; i < num; i ++ ) {
    var mesh = new THREE.Mesh( geometry, material );
    mesh.position.x = ( Math.random() - 0.5 ) * 1000;
    mesh.position.y = ( Math.random() - 0.5 ) * 1000;
    mesh.position.z = ( Math.random() - 0.5 ) * 1000;
    mesh.updateMatrix();
    mesh.matrixAutoUpdate = false;
    scene.add( mesh );
    if(indie_render){
      console.log("individual render");
      render();
    }
  }
}

function init() {
  camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 2000 );
  camera.position.set(500, 500, -1000);
    camera.up.set( 0, 1, 0 );
    camera.lookAt(500,500,500);
  controls = new THREE.OrbitControls( camera );
  controls.addEventListener( 'change', render );

  //world
  scene = new THREE.Scene();

  // lights
  light = new THREE.DirectionalLight( 0xffffff );
  light.position.set( 1, 1, 1 );
  scene.add( light );

  light = new THREE.DirectionalLight( 0x002288 );
  light.position.set( -1, -1, -1 );
  scene.add( light );

  light = new THREE.AmbientLight( 0x222222 );
  scene.add( light );

  renderer = new THREE.WebGLRenderer( { antialias: false } );
  renderer.setClearColor( 0x000000, 1 );
  renderer.setSize( window.innerWidth, window.innerHeight );
  renderer.sortObjects = false;
  container = document.getElementById( 'container' );
  container.appendChild( renderer.domElement );

  mouse = new THREE.Vector2();
  raycaster = new THREE.Raycaster();
  container.addEventListener( 'mousemove', onMouseMove, false );
  container.addEventListener( 'mousedown', onMouseDown, false );
  window.addEventListener( 'resize', onWindowResize, false );

}

function animate() {
  requestAnimationFrame( animate );
  controls.update();
}

function render() {
  renderer.render( scene, camera );
}


function onMouseMove( e ) {
  mouse.x = ( e.clientX / renderer.domElement.width ) * 2 - 1;
  mouse.y = - ( e.clientY / renderer.domElement.height ) * 2 + 1;
}

function onMouseDown( e ) {
  mouse.x = ( e.clientX / renderer.domElement.width ) * 2 - 1;
  mouse.y = - ( e.clientY / renderer.domElement.height ) * 2 + 1;

  if(e.button == 2){    //right button
    raycaster.setFromCamera( mouse, camera );
    var intersects = raycaster.intersectObjects( scene.children, true );
    if ( intersects.length > 0 ) {
      var geometry = new THREE.SphereGeometry( 5, 32,32 );
      var material = new THREE.MeshBasicMaterial( { color:0xff0000, shading: THREE.FlatShading } );
      var mesh = new THREE.Mesh( geometry, material );
      mesh.position.set(intersects[0].point.x, intersects[0].point.y, intersects[0].point.z);
      scene.add(mesh);
      render();
    }
  }
}

在这个演示中,我 init() 和 animate() 一个空白场景,然后添加一个半透明立方体,这似乎是惯例。然后我在嵌套的 for 循环中将球体组添加到场景中,将球体随机放置在立方体内,并在每次调用 scene.add() 后调用 render()。

目前,场景添加了所有球体,然后才对用户可见,即使我可以在添加 for 循环对象后添加单个对象(通过右键单击立方体)。我需要用户能够在添加球体时进行观察,而不是等待整个事情完成。

我意识到这可能不是渲染场景的最有效方式,但是如果要设置动画的对象的信息是从服务器异步到达的,那么它会很有帮助。有人有什么建议吗?

谢谢

【问题讨论】:

    标签: three.js


    【解决方案1】:

    1) 首先:将呼叫render() 移动到animate

    function animate() {
      requestAnimationFrame( animate );
      render();
      controls.update();
    }
    

    2) 异步调用add_objectssetTimeout( add_objects, 0, 20 );

    http://codepen.io/anon/pen/bVbEEP

    【讨论】:

    • 谢谢!我之前尝试过 setTimeout() 调用,但当时没有在正确的位置使用 render()。效果很好。
    猜你喜欢
    • 2016-02-03
    • 1970-01-01
    • 1970-01-01
    • 2015-03-12
    • 1970-01-01
    • 1970-01-01
    • 2019-03-20
    • 1970-01-01
    • 2021-08-11
    相关资源
    最近更新 更多