![Børre Stenseth](http://www.it.hiof.no/~borres/allround/selfimages/bs.gif)
En fotball (buckyball)
En roterende ball ser slik ut:
Du kan også inspisere resultatet og kildekoden på en enklere side:
index.html
http://www.it.hiof.no/~borres/dw/wgl/bucky/index.html
Javascript
Det er to javascript involvert, foruten Sylvester og GLUtils: render.js som drar dynamikken og ball.js som lager selve ballen og forbereder punkter, normaler og materialer.
//globals var canvas; var gl; var mvMatrix; var perspectiveMatrix; var shaderProgram; var SIZE=20; //shapes var aBall; //dynamic var xRot=0.0; var yRot=0.0; var deltayRot=0.5; var deltaxRot=0.4; // user controlled var showBlack=true; var showWhite=true; var showLines=true; //eofglobals //start function start() { canvas = document.getElementById("theball"); initWebGL(canvas); if (gl) { gl.clearColor(1.0, 1.0, 1.0, 1.0); gl.clearDepth(1.0); gl.enable(gl.DEPTH_TEST); gl.depthFunc(gl.LEQUAL); initBuffers(); initShaders(); tick(); } } //eofstart function tick() { // using webgl-utils.js requestAnimFrame(tick,canvas); yRot+=deltayRot; xRot+=deltaxRot; drawScene(); } //initWebGL function initWebGL() { gl = null; // browser and versions reckognize webgl differently ? var names = ["webgl", "experimental-webgl", "webkit-3d", "moz-webgl"]; for(var i = 0; i < names.length; i++){ try {gl = canvas.getContext("experimental-webgl");} catch(e) {} if(gl){break;} } if (!gl) { alert("Unable to initialize WebGL. Your browser may not support it."); } } //eofinitWebGL //initBuffers function initBuffers() { // set up the ball aBall=new Ball(); } //eofinitBuffers //drawScene function drawScene() { gl.viewport(0, 0, canvas.width, canvas.height); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); perspectiveMatrix = makeOrtho(-SIZE, SIZE , -SIZE, SIZE, 0.0, 300.0); loadIdentity(); setLight(10,10,10); //mvPushMatrix(); mvScale([10.0,10.0,10.0]); mvTranslate([0.0, 0.0, -10.0]); mvRotate(yRot, [0, 1, 0]); mvRotate(xRot, [1, 0, 0]); setMatrixUniforms(); aBall.draw(); } //eofdrawScene //initShaders function initShaders() { var fragmentShader = getShader(gl, "shader-fs"); var vertexShader = getShader(gl, "shader-vs"); // Create the shader program shaderProgram = gl.createProgram(); gl.attachShader(shaderProgram, vertexShader); gl.attachShader(shaderProgram, fragmentShader); gl.linkProgram(shaderProgram); // ok? if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) { alert("Unable to initialize the shader program."); } gl.useProgram(shaderProgram); // let the shaderprogram remember the addresses // so we can use when we fill the attribute buffers shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition"); gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); shaderProgram.vertexNormalAttribute = gl.getAttribLocation(shaderProgram, "aVertexNormal"); gl.enableVertexAttribArray(shaderProgram.vertexNormalAttribute); shaderProgram.vertexMaterialIndexAttribute = gl.getAttribLocation(shaderProgram, "aMaterialIndex"); gl.enableVertexAttribArray(shaderProgram.vertexMaterialIndexAttribute); // mark light shaderProgram.ambientLightingColorUniform = gl.getUniformLocation(shaderProgram, "uAmbientLightingColor"); shaderProgram.pointLightingLocationUniform = gl.getUniformLocation(shaderProgram, "uPointLightingLocation"); shaderProgram.pointLightingDiffuseColorUniform = gl.getUniformLocation(shaderProgram, "uPointLightingDiffuseColor"); shaderProgram.pointLightingSpecularColorUniform = gl.getUniformLocation(shaderProgram, "uPointLightingSpecularColor");} //eofinitShaders //getShader function getShader(gl, id) { var shaderScript = document.getElementById(id); // ok? if (!shaderScript) { return null; } // Building the shader source string. var theSource = ""; var currentChild = shaderScript.firstChild; while(currentChild) { if (currentChild.nodeType == 3) { theSource += currentChild.textContent; } currentChild = currentChild.nextSibling; } // What type of shader, based on its MIME type. var shader; if (shaderScript.type == "x-shader/x-fragment") { shader = gl.createShader(gl.FRAGMENT_SHADER); } else if (shaderScript.type == "x-shader/x-vertex") { shader = gl.createShader(gl.VERTEX_SHADER); } else { return null; // Unknown shader type } // Send the source to the shader object gl.shaderSource(shader, theSource); // Compile the shader program gl.compileShader(shader); // See if it compiled successfully if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { alert("An error occurred compiling the shaders: " + gl.getShaderInfoLog(shader)); return null; } return shader; } //eofgetShader // Matrix utility functions // function loadIdentity() { mvMatrix = Matrix.I(4); } function multMatrix(m) { mvMatrix = mvMatrix.x(m); } function mvTranslate(v) { multMatrix(Matrix.Translation($V([v[0], v[1], v[2]])).ensure4x4()); } //setlightandcolor function setLight(x,y,z) { gl.uniform3f(shaderProgram.pointLightingLocationUniform,x,y,z); gl.uniform3f(shaderProgram.ambientLightingColorUniform, 1.0, 1.0, 1.0); gl.uniform3f(shaderProgram.pointLightingDiffuseColorUniform, 1.0, 1.0, 1.0); gl.uniform3f(shaderProgram.pointLightingSpecularColorUniform, 1.0, 1.0, 1.0); gl.uniform1i(shaderProgram.showSpecularHighlightsUniform, true); } //eofsetlightandcolor //setMatrixUniforms function setMatrixUniforms() { // set al the transformation matrices (ModelView, perspective and normal var pUniform = gl.getUniformLocation(shaderProgram, "uPMatrix"); gl.uniformMatrix4fv(pUniform, false, new Float32Array(perspectiveMatrix.flatten())); var mvUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix"); gl.uniformMatrix4fv(mvUniform, false, new Float32Array(mvMatrix.flatten())); var normalMatrix = mvMatrix.inverse(); normalMatrix = normalMatrix.transpose(); var nUniform = gl.getUniformLocation(shaderProgram, "uNormalMatrix"); gl.uniformMatrix4fv(nUniform, false, new Float32Array(normalMatrix.flatten())); } //eofsetMatrixUniforms var mvMatrixStack = []; function mvPushMatrix(m) { if (m) { mvMatrixStack.push(m.dup()); mvMatrix = m.dup(); } else { mvMatrixStack.push(mvMatrix.dup()); } } function mvPopMatrix() { if (!mvMatrixStack.length) { throw("Can't pop from an empty matrix stack."); } mvMatrix = mvMatrixStack.pop(); return mvMatrix; } function mvRotate(angle, v) { var inRadians = angle * Math.PI / 180.0; var m = Matrix.Rotation(inRadians, $V([v[0], v[1], v[2]])).ensure4x4(); multMatrix(m); } //requestFrame //requestAnimationFrame in a cross browser way, from Googles webgl-lib window.requestAnimFrame = (function() { return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(/* function FrameRequestCallback */ callback, /* DOMElement Element */ element) { window.setTimeout(callback, 1000/60); }; })(); //eofrequestFrame
// a bucky ball with radius phi function Ball() { // golden ratio, the quotient between two consecutive fib-numbers var phi=1.61803398; // polygon objects var pol=new Array(); // databuffers var vertices=[]; var normals=[]; var indices=[]; var matix=[]; // colorflags var BLACK=0.9; var WHITE=2.2; function reduce(v) { return Vector.create([Math.round(v.e(1)*1000)/1000, Math.round(v.e(2)*1000)/1000, Math.round(v.e(3)*1000)/1000]); } // 5 or 6-sided closed polygon function poly(v1,v2,v3,v4,v5,v6) { // make a center point, adjust it and close the polygon var v0; if(v6) { v0=Vector.create([ (v1.e(1)+v2.e(1)+v3.e(1)+v4.e(1)+v5.e(1)+v6.e(1))/6.0, (v1.e(2)+v2.e(2)+v3.e(2)+v4.e(2)+v5.e(2)+v6.e(2))/6.0, (v1.e(3)+v2.e(3)+v3.e(3)+v4.e(3)+v5.e(3)+v6.e(3))/6.0]) .toUnitVector().multiply(phi); this.P=new Array(reduce(v0),reduce(v1),reduce(v2),reduce(v3),reduce(v4),reduce(v5),reduce(v6),reduce(v1)); } else { v0=Vector.create([ (v1.e(1)+v2.e(1)+v3.e(1)+v4.e(1)+v5.e(1))/5.0, (v1.e(2)+v2.e(2)+v3.e(2)+v4.e(2)+v5.e(2))/5.0, (v1.e(3)+v2.e(3)+v3.e(3)+v4.e(3)+v5.e(3))/5.0]) .toUnitVector().multiply(phi); this.P=new Array(reduce(v0),reduce(v1),reduce(v2),reduce(v3),reduce(v4),reduce(v5),reduce(v1)); } this.size=this.P.length; } // set up all polygons //---- 6 ---- [0..19] pol[0]=new poly( //1 Vector.create([-2/3.0, -1/3.0-2*phi/3.0, -phi/3.0]), Vector.create([-1/3.0, -2/3.0-phi/3.0, -2*phi/3.0]), Vector.create([1/3.0, -2/3.0-phi/3.0, -2*phi/3.0]), Vector.create([2/3.0, -1/3.0-2*phi/3.0, -phi/3.0]), Vector.create([1/3.0, -phi, 0.0]), Vector.create([-1/3.0, -phi, 0.0]) ); pol[1]=new poly( //2 Vector.create([-2/3.0-phi/3.0, -2*phi/3.0, -1/3.0]), Vector.create([-1/3.0-2*phi/3.0, -phi/3.0, -2/3.0]), Vector.create([-2*phi/3.0, -1/3.0, -2/3.0-phi/3.0]), Vector.create([-phi/3.0, -2/3.0, -1/3.0-2*phi/3.0]), Vector.create([-1/3.0, -2/3.0-phi/3.0, -2*phi/3.0]), Vector.create([-2/3.0, -1/3.0-2*phi/3.0, -phi/3.0]) ); pol[2]=new poly( //3 Vector.create([-1/3.0, -phi, 0.0]), Vector.create([1/3.0, -phi, 0.0]), Vector.create([2/3.0, -1/3.0-2*phi/3.0, phi/3.0]), Vector.create([1/3.0, -2/3.0-phi/3.0, 2*phi/3.0]), Vector.create([-1/3.0, -2/3.0-phi/3.0, 2*phi/3.0]), Vector.create([-2/3.0, -1/3.0-2*phi/3.0, phi/3.0]) ); pol[3]=new poly( //4 Vector.create([-2/3.0, -1/3.0-2*phi/3.0, phi/3.0]), Vector.create([-1/3.0, -2/3.0-phi/3.0, 2*phi/3.0]), Vector.create([-phi/3.0, -2/3.0, 1/3.0+2*phi/3.0]), Vector.create([-2*phi/3.0, -1/3.0, 2/3.0+phi/3.0]), Vector.create([-1/3.0-2*phi/3.0, -phi/3.0, 2/3.0]), Vector.create([-2/3.0-phi/3.0, -2*phi/3.0, 1/3.0]) ); pol[4]=new poly(//5 Vector.create([-2/3.0-phi/3.0, -2*phi/3.0, 1/3.0]), Vector.create([-1/3.0-2*phi/3.0, -phi/3.0, 2/3.0]), Vector.create([-phi, 0.0, 1/3.0]), Vector.create([-phi, 0.0, -1/3.0]), Vector.create([-1/3.0-2*phi/3.0, -phi/3.0, -2/3.0]), Vector.create([-2/3.0-phi/3.0, -2*phi/3.0, -1/3.0]) ); pol[5]=new poly( //6 Vector.create([-1/3.0, phi, 0.0]), Vector.create([1/3.0, phi, 0.0]), Vector.create([2/3.0, 1/3.0+2*phi/3.0, -phi/3.0]), Vector.create([1/3.0, 2/3.0+phi/3.0, -2*phi/3.0]), Vector.create([-1/3.0, 2/3.0+phi/3.0, -2*phi/3.0]), Vector.create([-2/3.0, 1/3.0+2*phi/3.0, -phi/3.0]) ); pol[6]=new poly(//7 Vector.create([-2/3.0, 1/3.0+2*phi/3.0, -phi/3.0]), Vector.create([-1/3.0, 2/3.0+phi/3.0, -2*phi/3.0]), Vector.create([-phi/3.0, 2/3.0, -1/3.0-2*phi/3.0]), Vector.create([-2*phi/3.0, 1/3.0, -2/3.0-phi/3.0]), Vector.create([-1/3.0-2*phi/3.0, phi/3.0, -2/3.0]), Vector.create([-2/3.0-phi/3.0, 2*phi/3.0, -1/3.0]) ); pol[7]=new poly(//8 Vector.create([-2/3.0, 1/3.0+2*phi/3.0, phi/3.0]), Vector.create([-1/3.0, 2/3.0+phi/3.0, 2*phi/3.0]), Vector.create([1/3.0, 2/3.0+phi/3.0, 2*phi/3.0]), Vector.create([2/3.0, 1/3.0+2*phi/3.0, phi/3.0]), Vector.create([1/3.0, phi, 0.0]), Vector.create([-1/3.0, phi, 0.0]) ); pol[8]=new poly(//9 Vector.create([-2/3.0-phi/3.0, 2*phi/3.0, 1/3.0]), Vector.create([-1/3.0-2*phi/3.0, phi/3.0, 2/3.0]), Vector.create([-2*phi/3.0, 1/3.0, 2/3.0+phi/3.0]), Vector.create([-phi/3.0, 2/3.0, 1/3.0+2*phi/3.0]), Vector.create([-1/3.0, 2/3.0+phi/3.0, 2*phi/3.0]), Vector.create([-2/3.0, 1/3.0+2*phi/3.0, phi/3.0]) ); pol[9]=new poly( //10 Vector.create([-2/3.0-phi/3.0, 2*phi/3.0, -1/3.0]), Vector.create([-1/3.0-2*phi/3.0, phi/3.0, -2/3.0]), Vector.create([-phi, 0.0, -1/3.0]), Vector.create([-phi, 0.0, 1/3.0]), Vector.create([-1/3.0-2*phi/3.0, phi/3.0, 2/3.0]), Vector.create([-2/3.0-phi/3.0, 2*phi/3.0, 1/3.0]) ); pol[10]=new poly( //11 Vector.create([-phi/3.0, -2/3.0, -1/3.0-2*phi/3.0]), Vector.create([-2*phi/3.0, -1/3.0, -2/3.0-phi/3.0,]), Vector.create([-2*phi/3.0, 1/3.0, -2/3.0-phi/3.0]), Vector.create([-phi/3.0, 2/3.0, -1/3.0-2*phi/3.0]), Vector.create([0.0, 1/3.0, -phi]), Vector.create([0.0, -1/3.0, -phi]) ); pol[11]=new poly( //12 Vector.create([0.0, -1/3.0, -phi]), Vector.create([0.0, 1/3.0, -phi]), Vector.create([phi/3.0, 2/3.0, -1/3.0-2*phi/3.0]), Vector.create([2*phi/3.0, 1/3.0, -2/3.0-phi/3.0]), Vector.create([2*phi/3.0, -1/3.0, -2/3.0-phi/3.0]), Vector.create([phi/3.0, -2/3.0, -1/3.0-2*phi/3.0]) ); pol[12]=new poly( //13 Vector.create([phi/3.0, -2/3.0, -1/3.0-2*phi/3.0]), Vector.create([2*phi/3.0, -1/3.0, -2/3.0-phi/3.0]), Vector.create([1/3.0+2*phi/3.0, -phi/3.0, -2/3.0]), Vector.create([2/3.0+phi/3.0, -2*phi/3.0, -1/3.0]), Vector.create([2/3.0, -1/3.0-2*phi/3.0, -phi/3.0]), Vector.create([1/3.0, -2/3.0-phi/3.0, -2*phi/3.0]) ); pol[13]=new poly( //14 Vector.create([0.0, -1/3.0, phi]), Vector.create([0.0, 1/3.0, phi]), Vector.create([-phi/3.0, 2/3.0, 1/3.0+2*phi/3.0]), Vector.create([-2*phi/3.0, 1/3.0, 2/3.0+phi/3.0]), Vector.create([-2*phi/3.0, -1/3.0, 2/3.0+phi/3.0]), Vector.create([-phi/3.0, -2/3.0, 1/3.0+2*phi/3.0]) ); pol[14]=new poly( //15 Vector.create([phi/3.0, -2/3.0, 1/3.0+2*phi/3.0]), Vector.create([2*phi/3.0, -1/3.0, 2/3.0+phi/3.0]), Vector.create([2*phi/3.0, 1/3.0, 2/3.0+phi/3.0]), Vector.create([phi/3.0, 2/3.0, 1/3.0+2*phi/3.0]), Vector.create([0.0, 1/3.0, phi]), Vector.create([0.0, -1/3.0, phi]) ); pol[15]=new poly( //16 Vector.create([1/3.0, -2/3.0-phi/3.0, 2*phi/3.0]), Vector.create([2/3.0, -1/3.0-2*phi/3.0, phi/3.0]), Vector.create([2/3.0+phi/3.0, -2*phi/3.0, 1/3.0]), Vector.create([1/3.0+2*phi/3.0, -phi/3.0, 2/3.0]), Vector.create([2*phi/3.0, -1/3.0, 2/3.0+phi/3.0]), Vector.create([phi/3.0, -2/3.0, 1/3.0+2*phi/3.0]) ); pol[16]=new poly( //17 Vector.create([1/3.0, 2/3.0+phi/3.0, -2*phi/3.0]), Vector.create([2/3.0, 1/3.0+2*phi/3.0, -phi/3.0]), Vector.create([2/3.0+phi/3.0, 2*phi/3.0, -1/3.0]), Vector.create([1/3.0+2*phi/3.0, phi/3.0, -2/3.0]), Vector.create([2*phi/3.0, 1/3.0, -2/3.0-phi/3.0]), Vector.create([phi/3.0, 2/3.0, -1/3.0-2*phi/3.0]) ); pol[17]=new poly( //18 Vector.create([phi/3.0, 2/3.0, 1/3.0+2*phi/3.0]), Vector.create([2*phi/3.0, 1/3.0, 2/3.0+phi/3.0]), Vector.create([1/3.0+2*phi/3.0, phi/3.0, 2/3.0]), Vector.create([2/3.0+phi/3.0, 2*phi/3.0, 1/3.0]), Vector.create([2/3.0, 1/3.0+2*phi/3.0, phi/3.0]), Vector.create([1/3.0, 2/3.0+phi/3.0, 2*phi/3.0]) ); pol[18]=new poly( //19 Vector.create([2/3.0+phi/3.0, -2*phi/3.0, -1/3.0]), Vector.create([1/3.0+2*phi/3.0, -phi/3.0, -2/3.0]), Vector.create([phi, 0.0, -1/3.0]), Vector.create([phi, 0.0, 1/3.0]), Vector.create([1/3.0+2*phi/3.0, -phi/3.0, 2/3.0]), Vector.create([2/3.0+phi/3.0, -2*phi/3.0, 1/3.0]) ); pol[19]=new poly( //20 Vector.create([2/3.0+phi/3.0, 2*phi/3.0, 1/3.0]), Vector.create([1/3.0+2*phi/3.0, phi/3.0, 2/3.0]), Vector.create([phi, 0.0, 1/3.0]), Vector.create([phi, 0.0, -1/3.0]), Vector.create([1/3.0+2*phi/3.0, phi/3.0, -2/3.0]), Vector.create([2/3.0+phi/3.0, 2*phi/3.0, -1/3.0]) ); //---- 5 ---- [20..31] pol[20]=new poly( //21 Vector.create([-2/3.0, -1/3.0-2*phi/3.0, -phi/3.0]), Vector.create([-1/3.0, -phi, 0.0]), Vector.create([-2/3.0, -1/3.0-2*phi/3.0, phi/3.0]), Vector.create([-2/3.0-phi/3.0, -2*phi/3.0, 1/3.0]), Vector.create([-2/3.0-phi/3.0, -2*phi/3.0, -1/3.0]) ); pol[21]=new poly(//22 Vector.create([-2/3.0-phi/3.0, 2*phi/3.0, -1/3.0]), Vector.create([-2/3.0-phi/3.0, 2*phi/3.0, 1/3.0]), Vector.create([-2/3.0, 1/3.0+2*phi/3.0, phi/3.0]), Vector.create([-1/3.0, phi, 0.0]), Vector.create([-2/3.0, 1/3.0+2*phi/3.0, -phi/3.0]) ); pol[22]=new poly( //23 Vector.create([-phi/3.0, -2/3.0, -1/3.0-2*phi/3.0]), Vector.create([0.0, -1/3.0, -phi]), Vector.create([phi/3.0, -2/3.0, -1/3.0-2*phi/3.0]), Vector.create([1/3.0, -2/3.0-phi/3.0, -2*phi/3.0]), Vector.create([-1/3.0, -2/3.0-phi/3.0, -2*phi/3.0]) ); pol[23]=new poly( //24 Vector.create([-1 / 3.0, -2 / 3.0 - phi / 3.0, 2 * phi / 3.0]), Vector.create([1 / 3.0, -2 / 3.0 - phi / 3.0, 2 * phi / 3.0]), Vector.create([phi / 3.0, -2 / 3.0, 1 / 3.0 + 2 * phi / 3.0]), Vector.create([0.0, -1 / 3.0, phi]), Vector.create([-phi / 3.0, -2 / 3.0, 1 / 3.0 + 2 * phi / 3.0]) ); pol[24]=new poly( //25 Vector.create([-1/3.0, 2/3.0+phi/3.0, -2*phi/3.0]), Vector.create([1/3.0, 2/3.0+phi/3.0, -2*phi/3.0]), Vector.create([phi/3.0, 2/3.0, -1/3.0-2*phi/3.0]), Vector.create([0.0, 1/3.0, -phi]), Vector.create([-phi/3.0, 2/3.0, -1/3.0-2*phi/3.0]) ); pol[25]=new poly( //26 Vector.create([-phi/3.0, 2/3.0, 1/3.0+2*phi/3.0]), Vector.create([0.0, 1/3.0, phi]), Vector.create([phi/3.0, 2/3.0, 1/3.0+2*phi/3.0]), Vector.create([1/3.0, 2/3.0+phi/3.0, 2*phi/3.0]), Vector.create([-1/3.0, 2/3.0+phi/3.0, 2*phi/3.0]) ); pol[26]=new poly( //27 Vector.create([1/3.0, -phi, 0.0]), Vector.create([2/3.0, -1/3.0-2*phi/3.0, -phi/3.0]), Vector.create([2/3.0+phi/3.0, -2*phi/3.0, -1/3.0]), Vector.create([2/3.0+phi/3.0, -2*phi/3.0, 1/3.0]), Vector.create([2/3.0, -1/3.0-2*phi/3.0, phi/3.0]) ); pol[27]=new poly( //28 Vector.create([2/3.0, 1/3.0+2*phi/3.0, phi/3.0]), Vector.create([2/3.0+phi/3.0, 2*phi/3.0, 1/3.0]), Vector.create([2/3.0+phi/3.0, 2*phi/3.0, -1/3.0]), Vector.create([2/3.0, 1/3.0+2*phi/3.0, -phi/3.0]), Vector.create([1/3.0, phi, 0.0]) ); pol[28]=new poly( //29 Vector.create([-phi, 0.0, -1/3.0]), Vector.create([-1/3.0-2*phi/3.0, phi/3.0, -2/3.0]), Vector.create([-2*phi/3.0, 1/3.0, -2/3.0-phi/3.0]), Vector.create([-2*phi/3.0, -1/3.0, -2/3.0-phi/3.0]), Vector.create([-1/3.0-2*phi/3.0, -phi/3.0, -2/3.0]) ); pol[29]=new poly( //30 Vector.create([-1/3.0-2*phi/3.0, -phi/3.0, 2/3.0]), Vector.create([-2*phi/3.0, -1/3.0, 2/3.0+phi/3.0]), Vector.create([-2*phi/3.0, 1/3.0, 2/3.0+phi/3.0]), Vector.create([-1/3.0-2*phi/3.0, phi/3.0, 2/3.0]), Vector.create([-phi, 0.0, 1/3.0]) ); pol[30]=new poly( //31 Vector.create([2*phi/3.0, -1/3.0, -2/3.0-phi/3.0]), Vector.create([2*phi/3.0, 1/3.0, -2/3.0-phi/3.0]), Vector.create([1/3.0+2*phi/3.0, phi/3.0, -2/3.0]), Vector.create([phi, 0.0, -1/3.0]), Vector.create([1/3.0+2*phi/3.0, -phi/3.0, -2/3.0]) ); pol[31]=new poly( //32 Vector.create([1/3.0+2*phi/3.0, -phi/3.0, 2/3.0]), Vector.create([phi, 0.0, 1/3.0]), Vector.create([1/3.0+2*phi/3.0, phi/3.0, 2/3.0]), Vector.create([2*phi/3.0, 1/3.0, 2/3.0+phi/3.0]), Vector.create([2*phi/3.0, -1/3.0, 2/3.0+phi/3.0]) ); //------------------------------- // set up indices, normals and material index var index=0; // set up for polygons (TRIANGLE_FAN) for(var ix=0;ix < pol.length; ix++) { for(var pix=0;pix < pol[ix].P.length;pix++) { vertices=vertices.concat([pol[ix].P[pix].e(1),pol[ix].P[pix].e(2),pol[ix].P[pix].e(3)]); //normal is same, except centerpoint but that is just ok normals=normals.concat([pol[ix].P[pix].e(1),pol[ix].P[pix].e(2),pol[ix].P[pix].e(3)]); if(ix > 19) matix=matix.concat([BLACK]); else matix=matix.concat([WHITE]); indices=indices.concat(index); index=index+1; } } // set up for outline (LINE_STRIP) for(var ix=0;ix < pol.length; ix++) { for(var pix=1;pix < pol[ix].P.length;pix++) // start at 1 to drop center point { vertices=vertices.concat([pol[ix].P[pix].e(1),pol[ix].P[pix].e(2),pol[ix].P[pix].e(3)]); //normal is same normals=normals.concat([pol[ix].P[pix].e(1),pol[ix].P[pix].e(2),pol[ix].P[pix].e(3)]); matix=matix.concat([BLACK]); indices=indices.concat(index); index=index+1; } } // prepare buffers once and for all this.verticesBuffer= gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, this.verticesBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); this.verticesNormalBuffer= gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, this.verticesNormalBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(normals), gl.STATIC_DRAW); this.verticesMaterialBuffer=gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, this.verticesMaterialBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(matix), gl.STATIC_DRAW); this.verticesIndexBuffer= gl.createBuffer(); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.verticesIndexBuffer); gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW); this.verticesIndexBuffer.COUNT=indices.length; // draw based on set buffers // for each vertex: position, normal, materialix // indices this.draw=function() { // vertices gl.bindBuffer(gl.ARRAY_BUFFER, this.verticesBuffer); gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute,3,gl.FLOAT,false,0,0); // Set the normal attribute for the vertices. gl.bindBuffer(gl.ARRAY_BUFFER,this.verticesNormalBuffer); gl.vertexAttribPointer(shaderProgram.vertexNormalAttribute,3,gl.FLOAT,false,0,0); // set material index attribute gl.bindBuffer(gl.ARRAY_BUFFER,this.verticesMaterialBuffer); gl.vertexAttribPointer(shaderProgram.vertexMaterialIndexAttribute,1,gl.FLOAT,false,0,0); // Draw the ball. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.verticesIndexBuffer); var startix=0; // whites ( 6 edges) for(var pix=0; pix < 20; pix++) { if(showWhite) gl.drawElements(gl.TRIANGLE_FAN,pol[pix].size,gl.UNSIGNED_SHORT,startix); startix=startix+2*pol[pix].size; } // blacks (5 edges) for(var pix=20; pix < 32; pix++) { if(showBlack) gl.drawElements(gl.TRIANGLE_FAN,pol[pix].size,gl.UNSIGNED_SHORT,startix); startix=startix+2*pol[pix].size; } // lines on white (6 edges) // size-1 to loose non-existing center point for(var pix=0; pix < 20; pix++) { if(showLines) gl.drawElements(gl.LINE_STRIP,pol[pix].size-1,gl.UNSIGNED_SHORT,startix); startix=startix+2*(pol[pix].size-1); } } }
Shadere
#ifdef GL_ES precision mediump float; #endif varying vec3 vTransformedNormal; varying vec4 vPosition; varying float materialIndex; uniform vec3 uAmbientLightingColor; uniform vec3 uPointLightingDiffuseColor; uniform vec3 uPointLightingSpecularColor; uniform vec3 uPointLightingLocation; void main(void) { // we deal with the ball // assume whitish vec3 materialAmbientColor = vec3(0.25, 0.20725, 0.20725); vec3 materialDiffuseColor = vec3(1.0, 0.829, 0.829); vec3 materialSpecularColor = vec3(0.296648, 0.296648, 0.296648); vec3 materialEmissiveColor = vec3(0.3, 0.3, 0.3); float materialShininess=11.264; if(materialIndex < 1.999)//black { materialAmbientColor = vec3(0.0, 0.0, 0.0); materialDiffuseColor = vec3(0.01, 0.01, 0.01); materialSpecularColor = vec3(0.50, 0.50, 0.50); materialEmissiveColor = vec3(0.0, 0.0, 0.0); materialShininess=32.0; } vec3 ambientLightWeighting = uAmbientLightingColor; vec3 lightDirection = normalize(uPointLightingLocation - vPosition.xyz); vec3 normal = normalize(vTransformedNormal); vec3 specularLightWeighting = vec3(0.0, 0.0, 0.0); vec3 eyeDirection = normalize(-vPosition.xyz); vec3 reflectionDirection = reflect(-lightDirection, normal); float specularLightBrightness = pow(max(dot(reflectionDirection, eyeDirection), 0.0), materialShininess); specularLightWeighting = uPointLightingSpecularColor * specularLightBrightness; float diffuseLightBrightness = max(dot(normal, lightDirection), 0.0); vec3 diffuseLightWeighting = uPointLightingDiffuseColor * diffuseLightBrightness; float alpha = 1.0; gl_FragColor = vec4( materialAmbientColor * ambientLightWeighting + materialDiffuseColor * diffuseLightWeighting + materialSpecularColor * specularLightWeighting + materialEmissiveColor, alpha ); }
attribute mediump vec3 aVertexNormal; // or in attribute mediump vec3 aVertexPosition; attribute mediump float aMaterialIndex; uniform mediump mat4 uNormalMatrix; uniform mediump mat4 uMVMatrix; uniform mediump mat4 uPMatrix; varying vec3 vTransformedNormal; varying vec4 vPosition; varying lowp vec4 vColor; varying mediump vec3 vLighting; varying float materialIndex; void main(void) { vPosition = uMVMatrix * vec4(aVertexPosition, 1.0); gl_Position = uPMatrix * vPosition; vTransformedNormal=(uNormalMatrix * vec4(aVertexNormal, 1.0)).xyz; materialIndex=aMaterialIndex; }
JSON
På lignende måte som i modulen Ikke en pipe kan vi skille datagenereringen fra framvisningen ved å lage en vevside som ikke har noen annen oppgave enn å generere en beskrivelse av geometrien i form av en JSON-string. I dette tilfellet kan det gjøres på mange måter. Her er valgt en svært enkel variant der vi uten videre dumper de listene som er laget som beskrevet ovenfor. Dette innebærer at ett og samme punkt beskrives mange ganger. Vi kunne lett redusert JSON-stringen betraktelig med noen litt smartere algoritmer.
Koden som lager JSON blir en forenklet variant av ball.js som beskrevet over:
// Describes a buckyball // 20 white polygons with 6 edges and 12 polygons with 5 edges // each polygon has attached a center point, p0 // a white polygon: p0,p1,p2,p3,p4,p5,p6,p1 // a black polygon: p0,p1,p2,p3,p4,p5,p1 // 2.2 trigger white and 0.9 trigger black // everything is described with origo in center and radius phi (1.61803398). // Normal is thus same as vertex, with the exception of the centerpoint (deviation is ignored) function Ball() { // golden ratio, the quotient between two consecutive fib-numbers var phi=1.61803398; var BLACK=0.9; var WHITE=2.2; // polygon objects var pol=new Array(); Vector.prototype.id=function() { return this.elements[0]+','+this.elements[1]+','+this.elements[2]; } function reduce(v) { return Vector.create([Math.round(v.e(1)*1000)/1000, Math.round(v.e(2)*1000)/1000, Math.round(v.e(3)*1000)/1000]); } // 5 or 6-sided closed polygon function poly(v1,v2,v3,v4,v5,v6) { // make a center point, adjust it and close the polygon var v0; if(v6) { v0=Vector.create([ (v1.e(1)+v2.e(1)+v3.e(1)+v4.e(1)+v5.e(1)+v6.e(1))/6.0, (v1.e(2)+v2.e(2)+v3.e(2)+v4.e(2)+v5.e(2)+v6.e(2))/6.0, (v1.e(3)+v2.e(3)+v3.e(3)+v4.e(3)+v5.e(3)+v6.e(3))/6.0]) .toUnitVector().multiply(phi); this.P=new Array(reduce(v0),reduce(v1),reduce(v2),reduce(v3),reduce(v4),reduce(v5),reduce(v6),reduce(v1)); } else { v0=Vector.create([ (v1.e(1)+v2.e(1)+v3.e(1)+v4.e(1)+v5.e(1))/5.0, (v1.e(2)+v2.e(2)+v3.e(2)+v4.e(2)+v5.e(2))/5.0, (v1.e(3)+v2.e(3)+v3.e(3)+v4.e(3)+v5.e(3))/5.0]) .toUnitVector().multiply(phi); this.P=new Array(reduce(v0),reduce(v1),reduce(v2),reduce(v3),reduce(v4),reduce(v5),reduce(v1)); } this.size=this.P.length; } // set up all polygons //---- 6 ---- [0..19] pol[0]=new poly( //1 Vector.create([-2/3.0, -1/3.0-2*phi/3.0, -phi/3.0]), Vector.create([-1/3.0, -2/3.0-phi/3.0, -2*phi/3.0]), Vector.create([1/3.0, -2/3.0-phi/3.0, -2*phi/3.0]), Vector.create([2/3.0, -1/3.0-2*phi/3.0, -phi/3.0]), Vector.create([1/3.0, -phi, 0.0]), Vector.create([-1/3.0, -phi, 0.0]) ); pol[1]=new poly( //2 Vector.create([-2/3.0-phi/3.0, -2*phi/3.0, -1/3.0]), Vector.create([-1/3.0-2*phi/3.0, -phi/3.0, -2/3.0]), Vector.create([-2*phi/3.0, -1/3.0, -2/3.0-phi/3.0]), Vector.create([-phi/3.0, -2/3.0, -1/3.0-2*phi/3.0]), Vector.create([-1/3.0, -2/3.0-phi/3.0, -2*phi/3.0]), Vector.create([-2/3.0, -1/3.0-2*phi/3.0, -phi/3.0]) ); pol[2]=new poly( //3 Vector.create([-1/3.0, -phi, 0.0]), Vector.create([1/3.0, -phi, 0.0]), Vector.create([2/3.0, -1/3.0-2*phi/3.0, phi/3.0]), Vector.create([1/3.0, -2/3.0-phi/3.0, 2*phi/3.0]), Vector.create([-1/3.0, -2/3.0-phi/3.0, 2*phi/3.0]), Vector.create([-2/3.0, -1/3.0-2*phi/3.0, phi/3.0]) ); pol[3]=new poly( //4 Vector.create([-2/3.0, -1/3.0-2*phi/3.0, phi/3.0]), Vector.create([-1/3.0, -2/3.0-phi/3.0, 2*phi/3.0]), Vector.create([-phi/3.0, -2/3.0, 1/3.0+2*phi/3.0]), Vector.create([-2*phi/3.0, -1/3.0, 2/3.0+phi/3.0]), Vector.create([-1/3.0-2*phi/3.0, -phi/3.0, 2/3.0]), Vector.create([-2/3.0-phi/3.0, -2*phi/3.0, 1/3.0]) ); pol[4]=new poly(//5 Vector.create([-2/3.0-phi/3.0, -2*phi/3.0, 1/3.0]), Vector.create([-1/3.0-2*phi/3.0, -phi/3.0, 2/3.0]), Vector.create([-phi, 0.0, 1/3.0]), Vector.create([-phi, 0.0, -1/3.0]), Vector.create([-1/3.0-2*phi/3.0, -phi/3.0, -2/3.0]), Vector.create([-2/3.0-phi/3.0, -2*phi/3.0, -1/3.0]) ); pol[5]=new poly( //6 Vector.create([-1/3.0, phi, 0.0]), Vector.create([1/3.0, phi, 0.0]), Vector.create([2/3.0, 1/3.0+2*phi/3.0, -phi/3.0]), Vector.create([1/3.0, 2/3.0+phi/3.0, -2*phi/3.0]), Vector.create([-1/3.0, 2/3.0+phi/3.0, -2*phi/3.0]), Vector.create([-2/3.0, 1/3.0+2*phi/3.0, -phi/3.0]) ); pol[6]=new poly(//7 Vector.create([-2/3.0, 1/3.0+2*phi/3.0, -phi/3.0]), Vector.create([-1/3.0, 2/3.0+phi/3.0, -2*phi/3.0]), Vector.create([-phi/3.0, 2/3.0, -1/3.0-2*phi/3.0]), Vector.create([-2*phi/3.0, 1/3.0, -2/3.0-phi/3.0]), Vector.create([-1/3.0-2*phi/3.0, phi/3.0, -2/3.0]), Vector.create([-2/3.0-phi/3.0, 2*phi/3.0, -1/3.0]) ); pol[7]=new poly(//8 Vector.create([-2/3.0, 1/3.0+2*phi/3.0, phi/3.0]), Vector.create([-1/3.0, 2/3.0+phi/3.0, 2*phi/3.0]), Vector.create([1/3.0, 2/3.0+phi/3.0, 2*phi/3.0]), Vector.create([2/3.0, 1/3.0+2*phi/3.0, phi/3.0]), Vector.create([1/3.0, phi, 0.0]), Vector.create([-1/3.0, phi, 0.0]) ); pol[8]=new poly(//9 Vector.create([-2/3.0-phi/3.0, 2*phi/3.0, 1/3.0]), Vector.create([-1/3.0-2*phi/3.0, phi/3.0, 2/3.0]), Vector.create([-2*phi/3.0, 1/3.0, 2/3.0+phi/3.0]), Vector.create([-phi/3.0, 2/3.0, 1/3.0+2*phi/3.0]), Vector.create([-1/3.0, 2/3.0+phi/3.0, 2*phi/3.0]), Vector.create([-2/3.0, 1/3.0+2*phi/3.0, phi/3.0]) ); pol[9]=new poly( //10 Vector.create([-2/3.0-phi/3.0, 2*phi/3.0, -1/3.0]), Vector.create([-1/3.0-2*phi/3.0, phi/3.0, -2/3.0]), Vector.create([-phi, 0.0, -1/3.0]), Vector.create([-phi, 0.0, 1/3.0]), Vector.create([-1/3.0-2*phi/3.0, phi/3.0, 2/3.0]), Vector.create([-2/3.0-phi/3.0, 2*phi/3.0, 1/3.0]) ); pol[10]=new poly( //11 Vector.create([-phi/3.0, -2/3.0, -1/3.0-2*phi/3.0]), Vector.create([-2*phi/3.0, -1/3.0, -2/3.0-phi/3.0,]), Vector.create([-2*phi/3.0, 1/3.0, -2/3.0-phi/3.0]), Vector.create([-phi/3.0, 2/3.0, -1/3.0-2*phi/3.0]), Vector.create([0.0, 1/3.0, -phi]), Vector.create([0.0, -1/3.0, -phi]) ); pol[11]=new poly( //12 Vector.create([0.0, -1/3.0, -phi]), Vector.create([0.0, 1/3.0, -phi]), Vector.create([phi/3.0, 2/3.0, -1/3.0-2*phi/3.0]), Vector.create([2*phi/3.0, 1/3.0, -2/3.0-phi/3.0]), Vector.create([2*phi/3.0, -1/3.0, -2/3.0-phi/3.0]), Vector.create([phi/3.0, -2/3.0, -1/3.0-2*phi/3.0]) ); pol[12]=new poly( //13 Vector.create([phi/3.0, -2/3.0, -1/3.0-2*phi/3.0]), Vector.create([2*phi/3.0, -1/3.0, -2/3.0-phi/3.0]), Vector.create([1/3.0+2*phi/3.0, -phi/3.0, -2/3.0]), Vector.create([2/3.0+phi/3.0, -2*phi/3.0, -1/3.0]), Vector.create([2/3.0, -1/3.0-2*phi/3.0, -phi/3.0]), Vector.create([1/3.0, -2/3.0-phi/3.0, -2*phi/3.0]) ); pol[13]=new poly( //14 Vector.create([0.0, -1/3.0, phi]), Vector.create([0.0, 1/3.0, phi]), Vector.create([-phi/3.0, 2/3.0, 1/3.0+2*phi/3.0]), Vector.create([-2*phi/3.0, 1/3.0, 2/3.0+phi/3.0]), Vector.create([-2*phi/3.0, -1/3.0, 2/3.0+phi/3.0]), Vector.create([-phi/3.0, -2/3.0, 1/3.0+2*phi/3.0]) ); pol[14]=new poly( //15 Vector.create([phi/3.0, -2/3.0, 1/3.0+2*phi/3.0]), Vector.create([2*phi/3.0, -1/3.0, 2/3.0+phi/3.0]), Vector.create([2*phi/3.0, 1/3.0, 2/3.0+phi/3.0]), Vector.create([phi/3.0, 2/3.0, 1/3.0+2*phi/3.0]), Vector.create([0.0, 1/3.0, phi]), Vector.create([0.0, -1/3.0, phi]) ); pol[15]=new poly( //16 Vector.create([1/3.0, -2/3.0-phi/3.0, 2*phi/3.0]), Vector.create([2/3.0, -1/3.0-2*phi/3.0, phi/3.0]), Vector.create([2/3.0+phi/3.0, -2*phi/3.0, 1/3.0]), Vector.create([1/3.0+2*phi/3.0, -phi/3.0, 2/3.0]), Vector.create([2*phi/3.0, -1/3.0, 2/3.0+phi/3.0]), Vector.create([phi/3.0, -2/3.0, 1/3.0+2*phi/3.0]) ); pol[16]=new poly( //17 Vector.create([1/3.0, 2/3.0+phi/3.0, -2*phi/3.0]), Vector.create([2/3.0, 1/3.0+2*phi/3.0, -phi/3.0]), Vector.create([2/3.0+phi/3.0, 2*phi/3.0, -1/3.0]), Vector.create([1/3.0+2*phi/3.0, phi/3.0, -2/3.0]), Vector.create([2*phi/3.0, 1/3.0, -2/3.0-phi/3.0]), Vector.create([phi/3.0, 2/3.0, -1/3.0-2*phi/3.0]) ); pol[17]=new poly( //18 Vector.create([phi/3.0, 2/3.0, 1/3.0+2*phi/3.0]), Vector.create([2*phi/3.0, 1/3.0, 2/3.0+phi/3.0]), Vector.create([1/3.0+2*phi/3.0, phi/3.0, 2/3.0]), Vector.create([2/3.0+phi/3.0, 2*phi/3.0, 1/3.0]), Vector.create([2/3.0, 1/3.0+2*phi/3.0, phi/3.0]), Vector.create([1/3.0, 2/3.0+phi/3.0, 2*phi/3.0]) ); pol[18]=new poly( //19 Vector.create([2/3.0+phi/3.0, -2*phi/3.0, -1/3.0]), Vector.create([1/3.0+2*phi/3.0, -phi/3.0, -2/3.0]), Vector.create([phi, 0.0, -1/3.0]), Vector.create([phi, 0.0, 1/3.0]), Vector.create([1/3.0+2*phi/3.0, -phi/3.0, 2/3.0]), Vector.create([2/3.0+phi/3.0, -2*phi/3.0, 1/3.0]) ); pol[19]=new poly( //20 Vector.create([2/3.0+phi/3.0, 2*phi/3.0, 1/3.0]), Vector.create([1/3.0+2*phi/3.0, phi/3.0, 2/3.0]), Vector.create([phi, 0.0, 1/3.0]), Vector.create([phi, 0.0, -1/3.0]), Vector.create([1/3.0+2*phi/3.0, phi/3.0, -2/3.0]), Vector.create([2/3.0+phi/3.0, 2*phi/3.0, -1/3.0]) ); //---- 5 ---- [20..31] pol[20]=new poly( //21 Vector.create([-2/3.0, -1/3.0-2*phi/3.0, -phi/3.0]), Vector.create([-1/3.0, -phi, 0.0]), Vector.create([-2/3.0, -1/3.0-2*phi/3.0, phi/3.0]), Vector.create([-2/3.0-phi/3.0, -2*phi/3.0, 1/3.0]), Vector.create([-2/3.0-phi/3.0, -2*phi/3.0, -1/3.0]) ); pol[21]=new poly(//22 Vector.create([-2/3.0-phi/3.0, 2*phi/3.0, -1/3.0]), Vector.create([-2/3.0-phi/3.0, 2*phi/3.0, 1/3.0]), Vector.create([-2/3.0, 1/3.0+2*phi/3.0, phi/3.0]), Vector.create([-1/3.0, phi, 0.0]), Vector.create([-2/3.0, 1/3.0+2*phi/3.0, -phi/3.0]) ); pol[22]=new poly( //23 Vector.create([-phi/3.0, -2/3.0, -1/3.0-2*phi/3.0]), Vector.create([0.0, -1/3.0, -phi]), Vector.create([phi/3.0, -2/3.0, -1/3.0-2*phi/3.0]), Vector.create([1/3.0, -2/3.0-phi/3.0, -2*phi/3.0]), Vector.create([-1/3.0, -2/3.0-phi/3.0, -2*phi/3.0]) ); pol[23]=new poly( //24 Vector.create([-1 / 3.0, -2 / 3.0 - phi / 3.0, 2 * phi / 3.0]), Vector.create([1 / 3.0, -2 / 3.0 - phi / 3.0, 2 * phi / 3.0]), Vector.create([phi / 3.0, -2 / 3.0, 1 / 3.0 + 2 * phi / 3.0]), Vector.create([0.0, -1 / 3.0, phi]), Vector.create([-phi / 3.0, -2 / 3.0, 1 / 3.0 + 2 * phi / 3.0]) ); pol[24]=new poly( //25 Vector.create([-1/3.0, 2/3.0+phi/3.0, -2*phi/3.0]), Vector.create([1/3.0, 2/3.0+phi/3.0, -2*phi/3.0]), Vector.create([phi/3.0, 2/3.0, -1/3.0-2*phi/3.0]), Vector.create([0.0, 1/3.0, -phi]), Vector.create([-phi/3.0, 2/3.0, -1/3.0-2*phi/3.0]) ); pol[25]=new poly( //26 Vector.create([-phi/3.0, 2/3.0, 1/3.0+2*phi/3.0]), Vector.create([0.0, 1/3.0, phi]), Vector.create([phi/3.0, 2/3.0, 1/3.0+2*phi/3.0]), Vector.create([1/3.0, 2/3.0+phi/3.0, 2*phi/3.0]), Vector.create([-1/3.0, 2/3.0+phi/3.0, 2*phi/3.0]) ); pol[26]=new poly( //27 Vector.create([1/3.0, -phi, 0.0]), Vector.create([2/3.0, -1/3.0-2*phi/3.0, -phi/3.0]), Vector.create([2/3.0+phi/3.0, -2*phi/3.0, -1/3.0]), Vector.create([2/3.0+phi/3.0, -2*phi/3.0, 1/3.0]), Vector.create([2/3.0, -1/3.0-2*phi/3.0, phi/3.0]) ); pol[27]=new poly( //28 Vector.create([2/3.0, 1/3.0+2*phi/3.0, phi/3.0]), Vector.create([2/3.0+phi/3.0, 2*phi/3.0, 1/3.0]), Vector.create([2/3.0+phi/3.0, 2*phi/3.0, -1/3.0]), Vector.create([2/3.0, 1/3.0+2*phi/3.0, -phi/3.0]), Vector.create([1/3.0, phi, 0.0]) ); pol[28]=new poly( //29 Vector.create([-phi, 0.0, -1/3.0]), Vector.create([-1/3.0-2*phi/3.0, phi/3.0, -2/3.0]), Vector.create([-2*phi/3.0, 1/3.0, -2/3.0-phi/3.0]), Vector.create([-2*phi/3.0, -1/3.0, -2/3.0-phi/3.0]), Vector.create([-1/3.0-2*phi/3.0, -phi/3.0, -2/3.0]) ); pol[29]=new poly( //30 Vector.create([-1/3.0-2*phi/3.0, -phi/3.0, 2/3.0]), Vector.create([-2*phi/3.0, -1/3.0, 2/3.0+phi/3.0]), Vector.create([-2*phi/3.0, 1/3.0, 2/3.0+phi/3.0]), Vector.create([-1/3.0-2*phi/3.0, phi/3.0, 2/3.0]), Vector.create([-phi, 0.0, 1/3.0]) ); pol[30]=new poly( //31 Vector.create([2*phi/3.0, -1/3.0, -2/3.0-phi/3.0]), Vector.create([2*phi/3.0, 1/3.0, -2/3.0-phi/3.0]), Vector.create([1/3.0+2*phi/3.0, phi/3.0, -2/3.0]), Vector.create([phi, 0.0, -1/3.0]), Vector.create([1/3.0+2*phi/3.0, -phi/3.0, -2/3.0]) ); pol[31]=new poly( //32 Vector.create([1/3.0+2*phi/3.0, -phi/3.0, 2/3.0]), Vector.create([phi, 0.0, 1/3.0]), Vector.create([1/3.0+2*phi/3.0, phi/3.0, 2/3.0]), Vector.create([2*phi/3.0, 1/3.0, 2/3.0+phi/3.0]), Vector.create([2*phi/3.0, -1/3.0, 2/3.0+phi/3.0]) ); //-------------------------- // uniquevectorlists var uniqueVW=new Array(); // whites var uniqueVB=new Array(); // blacks var uniqueVAll=new Array(); // all whites + blacks // materials var materialIx=new Array(); // indices var indexList=new Array(); function findInList(List,id) { for(vix=0;vix < List.length; vix++) if(pol[ix].P[pix].id()==List[vix].id()) return vix; return -1; } // make a compact point list for each color var counter=0; for(var ix=0;ix < pol.length; ix++) { if(pol[ix].size==8) { for(var pix=0;pix < pol[ix].P.length;pix++) { if(findInList(uniqueVW,pol[ix].P[pix].id())==-1) uniqueVW=uniqueVW.concat([pol[ix].P[pix]]); materialIx[findInList(uniqueVW,pol[ix].P[pix].id())]=WHITE; } } else { for(var pix=0;pix < pol[ix].P.length;pix++) { if(findInList(uniqueVB,pol[ix].P[pix].id())==-1) uniqueVB=uniqueVB.concat([pol[ix].P[pix]]); materialIx[uniqueVW.length+findInList(uniqueVB,pol[ix].P[pix].id())]=BLACK; } } } // join them uniqueVAll=uniqueVW.concat(uniqueVB); //set up vertex string var vertexStr=''; for(var ix=0;ix < uniqueVAll.length;ix++) { vertexStr+=uniqueVAll[ix].e(1)+','+ uniqueVAll[ix].e(2)+','+ uniqueVAll[ix].e(3)+','; } vertexStr=vertexStr.substring(0,vertexStr.length-1); // indices for(var ix=0;ix < pol.length; ix++) { if(pol[ix].P.length==8) { for(var pix=0;pix < pol[ix].P.length;pix++) { indexList= indexList.concat([findInList(uniqueVW,pol[ix].P[pix].id())]); } } else { for(var pix=0;pix < pol[ix].P.length;pix++) { indexList= indexList.concat([uniqueVW.length+findInList(uniqueVB,pol[ix].P[pix].id())]); } } } var mStr=materialIx.join(','); var indexStr=indexList.join(','); // report it var dump="var Bucky='{'+\n"+ "'"+'"indices" : ['+indexStr+"],'+\n"+ "'"+'"vertexPositions" : ['+vertexStr+"],'+\n"+ "'"+'"vertexMatIx" : ['+mStr+"]}';\n"; document.getElementById('dump').innerHTML=dump; /* while testing var msg="uniqueVAll.length: "+uniqueVAll.length+'\n'+ "uniqueVW.length: "+uniqueVW.length+'\n'+ "uniqueVB.length: "+uniqueVB.length+'\n'+ "materialIx.length: "+materialIx.length+'\n'+ "indexList.length: "+indexList.length; document.getElementById('test').innerHTML=msg; */ }
Du kan inspisere resultatet her.
makejson
http://www.it.hiof.no/~borres/dw/wgl/bucky/makejson/index.html
Bruken av JSON-formatet, blir igjen en forenklet ball.js.
// a bucky ball with radius phi (1.61803398) function Ball() { // evaluate JSON var buckyObj=eval('('+Bucky+')'); // make buffers and fill them from buckObj this.verticesBuffer= gl.createBuffer(); this.verticesNormalBuffer= gl.createBuffer(); this.verticesMaterialBuffer=gl.createBuffer(); this.verticesBlackMaterialBuffer=gl.createBuffer(); this.verticesIndexBuffer= gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER,this.verticesBuffer); gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(buckyObj.vertexPositions),gl.STATIC_DRAW); gl.bindBuffer(gl.ARRAY_BUFFER,this.verticesNormalBuffer); gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(buckyObj.vertexPositions),gl.STATIC_DRAW); gl.bindBuffer(gl.ARRAY_BUFFER,this.verticesMaterialBuffer); gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(buckyObj.vertexMatIx),gl.STATIC_DRAW); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,this.verticesIndexBuffer); gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,new Uint16Array(buckyObj.indices),gl.STATIC_DRAW) // want blackmaterial all over when we sraw outline var blacks=new Array(); for (var ix=0;ix<buckyObj.vertexMatIx.length;ix++) blacks=blacks.concat([0.9]); gl.bindBuffer(gl.ARRAY_BUFFER,this.verticesBlackMaterialBuffer); gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(blacks),gl.STATIC_DRAW); // draw based on prepared buffers this.draw=function() { // vertices gl.bindBuffer(gl.ARRAY_BUFFER, this.verticesBuffer); gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute,3,gl.FLOAT,false,0,0); // Set the normal attribute for the vertices. gl.bindBuffer(gl.ARRAY_BUFFER,this.verticesNormalBuffer); gl.vertexAttribPointer(shaderProgram.vertexNormalAttribute,3,gl.FLOAT,false,0,0); // set material index attribute gl.bindBuffer(gl.ARRAY_BUFFER,this.verticesMaterialBuffer); gl.vertexAttribPointer(shaderProgram.vertexMaterialIndexAttribute,1,gl.FLOAT,false,0,0); // Draw the ball. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.verticesIndexBuffer); var startix=0; // whites ( 6 edges, one is doubled and a center is supplied) for(var pix=0; pix < 20; pix++) { if(showWhite) gl.drawElements(gl.TRIANGLE_FAN,8,gl.UNSIGNED_SHORT,startix); startix=startix+16; } // blacks (5 edges, one is doubled and a center is supplied)) for(var pix=20; pix < 32; pix++) { if(showBlack) gl.drawElements(gl.TRIANGLE_FAN,7,gl.UNSIGNED_SHORT,startix); startix=startix+14; } if(showLines) { // switch to all black gl.bindBuffer(gl.ARRAY_BUFFER,this.verticesBlackMaterialBuffer); gl.vertexAttribPointer(shaderProgram.vertexMaterialIndexAttribute,1,gl.FLOAT,false,0,0); // lines on white (is all lines) // offset +2 to ignore center point startix=2; for(var pix=0; pix < 20; pix++) { gl.drawElements(gl.LINE_STRIP,7,gl.UNSIGNED_SHORT,startix); startix=startix+16; } } } }
Du kan inspisere resultatet på en enklere side:
showjson
http://www.it.hiof.no/~borres/dw/wgl/bucky/showjson/index.html