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.

## Introduction

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 “

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

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 `2π` 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 `2π` 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&lt;n;i++) for(var j=0;j&lt;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 &quot;vertices&quot; 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;} gl.enableVertexAttribArray(vattrib); // 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.

## Summary

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

in**TRIANGLE_STRIP****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 by

Luison December 23, 2013 - 21:39Hello,

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