scripts/machine.js
author Eugen Sawin <sawine@me73.com>
Fri, 15 Apr 2011 21:37:40 +0200
changeset 10 9c21841b3ef9
parent 9 610eb11054aa
child 11 9c0318d0f1c3
permissions -rwxr-xr-x
Refact.
     1 var machine;
     2 var renderer;
     3 
     4 function main()
     5 {
     6     var canvas = document.getElementById("machine");
     7     var context = new Context(canvas);
     8     context.expand();
     9     var gl = context.gl;
    10     var object = new Cube(1, context);
    11     gl.clearColor(0.0, 0.0, 0.0, 1.0);
    12     gl.enable(gl.DEPTH_TEST);
    13     machine = new Machine(object);
    14     renderer = new Renderer(context);    
    15     update();
    16 }
    17 
    18 function update()
    19 {    
    20     requestAnimFrame(update);
    21     machine.scene.rotation.x += (random(0, 2) - 2) * 0.001; 
    22     machine.scene.rotation.y += (random(0, 3) - 1) * 0.001; 
    23     machine.scene.rotation.z += (random(0, 2) - 1) * 0.001;
    24     machine.update(new Date().getTime());
    25     renderer.update(machine.scene);
    26 }
    27 
    28 function random(min, max)
    29 {
    30     return (min + Math.random() * (max - min));
    31 }
    32 
    33 function Renderer(context)
    34 {
    35     this.context = context;
    36     this.gl = context.gl;
    37     this.matrixStack = [];
    38 }
    39 Renderer.prototype.update = function(scene)
    40 { 
    41     var gl = this.context.gl;
    42     var viewport = this.context.viewport;
    43     var shader = this.context.shader;
    44     var mvMatrix = this.context.mvMatrix;
    45     var pMatrix = this.context.pMatrix;
    46 
    47     gl.viewport(0, 0, viewport.width, viewport.height);
    48     gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    49     mat4.perspective(45, viewport.width / viewport.height, 0.1, 100.0, pMatrix);
    50 
    51     mat4.identity(mvMatrix);
    52     mat4.translate(mvMatrix, [0.0, 0.0, -7.0]);
    53 
    54     this.pushMatrix(mvMatrix);
    55 
    56     mat4.rotate(mvMatrix, scene.rotation.x, [1, 0, 0]);
    57     mat4.rotate(mvMatrix, scene.rotation.y, [0, 1, 0]);
    58     mat4.rotate(mvMatrix, scene.rotation.z, [0, 0, 1]);
    59 
    60     gl.bindBuffer(gl.ARRAY_BUFFER, scene.positionBuffer);
    61     gl.vertexAttribPointer(shader.vertexPosition, scene.positionBuffer.itemSize, gl.FLOAT, false, 0, 0);
    62 
    63     gl.bindBuffer(gl.ARRAY_BUFFER, scene.colourBuffer);
    64     gl.vertexAttribPointer(shader.vertexColour, scene.colourBuffer.itemSize, gl.FLOAT, false, 0, 0);
    65     
    66     gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, scene.indexBuffer);
    67     this.context.updateMatrixUniforms();
    68     gl.drawElements(gl.TRIANGLES, scene.indexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
    69     //gl.drawArrays(gl.TRIANGLE_STRIP, 0, scene.positionBuffer.numItems);
    70     
    71     mvMatrix = this.popMatrix();
    72 
    73     if (this.next) this.next.draw(scene);
    74 }
    75 Renderer.prototype.pushMatrix = function(matrix)
    76 {
    77     var copy = mat4.create();
    78     mat4.set(matrix, copy);
    79     this.matrixStack.push(copy);
    80 }
    81 Renderer.prototype.popMatrix = function()    
    82 {
    83     if (this.matrixStack.length > 0) return this.matrixStack.pop();
    84 }
    85 
    86 function Machine(scene)
    87 {
    88     this.scene = scene;
    89     this.lastUpdate = 0;
    90 }
    91 Machine.prototype.update = function(time)
    92 {
    93     if (this.lastUpdate != 0)
    94     {
    95 	var diff = time - this.lastUpdate;
    96 	
    97     }
    98     this.lastUpdate = time;
    99 }
   100 
   101 function Context(canvas)
   102 {
   103     this.canvas = canvas;
   104     try 
   105     {
   106 	this.gl = canvas.getContext("experimental-webgl");
   107 	this.viewport = {'width': canvas.width,
   108 			 'height': canvas.height};
   109     } 
   110     catch(e) 
   111     {
   112 	alert(e);
   113     }
   114     if (!this.gl) alert("Failed: WebGL init.");
   115     this.mvMatrix = mat4.create();
   116     this.pMatrix = mat4.create();
   117     this.shader = new Shader(this);  
   118     window.onresize = this.expand();
   119 }
   120 Context.prototype.updateMatrixUniforms = function()
   121 {
   122     var gl = this.gl;
   123     var program = this.shader;
   124     var pMatrix = this.pMatrix;
   125     var mvMatrix = this.mvMatrix;
   126     gl.uniformMatrix4fv(program.pMatrixUniform, false, pMatrix);
   127     gl.uniformMatrix4fv(program.mvMatrixUniform, false, mvMatrix);
   128 }
   129 
   130 Context.prototype.expand = function()
   131 { 
   132     var width = window.innerWidth;
   133     var height = window.innerHeight;
   134     this.canvas.width = width;
   135     this.canvas.height = height;
   136     this.viewport.width = width;
   137     this.viewport.height = height;
   138 }
   139 
   140 function Shader(context)
   141 {
   142     var gl = context.gl;
   143     var fragment = loadShader(gl, "fragment-shader");
   144     var vertex = loadShader(gl, "vertex-shader");
   145     this.program = gl.createProgram();
   146     gl.attachShader(this.program, vertex);
   147     gl.attachShader(this.program, fragment);
   148     gl.linkProgram(this.program);
   149 
   150     if (!gl.getProgramParameter(this.program, gl.LINK_STATUS))
   151     {
   152 	alert("Failed: Shader init.");
   153     }
   154 
   155     gl.useProgram(this.program);
   156     this.vertexPosition = gl.getAttribLocation(this.program, "aVertexPosition");
   157     gl.enableVertexAttribArray(this.vertexPosition);
   158     
   159     this.vertexColour = gl.getAttribLocation(this.program, "aVertexColour");
   160     gl.enableVertexAttribArray(this.vertexColour);
   161 
   162     this.pMatrixUniform = gl.getUniformLocation(this.program, "uPMatrix");
   163     this.mvMatrixUniform = gl.getUniformLocation(this.program, "uMVMatrix");
   164 
   165     function loadShader(gl, id)
   166     {
   167 	var script = document.getElementById(id);
   168 	if (!script) return null;
   169 	
   170 	var str = "";
   171 	var child = script.firstChild;
   172 	while (child)
   173 	{
   174 	    if (child.nodeType == 3) str += child.textContent;
   175 	    child = child.nextSibling;
   176 	}
   177 	
   178 	var shader;
   179 	var common = "x-shader/x-";
   180 	if (script.type == common + "fragment") shader = gl.createShader(gl.FRAGMENT_SHADER);
   181 	else if (script.type == common + "vertex") shader = gl.createShader(gl.VERTEX_SHADER);
   182 	else return null;
   183 
   184 	gl.shaderSource(shader, str);
   185 	gl.compileShader(shader);
   186 
   187 	if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS))
   188         {
   189 	    alert(gl.getShaderInfoLog(shader));
   190 	    return null;
   191 	}
   192 
   193 	return shader;
   194     }
   195 }
   196 
   197 
   198 function Cube(size, context)
   199 {
   200     var gl = context.gl;
   201     this.size = size || 1;
   202     this.rotation = {'x': 0.0, 'y': 0.0, 'z': 0.0};
   203     
   204     this.positionBuffer = gl.createBuffer();
   205     gl.bindBuffer(gl.ARRAY_BUFFER, this.positionBuffer);
   206     var vertices = [
   207 	     // Front face
   208             -1.0, -1.0,  1.0,
   209              1.0, -1.0,  1.0,
   210              1.0,  1.0,  1.0,
   211             -1.0,  1.0,  1.0,
   212  
   213             // Back face
   214             -1.0, -1.0, -1.0,
   215             -1.0,  1.0, -1.0,
   216              1.0,  1.0, -1.0,
   217              1.0, -1.0, -1.0,
   218  
   219             // Top face
   220             -1.0,  1.0, -1.0,
   221             -1.0,  1.0,  1.0,
   222              1.0,  1.0,  1.0,
   223              1.0,  1.0, -1.0,
   224  
   225             // Bottom face
   226             -1.0, -1.0, -1.0,
   227              1.0, -1.0, -1.0,
   228              1.0, -1.0,  1.0,
   229             -1.0, -1.0,  1.0,
   230  
   231             // Right face
   232              1.0, -1.0, -1.0,
   233              1.0,  1.0, -1.0,
   234              1.0,  1.0,  1.0,
   235              1.0, -1.0,  1.0,
   236  
   237             // Left face
   238             -1.0, -1.0, -1.0,
   239             -1.0, -1.0,  1.0,
   240             -1.0,  1.0,  1.0,
   241             -1.0,  1.0, -1.0];
   242     gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
   243     this.positionBuffer.itemSize = 3;
   244     this.positionBuffer.numItems = 24;
   245 
   246     this.colourBuffer = gl.createBuffer();
   247     gl.bindBuffer(gl.ARRAY_BUFFER, this.colourBuffer);
   248     var alpha = 1.0;
   249     var colours = [[1.0, 0.0, 0.0, alpha],
   250 		   [0.0, 1.0, 0.0, alpha],
   251 		   [0.0, 0.0, 1.0, alpha],
   252 		   [1.0, 0.0, 1.0, alpha],
   253 		   [1.0, 1.0, 0.0, alpha],
   254 		   [0.0, 1.0, 1.0, alpha]];
   255     var unpackedColours = [];
   256     for (var i in colours)
   257     {
   258 	var colour = colours[i];
   259 	for (var j = 0; j < 4; j++)
   260 	{
   261 	    unpackedColours = unpackedColours.concat(colour);
   262 	}
   263 	//colours = colours.concat([0.5, 0.5, 1.0, 1.0]);
   264     }
   265     gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(unpackedColours), gl.STATIC_DRAW);
   266     this.colourBuffer.itemSize = 4;
   267     this.colourBuffer.numItems = 24;
   268 
   269     this.indexBuffer = gl.createBuffer();
   270     gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
   271     var indices = [0, 1, 2, 0, 2, 3,
   272 		   4, 5, 6, 4, 6, 7,
   273 		   8, 9, 10, 8, 10, 11,
   274 		   12, 13, 14, 12, 14, 15,
   275 		   16, 17, 18, 16, 18, 19,
   276 		   20, 21, 22, 20, 22, 23];
   277     gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
   278     this.indexBuffer.itemSize = 1;
   279     this.indexBuffer.numItems = 36;
   280 }