我可以使用three.js在渲染过程中的每一帧中合并几何体吗?

时间:2016-04-28 06:28:25

标签: javascript three.js

我是three.js的新手,只是尝试了一些想法。现在问题是我在场景中创建了一条线并将其用作克隆和转换的基础。这样克隆的那些将在场景中显示为一系列变换。

简化代码如下:

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>

这一切都运行良好,但是你可以看到我只能将新的行号限制为1500,当行号超过2000时,我开始出现渲染问题,fps在此之后迅速下降线数增加。

我尝试合并:

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()中使用上面的代码,它只渲染一行而不是整行行:

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

有人有建议吗?感谢。

1 个答案:

答案 0 :(得分:1)

您可以使用THREE.BufferGeometry更新线几何图形,而无需合并几何图形或向场景添加新的线条对象。像这样你将节省大量的内存,它将使你获得相同的效果。

我更新了 your fiddle here 来演示。

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

/**
 * 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函数:

/**
 * 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 他的回答on another related question here

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