WebGL Basics 6 – Torus-shaped strip

In the previous post we looked at complex mathematical transformations in order to set-up an environment where the observer can turn and move in all directions. This post deals with the creation of a torus object and the way WebGL renders a strip of triangles.


Our test page is now ready for more complex objects. This part 6 is dedicated to:

  • The creation (per Javascript code) of a torus composed of one long strip rolled around it
  • Some changes in the code to demonstrate different rendering modes and the dynamic control of the object being rendered

The results looks like a ring-shaped spring:

Torus surface formulas

First of all, we need to determine the coordinates of a point on the surface of the torus. In the previous post we saw the rotation formulas, so we use them again. Namely the torus is defined as a circle in the XZ plane that rotates around the Z axis (r is the radius of the big circle, θ the rotation angle around Z, sr the section radius, α the angle of the point in the section):

We start by defining the coordinates of the point on the section circle centered at (r,0,0) with radius sr (vector on the right hand side) and let it rotate around the Z axis, hence multiply the coordinates by a rotation matrix (see previous post for the formula):

The result of the product gives the coordinates of a point on the surface of the torus:

Creation of the toroidal strip

The idea here is to compute the coordinates of the points that form a long strip rolled on the surface of the torus. The strip itself is a made of a long broken zigzag line as illustrated hereafter:

By rendering the coordinates as a “TRIANGLE_STRIP“, WebGL will then use the points successively 3-by-3 to build a continuous strip of connected triangles.

The formulas giving the successive point coordinates are derived from the previous section, with a tweaked definition of the rotation angles. If we set n to be the number of times the strip is rolled around the torus, and sn the number of triangle pairs on one round of the strip. Then for each round, α goes from 0 to with steps of 2π/sn (every two points, due to the zigzag pattern). θ is continuously incremented during the complete torus computation such that the strip rolls around, θ goes hence from 0 to with a step equal to 2π/sn at each new round, and 2π/(sn*n) at each new zigzag pattern.

Finally, we introduce an interleave factor to control the space between one round of the strip and the next one. It is defined as a multiplication factor of the width of the strip, i.e. an interleave equal to 1 would leave no space between 2 successive rounds of the strip.

Changes in the code

The function that gives the torus coordinates is as following:

// Creates a 3D torus in the XY plane, returns the vertices in a Float32Array
// r:  big radius
// sr: section radius
// n:  number of faces
// sn: number of faces on section
// k:  factor between 0 and 1 defining the space between strips of the torus
function makeTorus(r, sr, n, sn, k)
  // Temporary arrays for the vertices and the normals
  var tv = new Array();
  // Iterates along the big circle and then around a section
  for(var i=0;i<n;i++)
    for(var j=0;j<sn+1*(i==n-1);j++)
      // Pre-calculation of angles
      var a =  2*Math.PI*(i+j/sn)/n;
      var a2 = 2*Math.PI*(i+j/sn+k)/n;
      var sa = 2*Math.PI*j/sn;
      // Coordinates on the surface of the torus  
      tv.push((r+sr*Math.cos(sa))*Math.cos(a)); // X
      tv.push((r+sr*Math.cos(sa))*Math.sin(a)); // Y
      tv.push(sr*Math.sin(sa));                 // Z
      // Second vertex to close triangle
      tv.push((r+sr*Math.cos(sa))*Math.cos(a2)); // X
      tv.push((r+sr*Math.cos(sa))*Math.sin(a2)); // Y
      tv.push(sr*Math.sin(sa));                  // Z

  // Converts and returns array
  return new Float32Array(tv);

The other changes are straightforward. First new controls are created in the HTML part to let the user play with the torus parameters. Second a new function updateObject is created, which gathers the code called each time the torus is re-computed:

// Updates object with global parameters
function updateObject()
  // ----------- added in part 6 --------------------
  // Gets the torus factor from the HTML page
  var interleave = parseFloat(document.getElementById('interleave').value);
  var numsegs = parseFloat(document.getElementById('numsegs').value);
  var numssegs = parseFloat(document.getElementById('numssegs').value);
  var sradius = parseFloat(document.getElementById('sradius').value);

  // Creates the object in "vertices"
  vertices = makeTorus(0.7, sradius, numsegs, numssegs, interleave);

  // ---------- moved from function start() -----------

  // Gets address of the input 'attribute' of the vertex shader
  var vattrib = gl.getAttribLocation(program, 'ppos');
  if(vattrib == -1)
   {alert('Error during attribute address retrieval');return;}

  // Initializes the vertex buffer and sets it as current one
  var vbuffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, vbuffer);

  // Puts vertices to buffer and links it to attribute variable 'ppos'
  gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
  gl.vertexAttribPointer(vattrib, 3, gl.FLOAT, false, 0, 0);

As usual you can play with the page on-line and experiment different combinations of parameters.


The main points to remember:

  • A torus has been defined as a sequence of point coordinates according to a zigzag pattern
  • WebGL renders these points as a continuous strip of triangles using the mode TRIANGLE_STRIP in drawArrays
  • New controls allow the user to change parameters of the torus, which is re-calculated on-the-fly

Stay tuned for the next part.

  1. #1 by Luis on December 23, 2013 - 21:39


    First of all, thanks for your posts.
    In second place, could you please kindly provide a link with whole code for shaped strip torus?

    Best regards

  1. WebGL around the net, 30 June 2011 | Learning WebGL
  2. WebGL Basics 7 – Colored torus | The Blog-o-Ben

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

%d bloggers like this: