The idea is that if you need to draw fixed stuff that involves a lot of calculation, you speed things up by 'drawing' it into a display list, just once, in init, say. Then in display you just draw the display list, rather than repeating the calculations
We follow the red book - but their torus has no normals, so we can't use lighting. Here is an alternative. It is wildly inefficient, calculating most points at least twice - but we want something with lots of calculations, so we leave it as it is:
/**
* Draw a torus.
* The torus has its 'axis' pointing at 0.0.-1, and its venctre
* is at 0,0,0
*
* @param gl The GL thing to draw it in
* @param numRound The number of divisions round the hole
* @param numCircle The number of divisions around the tube
* @param radius The radius of the main circle
* @param thickness The radius of the tube
*/
private void torus(GL gl, int numRound, int numCircle, float radius, float thickness)
{
double twoPi = Math.PI*2;
double dTheta = twoPi/numRound;
double dPhi = twoPi/numCircle;
double x0, y0, x,y,z, x1, y1, z1, x2, y2, z2, x3,y3,z3, xn, yn;
for (float theta=0; theta<twoPi; theta+=dTheta)
{
x0=radius*Math.sin(theta);
y0=radius*Math.cos(theta);
xn=radius*Math.sin(theta+dTheta);
yn=radius*Math.cos(theta+dTheta);
// we need a circle around x0, yo
for (float phi=0; phi<twoPi; phi+=dPhi)
{
z=thickness*Math.sin(phi);
x=x0+thickness*Math.cos(phi)*Math.sin(theta);
y=y0+thickness*Math.cos(phi)*Math.cos(theta);
z1=thickness*Math.sin(phi+dPhi);
x1=x0+thickness*Math.cos(phi+dPhi)*Math.sin(theta);
y1=y0+thickness*Math.cos(phi+dPhi)*Math.cos(theta);
z2=thickness*Math.sin(phi);
x2=xn+thickness*Math.cos(phi)*Math.sin(theta+dTheta);
y2=yn+thickness*Math.cos(phi)*Math.cos(theta+dTheta);
z3=thickness*Math.sin(phi+dPhi);
x3=xn+thickness*Math.cos(phi+dPhi)*Math.sin(theta+dTheta);
y3=yn+thickness*Math.cos(phi+dPhi)*Math.cos(theta+dTheta);
gl.glBegin(GL.GL_QUADS);
gl.glNormal3fv( WMVector.normal(x1,y1,z1,x,y,z,x2,y2,z2), 0);
gl.glVertex3d(x, y, z);
gl.glNormal3fv( WMVector.normal(x,y,z,x2,y2,z2,x3,y3,z3), 0);
gl.glVertex3d(x2, y2, z2);
gl.glNormal3fv( WMVector.normal(x2,y2,z2,x3,y3,z3,x1,y1,z1), 0);
gl.glVertex3d(x3, y3, z3);
gl.glNormal3fv( WMVector.normal(x3,y3,z3,x1,y1,z1,x,y,z), 0);
gl.glVertex3d(x1, y1, z1);
gl.glEnd();
}
}
}
This produces: 
We find the normals using this addition to WMVector:
public static float[] normal(double x0, double y0, double z0, double x1, double y1, double z1, double x2, double y2, double z2)
{
WMVector v0 = new WMVector(x0, y0, z0);
WMVector v1 = new WMVector(x1, y1, z1);
WMVector v2 = new WMVector(x2, y2, z2);
WMVector v3 = v0.sub(v1);
WMVector v4 = v2.sub(v1);
WMVector result=v3.cross(v4);
result=result.normalise();
return( new float[] { result.x, result.y, result.z} );
}
We want to draw a lot of these, so we actually draw a torus with a random displacement:
private void randomTorus(GL gl, int numRound, int numCircle, float radius, float thickness)
{
double a = Math.random()*20-10;
double b = Math.random()*20-10;
double c = Math.random()*20-10;
gl.glTranslated(a,b,c);
torus(gl, numRound, numCircle, radius, thickness);
}
In init, we write this 10 times into a display list:>
.. theTorus = gl.glGenLists (1); gl.glNewList(theTorus, GL.GL_COMPILE); for (int i=0; i<10; i++) randomTorus(gl,25,40, 3,1f); gl.glEndList();
theTorus is just a global int. Then in display we call this display list:
gl.glCallList(theTorus);
and this gives 
The point of this is how fast it is. We can work out the frames per second like this, at the start of display:
// frame timing
if (frameCount==0)
start=System.currentTimeMillis();
frameCount++;
if (frameCount==100)
{
long elapsed = System.currentTimeMillis()-start;
System.out.println("fps = "+1e5/elapsed);
frameCount=0;
start=System.currentTimeMillis();
}
frameCount is a global long. This shows around 100fps. If we actually re-calculate and draw them every time:
for (int i=0; i<10; i++)
randomTorus(gl,25,40, 3,1f);
Then they jump all over the screen, since they go into random positions every time. It also brings down the fps to around 15