1

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.

The simplified code is like:

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

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

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.

I tried to merge like:

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

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

Anyone got suggestions? Thanks.

lhrec_106
  • 630
  • 5
  • 18

1 Answers1

2

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.

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

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

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

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.

Community
  • 1
  • 1
Wilt
  • 41,477
  • 12
  • 152
  • 203
  • Hi @Wilt, may I ask a question? In the addLine function, for the number of vertices, we need 3 times of index in the positions array because of the xyz of each vertex. but when you addGroup for the bufferGeo, the start and end only multiplied the number of vertices. I checked the source code of bufferGeometry, it appears the group of buffergeometry will index the xyz part as default, so I do not need to multiply the 3 again. Am I right? – lhrec_106 Apr 29 '16 at 05:55
  • Yes, that is right. `count` is the the current amount of lines and we have 3 points per line thus `start` is `count * 3`. For positions there are 3 points per line and each point has x, y and z. So `index` is `count * 9` – Wilt Apr 29 '16 at 06:06
  • Thanks a lot, so in this case, how many elements should the positions array have? I am a bit confused, because in the getBufferGeometry() function, it is only total * 3, but in addLine() function, its index increased by 9. – lhrec_106 Apr 29 '16 at 06:17
  • It is increased by 9 because we have a line with 3 points and each point has 3 values (x, y and z). `3 * 3 = 9` position values per line :) – Wilt Apr 29 '16 at 06:19
  • Now I see where the confusion comes from. Total is the amount of `points` not the amount of lines. My if clause (`count < total `) doesn't make sense sine I compare line count with total amount of points. I will update later.. – Wilt Apr 29 '16 at 06:25