我可以在渲染过程中使用three.js 在每一帧中合并几何体吗? [英] Can I merge geometry in every frame in rendering process using three.js?

查看:23
本文介绍了我可以在渲染过程中使用three.js 在每一帧中合并几何体吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是 Three.js 的新手,刚刚尝试了一些想法.现在的问题是我在场景中创建了一条线,并将其用作克隆和变换的基础.这样克隆出来的就会在场景中显示为一个变换序列.

I'm new to three.js and just tried some ideas. Now the problem is I created a line in the scene and used it as a base to clone and transform. So that the cloned ones will be shown as a sequence of transformation in the scene.

简化后的代码如下:

var line, scene, camera, light, renderer;
var frame = 0;
var random_degree = Math.round(Math.random() * 360);
var container = document.getElementById( 'container' );
init();
animate();

function init() {
   renderer = new THREE.WebGLRenderer();
   renderer.setSize( window.innerWidth, window.innerHeight );
   container.appendChild( renderer.domElement );

   scene = new THREE.Scene();

   camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
    scene.add( camera );

    camera.position.x = 0;
    camera.position.y = 0;
    camera.position.z = 200;

   var material = new THREE.LineBasicMaterial({
      transparent: true,
      color: 0x0000ff
   });

   var geometry = new THREE.Geometry();
   geometry.vertices.push(
     new THREE.Vector3( -100, 0, 0 ),
     new THREE.Vector3( 0, 100, 0 ),
     new THREE.Vector3( 100, 0, 0 )
   );
   line = new THREE.Line( geometry, material );
   //borrowed the code from http://threejs.org/docs/#Reference/Objects/Line 
   //just wanted to make it simple
}

function animate() {
    requestAnimationFrame( animate );
    frame ++;
    if( frame < 1500){
        var newCurve = line.clone();
        newCurve.rotation.x = ((random_degree + frame * 0.25) % 360) * Math.PI / 180;
        newCurve.rotation.y = ((random_degree + frame * 0.25) % 360) * Math.PI / 180;
        newCurve.rotation.z = ((random_degree + frame * 0.25) % 360) * Math.PI / 180;
        newCurve.material.opacity = 0.2;
        scene.add(newCurve);
    }
    renderer.render( scene, camera );
}

和 html 部分只是 <div id='container'></div>

and The html part is just <div id='container'></div>

一切正常,但是正如你所看到的,我只能将新行号限制为 1500,当行号超过 2000 时,我开始出现渲染问题,之后帧率迅速下降,当行数增加.

It is all working well, but as you can see that I can only limit the new line numbers to 1500, when the line number is over 2000, I started to get rendering problem, the the fps drops quickly after then when the number of lines increasing.

我尝试合并:

var totalGeometry  = new THREE.Geometry();
....
function init(){
....
    for(var i=0; i< 1500; i++){
        var newCurve = line.clone();
        newCurve.rotation.x = ((random_degree + frame * 0.25) % 360) * Math.PI / 180;
        newCurve.rotation.y = ((random_degree + frame * 0.25) % 360) * Math.PI / 180;
        newCurve.rotation.z = ((random_degree + frame * 0.25) % 360) * Math.PI / 180;
        newCurve.updateMatrix();
        totalGeometry.merge(newCurve.geometry, newCurve.matrix);
    }
    var totalLine = new THREE.Line(totalGeometry, material);
....
}    

但是我只能在init进程中合并,不能在渲染进程中合并.如果我在 function animate() 中使用上面的代码,它只会渲染一行而不是一整组线:

But I can only merge in the init process not in the rendering process. If I use the above code in function animate(), It only render one line instead of a whole group of lines:

function animate(){
    .....
    if( frame < 1500){
       var newCurve = curve1.clone();
       newCurve.rotation.x = ((random_degree + frame * 0.25) % 360) * Math.PI / 180;
       newCurve.rotation.y = ((random_degree + frame * 0.25) % 360) * Math.PI / 180;
       newCurve.rotation.z = ((random_degree + frame * 0.25) % 360) * Math.PI / 180;
       newCurve.material.opacity = 0.2;
       newCurve.updateMatrix();
       totalGeo.merge(newCurve.geometry, newCurve.matrix);
       totalMesh = new THREE.Line(totalGeo, newCurve.material);

       scene.add(totalMesh);
     }
}

有人有建议吗?谢谢.

推荐答案

您可以使用 THREE.BufferGeometry 来更新您的线条几何图形,而无需合并几何图形或向场景中添加新的线条对象.像这样你会节省很多内存,它会让你得到同样的效果.

You can use a THREE.BufferGeometry to update your line geometry without merging geometries or adding new line objects to your scene. Like this you will save a lot of memory and it will allow you to get the same effect.

我更新了你的小提琴来演示.

I updated your fiddle here to demonstrate.

首先,您需要创建一个缓冲区几何图形(在 getBufferGeometry 函数中完成):

First you need to create a buffer geometry (done in the getBufferGeometry function):

/**
 * Create a buffer geometry
 * Positions attribute with 3 vertices per point
 */
function getBufferGeometry() {
    var geometry = new THREE.BufferGeometry();

    positions = new Float32Array(total * 3);
    geometry.addAttribute(
        'position', new THREE.BufferAttribute(positions, 3)
    );
    return geometry;
}

然后奇迹发生在 addLine 函数中:

And then the magic happens here in the addLine function:

/**
 * Add a new line to the geometry on each call
 */
function addLine() {
    if (count < total) {
        vertices = getVertices();

        var index = count * 9;
        positions[index] = vertices[0].x;
        positions[index++] = vertices[0].y;
        positions[index++] = vertices[0].z;
        positions[index++] = vertices[1].x;
        positions[index++] = vertices[1].y;
        positions[index++] = vertices[1].z;
        positions[index++] = vertices[2].x;
        positions[index++] = vertices[2].y;
        positions[index++] = vertices[2].z;

        var start = count * 3;
        var end = start + 3;

        bufferGeometry.addGroup(start, end);
        line.geometry.attributes.position.needsUpdate = true
        count++;
    }
}

此解决方案基于 @WestLangley 他在此处针对另一个相关问题的回答.

This solution is based on @WestLangley his answer on another related question here.

您仍然需要在示例中设置最大点数,此值设置为代码顶部的 total.

You will still need to set an maximum amount of points in the example this value is set as total at the top of the code.

这篇关于我可以在渲染过程中使用three.js 在每一帧中合并几何体吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆