Still bugged camera.
5 var cameraSpeed = {"x": 0.1, "y": 0.1, "z": 0.5, "pitch": 0.5, "yaw": 0.5};
6 var keyActionMap = {'A': moveCameraLeft,
10 var mouseActionMap = {"pitch": [[true, false, false], pitchCamera],
11 "yaw": [[true, false, false], yawCamera],
16 var canvas = document.getElementById("machine");
17 var context = new Context(canvas);
20 var object = new Cube(1, context);
21 gl.clearColor(0.0, 0.0, 0.0, 1.0);
22 gl.enable(gl.DEPTH_TEST);
23 machine = new Machine(object);
24 camera = new Camera(cameraSpeed);
25 renderer = new Renderer(camera, context);
26 controller = new Controller(keyActionMap, mouseActionMap, camera, machine, renderer);
28 window.onresize = expandContext;
29 document.onkeydown = handleKeyDown;
30 document.onkeyup = handleKeyUp;
31 canvas.onmousedown = handleMouseDown;
32 document.onmouseup = handleMouseUp;
33 document.onmousemove = handleMouseMove;
34 document.onmousewheel = handleMouseWheel;
35 //read("config/camera", configureCamera);
38 function configureCamera(config) {
44 requestAnimFrame(update);
46 machine.scene.rotation.x += (random(0, 2) - 2) * 0.001;
47 machine.scene.rotation.y += (random(0, 3) - 1) * 0.001;
48 machine.scene.rotation.z += (random(0, 2) - 1) * 0.001;
49 machine.update(new Date().getTime());
50 renderer.update(machine.scene);
53 function random(min, max)
55 return (min + Math.random() * (max - min));
58 function Camera(speed)
66 this.rotMatrix = mat4.create();
67 this.transMatrix = mat4.create();
68 this.matrix = mat4.create();
69 mat4.identity(this.rotMatrix);
70 mat4.identity(this.transMatrix);
71 mat4.identity(this.matrix);
73 Camera.prototype.moveLeft = function()
75 var d = 1 - Math.sin(this.yaw);
76 this.x -= d * this.speed.x;
77 this.z += (1 - d) * this.speed.z;
79 Camera.prototype.moveRight = function()
81 var d = 1 - Math.sin(this.yaw);
82 this.x += d * this.speed.x;
83 this.z -= (1 - d) * this.speed.z;
85 Camera.prototype.moveUp = function()
87 this.y += this.speed.y;
89 Camera.prototype.moveDown = function()
91 this.y -= this.speed.y;
93 Camera.prototype.zoom = function(delta)
95 this.x -= Math.sin(this.yaw) * this.speed.x * delta;
96 this.y -= Math.sin(this.pitch) * this.speed.y * delta;
97 this.z -= Math.cos(this.yaw) * Math.cos(this.pitch) * this.speed.z * delta;
99 Camera.prototype.changePitch = function(delta)
101 this.pitch += this.speed.pitch * delta;
103 Camera.prototype.changeYaw = function(delta)
105 this.yaw += this.speed.yaw * delta;
107 Camera.prototype.update = function()
109 //mat4.rotate(this.rotMatrix, -this.pitch, [1, 0, 0]);
110 //mat4.rotate(this.rotMatrix, -this.yaw, [0, 1, 0]);
111 //mat4.translate(this.transMatrix, [-this.x, -this.y, -this.z]);
112 mat4.translate(this.matrix, [-this.x, -this.y, -this.z]);
113 //mat4.rotate(this.matrix, -this.pitch, [1, 0, 0]);
114 //mat4.rotate(this.matrix, -this.yaw, [0, 1, 0]);
118 //mat4.rotate(mvMatrix, -camera.pitch, [1, 0, 0]);
119 //mat4.rotate(mvMatrix, -camera.yaw, [0, 1, 0]);
120 //mat4.translate(mvMatrix, [-camera.x, -camera.y, -camera.z]);
122 Camera.prototype.clear = function()
124 //this.x = this.y = this.z = 0;
125 //this.pitch = this.yaw = 0;
128 function Controller(keyActionMap, mouseActionMap, camera, machine, renderer)
130 this.keyboard = new Keyboard(keyActionMap);
131 this.mouse = new Mouse(mouseActionMap);
134 Controller.prototype.update = function()
136 this.keyboard.handle();
140 function Mouse(actionMap)
142 this.actionMap = actionMap;
143 this.pressed = [false, false, false];
146 Mouse.prototype.buttonDown = function(event)
148 this.pressed[event.which-1] = true;
150 Mouse.prototype.buttonUp = function(event)
152 this.pressed[event.which-1] = false;
154 Mouse.prototype.move = function(event)
156 this.currentPos = [event.clientX, event.clientY];
158 Mouse.prototype.moveWheel = function(event)
160 this.wheelDelta += event.wheelDelta;
162 Mouse.prototype.handle = function()
164 var pos = this.currentPos;
165 if (pos && this.lastPos)
167 var delta = [pos[0] - this.lastPos[0], pos[1] - this.lastPos[1]];
168 delta = normaliseMoveDelta(delta);
169 var action = this.actionMap["pitch"];
170 if (delta[1] != 0 && action)
172 for (var i = 0; i < 3; i++)
174 if (this.pressed[i] != action[0][i]) break;
175 if (i == 2) action[1](delta[1]);
178 action = this.actionMap["yaw"];
179 if (delta[0] != 0 && action)
181 for (var i = 0; i < 3; i++)
183 if (this.pressed[i] != action[0][i]) break;
184 if (i == 2) action[1](delta[0]);
190 if (this.wheelDelta != 0)
192 var delta = normaliseWheelDelta(this.wheelDelta);
193 var action = this.actionMap["wheel"];
194 if (delta > 0 && action) action(delta);
195 else if (delta < 0 && action) action(delta);
201 function normaliseMoveDelta(delta)
203 var width = renderer.context.canvas.width;
204 var height = renderer.context.canvas.height;
205 return [delta[0] / width, delta[1] / height];
208 function normaliseWheelDelta(delta)
213 function Keyboard(actionMap)
215 this.actionMap = actionMap;
218 Keyboard.prototype.keyDown = function(event)
220 this.pressed[event.keyCode] = true;
222 Keyboard.prototype.keyUp = function(event)
224 this.pressed[event.keyCode] = false;
226 Keyboard.prototype.handle = function()
228 for (key in this.pressed)
230 if (this.pressed[key])
232 key = String.fromCharCode(key);
233 if (this.actionMap[key]) this.actionMap[key]();
238 function Renderer(camera, context)
240 this.camera = camera;
241 this.context = context;
242 this.gl = context.gl;
243 this.matrixStack = [];
245 Renderer.prototype.update = function(scene)
247 var gl = this.context.gl;
248 var viewport = this.context.viewport;
249 var shader = this.context.shader;
250 var mvMatrix = this.context.mvMatrix;
251 var pMatrix = this.context.pMatrix;
252 var camera = this.camera;
255 gl.viewport(0, 0, viewport.width, viewport.height);
256 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
257 mat4.perspective(45, viewport.width / viewport.height, 0.1, 100.0, pMatrix);
259 mat4.identity(mvMatrix);
260 //mat4.multiply(mvMatrix, camera.rotMatrix);
261 //mat4.multiply(mvMatrix, camera.transMatrix);
262 mat4.rotate(mvMatrix, -camera.pitch, [1, 0, 0]);
263 mat4.rotate(mvMatrix, -camera.yaw, [0, 1, 0]);
264 mat4.translate(mvMatrix, [-camera.x, -camera.y, -camera.z]);
265 //mat4.multiply(mvMatrix, camera.matrix);
266 //mat4.rotate(camera.matrix, -camera.pitch, [1, 0, 0]);
267 //mat4.rotate(camera.matrix, -camera.yaw, [0, 1, 0]);
268 //camera.yaw = camera.pitch = 0;
271 //this.pushMatrix(mvMatrix);
273 //mat4.rotate(mvMatrix, scene.rotation.x, [1, 0, 0]);
274 //mat4.rotate(mvMatrix, scene.rotation.y, [0, 1, 0]);
275 //mat4.rotate(mvMatrix, scene.rotation.z, [0, 0, 1]);
277 gl.bindBuffer(gl.ARRAY_BUFFER, scene.positionBuffer);
278 gl.vertexAttribPointer(shader.vertexPosition, scene.positionBuffer.itemSize, gl.FLOAT, false, 0, 0);
280 gl.bindBuffer(gl.ARRAY_BUFFER, scene.colourBuffer);
281 gl.vertexAttribPointer(shader.vertexColour, scene.colourBuffer.itemSize, gl.FLOAT, false, 0, 0);
283 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, scene.indexBuffer);
285 this.context.updateMatrixUniforms();
286 gl.drawElements(gl.TRIANGLES, scene.indexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
287 //gl.drawArrays(gl.TRIANGLE_STRIP, 0, scene.positionBuffer.numItems);
289 //mvMatrix = this.popMatrix();
291 if (this.next) this.next.draw(scene);
293 Renderer.prototype.pushMatrix = function(matrix)
295 var copy = mat4.create();
296 mat4.set(matrix, copy);
297 this.matrixStack.push(copy);
299 Renderer.prototype.popMatrix = function()
301 if (this.matrixStack.length > 0) return this.matrixStack.pop();
304 function Machine(scene)
309 Machine.prototype.update = function(time)
311 if (this.lastUpdate != 0)
313 var diff = time - this.lastUpdate;
316 this.lastUpdate = time;
319 function Context(canvas)
321 this.canvas = canvas;
324 this.gl = canvas.getContext("experimental-webgl");
325 this.viewport = {'width': canvas.width,
326 'height': canvas.height};
332 if (!this.gl) alert("Failed: WebGL init.");
333 this.mvMatrix = mat4.create();
334 this.pMatrix = mat4.create();
335 this.shader = new Shader(this);
337 Context.prototype.updateMatrixUniforms = function()
340 var program = this.shader;
341 var pMatrix = this.pMatrix;
342 var mvMatrix = this.mvMatrix;
343 gl.uniformMatrix4fv(program.pMatrixUniform, false, pMatrix);
344 gl.uniformMatrix4fv(program.mvMatrixUniform, false, mvMatrix);
346 Context.prototype.expand = function()
348 var width = window.innerWidth;
349 var height = window.innerHeight;
350 this.canvas.width = width;
351 this.canvas.height = height;
352 this.viewport.width = width;
353 this.viewport.height = height;
356 function Shader(context)
359 var fragment = loadShader(gl, "fragment-shader");
360 var vertex = loadShader(gl, "vertex-shader");
361 this.program = gl.createProgram();
362 gl.attachShader(this.program, vertex);
363 gl.attachShader(this.program, fragment);
364 gl.linkProgram(this.program);
366 if (!gl.getProgramParameter(this.program, gl.LINK_STATUS))
368 alert("Failed: Shader init.");
371 gl.useProgram(this.program);
372 this.vertexPosition = gl.getAttribLocation(this.program, "aVertexPosition");
373 gl.enableVertexAttribArray(this.vertexPosition);
375 this.vertexColour = gl.getAttribLocation(this.program, "aVertexColour");
376 gl.enableVertexAttribArray(this.vertexColour);
378 this.pMatrixUniform = gl.getUniformLocation(this.program, "uPMatrix");
379 this.mvMatrixUniform = gl.getUniformLocation(this.program, "uMVMatrix");
381 function loadShader(gl, id)
383 var script = document.getElementById(id);
384 if (!script) return null;
387 var child = script.firstChild;
390 if (child.nodeType == 3) str += child.textContent;
391 child = child.nextSibling;
395 var common = "x-shader/x-";
396 if (script.type == common + "fragment") shader = gl.createShader(gl.FRAGMENT_SHADER);
397 else if (script.type == common + "vertex") shader = gl.createShader(gl.VERTEX_SHADER);
400 gl.shaderSource(shader, str);
401 gl.compileShader(shader);
403 if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS))
405 alert(gl.getShaderInfoLog(shader));
414 function Cube(size, context)
417 this.size = size || 1;
418 this.rotation = {'x': 0.0, 'y': 0.0, 'z': 0.0};
420 this.positionBuffer = gl.createBuffer();
421 gl.bindBuffer(gl.ARRAY_BUFFER, this.positionBuffer);
458 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
459 this.positionBuffer.itemSize = 3;
460 this.positionBuffer.numItems = 24;
462 this.colourBuffer = gl.createBuffer();
463 gl.bindBuffer(gl.ARRAY_BUFFER, this.colourBuffer);
465 var colours = [[1.0, 0.0, 0.0, alpha],
466 [0.0, 1.0, 0.0, alpha],
467 [0.0, 0.0, 1.0, alpha],
468 [1.0, 0.0, 1.0, alpha],
469 [1.0, 1.0, 0.0, alpha],
470 [0.0, 1.0, 1.0, alpha]];
471 var unpackedColours = [];
472 for (var i in colours)
474 var colour = colours[i];
475 for (var j = 0; j < 4; j++)
477 unpackedColours = unpackedColours.concat(colour);
479 //colours = colours.concat([0.5, 0.5, 1.0, 1.0]);
481 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(unpackedColours), gl.STATIC_DRAW);
482 this.colourBuffer.itemSize = 4;
483 this.colourBuffer.numItems = 24;
485 this.indexBuffer = gl.createBuffer();
486 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
487 var indices = [0, 1, 2, 0, 2, 3,
490 12, 13, 14, 12, 14, 15,
491 16, 17, 18, 16, 18, 19,
492 20, 21, 22, 20, 22, 23];
493 gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
494 this.indexBuffer.itemSize = 1;
495 this.indexBuffer.numItems = 36;
498 function read(file, handler)
500 var request = new XMLHttpRequest();
501 request.open("GET", file);
502 request.onreadystatechange = function() {
503 alert(request.readyState);
504 if (request.readyState == 4) {
505 handler(request.responseText);
512 function expandContext()
514 renderer.context.expand();
517 function moveCameraLeft()
522 function moveCameraRight()
527 function moveCameraUp()
532 function moveCameraDown()
537 function zoomCamera(delta)
542 function pitchCamera(delta)
544 camera.changePitch(delta);
547 function yawCamera(delta)
549 camera.changeYaw(delta);
552 function handleKeyDown(event)
554 controller.keyboard.keyDown(event);
557 function handleKeyUp(event)
559 controller.keyboard.keyUp(event);
562 function handleMouseDown(event)
564 controller.mouse.buttonDown(event);
567 function handleMouseUp(event)
569 controller.mouse.buttonUp(event);
572 function handleMouseMove(event)
574 controller.mouse.move(event);
577 function handleMouseWheel(event)
579 controller.mouse.moveWheel(event);