4

I'm currently building a web application to visualize CAD / CAE data.

data 

is an array with all my triangles.

My first approach to draw the triangles is to create one geometry:

triangles = new THREE.Geometry();

And then add all triangles to it:

 for (var i = 0; i < data.triangles.length; i++) {
    triangles.vertices.push(new THREE.Vector3(data.triangles[i][0].x, data.triangles[i][0].y, data.triangles[i][0].z));
    triangles.vertices.push(new THREE.Vector3(data.triangles[i][1].x, data.triangles[i][1].y, data.triangles[i][1].z));
    triangles.vertices.push(new THREE.Vector3(data.triangles[i][2].x, data.triangles[i][2].y, data.triangles[i][2].z));
    triangles.faces.push(new THREE.Face3(0,1,2));
    triangles.faces[i].vertexColors[0] = new THREE.Color(0xFF0000);
    triangles.faces[i].vertexColors[0].setRGB(data.triangles[i][0].r, data.triangles[i][0].g, data.triangles[i][0].b);
    triangles.faces[i].vertexColors[1] = new THREE.Color(0x00FF00);
    triangles.faces[i].vertexColors[1].setRGB(data.triangles[i][1].r, data.triangles[i][1].g, data.triangles[i][1].b);
    triangles.faces[i].vertexColors[2] = new THREE.Color(0x0000FF);
    triangles.faces[i].vertexColors[2].setRGB(data.triangles[i][2].r, data.triangles[i][2].g, data.triangles[i][2].b);
    lvar += 3;
 }

Add a material

material = new THREE.MeshBasicMaterial({
   vertexColors: THREE.VertexColors,
   side: THREE.DoubleSide,
   transparent: true,
   opacity: .99
});

and add the mesh to my scene object.

var mesh = new THREE.Mesh(triangles, material);
scene.add(mesh);

This approach works fine so far but because I only use one material I don't know how to add alpha to my vertexColors.

My second approach is to create a single geometry for every triangle.

for (var i = 0; i < data.triangles.length; i++) {
   triangles = new THREE.Geometry();
   triangles.vertices.push(new THREE.Vector3(data.triangles[i][0].x, data.triangles[i][0].y, data.triangles[i][0].z));
   triangles.vertices.push(new THREE.Vector3(data.triangles[i][1].x, data.triangles[i][1].y, data.triangles[i][1].z));
   triangles.vertices.push(new THREE.Vector3(data.triangles[i][2].x, data.triangles[i][2].y, data.triangles[i][2].z));
   triangles.faces.push(new THREE.Face3(0,1,2));
   triangles.faces[i].vertexColors[0] = new THREE.Color(0xFF0000);
   triangles.faces[i].vertexColors[0].setRGB(data.triangles[i][0].r, data.triangles[i][0].g, data.triangles[i][0].b);
   triangles.faces[i].vertexColors[1] = new THREE.Color(0x00FF00);
   triangles.faces[i].vertexColors[1].setRGB(data.triangles[i][1].r, data.triangles[i][1].g, data.triangles[i][1].b);
   triangles.faces[i].vertexColors[2] = new THREE.Color(0x0000FF);
   triangles.faces[i].vertexColors[2].setRGB(data.triangles[i][2].r, data.triangles[i][2].g, data.triangles[i][2].b);
   lvar += 3;
   material.triangles = new THREE.MeshBasicMaterial({
      vertexColors: THREE.VertexColors,
      side: THREE.DoubleSide,
      transparent: true,
      opacity: .99
   });
   var mesh = new THREE.Mesh(triangles, material);
   scene.add(mesh);
}

With this approach I could add my alpha / opacity to the material for every facet.

Unfortunately I get low fps with the second aproach.

Approach 1: 6000 triangles => 60 fps

Approach 2: 6000 triangles => 15 fps

Is there a way to draw lots of triangles (> 50.000) with alpha for every face / point and still beeing around 60 fps (yeah I know it depends on the hardware, too).

Edit: Using Raycaster is essential for my project.

Edit 2:
After some testing I decided to go with the following approach:
Create one geometry like I did in my first approach
Replace the MeshBasicMaterial with ShaderMaterial

First I created my two shaders:

<script type="x-shader/x-vertex" id="vertexshader">
   attribute vec3 customColor;
   attribute float customOpacity;

   varying vec3 vColor;
   varying float vOpacity;

   void main() {
      vColor = customColor;
      vOpacity = customOpacity;
      gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
   }
</script>
<script type="x-shader/x-fragment" id="fragmentshader">
   varying vec3 vColor;
   varying float vOpacity;

   void main() {
     gl_FragColor = vec4( vColor, vOpacity);
   }
</script>

Then I replaced my MeshBasicMaterial with ShaderMaterial.
Define my attributes.

attributes = {
   customColor: {    type: 'c', value: [] },
   customOpacity: { type: 'f', value: []}   
};

Create/Filled my geometry, colors and opacity:

geometry = new THREE.Geometry();
for (var i = 0, k, lvar = 0; i < data.triangles.length; i++) {
   for (k = 0; k < 3; k++) {
      geometry.vertices.push(new THREE.Vector3(data.triangles[i][k].x, data.triangles[i][k].y, data.triangles[i][k].z));
      attributes.customColor.value[lvar + k] = new THREE.Color(THREE.ColorKeywords.black);
      attributes.customColor.value[lvar + k].setRGB(data.triangles[i][k].r, data.triangles[i][k].g, data.triangles[i][k].b);
      attributes.customOpacity.value[lvar + k] = 1.0;
   }
   geometry.faces.push(new THREE.Face3(lvar, lvar + 1, lvar + 2));
   lvar += 3;
}

Created my ShaderMaterial:

var shaderMaterial = new THREE.ShaderMaterial({
   attributes: attributes,
   vertexShader: document.getElementById('vertexshader').textContent,
   fragmentShader: document.getElementById('fragmentshader').textContent,
   blending: THREE.NormalBlending,
   depthTest: true,
   transparent: true,
   side: THREE.DoubleSide,
   linewidth: 2
});

And finaly my mesh:

var mesh = new THREE.Mesh(sc.geometry.triangles, shaderMaterial);
scene.add(mesh);
endofsource
  • 354
  • 5
  • 18
  • 2
    See the `BufferGeometry` examples such as http://threejs.org/examples/webgl_buffergeometry.html which has 160,000 triangles. There are other examples, too. You can use `ShaderMaterial` with you own custom alpha attribute. Would that be an acceptable approach in your case? – WestLangley Jan 17 '14 at 15:31
  • @WestLangley Thanks for the hint! I check if it is usefull for me (: – endofsource Jan 17 '14 at 20:58
  • @WestLangley one of the reasons I use Three.js is the `Raycaster` component. I need it to work with `Line` and (based on your suggestion) `BufferGeomentry`. Is that possible? – endofsource Jan 17 '14 at 23:25
  • Read `Raycaster.js` and you can see what is supported. It works with `BufferGeometry` for meshes -- but not for lines. You can fix that yourself if you want. Do some experiments. – WestLangley Jan 18 '14 at 00:23

0 Answers0