Keys wasdUu to move the camera: u y down, U y up.
Keys hjkl to move the look at: hl: x, jk: y
<html> <head> <script id="vertex-shader" type="x-shader/x-vertex" > precision mediump float; attribute vec4 aPosition; attribute vec3 aBC; uniform mat4 uMatrix1, uWorld; uniform mat4 uCamera, uProject; varying vec3 vBC; void main() { gl_Position = uProject * uCamera * uWorld * uMatrix1 * aPosition; vBC = aBC; } </script> <script id="fragment-shader" type="x-shader/x-fragment"> #extension GL_OES_standard_derivatives : enable precision mediump float; varying vec3 vBC; uniform vec4 uEdgeColor; float edgeFactor(){ vec3 d = fwidth(vBC); vec3 a3 = smoothstep(vec3(0.0), d*1.5, vBC); return min(min(a3.x, a3.y), a3.z); } void main(){ vec4 tmp; tmp = uEdgeColor; tmp.a = (1.0-edgeFactor())*0.95; if (gl_FrontFacing) { gl_FragColor = tmp; } else { discard; } } </script> <script type="text/javascript" src="../../Common/webgl-utils.js"></script> <script type="text/javascript" src="../../Common/initShaders.js"></script> <script type="text/javascript" src="../../Common/MV.js"></script> <script type="text/javascript" src="../../Models/cone.js"></script> <script type="text/javascript" src="../../Models/cube.js"></script> <script type="text/javascript" src="../../Models/dragon.js"></script> <script type="text/javascript" src="../../Models/epcot.js"></script> <script type="text/javascript" src="../../Models/lizard.js"></script> <script type="text/javascript" src="../../Models/tank.js"></script> <script type="text/javascript" src="../../Models/teapot.js"></script> <script type="text/javascript" src="../../Models/xwing.js"></script> <script type="text/javascript" src="modelDisplay.js"></script> <script type="text/javascript" src="canvas.js"></script> <script type="text/javascript" src="main.js"></script> <style> input { text-align: right; } </style> </head> <body> <h1>A scene and a Camera </h1> <script> // set up the canvas var canvas = new Canvas(500, 500); var models = []; MakeScene(models); //add a callback for keypresses canvas.disp.addEventListener("keypress", function(evnt) { KeyFunc(evnt, canvas, models); } ); // display it. DoRedisplay(canvas, models); </script> <p> Keys <b>wasdUu</b> to move the camera: u y down, U y up. <p> Keys <b>hjkl</b> to move the look at: hl: x, jk: y <p> <lI> <img src="map.png"> </body>
'use strict'; function BuildTransform(i) { var a = mat4(1); var edge = vec4(1,0,0,1); switch(i) { case 0: // lizard is at 0. a = translate(.2,.2,.0); a = mult(rotate(-90,[1,0,0]),a); a = mult(scalem(3,3,3),a); edge = vec4(1,0,0,1); break; case 1: // cube is at x=-2 a = translate(-2,0,0); edge = vec4(0,1,0,1); break; case 2: // teapot is 2 x = 2 a = mult(translate(2,0,0), rotate(-90,[1,0,0])); edge = vec4(0,0,1,1); break; case 3: // cone is at z = 2 a = mult(translate(0,0,2), scalem(2,2,2)); edge = vec4(0,1,1,1); break; case 4: // epcot is at z= -2 a = translate(0,0,-2); edge = vec4(1,0,1,1); break; default: edge = vec4(0,0,0,1); break; } canvas.gl.uniformMatrix4fv(canvas.mat1Pos, false, flatten(a)); canvas.gl.uniform4fv(canvas.edgeColorPos, flatten(edge)); } function DoRedisplay(canvas, models) { var i; canvas.Redisplay(); for(i=0;i<models.length;i++) { BuildTransform(i); models[i].Display(); } return; }; function KeyFunc(evnt, canvas, models) { switch(evnt.key) { case 'X': canvas.Rotate('x', 'r'); break; case 'Y': canvas.Rotate('y', 'r'); break; case 'Z': canvas.Rotate('z', 'r'); break; case 'x': canvas.Rotate('x', 'f'); break; case 'y': canvas.Rotate('y', 'f'); break; case 'z': canvas.Rotate('z', 'f'); break; case 'r': canvas.Reset(); break; case 'w': canvas.MoveCamera([0,0,1]); break; case 's': canvas.MoveCamera([0,0,-1]); break; case 'a': canvas.MoveCamera([-1,0,0]); break; case 'd': canvas.MoveCamera([1,0,0]); break; case 'u': canvas.MoveCamera([0,-1,0]); break; case 'U': canvas.MoveCamera([0,1,0]); break; case 'h': canvas.MoveEye([-1,0]); break; case 'j': canvas.MoveEye([0,1]); break; case 'k': canvas.MoveEye([0,-1]); break; case 'l': canvas.MoveEye([1,0]); break; } DoRedisplay(canvas, models); }; function MakeScene(models) { var thing= new lizardModel(); models.push(new ModelDisplay(canvas, thing)); thing= new cubeModel(); models.push(new ModelDisplay(canvas, thing)); thing= new teapotModel(); models.push(new ModelDisplay(canvas, thing)); thing= new coneModel(); models.push(new ModelDisplay(canvas, thing)); thing= new epcotModel(); models.push(new ModelDisplay(canvas, thing)); return; }
'use strict'; function MakeCanvas(width, height, locID) { if (width == undefined || width < 0) { width = 300; } if (height == undefined || height < 0) { height = 300; } var canvas = document.createElement('canvas') canvas.tabIndex = 0; canvas.height = height; canvas.width = width; canvas.style.border = "1px solid #0000FF"; if(locID == undefined) { document.body.appendChild(canvas); } else { div = document.getElementById(locID); if (null == div) { document.body.appendChild(canvas); } else { div.appendChild(canvas); } } document.body.appendChild(canvas); return canvas; } function InitGL(canvas) { var gl = WebGLUtils.setupWebGL(canvas,'OES_standard_derivatives'); if (!gl) { alert ("WebGL isn't available"); } gl.getExtension('OES_standard_derivatives'); return gl; } function Canvas(width, height, locID) { this.disp = MakeCanvas(width, height, locID); var gl = InitGL(this.disp); this.gl = gl; var tmpCanvas = this; this.x = this.disp.offsetLeft; this.y = this.disp.offsetTop; gl.viewport(0,0, width, height); this.program = initShaders(gl, "vertex-shader","fragment-shader"); gl.useProgram(this.program); this.mat1Pos = gl.getUniformLocation(this.program, "uMatrix1"); this.mat2Pos = gl.getUniformLocation(this.program, "uMatrix2"); this.worldMatPos = gl.getUniformLocation(this.program, "uWorld"); this.cameraMatPos = gl.getUniformLocation(this.program, "uCamera"); this.projectionMatPos = gl.getUniformLocation(this.program, "uProject"); this.edgeColorPos = gl.getUniformLocation(this.program, "uEdgeColor"); this.Init(); return this; } Canvas.prototype = { Init: function() { this.gl.clearColor(1.0, 1.0, 1.0, 1.0); this.gl.enable(this.gl.BLEND); this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA); this.gl.enable(this.gl.DEPTH_TEST); this.gl.depthFunc(this.gl.LESS); this.gl.depthMask(this.gl.TRUE); this.shaderChoice = false; this.gl.uniform1f(this.shaderLoc, 0.0); this.gl.enable(this.gl.CULL_FACE); this.gl.frontFace(this.gl.CCW); this.gl.cullFace(this.gl.BACK); this.Reset(); }, Rotate: function(axis, dir) { var change = 5; if (dir =='r') { change = -5; } switch(axis) { case 'x': this.xr += change; break; case 'y': this.yr += change; break; case 'z': this.zr += change; break; } }, Reset: function() { this.xr = 0; this.yr = 0; this.zr = 0; this.ex = 0; this.ey = 0; this.ez = -3; this.atx = 0; this.aty = 0; this.atz = 0; this.RedoCameraMat(); this.near = .5; this.far = 5; this.left = -4; this.right = 4; this.top = 4; this.bottom = -4; this.RedoProjectionMatrix(); }, RedoProjectionMatrix: function() { var mat = ortho(this.left, this.right, this.bottom, this.top, this.near, this.far); this.gl.uniformMatrix4fv(this.projectionMatPos,false,flatten(mat)); }, ChangeView: function(x,y,near, far){ this.left = -x; this.right = x; this.near = near; this.far = far; this.top = y; this.bottom = -y; this.RedoProjectionMatrix(); }, MoveCamera: function(dvec) { var posDelta = 0.1; this.ex += dvec[0]*posDelta; this.ey += dvec[1]*posDelta; this.ez += dvec[2]*posDelta; this.atx += dvec[0]*posDelta; this.aty += dvec[1]*posDelta; this.atz += dvec[2]*posDelta; this.RedoCameraMat(); }, MoveEye: function(dvec) { var posDelta = 0.01; this.atx += dvec[0]*posDelta; this.aty += dvec[1]*posDelta; this.RedoCameraMat(); }, RedoCameraMat: function() { console.log("eye is ", this.ex, this.ey, this.ez); console.log("Look at is ", this.atx, this.aty, this.atz); var cameraMatrix = lookAt([this.ex, this.ey, this.ez], [this.atx, this.aty, this.atz], [0,1,0]); this.gl.uniformMatrix4fv(this.cameraMatPos,false,flatten(cameraMatrix)); }, Redisplay: function() { this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT); var transform = mat4(1); transform = mult(transform, rotate(this.xr, [1,0,0])); transform = mult(transform, rotate(this.yr, [0,1,0])); transform = mult(transform, rotate(this.zr, [0,0,1])); this.gl.uniformMatrix4fv(this.worldMatPos,false, flatten(transform )); return; } };
'use strict'; /* ModelDisplay is responsible for Maintaining a connection between the vertex buffer and the model Displaying the model when called. */ function ModelDisplay(canvas, model) { this.gl = canvas.gl; var gl = canvas.gl; this.vboTriangles = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, this.vboTriangles); this.pointCount = model.Triangles.length; this.vPos = gl.getAttribLocation(canvas.program, "aPosition"); gl.vertexAttribPointer(this.vPos,3,gl.FLOAT, false,0,0); gl.enableVertexAttribArray(this.vPos); gl.bufferData(gl.ARRAY_BUFFER,flatten(model.Triangles),gl.STATIC_DRAW); this.vboBC = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, this.vboBC); this.vBC = gl.getAttribLocation(canvas.program, "aBC"); gl.vertexAttribPointer(this.vBC,3,gl.FLOAT, false,0,0); gl.enableVertexAttribArray(this.vBC); gl.bufferData(gl.ARRAY_BUFFER,flatten(model.BC),gl.STATIC_DRAW); }; ModelDisplay.prototype= { Display() { var gl = this.gl; gl.bindBuffer(gl.ARRAY_BUFFER, this.vboTriangles); gl.vertexAttribPointer(this.vPos,3,gl.FLOAT, false,0,0); gl.bindBuffer(gl.ARRAY_BUFFER, this.vboBC); gl.vertexAttribPointer(this.vBC,3,gl.FLOAT, false,0,0); this.gl.drawArrays(this.gl.TRIANGLES, 0, this.pointCount); } };