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