Triangular meshes

TRIANGLE_STRIP with indexed points


Drag mouse to rotate model. Hold shift key or use mouse wheel to zoom it.

In the cone model one triangle strip and OpenGL call

    gl.drawArrays(gl.TRIANGLE_STRIP, 0, 2*nPhi);
were used. You can see above that torus (see also smooth demo) can be made as one "spiral" triangle strip too. As since every point appears in the torus twice therefore we make array of points, normals and twice larger array of indices
   var data = [], ind = [];
   var nPhi = 12, nTheta = 7,  r1 = .35, r2 = 1, Theta = 0, Phi = 0,
     dTheta = 2*Math.PI/nTheta, dPhi = dTheta/nPhi, nn = nTheta*nPhi;
   for (var i = 0; i < nTheta*(nPhi + 1); i++ ){
      Theta += dTheta;   Phi   += dPhi;
      var cosTheta = Math.cos( Theta ), sinTheta = Math.sin( Theta ),
          cosPhi = Math.cos( Phi ), sinPhi = Math.sin( Phi ),
          dist   = r2 + r1 * cosTheta;
      data.push ( cosPhi*dist, -sinPhi*dist, r1*sinTheta );     // points
      data.push ( cosPhi*cosTheta, -sinPhi*cosTheta, sinTheta); // normals
      ind.push( i, (i + nTheta) % nn);
   }
   ind.push( 0, nTheta);
bind attributes (similar to the cone script)
   var posLoc = gl.getAttribLocation(prog, "aPos");
   gl.enableVertexAttribArray( posLoc );
   var normLoc = gl.getAttribLocation(prog, "aNorm");
   gl.enableVertexAttribArray( normLoc );
   gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
   gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data), gl.STATIC_DRAW);
   gl.vertexAttribPointer(posLoc, 3, gl.FLOAT, false, 24, 0);
   gl.vertexAttribPointer(normLoc, 3, gl.FLOAT, false, 24, 12);
bind indices
   gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, gl.createBuffer());
   gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(ind),
     gl.STATIC_DRAW);
and draw strip with indexed points
   gl.drawElements(gl.TRIANGLE_STRIP, 2*nn + 2, gl.UNSIGNED_SHORT, 0);

TRIANGLES vs TRIANGLE_STRIP

One can draw a N×N rectangular patch with 2×N×N triangles as N triangle strips. But models with many spline patches (and large number of OpenGL calls) were accelerated after N calls with TRIANGLE_STRIP were replaced by one call with TRIANGLES (which has 3 times larger array of indices).

Large rectangular patches

In OpenGL ES (and WebGL) indices are Uint16 numbers. Therefore one can make maximum a 256×256 patch with indexed points. But one can use up to 2048×2048 patches (see big_hat script, sorry it uses OES_texture_float extension) with
   gl.drawArrays(gl.TRIANGLES, 0, 6*(N-1)*(N-1));
Note that it uses 6×N×N points instead of only N×N indexed points.

Attributes storage

There are 3 methods to store attributes (e.g. aPos and aNorm):
1. in separate buffers
2. two arrays in one buffer
3. attributes for a given vertex are stored in one structure (piece of memory) using stride = 24 and offset = 0, 12 parameters of the vertexAttribPointer() function.
   gl.vertexAttribPointer(posLoc, 3, gl.FLOAT, false, 24, 0);
   gl.vertexAttribPointer(normLoc, 3, gl.FLOAT, false, 24, 12);
Method 3 is natural for a few cores CPU but I read somewhere that array of attribute values are more convenient when a very large bunch of threads (vertex shaders) is prepared.

Many instances

To make the Ethanol molecule the drawBall( x,y,z, r,g,b, scale ) method is called with position, color and scale of 9 spheres
  function drawScene(){
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    rotMat.rotate(xRot/3, 1,0,0);  rotMat.rotate(yRot/3, 0,1,0);
    drawBall(0,0,0, .3,.3,.3, 1.5);
    drawBall(2,2,0, 1,1,1, 1);
    ...
    gl.flush();
  }
  function drawBall(x,y,z, r,g,b, scale){
these operators are used to translate (rotate) every instance
    mvMatrix.makeIdentity();
    mvMatrix.translate(x, y, z);
//  mvMatrix.rotate(90, 1,0,0);
this is rotation/translation of the whole model
    mvMatrix.multRight( rotMat );
    mvMatrix.translate(0, 0, -10.5);
    gl.uniformMatrix4fv( mvMatLoc, false, new Float32Array(mvMatrix.getAsArray()) );
color and scale uniforms are set. Then sphere is rendered
    gl.uniform1f( scaleLoc, scale );
    gl.uniform3f( colorLoc, r, g, b );
    for(var i=0; i < nTheta; i++)
      gl.drawElements(gl.TRIANGLE_STRIP, 2*(nPhi+1), gl.UNSIGNED_SHORT,
        4*(nPhi+1)*i);
  }
Note that this old script uses many TRIANGLE_STRIPs yet.

Compression on fly of the text files

Server will compress on fly your HTML files (4-5 times) and browsers will decompress them automatically if you put in your directory .htaccess file containing something like this
<IfModule mod_deflate.c>
  <FilesMatch "\.(css|js|x?html?|php)$">
        SetOutputFilter DEFLATE
  </FilesMatch>
</IfModule>

Contents     updated 21 March 2011