【问题标题】:display several times the same 3D object with three.js使用 three.js 多次显示相同的 3D 对象
【发布时间】:2014-07-24 23:31:08
【问题描述】:

我正在使用 Three.js javascript 库。为了测试它,我从here 下载了一个示例。

我正在尝试使用 for 循环多次显示相同的元素。有两个相关的问题(12)但这并不是我想要的。我的问题是,如果我在循环内创建元素,它只会显示迭代的最后一个元素。在这种特殊情况下,位置为 (12,12) 的元素。

但是,如果我执行类似 alert 的操作,它将显示所有元素。另外,如果我有任何其他延迟执行的功能。

我看到一些示例正在运行,例如 mrdoob 示例,但我希望运行此代码,因为我需要加载多个网格而不是生成原始图形。

// Set up the scene, camera, and renderer as global variables.
var scene, camera, renderer;
var group;

// Call functions
init();
animate();

// Sets up the scene.
function init() {

  // Iterator
  var i, j;

  // Create the scene and set the scene size.
  scene = new THREE.Scene();
  var WIDTH = window.innerWidth,
      HEIGHT = window.innerHeight;

  // Create a renderer and add it to the DOM.
  renderer = new THREE.WebGLRenderer({antialias:true});
  renderer.setSize(WIDTH, HEIGHT);
  document.body.appendChild(renderer.domElement);

  // Create a camera, zoom it out from the model a bit, and add it to the scene.
  camera = new THREE.PerspectiveCamera(45, WIDTH / HEIGHT, 0.1, 20000);
  camera.position.set(0,20,20);
  scene.add(camera);

  // Create an event listener that resizes the renderer with the browser window.
  window.addEventListener('resize', function() {
    var WIDTH = window.innerWidth,
        HEIGHT = window.innerHeight;
    renderer.setSize(WIDTH, HEIGHT);
    camera.aspect = WIDTH / HEIGHT;
    camera.updateProjectionMatrix();
  });

  // Set the background color of the scene.
  renderer.setClearColor(0x333F47, 1);

  // Create a light, set its position, and add it to the scene.
  var light = new THREE.PointLight(0xffffff);
  light.position.set(-100,200,100);
  scene.add(light);


  group = new THREE.Object3D();

  for(i=0; i < 15; i+=3) {
    for(j=0; j < 15; j+=3) {

      var loader = new THREE.JSONLoader();
      loader.load( "models/treehouse_logo.js", function(geometry){
        var material = new THREE.MeshLambertMaterial({color: 0x55B663});
        var mesh = new THREE.Mesh(geometry, material);
        mesh.position.set(i,0,j);
        group.add(mesh);
      });
    //alert("iteration"+i+" "+j);
    }
  }

  scene.add( group );

  // Add OrbitControls so that we can pan around with the mouse.
  controls = new THREE.OrbitControls(camera, renderer.domElement);
}

// Renders the scene and updates the render as needed.
function animate() {

  // Read more about requestAnimationFrame at http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
  requestAnimationFrame(animate);

  // Render the scene.
  renderer.render(scene, camera);
  controls.update();

}

【问题讨论】:

    标签: javascript three.js


    【解决方案1】:

    你在这里做的事情非常低效:

      for(i=0; i < 15; i+=3) {
        for(j=0; j < 15; j+=3) {
    
          var loader = new THREE.JSONLoader();
          loader.load( "models/treehouse_logo.js", function(geometry){
            var material = new THREE.MeshLambertMaterial({color: 0x55B663});
            var mesh = new THREE.Mesh(geometry, material);
            mesh.position.set(i,0,j);
            group.add(mesh);
          });
        //alert("iteration"+i+" "+j);
        }
      }
    

    这样会更好(未经测试):

      var loader = new THREE.JSONLoader();
      loader.load( "models/treehouse_logo.js", function( geometry ){
        var material, mesh, i, j, instance;
        material = new THREE.MeshLambertMaterial({ color: 0x55B663 });
        mesh = new THREE.Mesh( geometry, material );
        for ( i = 0; i < 15; i += 3 ) {
          for ( j = 0; j < 15; j += 3 ) {
            instance = mesh.clone();
            instance.position.set( i, 0, j );
            group.add( instance );
          }
        }
      });
    

    您需要为每个独特的网格重复此模式。

    您目前的方法存在的问题是:

    • GPU 需要更多内存用于每个相同的网格
    • 浏览器需要更多内存来记住每个相同的网格
    • GPU 需要更多处理能力,因为需要处理更多内存
    • 每次调用加载程序时,都会指示浏览器执行请求。在您的情况下,这是大约 25 个相同的请求。它们应该来自缓存,但仍然很慢。
    • 您也可能遇到变量范围问题,这会导致加载程序回调出现问题,但我对此并不完全确定。

    alert() 是一个非常糟糕的调试工具,因为它改变了浏览器的反应方式:当警报打开时它会停止执行 JavaScript,这会影响加载器和类似的东西。最好使用Console 日志记录方法。

    【讨论】:

      【解决方案2】:

      我会说这是因为您在循环的每次迭代中都设置了 loader 变量,这将覆盖最后一次迭代的加载器。

      为什么实际加载是在循环中完成的?为什么不加载一次并克隆它?
      例如。

        group = new THREE.Object3D();
            var loader = new THREE.JSONLoader();
            loader.load( "models/treehouse_logo.js", function(geometry){
              var material = new THREE.MeshLambertMaterial({color: 0x55B663});
              for(i=0; i < 15; i+=3) {
                for(j=0; j < 15; j+=3) {
                  var mesh = new THREE.Mesh(geometry.clone(), material);
                  mesh.position.set(i,0,j);
                  group.add(mesh);
                }
              }
            });
        scene.add( group );
      

      以上代码未经测试

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-23
        • 2020-07-23
        • 2022-04-28
        • 1970-01-01
        相关资源
        最近更新 更多