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);
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.
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.
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.
<IfModule mod_deflate.c> <FilesMatch "\.(css|js|x?html?|php)$"> SetOutputFilter DEFLATE </FilesMatch> </IfModule>