2

I display 25000 lines in THREEJS and the performance is pretty poor. (<5FPS)

I follow the "simplest" approach by creating 1 mesh per line and adding it to the scene:

  // trks is an array that contains 25000 geometries
  var trks = ...;

  var material = new THREE.LineBasicMaterial({ vertexColors: THREE.VertexColors });

  for(var i = 0; i<trks.length; i++) {
    var line = new THREE.Line( trks[i].geometry, material);
    scene.add( line );
  }

I generate regular geometries (vs buffer geometries) as:

var geometry = new THREE.Geometry();
...
// push n vertices
geometry.vertices.push(new THREE.Vector3(track.points[k][0], track.points[k][1], track.points[k][2]));
...
// push n colors
geometry.colors.push(new THREE.Color(diff[0], diff[1], diff[2]));

Live JSFiddle: http://jsfiddle.net/16fnyb8k/34/

Geometry creation: https://github.com/FNNDSC/ami/blob/dev/src/loaders/loaders.trk.js#L328-L408

Should I merge all the geometries together somehow? Use buffer geometries instead (would that have any impact on performace)? both?

=== UPDATE ===

I did a dummy test with N BufferGeometries but it doesn't seem to really have any impact:

  for(var i = 0; i<trks.length; i++) {

    // create buffer geometry per track
    var bufferGeometry = new THREE.BufferGeometry();
    var vertices = [];
    for(var j=0; j<trks[i].geometry.vertices.length; j++) {
      vertices.push(trks[i].geometry.vertices[j].x);
      vertices.push(trks[i].geometry.vertices[j].y);
      vertices.push(trks[i].geometry.vertices[j].z);
     }
     var fvertices = new Float32Array(vertices);
     bufferGeometry.addAttribute( 'position', new THREE.BufferAttribute( fvertices, 3 ) );

    // create mesh
    var line = new THREE.Line( bufferGeometry, material);
    line.applyMatrix(series[0].stack[0].ijk2LPS);
    scene.add( line );
  }

Live Fiddle: http://jsfiddle.net/16fnyb8k/51/

enter image description here

=== UPDATE 2 ===

Using buffer geometries and merging all lines together makes it much smoother, however all the lines are now connected:

var bufferGeometry = new THREE.BufferGeometry();
var vertices = [];
var colors = [];

for(var i = 0; i<trks.length; i++) {

  for(var j=0; j<trks[i].geometry.vertices.length; j++) {

    vertices.push(trks[i].geometry.vertices[j].x);
    vertices.push(trks[i].geometry.vertices[j].y);
    vertices.push(trks[i].geometry.vertices[j].z);

    colors.push(trks[i].geometry.colors[j].r);
    colors.push(trks[i].geometry.colors[j].g);
    colors.push(trks[i].geometry.colors[j].b);

  }

}

var fvertices = new Float32Array(vertices);
var fcolors = new Float32Array(colors);
bufferGeometry.addAttribute( 'position', new THREE.BufferAttribute( fvertices, 3 ) );
bufferGeometry.addAttribute( 'color', new THREE.BufferAttribute( fcolors, 3 ) );

var line = new THREE.Line( bufferGeometry, material);
line.applyMatrix(series[0].stack[0].ijk2LPS);
scene.add( line );

JS Fiddle: http://jsfiddle.net/16fnyb8k/59/

enter image description here

Thanks

Nicolas
  • 2,191
  • 3
  • 29
  • 49
  • Look into `THREE.InstancedBufferGeometry` – pailhead Sep 06 '17 at 15:49
  • Thanks for the suggestion @pailhead but unfortunately it doesn't seem to have impact (see edits) - still very low FPS – Nicolas Sep 06 '17 at 16:20
  • Actually it is already better but I was hoping to get more of a bump – Nicolas Sep 06 '17 at 16:28
  • how big is `trks` – pailhead Sep 06 '17 at 16:43
  • trks is an array that contains 25000 geometries. Each "line" geometry has between 1 and 50 points. – Nicolas Sep 06 '17 at 16:45
  • I am considering grouping my lines by "length", that will give me 50 objects to add to the scene. Looking for how to properly merge bufferGeometries (to keep lines visually distincts) – Nicolas Sep 06 '17 at 16:48
  • @Nicolas Create one instance of `THREE.LineSegments` with `BufferGeometry` and vertex colors. Draw all your lines in a single draw call. Type `renderer.info` into the console. – WestLangley Sep 06 '17 at 17:02
  • @WestLangley I did what you suggested, it works smoothly however all the lines are now connected. Any advice on how to keep lines "separated"? See update in post – Nicolas Sep 06 '17 at 17:09
  • 1
    You worked on what I suggested for 7 minutes? – WestLangley Sep 06 '17 at 17:11
  • Oh misread your suggestion – Nicolas Sep 06 '17 at 17:12
  • You are suggesting to create 1 global object of type `THREE.LineSegments` with all lines packed into 1 big buffer geometry, correct? http://jsfiddle.net/16fnyb8k/60/ - it doesn't seem to work as my "lines" can have more than 2 points and in using only one buffer geometry may result in have 2 independent lines connected – Nicolas Sep 06 '17 at 17:21
  • yes, everywhere you have a connection (two segments belonging to the same line) you will duplicate the vertex, [(0,0,0)(1,1,1)]_[(1,1,1)(2,2,2)] – pailhead Sep 06 '17 at 17:27
  • I guess `THREE.LineSegment` will work if I add extra points to make sure all segments of a line are properly defined - was it what you where suggesting? – Nicolas Sep 06 '17 at 17:28
  • beautiful - thanks for your time guys - http://jsfiddle.net/16fnyb8k/61/ feel free to post an answer if you'd like me to accept it, if now will post an answer later - – Nicolas Sep 06 '17 at 17:30
  • @Nicolas, why not post and accept your answer? Then this won't show up as an unresolved question... – duhaime Apr 24 '18 at 22:06
  • 1
    @duhaime to post/accept your own answer you have to wait a couple of days - so I just forgot about it – Nicolas Apr 25 '18 at 11:30

1 Answers1

2

Create line segments from a buffer geometry.

Live demo: http://jsfiddle.net/16fnyb8k/61/

var material = new THREE.LineBasicMaterial({ vertexColors: THREE.VertexColors });
var bufferGeometry = new THREE.BufferGeometry();

var vertices = [];
var colors = [];

for(var i = 0; i<trks.length; i++) {
  for(var j=0; j<trks[i].geometry.vertices.length; j++) {

    vertices.push(trks[i].geometry.vertices[j].x);
    vertices.push(trks[i].geometry.vertices[j].y);
    vertices.push(trks[i].geometry.vertices[j].z);

    colors.push(trks[i].geometry.colors[j].r);
    colors.push(trks[i].geometry.colors[j].g);
    colors.push(trks[i].geometry.colors[j].b);

    if(j > 0 && j<trks[i].geometry.vertices.length - 1) {
      vertices.push(trks[i].geometry.vertices[j].x);
      vertices.push(trks[i].geometry.vertices[j].y);
      vertices.push(trks[i].geometry.vertices[j].z);

      colors.push(trks[i].geometry.colors[j].r);
      colors.push(trks[i].geometry.colors[j].g);
      colors.push(trks[i].geometry.colors[j].b);
    }
  }

}

var fvertices = new Float32Array(vertices);
var fcolors = new Float32Array(colors);
// itemSize = 3 because there are 3 values (components) per vertex
bufferGeometry.addAttribute( 'position', new THREE.BufferAttribute( fvertices, 3 ) );
bufferGeometry.addAttribute( 'color', new THREE.BufferAttribute( fcolors, 3 ) );
var line = new THREE.LineSegments( bufferGeometry, material);
line.applyMatrix(series[0].stack[0].ijk2LPS);
scene.add( line );
Nicolas
  • 2,191
  • 3
  • 29
  • 49