├── .gitignore ├── .npmignore ├── CHANGELOG.md ├── README.md ├── examples ├── 00_Basic_Application │ └── app.js ├── 01_Projection │ └── app.js ├── 02_Texture │ ├── app.js │ ├── texture.jpg │ └── texture.png ├── 03_Fbo │ └── app.js ├── 04_Frustum │ └── app.js ├── 05_Culling │ └── app.js ├── 06_Input │ └── app.js ├── 07_TextureFont │ ├── Roboto-Black.ttf │ └── app.js ├── 08_Raymarching │ ├── app.js │ ├── frag.glsl │ └── vert.glsl ├── 09_Draw_Immediate_2d │ └── app.js ├── 10_TextureData │ └── app.js ├── 11_Light │ └── app.js ├── 12_Quaternions │ └── app.js └── 13_FileWatcher │ ├── app.js │ ├── file0.txt │ ├── file1.txt │ └── file2.txt ├── index.js ├── lib ├── app │ ├── App.js │ ├── Time.js │ ├── TimeEvent.js │ ├── Window.js │ └── WindowEvent.js ├── geom │ ├── AABB.js │ ├── AABR.js │ ├── Geom.js │ ├── Plane.js │ └── Rect.js ├── gl │ ├── Arcball.js │ ├── CameraAbstract.js │ ├── CameraOrbiter.js │ ├── CameraOrtho.js │ ├── CameraPersp.js │ ├── DirectionalLight.js │ ├── Fbo.js │ ├── Frustum.js │ ├── FrustumOrtho.js │ ├── FrustumPersp.js │ ├── Light.js │ ├── Material.js │ ├── Mesh.js │ ├── MeshPrimitive.js │ ├── PointLight.js │ ├── PrimitiveScheme.js │ ├── Program.js │ ├── ProgramPreset.js │ ├── SpotLight.js │ ├── Texture.js │ ├── TextureFont.js │ ├── Vbo.js │ ├── VboMesh.js │ ├── VboMeshPrimitive.js │ ├── gl.js │ ├── glDraw.js │ ├── glExtensions.js │ ├── glObject.js │ ├── glTrans.js │ ├── glValueType.js │ └── glu.js ├── input │ ├── KeyEvent.js │ ├── Keyboard.js │ ├── Mouse.js │ └── MouseEvent.js ├── math │ ├── Ease.js │ ├── Math.js │ ├── Matrix33.js │ ├── Matrix44.js │ ├── OnB.js │ ├── Quat.js │ ├── Random.js │ ├── Vec2.js │ ├── Vec3.js │ └── Vec4.js ├── system │ ├── Event.js │ ├── EventDispatcher.js │ ├── FileEvent.js │ ├── FileWatcher.js │ ├── Flags.js │ ├── Id.js │ ├── ObjLoader.js │ ├── Resource.js │ ├── ResourceType.js │ ├── Resources.js │ ├── System.js │ └── common │ │ ├── Error.js │ │ └── Platform.js └── util │ ├── ArrayUtil.js │ ├── Color.js │ ├── ElementArrayUtil.js │ ├── ObjectUtil.js │ ├── StringUtil.js │ ├── Value1State.js │ └── WorkerConsole.js ├── package.json ├── resources ├── basic2d.glsl ├── basic3d.glsl ├── basic3dLight.glsl └── basic3dTexture.glsl └── scripts ├── buildNodeWebkit.sh ├── buildProgramPresets.js ├── buildWeb.sh ├── new.js ├── paths ├── profilePlaskRun.sh └── templates ├── basic2d.js ├── basic3d.js ├── basic3dLight.js ├── basic3dTexture.js └── index.html /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_STORE 2 | .idea/ 3 | 4 | *.BAK 5 | *.TEST 6 | 7 | .temp 8 | .tests 9 | 10 | node_modules/ 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .git* 2 | .temp/ 3 | .templates/ 4 | .tests 5 | .idea 6 | build 7 | docs 8 | examples 9 | scripts 10 | tests 11 | .DS_Store -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 0.0.6 / 2015-02-14 2 | ================== 3 | 4 | * package.json update publish 5 | * glDraw added drawOnB 6 | * OnB added setf 7 | * index.js export OnB 8 | * Ease cleanup 9 | * VboMesh added get{Vertices,Normals,Colors,Texcoords,Indices}Length 10 | * Mesh added get{Vertices,Normals,Colors,Texcoords,Indices}Length 11 | * Ease added none 12 | * VboMesh added append{Vertices,Normals,Colors,Texcoords,Indices} 13 | * Mesh added append{Vertices,Colors,Normals,Texcoords,Indices}, doc++ 14 | * index.js update Time 15 | * Time initial 16 | * App moved internal time handling to Time 17 | * Color added to{RGBA,RGB}String 18 | * Merge branch 'master' of https://github.com/automat/Foam 19 | * Deleted async 20 | * Delete async, 21 | * AABB added option relative to normalize{Points,Pointsf} 22 | * Ease misc optimizations 23 | * Vec3 added toAbs, abs 24 | * Vec2 added toAbs, abs 25 | * AABB added get{MinMin,MaxMax}, normalize 26 | * 09_Draw_Immediate_2d fixed module import, initial random velocity 27 | * AABB added setMinMax{f,fv}, fromMinMax{f,fv} 28 | * 13_FileWatcher initial 29 | * Color added setHSV 30 | * Fixed async in commit msg 31 | * FileWatcher sync -> async, caused by sync XMLHttpRequest getting deprecated on the main thread 32 | * Light fixed setCustomUniform4 w set 33 | * ObjLoader fixed options skip 34 | * Color changed constructor, set{i,f} to more flexible rgba pass 35 | * Light added isEnabled, removed color set from debugDraw, moved to static temps 36 | * VboMesh added returns, doc++ 37 | * Matrix44 added setTranslation, fromScalef 38 | * Mouse doc++ 39 | * App added options 40 | * 03_Fbo fixed whitespaces 41 | * Rect isEqual => equals 42 | * glDraw itr++ 43 | * glDraw added drawLine{Part,Partf}, fixed missing attribLocation check on drawPoints, fixed drawLineStripf color 44 | * AABB fixed param out from{Points, Pointsf}, doc++ 45 | * AABB added setMinMax 46 | * update 2015 47 | * AABB added reset, include{Pointf,Point} 48 | * CameraOrbiter added getDistance{Min,Max} 49 | * glDraw drawCube removed unnecessary disableVertexAttribArray 50 | * Fbo fixed width & height set on resize, added returns 51 | * Program added returns, default UNIFORM_SKYBOX 52 | * App fixed Firefox mouse drag 53 | * index.js added Matrix33 export 54 | * Matrix33 added setFrom{Scale,Scalef,Rotation,Translationf}, mult{Vec2,Vec2f} 55 | * Color added copy, lerp 56 | * Vec2 added direction 57 | * AABR fixed center and rect points calc, args naming fromPoints & fromPointsf 58 | * Vec2 added lerp,lerped,slerp,slerped 59 | * index.js update 60 | * AABR initial 61 | * AABB removed NORM_RANGE 62 | * AABB fixed get{X,Y}RangeNormalized 63 | * Vec2 added set1f, add1f, sub1f, cross, interpolateTo, interpolatedTo, toZero, isZero, toOne, random, randomDirection 64 | * Vec3 removed set{X,Y,Z}, added set1f, fixed docs 65 | * added Texture video support, removed ObjectUtil 66 | * added CameraAbstract get{Near,Far,Fov} 67 | * fixed Vec3 random arguments override 68 | * added Vec3 {add,sub}1f, prototype random,randomDirection, cleanup static methods 69 | * added Fbo resizef & resize 70 | * added CameraOrbiter getDistanceNormalized 71 | * temp fix ObjLoader no texcoords 72 | * fixed AABB getXYZRange out constructor 73 | * added AABB get{X,Y,Z}Range, get{X,Y,Z}RangeNormalized, normalizePoints{f} 74 | * fixed Mesh getBoundingBox optional out param naming 75 | * fixed AABB setFromPointsf 76 | * fixed ObjLoader wrong options check order 77 | * added ObjLoader 'plain' option, changed param order 78 | * added glDraw drawGridPoints 79 | * fixed Vec3 randomPosition 80 | * fixed Vec2 randomPosition 81 | * changed Vec3 to use Random module 82 | * changed Vec2 to use Random module, fixed optional params 83 | * added Random null seed check 84 | * added CameraOrbiter constrainDistanceTarget on distance set min/max 85 | * added {Mesh,VboMesh}Primitive Disk 86 | * added Vbo return this on unbind 87 | * renamed Texture create{Blank,FromImage,FromRandom} => from{Blank,Image,Random} 88 | * added ObjLoader optional group merge 89 | -------------------------------------------------------------------------------- /examples/00_Basic_Application/app.js: -------------------------------------------------------------------------------- 1 | var Foam = require('foam-gl'), 2 | Ease = Foam.Ease, 3 | System = Foam.System, 4 | Matrix44 = Foam.Matrix44, 5 | Program = Foam.Program; 6 | 7 | 8 | 9 | Foam.App.newOnLoadWithResource( 10 | { 11 | path : '../resources/basic2d.glsl' // bundle.js relative 12 | }, 13 | { 14 | setup : function(resource){ 15 | var gl = this._gl; 16 | gl.viewport(0,0,this.getWindowWidth(),this.getWindowHeight()); 17 | 18 | this._program = new Program(resource); 19 | this._program.bind(); 20 | 21 | this._vbo = gl.createBuffer(); 22 | gl.bindBuffer(gl.ARRAY_BUFFER, this._vbo); 23 | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array( 24 | [0,0,0,100,0,0,0,100,0,100,100,0]), 25 | gl.STATIC_DRAW); 26 | 27 | this._program.vertexAttribPointer('aVertexPosition',3,gl.FLOAT,false,0,0); 28 | gl.enable(gl.SCISSOR_TEST); 29 | }, 30 | 31 | update : function(){ 32 | var gl = this._gl, 33 | glTrans = this._glTrans; 34 | 35 | var program = this._program; 36 | 37 | var t = this.getSecondsElapsed(); 38 | 39 | var windowWidth = this.getWindowWidth(); 40 | var windowWidth_2 = windowWidth * 0.5; 41 | var windowWidth_4 = windowWidth * 0.25; 42 | var windowHeight = this.getWindowHeight(); 43 | var windowHeight_2 = windowHeight * 0.5; 44 | var windowHeight_4 = windowHeight * 0.25; 45 | 46 | program.uniform4f('uColor',1,1,1,1); 47 | 48 | // tl 49 | 50 | gl.scissor( 0,windowHeight_2, windowWidth_2, windowHeight_2); 51 | gl.viewport(0,windowHeight_2, windowWidth_2, windowHeight_2); 52 | glTrans.setWindowMatrices(windowWidth_2, windowHeight_2, true); 53 | 54 | gl.clearColor(1,0,0,1); 55 | gl.clear(gl.COLOR_BUFFER_BIT); 56 | 57 | glTrans.pushMatrix(); 58 | glTrans.translate3f(windowWidth_4, windowHeight_4, 0.0); 59 | glTrans.rotate3f(0,0,t); 60 | glTrans.scale1f(Math.sin(t)); 61 | this.drawGeom(); 62 | glTrans.popMatrix(); 63 | 64 | // tr 65 | 66 | gl.scissor( windowWidth_2,windowHeight_2,windowWidth,windowHeight_2); 67 | gl.viewport(windowWidth_2,windowHeight_2,windowWidth_2,windowHeight_2); 68 | glTrans.setWindowMatrices(windowWidth_2, windowHeight_2, true); 69 | 70 | gl.clearColor(1,0,1,1); 71 | gl.clear(gl.COLOR_BUFFER_BIT); 72 | 73 | glTrans.pushMatrix(); 74 | glTrans.translate3f(0,(0.5 + Math.sin(t) * 0.5) * windowHeight_2,0); 75 | glTrans.rotate3f(0,0,(0.5 + Math.sin(t) * 0.5) * Math.PI * 0.5); 76 | this.drawGeom(); 77 | glTrans.popMatrix(); 78 | 79 | // bl 80 | 81 | gl.scissor( 0,0,windowWidth_2,windowHeight_2); 82 | gl.viewport(0,0,windowWidth_2,windowHeight_2); 83 | glTrans.setWindowMatrices(windowWidth_2, windowHeight_2, true); 84 | 85 | gl.clearColor(0,0,1,1); 86 | gl.clear(gl.COLOR_BUFFER_BIT); 87 | 88 | glTrans.pushMatrix(); 89 | glTrans.multMatrix(Matrix44.fromTranslation(windowWidth_4,windowHeight_4,0)); 90 | glTrans.scale1f(Math.sin(t)); 91 | this.drawGeom(); 92 | glTrans.popMatrix(); 93 | 94 | 95 | // br 96 | 97 | gl.scissor( windowWidth_2,0,windowWidth,windowHeight_2); 98 | gl.viewport(windowWidth_2,0,windowWidth_2,windowHeight_2); 99 | glTrans.setWindowMatrices(windowWidth_2, windowHeight_2, true); 100 | 101 | gl.clearColor(1,1,0,1); 102 | gl.clear(gl.COLOR_BUFFER_BIT); 103 | 104 | var offset = Ease.stepCubed(Math.sin(t * 2)) * Math.round(Math.sin(t*2)); 105 | 106 | glTrans.pushMatrix(); 107 | glTrans.translate3f(windowWidth_4 - 50,windowHeight_4,0); 108 | glTrans.scale3f(1,offset / 100 * windowHeight_2,1); 109 | program.uniform4f('uColor',10,1,1,1); 110 | this.drawGeom(); 111 | glTrans.popMatrix(); 112 | }, 113 | 114 | drawGeom : function(){ 115 | var gl = this._gl, glTrans = this._glTrans; 116 | var program = this._program; 117 | program.uniformMatrix4fv('uProjectionMatrix', false, glTrans.getProjectionMatrixF32()); 118 | program.uniformMatrix4fv('uModelViewMatrix' , false, glTrans.getModelViewMatrixF32()); 119 | gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); 120 | } 121 | } 122 | ); 123 | 124 | -------------------------------------------------------------------------------- /examples/01_Projection/app.js: -------------------------------------------------------------------------------- 1 | var Foam = require('foam-gl'), 2 | System = Foam.System, 3 | Vec2 = Foam.Vec2, 4 | Vec3 = Foam.Vec3, 5 | Matrix44 = Foam.Matrix44, 6 | Program = Foam.Program, 7 | CameraPersp = Foam.CameraPersp, 8 | CameraOrtho = Foam.CameraOrtho, 9 | Ease = Foam.Ease; 10 | 11 | Foam.App.newOnLoadWithResource( 12 | { 13 | path : '../resources/basic3d.glsl' // bundle.js relative 14 | 15 | }, 16 | { 17 | setup : function(resource){ 18 | this.setFPS(60); 19 | this.setWindowSize(800, 600); 20 | 21 | var gl = this._gl; 22 | 23 | gl.viewport(0,0,this.getWindowWidth(),this.getWindowHeight()); 24 | 25 | var program = new Program(resource); 26 | program.bind(); 27 | 28 | var windowAspectRatio = this.getWindowAspectRatio(); 29 | 30 | this._camera0 = new CameraPersp(); 31 | this._camera0.setPerspective(45.0,windowAspectRatio,0.00125, 20.0); 32 | this._camera0.lookAt(Vec3.one(), Vec3.zero()); 33 | this._camera0.updateMatrices(); 34 | 35 | this._camera1 = new CameraPersp(); 36 | this._camera1.setPerspective(45.0,windowAspectRatio,0.00125, 20.0); 37 | 38 | var zoom = 2; 39 | 40 | this._camera2 = new CameraOrtho(); 41 | this._camera2.setOrtho(-windowAspectRatio * zoom,windowAspectRatio * zoom,-zoom,zoom,-2,20); 42 | this._camera2.lookAt(Vec3.one(),Vec3.zero()); 43 | this._camera2.updateMatrices(); 44 | 45 | this._camera3 = new CameraOrtho(); 46 | this._camera3.setOrtho(-windowAspectRatio * zoom,windowAspectRatio * zoom,-zoom,zoom,-20,20); 47 | this._camera3.lookAt(Vec3.one(),Vec3.zero()); 48 | this._camera3.updateMatrices(); 49 | 50 | this._gridSize0 = new Vec2(20,20); 51 | this._gridSize1 = new Vec2(10,10); 52 | 53 | gl.enable(gl.SCISSOR_TEST); 54 | gl.enable(gl.DEPTH_TEST); 55 | gl.uniform1f(program['uPointSize'],4.0); 56 | 57 | }, 58 | 59 | update : function(){ 60 | var gl = this._gl, 61 | glDraw = this._glDraw, 62 | glTrans = this._glTrans; 63 | 64 | var t = this.getSecondsElapsed(); 65 | 66 | var windowWidth = this.getWindowWidth(); 67 | var windowWidth_2 = windowWidth * 0.5; 68 | var windowHeight = this.getWindowHeight(); 69 | var windowHeight_2 = windowHeight * 0.5; 70 | 71 | var gridSubDivs = 20; 72 | 73 | // tl 74 | 75 | gl.scissor( 0,windowHeight_2, windowWidth_2, windowHeight_2); 76 | gl.viewport(0,windowHeight_2, windowWidth_2, windowHeight_2); 77 | 78 | 79 | gl.clearColor(0.1,0.1,0.1,1); 80 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 81 | 82 | var camera = this._camera0; 83 | camera.setEye3f(Math.cos(t) * 2,1,Math.sin(t) * 2); 84 | camera.updateMatrices(); 85 | glTrans.setMatricesCamera(camera); 86 | 87 | glDraw.drawGrid(this._gridSize0,gridSubDivs); 88 | glDraw.drawPivot(); 89 | 90 | glTrans.pushMatrix(); 91 | glTrans.translate3f(Math.cos(-t) * 0.5, 0.5, Math.sin(-t) * 0.5); 92 | glTrans.rotate3f(Math.sin(t) * Math.PI ,0,Math.sin(t)); 93 | glDraw.drawPivot(); 94 | glTrans.scale1f(0.75); 95 | this.drawGeom(); 96 | glTrans.popMatrix(); 97 | 98 | 99 | // tr 100 | 101 | gl.scissor( windowWidth_2,windowHeight_2,windowWidth,windowHeight_2); 102 | gl.viewport(windowWidth_2,windowHeight_2,windowWidth_2,windowHeight_2); 103 | 104 | gl.clearColor(0.15,0.15,0.15,1); 105 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 106 | 107 | camera = this._camera1; 108 | 109 | camera.setEye3f(Math.cos(t)*3,Math.sin(t)*Math.PI,Math.sin(t)*3); 110 | camera.updateMatrices(); 111 | glTrans.setMatricesCamera(camera); 112 | 113 | glDraw.drawGrid(this._gridSize0,gridSubDivs); 114 | glDraw.drawPivot(); 115 | 116 | glTrans.pushMatrix(); 117 | glTrans.rotate3f(t,0,0); 118 | glDraw.drawPivot(1.5); 119 | glTrans.scale3f(2,0.05,2); 120 | this.drawGeom(); 121 | glTrans.popMatrix(); 122 | 123 | 124 | // bl 125 | 126 | gl.scissor( 0,0,windowWidth_2,windowHeight_2); 127 | gl.viewport(0,0,windowWidth_2,windowHeight_2); 128 | 129 | gl.clearColor(0.15,0.15,0.15,1); 130 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 131 | 132 | camera = this._camera2; 133 | glTrans.setMatricesCamera(camera); 134 | 135 | glDraw.drawGrid(this._gridSize0,gridSubDivs); 136 | glDraw.drawPivot(); 137 | 138 | glTrans.pushMatrix(); 139 | glTrans.translate3f(Math.sin(t),0,0); 140 | glTrans.rotate3f(Ease.stepSmoothInvSquared(0.5 + Math.sin(t) * 0.5) * Math.PI * 2,0,0); 141 | glDraw.drawGrid(this._gridSize0,gridSubDivs); 142 | glDraw.drawPivot(1.5); 143 | 144 | var scaleY = Ease.stepInvCubed(0.5 + Math.sin(t * 4) * 0.5) * 1.75 + 0.25; 145 | var scaleXZ = Ease.stepCubed(0.5 + Math.sin(t * 4)) * 0.125 + 0.15; 146 | 147 | glTrans.scale3f(scaleXZ, scaleY, scaleXZ); 148 | this.drawGeom(); 149 | glTrans.popMatrix(); 150 | 151 | 152 | // br 153 | 154 | gl.scissor( windowWidth_2,0,windowWidth,windowHeight_2); 155 | gl.viewport(windowWidth_2,0,windowWidth_2,windowHeight_2); 156 | glTrans.setWindowMatrices(windowWidth_2, windowHeight_2, true); 157 | 158 | gl.clearColor(0.1,0.1,0.1,1); 159 | gl.clear(gl.COLOR_BUFFER_BIT); 160 | 161 | camera = this._camera3; 162 | camera.setDistance(2 + Ease.stepSmoothInvSquared(0.5 + Math.sin(t) * 0.5) * 8); 163 | camera.setEye3f(Math.cos(t),1,Math.sin(t)); 164 | camera.updateMatrices(); 165 | glTrans.setMatricesCamera(camera); 166 | 167 | glDraw.drawGrid(this._gridSize0,gridSubDivs); 168 | glDraw.drawPivot(2.0); 169 | 170 | glTrans.pushMatrix(); 171 | glTrans.translate3f(0,0.5,0); 172 | this.drawGeom(); 173 | glTrans.popMatrix(); 174 | }, 175 | 176 | drawGeom : function(){ 177 | var glDraw = this._glDraw; 178 | glDraw.drawCubeColored(); 179 | glDraw.drawCubePoints(); 180 | } 181 | 182 | } 183 | ); -------------------------------------------------------------------------------- /examples/02_Texture/app.js: -------------------------------------------------------------------------------- 1 | var Foam = require('foam-gl'), 2 | System = Foam.System, 3 | Vec3 = Foam.Vec3, 4 | Program = Foam.Program, 5 | CameraPersp = Foam.CameraPersp, 6 | Texture = Foam.Texture, 7 | Ease = Foam.Ease; 8 | 9 | Foam.App.newOnLoadWithResource({ // bundle.js relative 10 | shader: { 11 | path: '../resources/basic3dTexture.glsl' 12 | }, 13 | 14 | image0: { 15 | path: '../examples/02_Texture/texture.jpg', 16 | type: 'image' 17 | }, 18 | 19 | image1: { 20 | path: '../examples/02_Texture/texture.png', 21 | type: 'image' 22 | } 23 | },{ 24 | setup : function(resources){ 25 | this.setFPS(60); 26 | this.setWindowSize(800, 600); 27 | 28 | var gl = this._gl; 29 | 30 | gl.viewport(0,0,this.getWindowWidth(),this.getWindowHeight()); 31 | 32 | this._program = new Program(resources.shader); 33 | this._program.bind(); 34 | 35 | this._camera = new CameraPersp(); 36 | this._camera.setPerspective(45.0,this.getWindowAspectRatio(),0.00125, 20.0); 37 | this._camera.lookAt(Vec3.one(), Vec3.zero()); 38 | this._camera.updateMatrices(); 39 | 40 | this._texture0 = Texture.fromImage(resources.image0); 41 | this._texture0.bind(0); 42 | this._texture1 = Texture.fromImage(resources.image1); 43 | this._texture1.bind(1); 44 | 45 | gl.enable(gl.DEPTH_TEST); 46 | this._program.uniform1f('uPointSize',4.0); 47 | }, 48 | 49 | update : function(){ 50 | var gl = this._gl, 51 | glDraw = this._glDraw, 52 | glTrans = this._glTrans; 53 | 54 | var program = this._program, 55 | camera = this._camera; 56 | 57 | var t = this.getSecondsElapsed(); 58 | 59 | gl.clearColor(0.1,0.1,0.1,1); 60 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 61 | 62 | camera.setEye3f(Math.cos(t) * 2,1,Math.sin(t) * 2); 63 | camera.updateMatrices(); 64 | glTrans.setMatricesCamera(camera); 65 | 66 | glDraw.drawPivot(); 67 | 68 | program.uniform1i('uTexture',Math.sin(t) < 0 ? 0 : 1); //switch texture 69 | program.uniform1f('uUseTexture',Ease.stepSmooth(Math.sin(t * 4) * 0.5 + 0.5)); 70 | glDraw.colorf(1,0,0.25); 71 | glTrans.pushMatrix(); 72 | glTrans.translate3f(-0.5,-0.5,0); 73 | glDraw.drawRect(); 74 | glTrans.popMatrix(); 75 | program.uniform1f('uUseTexture',0); 76 | } 77 | }); -------------------------------------------------------------------------------- /examples/02_Texture/texture.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/automat/foam-gl/ff887b30d9d13635c7203476b97d1f34ce1d76b2/examples/02_Texture/texture.jpg -------------------------------------------------------------------------------- /examples/02_Texture/texture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/automat/foam-gl/ff887b30d9d13635c7203476b97d1f34ce1d76b2/examples/02_Texture/texture.png -------------------------------------------------------------------------------- /examples/03_Fbo/app.js: -------------------------------------------------------------------------------- 1 | var Foam = require('foam-gl'), 2 | glTrans = Foam.glTrans, 3 | glDraw = Foam.glDraw, 4 | System = Foam.System, 5 | Vec3 = Foam.Vec3, 6 | Program = Foam.Program, 7 | CameraPersp = Foam.CameraPersp, 8 | Ease = Foam.Ease, 9 | Fbo = Foam.Fbo; 10 | 11 | Foam.App.newOnLoadWithResource({ 12 | path : '../resources/basic3dTexture.glsl' // bundle.js relative 13 | },{ 14 | setup : function(resource){ 15 | this.setFPS(60); 16 | this.setWindowSize(800, 600); 17 | 18 | this._program = new Program(resource); 19 | this._program.bind(); 20 | 21 | this._camera = new CameraPersp(); 22 | this._camera.setPerspective(45.0,this.getWindowAspectRatio(),0.00125, 20.0); 23 | this._camera.lookAt(new Vec3(5,5,5), Vec3.zero()); 24 | this._camera.updateMatrices(); 25 | 26 | 27 | var fboScale = this._fboScale = 2; 28 | this._fbo = new Fbo(this.getWindowWidth() * fboScale, this.getWindowHeight() * fboScale); 29 | 30 | var gl = this._gl; 31 | 32 | gl.enable(gl.DEPTH_TEST); 33 | this._program.uniform1f('uPointSize',4.0); 34 | }, 35 | update : function(){ 36 | var gl = this._gl, 37 | glDraw = this._glDraw, 38 | glTrans = this._glTrans; 39 | 40 | var t = this.getSecondsElapsed(); 41 | 42 | var fboScale = this._fboScale; 43 | var windowWidth = this.getWindowWidth(); 44 | var windowHeight = this.getWindowHeight(); 45 | 46 | var fbo = this._fbo; 47 | var program = this._program; 48 | 49 | fbo.bind(); 50 | gl.viewport(0,0,windowWidth * fboScale, windowHeight * fboScale); 51 | gl.clearColor(1,0,1,1); 52 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 53 | 54 | var camera = this._camera; 55 | camera.setEye3f(Math.cos(t) * 2,1,Math.sin(t) * 2); 56 | camera.updateMatrices(); 57 | glTrans.setMatricesCamera(camera); 58 | 59 | glDraw.drawPivot(); 60 | 61 | 62 | var num = 5; 63 | var step = 1 / (num-1); 64 | var i, j, k; 65 | i = -1; 66 | while(++i < num){ 67 | j = -1; 68 | while(++j < num){ 69 | k = -1; 70 | while(++k < num){ 71 | glTrans.pushMatrix(); 72 | glTrans.translate3f(-0.5 + i * step, -0.5 + j * step, -0.5 + k * step); 73 | glTrans.scale1f(0.105); 74 | glDraw.drawCubeColored(); 75 | glTrans.popMatrix(); 76 | } 77 | } 78 | } 79 | 80 | fbo.unbind(); 81 | 82 | gl.viewport(0,0,windowWidth,windowHeight); 83 | 84 | gl.clearColor(0,0,0,1); 85 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 86 | 87 | glTrans.setWindowMatrices(windowWidth, windowHeight, false); 88 | 89 | glDraw.colorf(1,1,1); 90 | fbo.bindTexture(); 91 | program.uniform1f('uUseTexture',1.0); 92 | glDraw.drawRect(windowWidth,windowHeight); 93 | program.uniform1f('uUseTexture',0.0); 94 | fbo.unbindTexture(); 95 | }, 96 | 97 | drawGeom : function(){ 98 | glDraw.drawCubeColored(); 99 | glDraw.drawCubePoints(); 100 | } 101 | }); -------------------------------------------------------------------------------- /examples/05_Culling/app.js: -------------------------------------------------------------------------------- 1 | var Foam = require('foam-gl'), 2 | System = Foam.System, 3 | Vec3 = Foam.Vec3, 4 | Program = Foam.Program, 5 | CameraPersp = Foam.CameraPersp, 6 | CameraOrtho = Foam.CameraOrtho, 7 | AABB = Foam.AABB, 8 | Matrix44 = Foam.Matrix44, 9 | Random = Foam.Random, 10 | Color = Foam.Color, 11 | FrustumPersp = Foam.FrustumPersp; 12 | 13 | function Cluster(){ 14 | this.points = null; 15 | this.aabb = null; 16 | this.color = null; 17 | this.inFrustum = false; 18 | } 19 | 20 | Cluster.prototype.updateAABB = function(){ 21 | this.aabb.setFromPoints(this.points); 22 | }; 23 | 24 | Foam.App.newOnLoadWithResource({ 25 | path : '../resources/basic3d.glsl' // bundle.js relative 26 | }, 27 | { 28 | setup : function (resource) { 29 | this.setFPS(60); 30 | this.setWindowSize(800, 600); 31 | 32 | var gl = this._gl; 33 | 34 | gl.viewport(0,0,this.getWindowWidth(),this.getWindowHeight()); 35 | var windowAspectRatio = this.getWindowAspectRatio(); 36 | 37 | var program = this._program = new Program(resource); 38 | program.bind(); 39 | 40 | var camera = this._cameraPersp = new CameraPersp(); 41 | camera.setPerspective(45.0,windowAspectRatio,0.00125, 10.0); 42 | camera.lookAt(Vec3.one(), Vec3.zero()); 43 | camera.updateMatrices(); 44 | 45 | this._frustumPersp = new FrustumPersp(); 46 | 47 | 48 | var zoom = 10; 49 | 50 | camera = this._camera = new CameraOrtho(); 51 | camera.setOrtho(-windowAspectRatio * zoom, windowAspectRatio * zoom, -zoom, zoom,-20,20); 52 | camera.lookAt(Vec3.one(),Vec3.zero()); 53 | camera.updateMatrices(); 54 | 55 | var numClusters = Random.randomInteger(100,300);//50,100); 56 | var clusters = this._clusters = new Array(numClusters); 57 | var box = this._box = new AABB(); 58 | this._boxIsWithinFrustum = false; 59 | 60 | var i = -1, j, scale, cluster, center; 61 | while(++i < numClusters){ 62 | center = Vec3.randomPosition(-10,10); 63 | scale = Random.randomFloat(0.125,0.5); 64 | cluster = clusters[i] = new Cluster(); 65 | cluster.points = new Array(Random.randomInteger(100,300)); 66 | cluster.aabb = new AABB(); 67 | cluster.color = new Color(Math.random(),0,Math.random()); 68 | 69 | j = -1; 70 | while(++j < cluster.points.length){ 71 | cluster.points[j] = new Vec3(Random.randomFloat(-1,1) * scale * Random.randomFloat(1,4), 72 | Random.randomFloat(-1,1) * scale * Random.randomFloat(1,4), 73 | Random.randomFloat(-1,1) * scale * Random.randomFloat(1,4)).add(center); 74 | } 75 | cluster.updateAABB(); 76 | 77 | box.include(cluster.aabb); 78 | } 79 | 80 | gl.enable(gl.DEPTH_TEST); 81 | gl.enable(gl.SCISSOR_TEST); 82 | program.uniform1f('uPointSize',3.0); 83 | }, 84 | 85 | update : function () { 86 | var gl = this._gl, 87 | glTrans = this._glTrans; 88 | 89 | var t = this.getSecondsElapsed(); 90 | 91 | var camera = this._camera, 92 | cameraPersp = this._cameraPersp, 93 | frustumPersp = this._frustumPersp; 94 | 95 | var dist = 3 + (0.5 + Math.sin(t) * 0.5) * 7; 96 | 97 | cameraPersp.setEye3f(Math.cos(t * 0.25) * dist, Math.sin(t), Math.sin(t * 0.25) * dist); 98 | cameraPersp.updateMatrices(); 99 | 100 | this.updateScene(); 101 | 102 | var windowWidth = this.getWindowWidth(), 103 | windowHeight = this.getWindowHeight(); 104 | var windowWidth_3 = windowWidth / 3, 105 | windowHeight_3 = windowHeight / 3, 106 | margin = 10; 107 | 108 | 109 | gl.scissor(0,0,windowWidth,windowHeight); 110 | gl.viewport(0,0,windowWidth,windowHeight); 111 | gl.clearColor(0.1,0.1,0.1,1); 112 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 113 | 114 | camera.lookAt(Vec3.one(),Vec3.zero()); 115 | camera.updateMatrices(); 116 | glTrans.setMatricesCamera(camera); 117 | 118 | this.drawScene(); 119 | frustumPersp.draw(); 120 | 121 | gl.scissor( margin, windowHeight - windowHeight_3 * 2 - margin * 2,windowWidth_3, windowHeight_3); 122 | gl.viewport(margin, windowHeight - windowHeight_3 * 2 - margin * 2,windowWidth_3, windowHeight_3 ); 123 | 124 | gl.clearColor(0.01,0.01,0.01,1); 125 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 126 | 127 | camera.lookAt(new Vec3(0.0001,1,0),Vec3.zero()); 128 | camera.updateMatrices(); 129 | glTrans.setMatricesCamera(camera); 130 | this.drawScene(); 131 | frustumPersp.draw(); 132 | 133 | gl.scissor( margin, windowHeight - windowHeight_3 - margin,windowWidth_3, windowHeight_3); 134 | gl.viewport(margin, windowHeight - windowHeight_3 - margin,windowWidth_3, windowHeight_3 ); 135 | 136 | gl.clearColor(0.01,0.01,0.01,1); 137 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 138 | glTrans.setMatricesCamera(cameraPersp); 139 | this.drawScene(); 140 | }, 141 | 142 | drawScene : function(){ 143 | var glDraw = this._glDraw; 144 | var clusters = this._clusters; 145 | var cluster; 146 | var i = -1 , l = clusters.length; 147 | while(++i < l){ 148 | cluster = clusters[i]; 149 | if(cluster.inFrustum){ 150 | glDraw.color(cluster.color); 151 | glDraw.drawPoints(cluster.points); 152 | cluster.aabb.draw(true); 153 | } else { 154 | glDraw.colorf(0,0,0.75); 155 | glDraw.drawPoints(cluster.aabb.points); 156 | cluster.aabb.draw(false); 157 | } 158 | 159 | } 160 | if(this._boxIsWithinFrustum){ 161 | glDraw.colorf(1,1,1,1); 162 | } else { 163 | glDraw.colorf(1,0,0,1); 164 | } 165 | this._box.draw(); 166 | glDraw.drawPivot(); 167 | }, 168 | 169 | updateScene : function(){ 170 | var frustum = this._frustumPersp; 171 | frustum.set(this._cameraPersp); 172 | 173 | var clusters = this._clusters; 174 | var cluster; 175 | var i = -1 , l = clusters.length; 176 | while(++i < l){ 177 | cluster = clusters[i]; 178 | cluster.inFrustum = frustum.containsAABB(cluster.aabb); 179 | } 180 | 181 | this._boxIsWithinFrustum = frustum.containsAABB(this._box); 182 | } 183 | 184 | } 185 | ); 186 | -------------------------------------------------------------------------------- /examples/06_Input/app.js: -------------------------------------------------------------------------------- 1 | var Foam = require('foam-gl'), 2 | MouseEvent = Foam.MouseEvent, 3 | Mouse = Foam.Mouse, 4 | KeyEvent = Foam.KeyEvent, 5 | Keyboard = Foam.Keyboard; 6 | 7 | Foam.App.newOnLoad({ 8 | setup : function(){ 9 | Mouse.getInstance().addEventListener(MouseEvent.MOUSE_DOWN,this.onMouseDown.bind(this)); 10 | Keyboard.getInstance().addEventListener(KeyEvent.KEY_DOWN, this.onKeyDown.bind(this)); 11 | Keyboard.getInstance().addEventListener(KeyEvent.KEY_PRESS, this.onKeyPress.bind(this)); 12 | }, 13 | 14 | update : function(){ 15 | /* 16 | var mouse = Mouse.getInstance(); 17 | 18 | console.log('Mouse down: ' + mouse.isDown() + '\n' + 19 | ' pressed: ' + mouse.isPressed() + '\n' + 20 | ' moved: ' + mouse.didMove() + '\n' + 21 | ' dragged: ' + mouse.isDragged() + '\n' + 22 | ' positionLast: ' + 'x: ' + mouse.getXLast() + ', y:' + mouse.getYLast() + '\n' + 23 | ' position: ' + 'x: ' + mouse.getX() + ', y: ' + mouse.getY() + '\n' + 24 | ' didEnter: ' + mouse.didEnter() + '\n' + 25 | ' didLeave: ' + mouse.didLeave()); 26 | */ 27 | }, 28 | 29 | onMouseDown : function(event) { 30 | console.log(event); 31 | }, 32 | 33 | onKeyDown : function(event){ 34 | console.log(event); 35 | }, 36 | 37 | onKeyUp : function(event){ 38 | console.log(event); 39 | }, 40 | 41 | onKeyPress : function(event){ 42 | console.log(event.type); 43 | } 44 | }); -------------------------------------------------------------------------------- /examples/07_TextureFont/Roboto-Black.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/automat/foam-gl/ff887b30d9d13635c7203476b97d1f34ce1d76b2/examples/07_TextureFont/Roboto-Black.ttf -------------------------------------------------------------------------------- /examples/07_TextureFont/app.js: -------------------------------------------------------------------------------- 1 | var Foam = require('foam-gl'), 2 | System = Foam.System, 3 | Program = Foam.Program, 4 | TextureFont = Foam.TextureFont, 5 | Random = Foam.Random, 6 | Color = Foam.Color, 7 | Vec2 = Foam.Vec2, 8 | Rect = Foam.Rect, 9 | Texture = Foam.Texture; 10 | 11 | 12 | var dir = '../examples/07_TextureFont/'; // bundle.js relative 13 | 14 | Foam.App.newOnLoadWithResource({ 15 | shader : { 16 | path : '../resources/basic3dTexture.glsl', 17 | type : 'text' 18 | }, 19 | fontData : { 20 | path : dir + 'Roboto-Black.ttf', 21 | type : 'arraybuffer' 22 | } 23 | 24 | },{ 25 | setup : function(resources){ 26 | this.setFPS(60.0); 27 | this.setWindowSize(800, 600); 28 | 29 | var windowWidth = this.getWindowWidth(), 30 | windowHeight = this.getWindowHeight(); 31 | 32 | var gl = this._gl; 33 | gl.viewport(0,0,windowWidth,windowHeight); 34 | 35 | this._program = new Program(resources.shader); 36 | this._program.bind(); 37 | 38 | this._textureFont24 = new TextureFont(resources.fontData); 39 | this._textureFont24.setFontSize(24); 40 | this._textureFont24.setLineHeight(1.25); 41 | 42 | this._textureFont96 = new TextureFont(resources.fontData); 43 | this._textureFont96.setFontSize(96); 44 | 45 | this._texture = Texture.fromRandom(windowWidth,windowHeight,null,null,0,0,255); 46 | this._texture.bind(); 47 | 48 | this._string = "Drop it, Mr. Data and attack the Romulans.\n Well, that's certainly good to know. How long can two people talk about nothing? Congratulations - you just destroyed the Enterprise. Flair is what marks the difference between artistry and mere competence. When has justice ever been as simple as a rule book?"; 49 | 50 | gl.disable(gl.DEPTH_TEST); 51 | this._program.uniform1f('uTexture',0); 52 | }, 53 | 54 | update : function(){ 55 | var gl = this._gl, 56 | glDraw = this._glDraw, 57 | glTrans = this._glTrans; 58 | 59 | var program = this._program; 60 | var t = this.getSecondsElapsed(); 61 | 62 | var windowSize = this.getWindowSize(), 63 | windowWidth_2 = windowSize.x * 0.5; 64 | 65 | var font24 = this._textureFont24, 66 | font96 = this._textureFont96; 67 | var string = this._string; 68 | 69 | var intrpl = 0.5 + Math.sin(t) * 0.5; 70 | var size = new Vec2(200 + intrpl * (windowWidth_2 - 200),250 + (1 - intrpl) * (windowSize.y - 250)); 71 | 72 | 73 | gl.clearColor(0,0,0,1); 74 | gl.clear(gl.COLOR_BUFFER_BIT); 75 | glTrans.setWindowMatrices(this.getWindowWidth(), this.getWindowHeight(), true); 76 | 77 | program.uniform1f('uUseTexture',1.0); 78 | 79 | glTrans.pushMatrix(); 80 | glDraw.colorf(1,1,1,1); 81 | glDraw.drawRect(this.getWindowWidth(),this.getWindowHeight()); 82 | glTrans.popMatrix(); 83 | 84 | gl.enable(gl.BLEND); 85 | gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); 86 | 87 | glTrans.pushMatrix(); 88 | font24.drawTextBox(string, size); 89 | glTrans.translate3f(windowWidth_2,0,0); 90 | font96.setLineHeight(1 + intrpl * 0.25); 91 | font96.drawTextBox(string, size, new Color(intrpl,intrpl,1)); 92 | glTrans.popMatrix(); 93 | 94 | gl.disable(gl.BLEND); 95 | 96 | program.uniform1f('uUseTexture',0); 97 | 98 | glTrans.pushMatrix(); 99 | glDraw.colorf(0,0,1,1); 100 | glDraw.drawRectStroked(size.x,size.y); 101 | glTrans.translate3f(windowWidth_2,0,0); 102 | glDraw.drawRectStroked(size.x,size.y); 103 | glTrans.popMatrix(); 104 | } 105 | }); 106 | -------------------------------------------------------------------------------- /examples/08_Raymarching/app.js: -------------------------------------------------------------------------------- 1 | var Foam = require('foam-gl'); 2 | var Mouse = Foam.Mouse, 3 | FileWatcher = Foam.FileWatcher, 4 | Program = Foam.Program; 5 | 6 | var root = '../examples/08_Raymarching/'; // bundle.js relative 7 | var pathVertGlsl = root + 'vert.glsl', 8 | pathFragGlsl = root + 'frag.glsl'; 9 | 10 | 11 | 12 | Foam.App.newOnLoadWithResource({ 13 | vertShader: { 14 | path: pathVertGlsl, 15 | type: 'text' 16 | }, 17 | fragShader: { 18 | path: pathFragGlsl, 19 | type: 'text' 20 | } 21 | },{ 22 | setup : function(resources){ 23 | var gl = this._gl, 24 | glTrans = this._glTrans; 25 | 26 | var windowSize, program, fileWatcher; 27 | 28 | windowSize = this._windowSize = this.getWindowSize(); 29 | program = this._program = new Program(resources.vertShader,resources.fragShader) 30 | .bind() 31 | .uniform2fv('uScreenSize', windowSize.toFloat32Array()) 32 | .uniform1f('uScreenRatio', this.getWindowAspectRatio()); 33 | 34 | gl.viewport(0,0,windowSize.x, windowSize.y); 35 | glTrans.setWindowMatrices(windowSize.x, windowSize.y, true); 36 | 37 | fileWatcher = this._fileWatcher = new FileWatcher(); 38 | 39 | var self = this; 40 | fileWatcher.addFile(pathFragGlsl, function (e) { 41 | try{ 42 | console.log('File :' + e.sender.path + ' did change.'); 43 | program.load(resources.vertShader, e.data) 44 | .bind() 45 | .uniform2fv('uScreenSize', windowSize.toFloat32Array()) 46 | .uniform1f('uScreenRatio', self.getWindowAspectRatio()); 47 | } catch (error){ 48 | console.log(error.message); 49 | } 50 | }); 51 | 52 | }, 53 | 54 | update : function(){ 55 | var gl = this._gl, 56 | glDraw = this._glDraw; 57 | 58 | gl.clearColor(0.1,0.1,0.1,1); 59 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 60 | 61 | var program = this._program, 62 | windowSize = this._windowSize, 63 | mouse = Mouse.getInstance(); 64 | 65 | 66 | program.uniform2f('uMousePosition', mouse.getXNormalized(), mouse.getYNormalized()); 67 | program.uniform1f('uTime',this.getSecondsElapsed()); 68 | glDraw.drawRect(windowSize.x,windowSize.y); 69 | } 70 | } 71 | ); -------------------------------------------------------------------------------- /examples/08_Raymarching/frag.glsl: -------------------------------------------------------------------------------- 1 | precision highp float; 2 | 3 | uniform vec2 uScreenSize; 4 | uniform float uScreenRatio; 5 | uniform float uTime; 6 | uniform vec2 uMousePosition; 7 | 8 | varying vec2 vTexcoord; 9 | 10 | //Simple raymarching sandbox with camera 11 | 12 | //Raymarching Distance Fields 13 | //About http://www.iquilezles.org/www/articles/raymarchingdf/raymarchingdf.htm 14 | //Also known as Sphere Tracing 15 | 16 | //Util Start 17 | vec2 ObjUnion(in vec2 obj0,in vec2 obj1){ 18 | if (obj0.x.5) 34 | if (fract(p.z*.5)>.5) 35 | return vec3(0,0,0); 36 | else 37 | return vec3(1,1,1); 38 | else 39 | if (fract(p.z*.5)>.5) 40 | return vec3(1,1,1); 41 | else 42 | return vec3(0,0,0); 43 | } 44 | 45 | 46 | //IQs RoundBox (try other objects http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm) 47 | vec2 obj1(in vec3 p){ 48 | //return vec2(length(max(abs(p)-vec3(1,1,1),0.0))-0.3,1); 49 | return vec2(length(p)-1.0,1); 50 | } 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | //RoundBox with simple solid color 59 | vec3 obj1_c(in vec3 p){ 60 | return vec3(1.0,0.5,0.2); 61 | } 62 | 63 | //Objects union 64 | vec2 inObj(in vec3 p){ 65 | return ObjUnion(obj0(p),obj1(p)); 66 | } 67 | 68 | //Scene End 69 | 70 | void main(void){ 71 | vec2 vPos=-1.0+2.0*gl_FragCoord.xy/uScreenSize.xy; 72 | 73 | //Camera animation 74 | vec3 vuv=vec3(0,1,0);//Change camere up vector here 75 | vec3 vrp=vec3(0,0,0); //Change camere view here 76 | vec3 prp=vec3(-sin(uTime)*20.0,4,cos(uTime)*8.0); //Change camera path position here 77 | 78 | //Camera setup 79 | vec3 vpn=normalize(vrp-prp); // w 80 | vec3 u=normalize(cross(vuv,vpn)); // u 81 | vec3 v=cross(vpn,u); 82 | 83 | 84 | 85 | vec3 vcv=(prp+vpn); 86 | 87 | 88 | 89 | 90 | vec3 scrCoord=vcv+vPos.x*u*uScreenRatio+vPos.y*v; 91 | vec3 scp=normalize(scrCoord-prp); 92 | 93 | //Raymarching 94 | const vec3 e=vec3(0.1,0,0); 95 | const float maxd=60.0; //Max depth 96 | 97 | vec2 s=vec2(0.1,0.0); 98 | vec3 c,p,n; 99 | 100 | float f=1.0; 101 | for(int i=0;i<256;i++){ 102 | if (abs(s.x)<.01||f>maxd) break; 103 | f+=s.x; 104 | p=prp+scp*f; 105 | s=inObj(p); 106 | } 107 | 108 | if (f windowSize.x + radius){ 78 | position.x = -radius; 79 | } 80 | if(position.x < -radius){ 81 | position.x = windowSize.x + radius; 82 | } 83 | if(position.y > windowSize.y + radius){ 84 | position.y = -radius; 85 | } 86 | if(position.y < -radius){ 87 | position.y = windowSize.y + radius; 88 | } 89 | 90 | j = -1; 91 | var c = 0; 92 | while(++j < l){ 93 | if(position.distance(positions[j]) < 40){ 94 | glDraw.drawLine(position,positions[j]); 95 | c++; 96 | } 97 | } 98 | 99 | } 100 | glDraw.drawCircles(positions,3); 101 | }, 102 | 103 | onWindowResize : function(){ 104 | var gl = this._gl, 105 | glTrans = this._glTrans; 106 | 107 | this.setWindowSize(window.innerWidth,window.innerHeight); 108 | var windowSize = this.getWindowSize(); 109 | 110 | gl.viewport(0,0,windowSize.x, windowSize.y); 111 | glTrans.setWindowMatrices(windowSize.x, windowSize.y); 112 | } 113 | } 114 | ); 115 | 116 | -------------------------------------------------------------------------------- /examples/10_TextureData/app.js: -------------------------------------------------------------------------------- 1 | var Foam = require('foam-gl'), 2 | Texture = Foam.Texture, 3 | Program = Foam.Program, 4 | Random = Foam.Random; 5 | 6 | Foam.App.newOnLoadWithResource({ 7 | path : '../resources/basic3dTexture.glsl' // bundle.js relative 8 | }, 9 | { 10 | setup : function(resource){ 11 | var gl = this._gl, 12 | glTrans = this._glTrans; 13 | 14 | var windowSize = this.getWindowSize(); 15 | 16 | gl.viewport(0,0,windowSize.x,windowSize.y); 17 | glTrans.setWindowMatrices(windowSize.x,windowSize.y); 18 | 19 | this._program = new Program(resource); 20 | this._program.bind(); 21 | 22 | var textureSize = this._textureSize = 256, 23 | textureSize_1 = textureSize - 1, 24 | textureSizeSq = textureSize * textureSize; 25 | var data = new Float32Array(textureSizeSq * 4 /*rgba*/); 26 | var i = -1, j, _i, i_, j_; 27 | while(++i < textureSize){ 28 | i_ = i / textureSize_1 * Math.PI; 29 | j = -1; 30 | while(++j < textureSize){ 31 | _i = (j * textureSize + i) * 4; 32 | j_ = j / textureSize_1 * Math.PI; 33 | data[_i ] = 0.5 + Math.sin(j_) * 0.5; 34 | data[_i+1] = 0.5 + Math.sin(i_) * 0.5; 35 | data[_i+2] = 0.5 + Math.sin(i_ * j_) * 0.5; 36 | data[_i+3] = 1.0; 37 | } 38 | } 39 | 40 | var format = new Texture.Format(); 41 | format.dataType = gl.FLOAT; 42 | format.wrapS = format.wrapT = gl.CLAMP_TO_EDGE; 43 | format.minFilter = format.magFilter = gl.NEAREST; 44 | 45 | var texture = new Texture(data,textureSize,textureSize,format); 46 | texture.bind(); 47 | 48 | textureSize = 16; 49 | textureSizeSq = textureSize * textureSize; 50 | data = new Float32Array(textureSizeSq * 4); 51 | i = -1; 52 | while(++i < textureSizeSq){ 53 | data[i * 4 ] = 1; 54 | data[i * 4 + 1] = 0; 55 | data[i * 4 + 2] = 1; 56 | data[i * 4 + 3] = 1; 57 | } 58 | 59 | texture.writeData(data,0,0,textureSize,textureSize); 60 | 61 | this._program.uniform1f('uUseTexture',1.0); 62 | this._program.uniform1i('uTexture',0); 63 | gl.clearColor(0,0,1,1); 64 | }, 65 | 66 | update : function(){ 67 | var gl = this._gl, glDraw = this._glDraw; 68 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 69 | 70 | var textureSize = this._textureSize; 71 | glDraw.drawRect(textureSize,textureSize); 72 | } 73 | } 74 | ); -------------------------------------------------------------------------------- /examples/11_Light/app.js: -------------------------------------------------------------------------------- 1 | var Foam = require('foam-gl'), 2 | Vec3 = Foam.Vec3, 3 | CameraPersp = Foam.CameraPersp, 4 | Arcball = Foam.Arcball, 5 | Program = Foam.Program, 6 | VboMeshPrimitive = Foam.VboMeshPrimitive, 7 | Light = Foam.Light, 8 | Material = Foam.Material; 9 | 10 | Foam.App.newOnLoadWithResource({ 11 | path: '../resources/basic3dLight.glsl' //bundle js relative 12 | }, { 13 | setup: function (resource) { 14 | var gl = this._gl; 15 | 16 | this.setWindowSize(window.innerWidth, window.innerHeight); 17 | gl.viewport(0, 0, this.getWindowWidth(), this.getWindowHeight()); 18 | 19 | this._program = new Program(resource); 20 | this._program.bind(); 21 | 22 | this._camera = new CameraPersp(60.0, this.getWindowAspectRatio(), 0.01, 20.0); 23 | this._camera.setEye(Vec3.one().scale(3)); 24 | this._camera.updateMatrices(); 25 | 26 | this._arcball = new Arcball(this._camera); 27 | 28 | this._light0 = new Light(0); 29 | this._light1 = new Light(1); 30 | this._light2 = new Light(2); 31 | 32 | this._light0.ambient.setf(1,1,1); 33 | this._light1.ambient.setf(1,0,0); 34 | this._light2.ambient.setf(0,0,1); 35 | 36 | this._material = new Material(); 37 | this._material.ambient.setf(1,0,1); 38 | 39 | this._mesh = new VboMeshPrimitive.Cube(); 40 | 41 | this._program.uniform1f(Program.UNIFORM_POINT_SIZE,3.0); 42 | gl.enable(gl.DEPTH_TEST); 43 | }, 44 | 45 | update: function () { 46 | var gl = this._gl, 47 | glTrans = this._glTrans, 48 | glDraw = this._glDraw; 49 | 50 | var program = this._program; 51 | var t = this.getSecondsElapsed(); 52 | 53 | gl.clearColor(0.125, 0.125, 0.125, 1); 54 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 55 | 56 | this._arcball.apply(); 57 | 58 | glTrans.setMatricesCamera(this._camera); 59 | glDraw.drawPivot(); 60 | this._arcball.debugDraw(); 61 | 62 | var light = this._light0; 63 | light.position.setf(Math.cos(t) * 3,1,Math.sin(t) * 3); 64 | 65 | light.position.setf(Math.cos(t)*0.85,0.5,Math.sin(t)*0.85); 66 | light.draw(); 67 | light.debugDraw(); 68 | 69 | light = this._light1; 70 | light.position.setf(Math.cos(t),Math.sin(t),Math.sin(t)*0.65); 71 | light.draw(); 72 | light.debugDraw(); 73 | 74 | light = this._light2; 75 | light.position.setf(0,0.55 + (0.5 + Math.sin(t) * 0.5) * 0.5,0); 76 | light.draw(); 77 | light.debugDraw(); 78 | 79 | this._material.apply(); 80 | 81 | program.uniform1f(Program.UNIFORM_USE_LIGHTING, 1.0); 82 | this._mesh.draw(); 83 | program.uniform1f(Program.UNIFORM_USE_LIGHTING, 0.0); 84 | }, 85 | 86 | onWindowResize: function () { 87 | this.setWindowSize(window.innerWidth,window.innerHeight); 88 | this._camera.setAspectRatio(this.getWindowAspectRatio()); 89 | this._camera.updateProjectionMatrix(); 90 | this._gl.viewport(0, 0, this.getWindowWidth(),this.getWindowHeight()); 91 | } 92 | } 93 | ); -------------------------------------------------------------------------------- /examples/12_Quaternions/app.js: -------------------------------------------------------------------------------- 1 | var Foam = require('foam-gl'), 2 | Program = Foam.Program, 3 | CameraPersp = Foam.CameraPersp; 4 | 5 | var Quat = Foam.Quat, 6 | Vec3 = Foam.Vec3; 7 | 8 | Foam.App.newOnLoadWithResource({ 9 | path : "../resources/basic3d.glsl" 10 | },{ 11 | setup : function(resource){ 12 | this.setWindowSize(800, 600); 13 | this.setFPS(60); 14 | 15 | this._program = new Program(resource); 16 | this._program.bind(); 17 | 18 | this._camera = new CameraPersp(); 19 | this._camera.setPerspective(45.0,this.getWindowAspectRatio(),0.00125, 40.0); 20 | this._camera.setEye3f(0,5,5); 21 | this._camera.updateMatrices(); 22 | 23 | var gl = this._gl; 24 | gl.viewport(0,0,this.getWindowWidth(),this.getWindowHeight()); 25 | gl.enable(gl.DEPTH_TEST); 26 | }, 27 | update : function(){ 28 | var gl = this._gl, 29 | glDraw = this._glDraw, 30 | glTrans = this._glTrans; 31 | 32 | var program = this._program; 33 | 34 | var t = this.getSecondsElapsed(), 35 | t_= t * 0.125; 36 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 37 | gl.clearColor(0.25,0.25,0.25,1.0); 38 | 39 | this._camera.setEye3f(Math.cos(t_)*5,2 + (0.5 + Math.sin(t * 0.125) * 0.5) * 3,Math.sin(t_)*5); 40 | this._camera.updateViewMatrix(); 41 | 42 | glTrans.setMatricesCamera(this._camera); 43 | glDraw.colorf(0.15,0.15,0.15); 44 | glDraw.drawGrid(Vec3.one().scale(45),45); 45 | glDraw.drawPivot(0.5); 46 | glDraw.colorf(0,0,0.15); 47 | glDraw.drawCubeStroked(); 48 | 49 | program.uniform1f('uPointSize',4.0); 50 | 51 | function drawQuat(q,length){ 52 | glTrans.pushMatrix(); 53 | glTrans.rotateQuat(q); 54 | glDraw.colorf(1,1,1); 55 | glDraw.drawCubeStroked(0.05); 56 | glDraw.drawPivot(length || 0.35,0.125,0.025); 57 | glTrans.popMatrix(); 58 | } 59 | 60 | function drawQuatLookAt(from,to,length){ 61 | glDraw.colorf(1,1,1); 62 | glDraw.drawPoint(from); 63 | glDraw.drawPoint(to); 64 | glTrans.pushMatrix(); 65 | glTrans.translate(from); 66 | glDraw.colorf(0,0,0.15); 67 | glDraw.drawVector(to.subbed(from)); 68 | drawQuat(Quat.fromLookAt(from,to),length); 69 | glTrans.popMatrix(); 70 | } 71 | 72 | function drawAxisf(x,y,z,length){ 73 | length = length !== undefined ? length : 0.5; 74 | var len = 1.0 / Math.sqrt(x * x + y * y + z * z); 75 | x *= len;y *= len;z *= len; 76 | glDraw.drawVectorf(0,0,0,x*length,y*length,z*length,0.0635,0.0375); 77 | } 78 | 79 | 80 | glTrans.pushMatrix(); 81 | glTrans.translate3f(0,0,-2); 82 | drawQuat(Quat.fromAxisAnglef(1,0,0,t)); 83 | drawAxisf(1,0,0); 84 | glTrans.translate3f(0,1,0); 85 | drawQuat(Quat.fromAxisAnglef(0,1,0,t * 3)); 86 | drawAxisf(0,1,0); 87 | glTrans.translate3f(0,1,0); 88 | drawQuat(Quat.fromAxisAnglef(0,0,1,t)); 89 | drawAxisf(0,0,1); 90 | glTrans.translate3f(1,-1,0); 91 | drawQuat(Quat.fromAxisAngle(new Vec3(1,1,1),t)); 92 | drawAxisf(1,1,1); 93 | glTrans.popMatrix(); 94 | 95 | var q0,q1,q2,v; 96 | 97 | glTrans.pushMatrix(); 98 | glTrans.translate3f(0,1,0); 99 | drawQuatLookAt(new Vec3(0,0,0),new Vec3(Math.cos(t),Math.sin(t*2),Math.sin(t))); 100 | for(var i = 0, l = 50, s = 1.0 / l,s_,a; i < l; ++i){ 101 | s_= s * i; 102 | a = t - s_ * Math.PI; 103 | program.uniform1f('uPointSize',(1.0 - s_) * 6); 104 | glDraw.colorf(1,0,s_); 105 | glDraw.drawPointf(Math.cos(a),Math.sin(t * 2 - s_ * Math.PI * 2),Math.sin(a)); 106 | } 107 | glTrans.translate3f(0,-1,0); 108 | drawQuatLookAt(new Vec3(Math.cos(-t)*0.5,Math.sin(t*0.5),Math.sin(-t)*0.25),new Vec3(0,0,0)); 109 | glTrans.popMatrix(); 110 | 111 | program.uniform1f('uPointSize',4); 112 | 113 | glTrans.pushMatrix(); 114 | glTrans.translate3f(0,0,2); 115 | glDraw.colorf(1,1,1); 116 | glDraw.drawPoint(); 117 | q0 = Quat.fromDirection(Vec3.xAxis()); 118 | drawQuat(q0); 119 | drawAxisf(1,0,0); 120 | q1 = Quat.fromDirection(new Vec3(-1,1,1).normalize()); 121 | drawQuat(q1); 122 | drawAxisf(1,1,1); 123 | q2 = Quat.fromInterpolationTo(q0,q1,0.5 + Math.sin(t) * 0.5); 124 | drawQuat(q2,0.75); 125 | glTrans.pushMatrix(); 126 | glTrans.rotateQuat(q2); 127 | glDraw.drawCubeColored(0.125); 128 | glTrans.popMatrix(); 129 | glTrans.popMatrix(); 130 | 131 | glTrans.pushMatrix(); 132 | glTrans.translate3f(-2,0,0); 133 | v = new Vec3(1,Math.sin(t),1); 134 | q0 = Quat.fromDirection(v.normalize()); 135 | q0.mult(Quat.fromAxisAnglef(0,1,0,t)); 136 | q0.mult(Quat.fromAxisAnglef(0,0,1,(0.5 + Math.sin(t) * 0.5) * Math.PI * 0.5)); 137 | drawQuat(q0,1.15); 138 | drawAxisf(v.x, v.y, v.z,1.15); 139 | glTrans.rotateQuat(q0); 140 | glTrans.pushMatrix(); 141 | glTrans.translate3f(0.5,0,0); 142 | glTrans.scale3f(1.0,0.25,0.25); 143 | glDraw.drawCubeColored(); 144 | glTrans.popMatrix(); 145 | glTrans.pushMatrix(); 146 | glTrans.translate3f(1,0,0); 147 | q0 = Quat.fromAxisAngle(Vec3.zAxis(),(0.5 + Math.sin(t) * 0.5) * Math.PI * 0.5); 148 | q1 = Quat.fromAxisAngle(Vec3.xAxis(),(0.5 + Math.sin(t * 2) * 0.5) * Math.PI * 0.15); 149 | q0.mult(q1); 150 | drawQuat(q0,1.15); 151 | glTrans.pushMatrix(); 152 | glTrans.rotateQuat(q0); 153 | glTrans.translate3f(0.5,0,0); 154 | glTrans.scale3f(1.0,0.25,0.25); 155 | glDraw.drawCubeColored(); 156 | glTrans.popMatrix(); 157 | glTrans.popMatrix(); 158 | glTrans.popMatrix(); 159 | } 160 | } 161 | ); -------------------------------------------------------------------------------- /examples/13_FileWatcher/app.js: -------------------------------------------------------------------------------- 1 | var FileWatcher = require('foam-gl').FileWatcher; 2 | 3 | function resourcePathLocal(path){ 4 | return '../examples/13_FileWatcher/' + path; 5 | } 6 | 7 | window.addEventListener('load',function(){ 8 | var watcher; 9 | 10 | function onFileAdded(e){ 11 | console.log('File added.\n','File content:', e.data); 12 | } 13 | 14 | function onFileChanged(e){ 15 | console.log('File changed\n','File content:', e.data); 16 | } 17 | 18 | watcher = new FileWatcher(); 19 | watcher.addFile(resourcePathLocal('file0.txt'),onFileChanged,onFileAdded); 20 | watcher.addFile(resourcePathLocal('file1.txt'),onFileChanged,onFileAdded); 21 | watcher.addFile(resourcePathLocal('file2.txt'),onFileChanged,onFileAdded); 22 | }); -------------------------------------------------------------------------------- /examples/13_FileWatcher/file0.txt: -------------------------------------------------------------------------------- 1 | ABC -------------------------------------------------------------------------------- /examples/13_FileWatcher/file1.txt: -------------------------------------------------------------------------------- 1 | DEF -------------------------------------------------------------------------------- /examples/13_FileWatcher/file2.txt: -------------------------------------------------------------------------------- 1 | FGH -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * 4 | * F | O | A | M 5 | * 6 | * 7 | * Foam - A WebGL toolkit 8 | * 9 | * Foam is available under the terms of the MIT license. The full text of the 10 | * MIT license is included below. 11 | * 12 | * MIT License 13 | * =========== 14 | * 15 | * Copyright (c) 2013 - 2015 Henryk Wollik. All rights reserved. 16 | * 17 | * Permission is hereby granted, free of charge, to any person obtaining a copy 18 | * of this software and associated documentation files (the "Software"), to deal 19 | * in the Software without restriction, including without limitation the rights 20 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 21 | * copies of the Software, and to permit persons to whom the Software is 22 | * furnished to do so, subject to the following conditions: 23 | * 24 | * The above copyright notice and this permission notice shall be included in all 25 | * copies or substantial portions of the Software. 26 | * 27 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 28 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 29 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 30 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 31 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 32 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 33 | * SOFTWARE. 34 | * 35 | */ 36 | 37 | 38 | module.exports = { 39 | Math: require('./lib/math/Math'), 40 | Vec2: require('./lib/math/Vec2'), 41 | Vec3: require('./lib/math/Vec3'), 42 | Vec4: require('./lib/math/Vec4'), 43 | Matrix33: require('./lib/math/Matrix33'), 44 | Matrix44: require('./lib/math/Matrix44'), 45 | Quat: require('./lib/math/Quat'), 46 | OnB : require('./lib/math/OnB'), 47 | Ease: require('./lib/math/Ease'), 48 | Random: require('./lib/math/Random'), 49 | 50 | Geom: require('./lib/geom/Geom'), 51 | 52 | Color: require('./lib/util/Color'), 53 | AABB: require('./lib/geom/AABB'), 54 | AABR: require('./lib/geom/AABR'), 55 | Plane: require('./lib/geom/Plane'), 56 | Rect: require('./lib/geom/Rect'), 57 | 58 | Window : require('./lib/app/Window'), 59 | WindowEvent : require('./lib/app/WindowEvent'), 60 | App: require('./lib/app/App'), 61 | Time: require('./lib/app/Time'), 62 | TimeEvent : require('./lib/app/TimeEvent'), 63 | 64 | gl: require('./lib/gl/gl'), 65 | glTrans: require('./lib/gl/glTrans'), 66 | glDraw: require('./lib/gl/glDraw'), 67 | glObject : require('./lib/gl/glObject'), 68 | glu: require('./lib/gl/glu'), 69 | glExtensions: require('./lib/gl/glExtensions'), 70 | 71 | Vbo: require('./lib/gl/Vbo'), 72 | 73 | TextureFont: require('./lib/gl/TextureFont'), 74 | 75 | Program: require('./lib/gl/Program'), 76 | ProgramPreset: require('./lib/gl/ProgramPreset'), 77 | CameraPersp: require('./lib/gl/CameraPersp'), 78 | CameraOrtho: require('./lib/gl/CameraOrtho'), 79 | Arcball: require('./lib/gl/Arcball'), 80 | CameraOrbiter : require('./lib/gl/CameraOrbiter'), 81 | FrustumOrtho: require('./lib/gl/FrustumOrtho'), 82 | FrustumPersp: require('./lib/gl/FrustumPersp'), 83 | 84 | Texture: require('./lib/gl/Texture'), 85 | Fbo: require('./lib/gl/Fbo'), 86 | 87 | System: require('./lib/system/System'), 88 | Resource: require('./lib/system/Resource'), 89 | ResourceType : require('./lib/system/ResourceType'), 90 | Resources : require('./lib/system/Resources'), 91 | FileWatcher : require('./lib/system/FileWatcher'), 92 | EventDispatcher : require('./lib/system/EventDispatcher'), 93 | Event : require('./lib/system/Event'), 94 | 95 | Mouse : require('./lib/input/Mouse'), 96 | MouseEvent : require('./lib/input/MouseEvent'), 97 | Keyboard : require('./lib/input/Keyboard'), 98 | KeyEvent : require('./lib/input/KeyEvent'), 99 | 100 | Mesh : require('./lib/gl/Mesh'), 101 | MeshPrimitive : require('./lib/gl/MeshPrimitive'), 102 | VboMesh : require('./lib/gl/VboMesh'), 103 | VboMeshPrimitive : require('./lib/gl/VboMeshPrimitive'), 104 | 105 | Light : require('./lib/gl/Light'), 106 | PointLight : require('./lib/gl/PointLight'), 107 | DirectionalLight : require('./lib/gl/DirectionalLight'), 108 | SpotLight : require('./lib/gl/SpotLight'), 109 | 110 | Material : require('./lib/gl/Material'), 111 | 112 | ObjectUtil : require('./lib/util/ObjectUtil'), 113 | StringUtil : require('./lib/util/StringUtil'), 114 | ArrayUtil : require('./lib/util/ArrayUtil'), 115 | ElementArrayUtil : require('./lib/util/ElementArrayUtil') 116 | }; -------------------------------------------------------------------------------- /lib/app/Time.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Represents application time. 3 | * @type {{}} 4 | */ 5 | 6 | var Time = {}; 7 | 8 | /** 9 | * Indicates whether time updates are currently stopped. 10 | * @type {boolean} 11 | * @private 12 | */ 13 | 14 | Time.__stopped = false; 15 | 16 | /** 17 | * Timestamp before update loop start. 18 | * @type {number} 19 | * @private 20 | */ 21 | 22 | Time.__start = -1; 23 | 24 | /** 25 | * Current timestamp update loop. 26 | * @type {number} 27 | * @private 28 | */ 29 | 30 | Time.__now = -1; 31 | 32 | /** 33 | * Previous timestamp update loop. 34 | * @type {number} 35 | * @private 36 | */ 37 | 38 | Time.__previous = -1; 39 | 40 | /** 41 | * Timestamp now and previous diff. 42 | * @type {number} 43 | * @private 44 | */ 45 | 46 | Time.__elapsed = -1; 47 | 48 | /** 49 | * Timestamp diff between two frames. 50 | * @type {number} 51 | * @private 52 | */ 53 | 54 | Time.__frame = -1; 55 | 56 | /** 57 | * Frame time in seconds. 58 | * @type {number} 59 | * @private 60 | */ 61 | 62 | Time.__delta = -1; 63 | 64 | /** 65 | * Time elapsed since Time.getStart() in seconds. 66 | * @type {number} 67 | * @private 68 | */ 69 | 70 | Time.__secondsElapsed = -1; 71 | 72 | /** 73 | * Current fixed update loop set. 74 | * @type {number} 75 | * @private 76 | */ 77 | 78 | Time.__fixedStep = -1; 79 | 80 | /** 81 | * Resets time properties. 82 | * @private 83 | */ 84 | 85 | Time.__reset = function(){ 86 | this.__start = 0; 87 | this.__now = 0; 88 | this.__previous = 0; 89 | this.__elapsed = 0; 90 | this.__frame = 0; 91 | this.__delta = 0; 92 | 93 | this.__secondsElapsed = 0; 94 | }; 95 | 96 | /** 97 | * Returns the update loops current timestamp. 98 | * @returns {number} 99 | */ 100 | 101 | Time.getNow = function(){ 102 | return this.__now; 103 | }; 104 | 105 | /** 106 | * Returns the difference between the update loops current time stamp and Time.getStart(). 107 | * @returns {number} 108 | */ 109 | 110 | Time.getElapsed = function(){ 111 | return this.__elapsed; 112 | }; 113 | 114 | /** 115 | * Returns the seconds elapsed since update loop start. 116 | * @returns {number} 117 | */ 118 | 119 | Time.getSecondsElapsed = function(){ 120 | return this.__secondsElapsed; 121 | }; 122 | 123 | /** 124 | * Returns the timestamp right before the update loop is called. 125 | * @returns {number} 126 | */ 127 | 128 | Time.getStart = function(){ 129 | return this.__start; 130 | }; 131 | 132 | /** 133 | * Returns the delta time in milliseconds. 134 | * @returns {number} 135 | */ 136 | 137 | Time.getDelta = function(){ 138 | return this.__delta; 139 | }; 140 | 141 | /** 142 | * Returns the fixed time step. 143 | * @returns {number} 144 | */ 145 | 146 | Time.getFixedStep = function(){ 147 | return this.__fixedStep; 148 | }; 149 | 150 | /** 151 | * Returns true if Time updates are stopped. 152 | * @returns {boolean} 153 | */ 154 | 155 | Time.isStopped = function(){ 156 | return this.__stopped; 157 | }; 158 | 159 | 160 | /** 161 | * Returns a loggable string representation of Time. 162 | * @returns {string} 163 | */ 164 | 165 | Time.toString = function(){ 166 | return 'start: ' + this.__start + '\n' + 167 | 'now: ' + this.__now + '\n' + 168 | 'previous: ' + this.__previous + '\n' + 169 | 'elapsed: ' + this.__elapsed + '\n' + 170 | 'frame: ' + this.__frame + '\n' + 171 | 'delta: ' + this.__delta + '\n' + 172 | 'secondsElapsed: ' + this.__secondsElapsed + '\n' + 173 | 'fixedStep: ' + this.__fixedStep + '\n'; 174 | }; 175 | 176 | module.exports = Time; -------------------------------------------------------------------------------- /lib/app/TimeEvent.js: -------------------------------------------------------------------------------- 1 | var TimeEvent = { 2 | STOP : 'timeStop', 3 | CONTINUE : 'timeContinue' 4 | }; 5 | 6 | module.exports = TimeEvent; -------------------------------------------------------------------------------- /lib/app/Window.js: -------------------------------------------------------------------------------- 1 | var EventDispatcher = require('../system/EventDispatcher'); 2 | 3 | var instance = null; 4 | 5 | function Window_(){ 6 | EventDispatcher.call(this); 7 | 8 | this._bounds = null; 9 | this._scale = -1; 10 | this._aspectRatio = -1; 11 | this._fullscreen = false; 12 | } 13 | 14 | Window_.prototype = Object.create(EventDispatcher.prototype); 15 | Window_.prototype.constructor = Window_; 16 | 17 | /** 18 | * Returns the current app window width. 19 | * @returns {number} 20 | */ 21 | 22 | Window_.prototype.getWidth = function () { 23 | return this._bounds.getWidth(); 24 | }; 25 | 26 | /** 27 | * Returns the current app window height. 28 | * @returns {number} 29 | */ 30 | 31 | Window_.prototype.getHeight = function () { 32 | return this._bounds.getHeight(); 33 | }; 34 | 35 | /** 36 | * Returns the current app window size. 37 | * @param {Vec2} [out] - Optional out 38 | * @returns {Vec2} 39 | */ 40 | 41 | Window_.prototype.getSize = function(out) { 42 | return this._bounds.getSize(out); 43 | }; 44 | 45 | /** 46 | * Returns the current app window aspect ratio. 47 | * @returns {number} 48 | */ 49 | 50 | Window_.prototype.getAspectRatio = function(){ 51 | return this._aspectRatio; 52 | }; 53 | 54 | /** 55 | * Returns the current app window scale. 56 | * @returns {number} 57 | */ 58 | 59 | Window_.prototype.getScale = function(){ 60 | return this._scale; 61 | }; 62 | 63 | /** 64 | * Returns the current app window bounds. 65 | * @param {Rect} [out] - Optional out 66 | * @returns {Rect} 67 | */ 68 | 69 | Window_.prototype.getBounds = function(out){ 70 | return this._bounds.copy(out); 71 | }; 72 | 73 | /** 74 | * Returns true if the app is in fullscreen mode. 75 | * @returns {boolean} 76 | */ 77 | 78 | Window_.prototype.isFullscreen = function(){ 79 | return this._fullscreen; 80 | }; 81 | 82 | Window_.init = function(){ 83 | instance = instance || new Window_(); 84 | return instance; 85 | }; 86 | 87 | /** 88 | * Returns a reference to the apps window. 89 | * @returns {Window_} 90 | */ 91 | 92 | Window_.get = function() { 93 | return instance; 94 | }; 95 | 96 | Window_.dispose = function() { 97 | instance.removeAllEventListeners(); 98 | instance = null; 99 | }; 100 | 101 | module.exports = Window_; -------------------------------------------------------------------------------- /lib/app/WindowEvent.js: -------------------------------------------------------------------------------- 1 | var WindowEvent = { 2 | RESIZE : 'resize' 3 | }; 4 | 5 | module.exports = WindowEvent; -------------------------------------------------------------------------------- /lib/geom/AABR.js: -------------------------------------------------------------------------------- 1 | var Math_ = require('../math/Math'), 2 | Vec2 = require('../math/Vec2'), 3 | glTrans = require('../gl/glTrans'), 4 | glDraw, _glDraw = require('../gl/glDraw'); 5 | 6 | /** 7 | * Representation of an axis aligned bounding rect. 8 | * @constructor 9 | */ 10 | 11 | function AABR() { 12 | /** 13 | * The minimal point. 14 | * @type {Vec2} 15 | */ 16 | var min = this.min = Vec2.max(), 17 | /** 18 | * The maximal point 19 | * @type {Vec2} 20 | */ 21 | max = this.max = Vec2.min(); 22 | 23 | /** 24 | * The center of the box. 25 | * @type {Vec3} 26 | */ 27 | this.center = new Vec2(); 28 | /** 29 | * The size of the box. (max - min) 30 | * @type {Vec2} 31 | */ 32 | this.size = new Vec2(); 33 | 34 | /** 35 | * The 8 defining points of the box. 36 | * @type {Array} 37 | */ 38 | this.points = new Array(4); 39 | 40 | switch (arguments.length){ 41 | case 1 : 42 | if(arguments[0] instanceof AABR){ 43 | this.set(arguments[0]); 44 | } else if(arguments[0] instanceof Vec2) { 45 | max.set(arguments[0]); 46 | } 47 | break; 48 | case 2 : 49 | if(arguments[0] instanceof Vec2 && 50 | arguments[1] instanceof Vec2){ 51 | min.set(arguments[0]); 52 | max.set(arguments[1]); 53 | } 54 | break; 55 | } 56 | 57 | var points = this.points; 58 | var i = -1, 59 | l = points.length; 60 | while(++i < l){ 61 | points[i] = new Vec2(); 62 | } 63 | this._update(); 64 | 65 | glDraw = glDraw || _glDraw.get(); 66 | } 67 | /** 68 | * Sets box from another box 69 | * @param {AABR} AABR - Another box 70 | * @returns {AABR} 71 | */ 72 | 73 | AABR.prototype.set = function(AABR){ 74 | this.min.set(AABR.min); 75 | this.max.set(AABR.max); 76 | this.size.set(AABR.size); 77 | return this; 78 | }; 79 | 80 | /** 81 | * Returns the range from min.x to max.x 82 | * @returns {Number} 83 | */ 84 | 85 | AABR.prototype.getXRange = function(){ 86 | return Math.abs(this.min.x) + this.max.x; 87 | }; 88 | 89 | /** 90 | * Returns the range from min.y to max.y 91 | * @returns {Number} 92 | */ 93 | 94 | AABR.prototype.getYRange = function(){ 95 | return Math.abs(this.min.y) + this.max.y; 96 | }; 97 | 98 | /** 99 | * Returns the xy range 100 | * @param {Vec2}[out] - Optional out 101 | * @returns {Vec2} 102 | */ 103 | 104 | AABR.prototype.getXYRange = function(out){ 105 | return (out || new Vec3()).setf(this.getXRange(),this.getYRange()); 106 | }; 107 | 108 | /** 109 | * Returns the normalized range from min.x to max.x 110 | * @returns {number} 111 | */ 112 | 113 | AABR.prototype.getXRangeNormalized = function(){ 114 | var range = this.getXRange(); 115 | return range / Math.max(range,this.getYRange()); 116 | }; 117 | 118 | /** 119 | * Returns the normalized range from min.y to max.y 120 | * @returns {number} 121 | */ 122 | 123 | 124 | AABR.prototype.getYRangeNormalized = function(){ 125 | var range = this.getYRange(); 126 | return range / Math.max(range,this.getXRange()); 127 | }; 128 | 129 | /** 130 | * Returns the xyz normalized range 131 | * @param {Vec2}[out] - Optional out 132 | * @returns {Vec2} 133 | */ 134 | 135 | AABR.prototype.getXYRangeNormalized = function(out){ 136 | var x = this.getXRange(), 137 | y = this.getYRange(), 138 | max = Math.max(x,y); 139 | 140 | x /= max; 141 | y /= max; 142 | 143 | return (out || new Vec2()).setf(x,y); 144 | }; 145 | 146 | 147 | AABR.prototype.normalizePointsf = function(points,scale){ 148 | scale = scale === undefined ? 1.0 : scale; 149 | 150 | var min = this.min, 151 | max = this.max; 152 | var minx = min.x, miny = min.y, 153 | maxx = max.x, maxy = max.y; 154 | 155 | var xnorm = this.getXRangeNormalized() * scale, 156 | ynorm = this.getYRangeNormalized() * scale; 157 | 158 | var i = 0, l = points.length; 159 | while(i < l){ 160 | points[i] = Math_.map(points[i++],minx,maxx,0.0,xnorm); 161 | points[i] = Math_.map(points[i++],miny,maxy,0.0,ynorm); 162 | } 163 | 164 | return points; 165 | }; 166 | 167 | AABR.prototype.normalizePoints = function(points,scale){ 168 | scale = scale === undefined ? 1.0 : scale; 169 | 170 | var min = this.min, 171 | max = this.max; 172 | var minx = min.x, miny = min.y, 173 | maxx = max.x, maxy = max.y; 174 | 175 | var xnorm = this.getXRangeNormalized() * scale, 176 | ynorm = this.getYRangeNormalized() * scale; 177 | var point; 178 | 179 | var i = 0, l = points.length; 180 | while(i < l){ 181 | point = points[i++]; 182 | point.x = Math_.map(point.x,minx,maxx,0.0,xnorm); 183 | point.y = Math_.map(point.y,miny,maxy,0.0,ynorm); 184 | } 185 | 186 | return points; 187 | }; 188 | 189 | /** 190 | * Adjusts the box size to include another rect. 191 | * @param {AABR} aabr - Another box 192 | * @returns {AABR} 193 | */ 194 | 195 | AABR.prototype.include = function(aabr){ 196 | var min = this.min, 197 | max = this.max, 198 | amin = aabr.min, 199 | amax = aabr.max; 200 | 201 | min.x = Math.min(min.x,amin.x); 202 | min.y = Math.min(min.y,amin.y); 203 | max.x = Math.max(max.x,amax.x); 204 | max.y = Math.max(max.y,amax.y); 205 | 206 | this._update(); 207 | return this; 208 | }; 209 | 210 | AABR.prototype._update = function(){ 211 | var min = this.min, 212 | max = this.max, 213 | size = this.size.set(max).sub(min); 214 | 215 | var points = this.points; 216 | 217 | var p0 = points[0], 218 | p1 = points[1], 219 | p2 = points[2], 220 | p3 = points[3]; 221 | 222 | p0.x = p2.x = min.x; 223 | p1.x = p3.x = max.x; 224 | p0.y = p1.y = min.y; 225 | p2.y = p3.y = max.y; 226 | 227 | this.center.setf(min.x + size.x * 0.5,min.y + size.y * 0.5); 228 | }; 229 | 230 | /** 231 | * Returns an axis aligned bounding rect from a set of points. 232 | * @param {Vec2[]} points - N points 233 | * @returns {AABR} 234 | */ 235 | 236 | AABR.prototype.setFromPoints = function(points){ 237 | var min = this.min.toMax(), 238 | max = this.max.toMin(); 239 | var i = -1, l = points.length; 240 | var point; 241 | var px,py; 242 | 243 | while(++i < l){ 244 | point = points[i]; 245 | px = point.x; 246 | py = point.y; 247 | 248 | min.x = Math.min(min.x,px); 249 | max.x = Math.max(max.x,px); 250 | min.y = Math.min(min.y,py); 251 | max.y = Math.max(max.y,py); 252 | } 253 | 254 | this._update(); 255 | return this; 256 | }; 257 | 258 | AABR.prototype.draw = function(center){ 259 | glTrans.pushMatrix(); 260 | glTrans.translate3f(this.center.x,this.center.y,0); 261 | if(center){ 262 | glDraw.drawPivot(); 263 | } 264 | glTrans.scale3f(this.size.x,this.size.y,1.0); 265 | glDraw.drawCubeStroked(); 266 | glTrans.popMatrix(); 267 | }; 268 | 269 | AABR.fromPoints = function(points,aabr){ 270 | return (aabr || new AABR()).setFromPoints(points); 271 | }; 272 | 273 | AABR.fromPointsf = function(points,aabr){ 274 | return (aabr || new AABR()).setFromPointsf(points); 275 | }; 276 | 277 | module.exports = AABR; -------------------------------------------------------------------------------- /lib/geom/Geom.js: -------------------------------------------------------------------------------- 1 | var Vec3 = require('../math/Vec3'); 2 | 3 | /** 4 | * General geometry utilities. 5 | * @type {{}} 6 | */ 7 | 8 | var Geom = {}; 9 | 10 | /** 11 | * @param {Number} phi - azimuthal angle phi φ 12 | * @param {Number} theta - polar angle theta θ 13 | * @param {Number} rho - radial distance rho 14 | * @param {Vec3}[out] - Optional out 15 | * @returns {Vec3} 16 | */ 17 | 18 | Geom.sphericalToCartesian = function(phi,theta,rho,out){ 19 | return (out || new Vec3()).setf( 20 | rho * Math.sin(theta) * Math.cos(phi), 21 | rho * Math.cos(theta), 22 | rho * Math.sin(theta) * Math.sin(phi)); 23 | }; 24 | 25 | /** 26 | * 27 | * @param p 28 | * @param {Vec3}[out] - Optional out 29 | * @returns {Vec3} 30 | */ 31 | 32 | Geom.cartesianToSpherical = function(p,out){ 33 | var x = p.x, 34 | y = p.y, 35 | z = p.z; 36 | return (out || new Vec3()).setf( 37 | Math.atan2(z,x), //theta 38 | Math.atan2(Math.sqrt(x * x + z * z),y), //phi 39 | p.length() //rho 40 | ); 41 | }; 42 | 43 | module.exports = Geom; -------------------------------------------------------------------------------- /lib/geom/Plane.js: -------------------------------------------------------------------------------- 1 | var Vec3 = require('../math/Vec3'), 2 | glTrans = require('../gl/glTrans'), 3 | glDraw,_glDraw = require('../gl/glDraw'); 4 | 5 | function Plane(point,normal){ 6 | this.point = point || Vec3.zero(); 7 | this.normal = normal || Vec3.yAxis(); 8 | this._update(); 9 | 10 | glDraw = glDraw || _glDraw.get(); 11 | } 12 | 13 | Plane.prototype.set = function(origin,normal){ 14 | this.point = origin; 15 | this.normal = normal; 16 | return this; 17 | }; 18 | 19 | Plane.prototype.setFromPoints = function(v0,v1,v2){ 20 | var point = this.point, 21 | normal = this.normal; 22 | 23 | var _1_3 = 1.0 / 3.0; 24 | 25 | point.x = (v0.x + v1.x + v2.x) * _1_3; 26 | point.y = (v0.y + v1.y + v2.y) * _1_3; 27 | point.z = (v0.z + v1.z + v2.z) * _1_3; 28 | 29 | var e0x = v1.x - v0.x, 30 | e0y = v1.y - v0.y, 31 | e0z = v1.z - v0.z, 32 | e1x = v2.x - v0.x, 33 | e1y = v2.y - v0.y, 34 | e1z = v2.z - v0.z; 35 | 36 | normal.x = e0y * e1z - e1y * e0z; 37 | normal.y = e0z * e1x - e1z * e0x; 38 | normal.z = e0x * e1y - e1x * e0y; 39 | 40 | this._update(); 41 | 42 | return this; 43 | }; 44 | 45 | Plane.prototype.setNormal = function(normal){ 46 | this.normal.set(normal); 47 | this._update(); 48 | }; 49 | 50 | Plane.prototype.setNormal3f = function(x,y,z){ 51 | this.normal.setf(x,y,z); 52 | this._update(); 53 | }; 54 | 55 | Plane.prototype._update = function(){ 56 | var normal = this.normal; 57 | var nx = normal.x, 58 | ny = normal.y, 59 | nz = normal.z; 60 | 61 | var length = nx * nx + ny * ny + nz * nz; 62 | 63 | if(length){ 64 | length = 1.0 / Math.sqrt(length); 65 | normal.x *= length; 66 | normal.y *= length; 67 | normal.z *= length; 68 | } else { 69 | throw new Error('Plane: Normal cant be zero length.'); 70 | } 71 | 72 | this.dist = -normal.dot(this.point); 73 | }; 74 | 75 | 76 | Plane.prototype.distanceSigned = function(point){ 77 | var normal = this.normal; 78 | return normal.x * point.x + normal.y * point.y + normal.z * point.z + this.dist; 79 | }; 80 | 81 | Plane.prototype.distanceSigned3f = function(x,y,z){ 82 | var normal = this.normal; 83 | return normal.x * x + normal.y * y+ normal.z * z + this.dist; 84 | }; 85 | 86 | Plane.prototype.copy = function(plane){ 87 | return (plane || new Plane()).set(this.origin,this.normal); 88 | }; 89 | 90 | Plane.prototype.draw = function(){ 91 | glTrans.pushMatrix(); 92 | glTrans.translate(this.point); 93 | glDraw.drawVector(this.normal); 94 | glTrans.popMatrix(); 95 | 96 | }; 97 | 98 | Plane.fromPoints = function(v0,v1,v2){ 99 | return new Plane().setFromPoints(v0,v1,v2); 100 | }; 101 | 102 | 103 | 104 | module.exports = Plane; -------------------------------------------------------------------------------- /lib/gl/CameraAbstract.js: -------------------------------------------------------------------------------- 1 | var Vec3 = require('../math/Vec3'), 2 | Matrix44 = require('../math/Matrix44'), 3 | ObjectUtil = require('../util/ObjectUtil'); 4 | 5 | var Color = require('../util/Color'); 6 | 7 | var glDraw, _glDraw = require('./glDraw'); 8 | var glTrans = require('./glTrans'); 9 | 10 | function CameraAbstract() { 11 | glDraw = _glDraw.get(); 12 | 13 | this._eye = new Vec3(); 14 | this._target = new Vec3(); 15 | this._up = Vec3.yAxis(); 16 | 17 | this._fov = 0; 18 | this._near = 0; 19 | this._far = 0; 20 | 21 | this._u = new Vec3(); 22 | this._v = new Vec3(); 23 | this._w = new Vec3(); 24 | 25 | 26 | this._frustumLeft = this._frustumRight = this._frustumBottom = this._frustumTop = 0; 27 | 28 | this._viewMatrixDirty = true; 29 | this._projectionMatrixDirty = true; 30 | 31 | this.projectionMatrix = new Matrix44(); 32 | this.viewMatrix = new Matrix44(); 33 | } 34 | 35 | CameraAbstract.prototype._updateOnB = function(){ 36 | var up = this._up; 37 | var eye = this._eye, target = this._target; 38 | var u = this._u, v = this._v, w = this._w; 39 | target.subbed(eye,w).normalize(); 40 | up.crossed(w, u).normalize(); 41 | w.crossed(u, v).normalize(); 42 | 43 | if(eye.x == target.x && eye.z == target.z){ 44 | if(eye.y > target.y){ 45 | u.setf(0,0,1); 46 | v.setf(1,0,0); 47 | w.setf(0,-1,0); 48 | } else { 49 | u.setf(1,0,0); 50 | v.setf(0,0,1); 51 | w.setf(0,1,0); 52 | } 53 | } 54 | }; 55 | 56 | 57 | CameraAbstract.prototype.setTarget = function (v) { 58 | this.setTarget3f(v.x, v.y, v.z); 59 | }; 60 | 61 | CameraAbstract.prototype.setTarget3f = function (x, y, z) { 62 | this._target.setf(x, y, z); 63 | this._viewMatrixDirty = false; 64 | }; 65 | 66 | CameraAbstract.prototype.getTarget = function(v){ 67 | return this._target.copy(v); 68 | }; 69 | 70 | CameraAbstract.prototype.setEye = function (v) { 71 | this.setEye3f(v.x, v.y, v.z); 72 | }; 73 | 74 | CameraAbstract.prototype.setEye3f = function (x, y, z) { 75 | this._eye.setf(x,y,z); 76 | this._viewMatrixDirty = true; 77 | }; 78 | 79 | CameraAbstract.prototype.getEye = function(v){ 80 | return this._eye.copy(v); 81 | }; 82 | 83 | CameraAbstract.prototype.lookAt = function(eye,target,up){ 84 | this._eye.set(eye); 85 | this._target.set(target); 86 | this._up.set(up || this._up); 87 | this._viewMatrixDirty = true; 88 | }; 89 | 90 | var temp0 = new Vec3(); 91 | 92 | CameraAbstract.prototype.getDistance = function(){ 93 | return this._eye.subbed(this._target,temp0).length(); 94 | }; 95 | 96 | CameraAbstract.prototype.setUp = function (v) { 97 | this._up.set(v); 98 | this._viewMatrixDirty = true; 99 | }; 100 | 101 | CameraAbstract.prototype.setUp3f = function (x, y, z) { 102 | this._up.setf(x,y,z); 103 | this._viewMatrixDirty = true; 104 | }; 105 | 106 | CameraAbstract.prototype.setNear = function (near) { 107 | this._near = near; 108 | this._projectionMatrixDirty = true; 109 | }; 110 | 111 | CameraAbstract.prototype.getNear = function(){ 112 | return this._near; 113 | }; 114 | 115 | CameraAbstract.prototype.setFar = function (far) { 116 | this._far = far; 117 | this._projectionMatrixDirty = true; 118 | }; 119 | 120 | CameraAbstract.prototype.getFar = function(){ 121 | return this._far; 122 | }; 123 | 124 | CameraAbstract.prototype.setFov = function (fov) { 125 | this._fov = fov; 126 | this._projectionMatrixDirty = true; 127 | }; 128 | 129 | CameraAbstract.prototype.getFov = function(){ 130 | return this._fov; 131 | } 132 | 133 | 134 | CameraAbstract.prototype.updateMatrices = function () { 135 | this.updateViewMatrix(); 136 | this.updateProjectionMatrix(); 137 | }; 138 | 139 | 140 | CameraAbstract.prototype.getFrustum = function(frustum){ 141 | frustum = frustum || new Array(6); 142 | 143 | frustum[0] = this._frustumLeft; 144 | frustum[1] = this._frustumTop; 145 | frustum[2] = this._frustumRight; 146 | frustum[3] = this._frustumBottom; 147 | frustum[4] = this._near; 148 | frustum[5] = this._far; 149 | 150 | return frustum; 151 | }; 152 | 153 | CameraAbstract.prototype.getU = function(v) { 154 | return (v || new Vec3()).set(this._u); 155 | }; 156 | 157 | CameraAbstract.prototype.getV = function(v){ 158 | return (v || new Vec3()).set(this._v); 159 | }; 160 | 161 | CameraAbstract.prototype.getW = function(v){ 162 | return (v || new Vec3()).set(this._w); 163 | }; 164 | 165 | // draw orthonormal frame 166 | 167 | CameraAbstract.prototype.draw = function(){ 168 | var trans = Matrix44.fromOnBAxes(this._w,this._v,this._u); 169 | var color = glDraw.getColor(); 170 | 171 | glTrans.pushMatrix(); 172 | glTrans.translate(this._eye); 173 | glTrans.multMatrix(trans); 174 | glDraw.drawPivot(); 175 | glTrans.scale3f(0.25,0.125,0.125); 176 | glDraw.color(Color.white()); 177 | glDraw.drawCubeStroked(); 178 | glTrans.popMatrix(); 179 | 180 | glDraw.color(color); 181 | }; 182 | 183 | module.exports = CameraAbstract; 184 | -------------------------------------------------------------------------------- /lib/gl/CameraOrtho.js: -------------------------------------------------------------------------------- 1 | var CameraAbstract = require('./CameraAbstract'), 2 | Vec3 = require('../math/Vec3'), 3 | Window_ = require('../app/Window'), 4 | glu = require('./glu'); 5 | 6 | var DEFAULT_NEAR = -10, 7 | DEFAUTL_FAR = 10; 8 | 9 | function CameraOrtho() { 10 | CameraAbstract.call(this); 11 | var aspectRatio = Window_.get().getAspectRatio(); 12 | this.setOrtho(-aspectRatio,aspectRatio,-1,1,DEFAULT_NEAR,DEFAUTL_FAR); 13 | this.setEye(Vec3.one()); 14 | this.updateViewMatrix(); 15 | } 16 | 17 | CameraOrtho.prototype = Object.create(CameraAbstract.prototype); 18 | CameraOrtho.prototype.constructor = CameraOrtho; 19 | 20 | CameraOrtho.prototype.setOrtho = function (left, right, bottom, top, near, far) { 21 | this._frustumLeft = this._frustumLeftInit = left; 22 | this._frustumRight = this._frustumRightInit = right; 23 | this._frustumBottom = this._frustumBottomInit = bottom; 24 | this._frustumTop = this._frustumTopInit = top; 25 | this._near = near; 26 | this._far = far; 27 | this._projectionMatrixDirty = true; 28 | this.updateProjectionMatrix(); 29 | }; 30 | 31 | CameraOrtho.prototype.updateViewMatrix = function () { 32 | if (!this._viewMatrixDirty) { 33 | return; 34 | } 35 | var eye = this._eye, 36 | target = this._target, 37 | up = this._up; 38 | 39 | glu.lookAt(this.viewMatrix.m, eye.x, eye.y, eye.z, target.x, target.y, target.z, up.x, up.y, up.z); 40 | this._updateOnB(); 41 | this._viewMatrixDirty = false; 42 | }; 43 | 44 | CameraOrtho.prototype.updateProjectionMatrix = function () { 45 | if (!this._projectionMatrixDirty) { 46 | return; 47 | } 48 | glu.ortho(this.projectionMatrix.m, this._frustumLeft, this._frustumRight, this._frustumBottom, this._frustumTop, this._near, this._far); 49 | this._projectionMatrixDirty = false; 50 | }; 51 | 52 | CameraOrtho.prototype.setDistance = function (zoom) { 53 | this._frustumLeft = this._frustumLeftInit * zoom; 54 | this._frustumRight = this._frustumRightInit * zoom; 55 | this._frustumBottom = this._frustumBottomInit * zoom; 56 | this._frustumTop = this._frustumTopInit * zoom; 57 | this._projectionMatrixDirty = true; 58 | this.updateProjectionMatrix(); 59 | }; 60 | 61 | module.exports = CameraOrtho; 62 | -------------------------------------------------------------------------------- /lib/gl/CameraPersp.js: -------------------------------------------------------------------------------- 1 | var CameraAbstract = require('./CameraAbstract'), 2 | Window_ = require('../app/Window'), 3 | Vec3 = require('../math/Vec3'), 4 | glu = require('./glu'); 5 | 6 | var DEFAULT_FOV = 60.0, 7 | DEFAULT_NEAR = 0.0001, 8 | DEFAULT_FAR = 10.0; 9 | 10 | function CameraPersp(fov,windowAspectRatio,near,far) { 11 | CameraAbstract.call(this); 12 | 13 | fov = fov === undefined ? DEFAULT_FOV : fov; 14 | windowAspectRatio = windowAspectRatio === undefined ? Window_.get().getAspectRatio() : windowAspectRatio; 15 | near = near === undefined ? DEFAULT_NEAR : near; 16 | far = far === undefined ? DEFAULT_FAR : far; 17 | 18 | this.setPerspective(fov, windowAspectRatio, near, far); 19 | this.setEye(Vec3.one()); 20 | this.updateViewMatrix(); 21 | } 22 | 23 | CameraPersp.prototype = Object.create(CameraAbstract.prototype); 24 | CameraPersp.prototype.constructor = CameraPersp; 25 | 26 | CameraPersp.prototype.setPerspective = function (fov, windowAspectRatio, near, far) { 27 | this._fov = fov; 28 | this._near = near; 29 | this._far = far; 30 | this._aspectRatio = windowAspectRatio; 31 | this._projectionMatrixDirty = true; 32 | this.updateProjectionMatrix(); 33 | }; 34 | 35 | CameraPersp.prototype.setDistance = function(dist){ 36 | this._eye.sub(this._target).normalize().scale(dist); 37 | this._viewMatrixDirty = true; 38 | }; 39 | 40 | CameraPersp.prototype.updateViewMatrix = function () { 41 | if (!this._viewMatrixDirty){ 42 | return; 43 | } 44 | var eye, target, up; 45 | 46 | eye = this._eye; 47 | target = this._target; 48 | up = this._up; 49 | 50 | glu.lookAt(this.viewMatrix.m, eye.x, eye.y, eye.z, target.x, target.y, target.z, up.x, up.y, up.z); 51 | 52 | this._updateOnB(); 53 | this._viewMatrixDirty = false; 54 | }; 55 | 56 | 57 | CameraPersp.prototype.updateProjectionMatrix = function () { 58 | if (!this._projectionMatrixDirty){ 59 | return; 60 | } 61 | var aspectRatio, fov, near, far; 62 | var fov_2; 63 | var frustumTop, frustumRight; 64 | var f, nf, m; 65 | 66 | aspectRatio = this._aspectRatio; 67 | fov = this._fov; 68 | near = this._near; 69 | far = this._far; 70 | 71 | fov_2 = Math.tan(fov * Math.PI / 180 * 0.5); 72 | 73 | frustumTop = this._frustumTop = near * fov_2; 74 | frustumRight = this._frustumRight = frustumTop * aspectRatio; 75 | 76 | this._frustumBottom = frustumTop * -1; 77 | this._frustumLeft = frustumRight * -1; 78 | 79 | f = 1.0 / fov_2; 80 | nf = 1.0 / (near - far); 81 | m = this.projectionMatrix.m; 82 | 83 | m[ 1] = m[ 2] = m[ 3] = m[ 4] = m[ 6] = m[ 7] = m[ 8] = m[ 9] = m[12] = m[13] = m[15] = 0; 84 | 85 | m[ 0] = f / aspectRatio; 86 | m[ 5] = f; 87 | m[10] = (far + near) * nf; 88 | m[11] = -1; 89 | m[14] = (2 * far * near) * nf; 90 | 91 | this._projectionMatrixDirty = false; 92 | }; 93 | 94 | CameraPersp.prototype.setAspectRatio = function (aspectRatio) { 95 | this._aspectRatio = aspectRatio; 96 | this._projectionMatrixDirty = true; 97 | }; 98 | 99 | module.exports = CameraPersp; 100 | 101 | 102 | -------------------------------------------------------------------------------- /lib/gl/DirectionalLight.js: -------------------------------------------------------------------------------- 1 | var Vec3 = require('../math/Vec3'), 2 | Light = require('./Light'); 3 | 4 | function DirectionalLight(id) { 5 | Light.apply(this, arguments); 6 | } 7 | 8 | DirectionalLight.prototype = Object.create(Light.prototype); 9 | 10 | DirectionalLight.prototype.setDirection = function (v) { 11 | this.direction.set(v); 12 | }; 13 | 14 | DirectionalLight.prototype.setDirection3f = function (x, y, z) { 15 | this.direction.setf(x,y,z); 16 | }; 17 | 18 | DirectionalLight.prototype.lookAt = function (position, target) { 19 | this.setEye(position); 20 | this.setDirection(position.subbed(target).normalize()); 21 | }; 22 | 23 | module.exports = DirectionalLight; -------------------------------------------------------------------------------- /lib/gl/Fbo.js: -------------------------------------------------------------------------------- 1 | var _gl = require('./gl'), 2 | _Math = require('../math/Math'), 3 | Vec2 = require('../math/Vec2'), 4 | ObjectUtil = require('../util/ObjectUtil'), 5 | Texture = require('./Texture'); 6 | 7 | /** 8 | * Framebuffer object for offscreen rendering. 9 | * @param {Number} width - The width 10 | * @param {Number} height - The height 11 | * @param {Fbo.Format} [format] - The format 12 | * @constructor 13 | */ 14 | 15 | function Fbo(width,height,format){ 16 | this._format = format = format === undefined ? new Fbo.Format() : format.copy(); 17 | this._width = width; 18 | this._height = height; 19 | 20 | var gl = this._gl = _gl.get(); 21 | var pot = _Math.isPOT(width) && _Math.isPOT(height); 22 | 23 | if(!pot && (format.wrapS == gl.REPEAT || format.wrapT == gl.REPEAT)){ 24 | throw new Error('TEXTURE: Texture size must be power of 2 if wrapmode REPEAT is used.'); 25 | } 26 | if(pot && format.mipmapping){ 27 | throw new Error('TEXTURE: Texture size must be power of 2 when generating mipmap.'); 28 | } 29 | 30 | this._renderBuffer = gl.createRenderbuffer(); 31 | this._frameBuffer = gl.createFramebuffer(); 32 | this._texture = gl.createTexture(); 33 | this._textureUnit = 0; 34 | 35 | var prevTex = gl.getParameter(gl.TEXTURE_BINDING_2D); 36 | 37 | gl.bindTexture(gl.TEXTURE_2D, this._texture); 38 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, format.magFilter); 39 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, format.minFilter); 40 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, format.wrapS); 41 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, format.wrapT); 42 | if(format.mipmapping){ 43 | gl.generateMipmap(gl.TEXTURE_2D); 44 | } 45 | gl.bindTexture(gl.TEXTURE_2D,prevTex); 46 | 47 | this.resizef(width,height); 48 | } 49 | 50 | /** 51 | * Format for fbo. 52 | * @constructor 53 | */ 54 | 55 | Fbo.Format = function(){ 56 | Texture.Format.call(this); 57 | 58 | this.dataFormat = _gl.get().RGBA; 59 | this.depthBuffer = false; 60 | this.stencilBuffer = false; 61 | //this.numColorBuffers = 1; 62 | }; 63 | 64 | Fbo.Format.prototype = Object.create(Texture.Format); 65 | Fbo.Format.prototype.constructor = Fbo.Format; 66 | 67 | /** 68 | * Returns a copy of the format. 69 | * @param {Fbo.Format} [format] - Out format 70 | * @returns {Fbo.Format} 71 | */ 72 | 73 | Fbo.Format.prototype.copy = function(format){ 74 | format = format || new Fbo.Format(); 75 | format.wrapS = this.wrapS; 76 | format.wrapT = this.wrapT; 77 | format.minFilter = this.minFilter; 78 | format.magFilter = this.magFilter; 79 | format.mipmapping = this.mipmapping; 80 | format.dataFormatInternal = this.dataFormatInternal; 81 | format.dataFormat = this.dataFormat; 82 | format.dataType = this.dataType; 83 | format.depthBuffer = this.depthBuffer; 84 | format.stencilBuffer = this.stencilBuffer; 85 | return format; 86 | }; 87 | 88 | /** 89 | * Resizes the fbo. Clears buffered content. 90 | * @param width 91 | * @param height 92 | * @returns {Fbo} 93 | */ 94 | 95 | Fbo.prototype.resizef = function(width,height){ 96 | var gl = this._gl, format = this._format; 97 | var prevTex = gl.getParameter(gl.TEXTURE_BINDING_2D), 98 | prevRbo = gl.getParameter(gl.RENDERBUFFER_BINDING), 99 | prevFbo = gl.getParameter(gl.FRAMEBUFFER_BINDING); 100 | 101 | var renderBuffer = this._renderBuffer, 102 | texture = this._texture; 103 | 104 | 105 | gl.bindFramebuffer(gl.FRAMEBUFFER,this._frameBuffer); 106 | 107 | gl.bindTexture(gl.TEXTURE_2D, this._texture); 108 | gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height,0, format.dataFormat, format.dataType, null); 109 | gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0); 110 | 111 | gl.bindRenderbuffer(gl.RENDERBUFFER, renderBuffer); 112 | gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, width, height); 113 | gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, renderBuffer); 114 | 115 | gl.bindTexture(gl.TEXTURE_2D, prevTex); 116 | gl.bindRenderbuffer(gl.RENDERBUFFER, prevRbo); 117 | gl.bindFramebuffer(gl.FRAMEBUFFER,prevFbo); 118 | 119 | this._width = width; 120 | this._height = height; 121 | 122 | return this; 123 | }; 124 | 125 | /** 126 | * Resizes the fbo. Clears buffered content. 127 | * @param size 128 | * @returns {Fbo} 129 | */ 130 | 131 | Fbo.prototype.resize = function (size) { 132 | return this.resizef(size.x,size.y); 133 | }; 134 | 135 | /** 136 | * Returns the width of the fbo. 137 | * @returns {Number} 138 | */ 139 | 140 | Fbo.prototype.getWidth = function(){ 141 | return this._width; 142 | }; 143 | 144 | /** 145 | * Returns the height of the fbo. 146 | * @returns {Number} 147 | */ 148 | 149 | Fbo.prototype.getHeight = function(){ 150 | return this._height; 151 | }; 152 | 153 | /** 154 | * Returns the size of the fbo. 155 | * @param {Vec2} [v] - Out size 156 | * @returns {Vec2} 157 | */ 158 | 159 | Fbo.prototype.getSize = function(v){ 160 | return (v || new Vec2()).setf(this._width,this._height); 161 | }; 162 | 163 | /** 164 | * Binds the fbo. 165 | * @returns {Fbo} 166 | */ 167 | 168 | Fbo.prototype.bind = function(){ 169 | var gl = this._gl; 170 | gl.bindFramebuffer(gl.FRAMEBUFFER, this._frameBuffer); 171 | return this; 172 | }; 173 | 174 | /** 175 | * Unbinds the fbo. 176 | * @returns {Fbo} 177 | */ 178 | 179 | Fbo.prototype.unbind = function(){ 180 | var gl = this._gl; 181 | gl.bindFramebuffer(gl.FRAMEBUFFER, null); 182 | return this; 183 | }; 184 | 185 | /** 186 | * Binds the texture rendered to. 187 | * @param {Number} [unit] - The texture unit 188 | * @returns {Fbo} 189 | */ 190 | 191 | Fbo.prototype.bindTexture = function(unit){ 192 | var gl = this._gl; 193 | if(!ObjectUtil.isUndefined(unit)){ 194 | this._textureUnit = unit; 195 | gl.activeTexture(gl.TEXTURE0 + unit); 196 | } 197 | gl.bindTexture(gl.TEXTURE_2D, this._texture); 198 | return this; 199 | }; 200 | 201 | /** 202 | * Unbinds the texture rendered to. 203 | * @param {Number} [unit] - The texture unit 204 | * @returns {Fbo} 205 | */ 206 | 207 | Fbo.prototype.unbindTexture = function(unit){ 208 | var gl = this._gl; 209 | if(!ObjectUtil.isUndefined(unit)){ 210 | gl.activeTexture(gl.TEXTURE0 + unit); 211 | } else { 212 | gl.activeTexture(gl.TEXTURE0 + this._textureUnit); 213 | } 214 | gl.bindTexture(gl.TEXTURE_2D, null); 215 | return this; 216 | }; 217 | 218 | /** 219 | * Returns the texture´s unit. 220 | * @returns {number} 221 | */ 222 | 223 | Fbo.prototype.getTextureUnit = function(){ 224 | return this._textureUnit; 225 | }; 226 | 227 | /** 228 | * Deletes the fbo. 229 | * @returns {Fbo} 230 | */ 231 | 232 | Fbo.prototype.dispose = function(){ 233 | var gl = this._gl; 234 | gl.deleteTexture(this._texture); 235 | gl.deleteFramebuffer(this._frameBuffer); 236 | gl.deleteRenderbuffer(this._renderBuffer); 237 | return this; 238 | }; 239 | 240 | 241 | module.exports = Fbo; -------------------------------------------------------------------------------- /lib/gl/Frustum.js: -------------------------------------------------------------------------------- 1 | var Vec3 = require('../math/Vec3'); 2 | var AABB = require('../geom/AABB'); 3 | var Plane = require('../geom/Plane'); 4 | var glDraw, _glDraw = require('./glDraw'); 5 | 6 | 7 | function Frustum(){ 8 | this._vec3Temp = new Vec3(); 9 | this._frustumCamera = new Array(6); 10 | var frustumTemp = this._frustumTemp = new Array(6); 11 | var planes = this._planes = new Array(6); 12 | 13 | var i = -1, l = 6; 14 | while(++i < l){ 15 | planes[i] = new Plane(); 16 | frustumTemp[i] = new Vec3(); 17 | } 18 | 19 | this._eye = new Vec3(); 20 | 21 | var near = this._near = new Array(4), 22 | far = this._far = new Array(4); 23 | 24 | i = -1; l = 4; 25 | while(++i < l){ 26 | near[i] = new Vec3(); 27 | far[i] = new Vec3(); 28 | } 29 | 30 | glDraw = glDraw || _glDraw.get(); 31 | } 32 | 33 | Frustum.prototype.draw = function(){ 34 | var n = this._near, 35 | n0 = n[0], 36 | n1 = n[1], 37 | n2 = n[2], 38 | n3 = n[3]; 39 | var f = this._far, 40 | f0 = f[0], 41 | f1 = f[1], 42 | f2 = f[2], 43 | f3 = f[3]; 44 | 45 | var prevColor = glDraw.getColor(); 46 | 47 | glDraw.colorf(0,1,0,1); 48 | glDraw.drawLines(n0,n1,n1,n2,n2,n3,n3,n0, 49 | n0,f0,n1,f1,n2,f2,n3,f3, 50 | f0,f1,f1,f2,f2,f3,f3,f0); 51 | glDraw.color(prevColor); 52 | }; 53 | 54 | Frustum.prototype.getNearPlane = function(){ 55 | return this._near; 56 | }; 57 | 58 | Frustum.prototype.getFarPlane =function(){ 59 | return this._far; 60 | }; 61 | 62 | Frustum.prototype.containsPoint = function(point){ 63 | return this.containsPoint3f(point.x,point.y,point.z); 64 | }; 65 | 66 | Frustum.prototype.containsPoint3f = function(x,y,z){ 67 | var planes = this._planes; 68 | var i = -1; 69 | while(++i < 6){ 70 | if(planes[i].distanceSigned3f(x,y,z) < 0){ 71 | return false; 72 | } 73 | } 74 | return true; 75 | }; 76 | 77 | //test n / p point 78 | 79 | Frustum.prototype.containsAABB = function(aabb){ 80 | var planes = this._planes; 81 | var center = aabb.center; 82 | var x, y, z; 83 | var count = 0; 84 | 85 | x = center.x; 86 | y = center.y; 87 | z = center.z; 88 | 89 | // first check center 90 | var i = -1; 91 | while(++i < 6){ 92 | if(planes[i].distanceSigned3f(x,y,z) < 0){ 93 | break; 94 | } 95 | count++; 96 | } 97 | if(count == 6){ 98 | return true; 99 | } 100 | 101 | var plane; 102 | var pointTemp = this._vec3Temp; 103 | var near,far; 104 | 105 | // check nearest / farthest 106 | i = -1; 107 | while(++i < 6){ 108 | plane = planes[i]; 109 | near = plane.distanceSigned(aabb.getPPoint(plane.normal,pointTemp)) > 0; 110 | far = plane.distanceSigned(aabb.getNPoint(plane.normal,pointTemp)) > 0; 111 | 112 | if(!near && !far){ 113 | return false; 114 | } 115 | } 116 | return true; 117 | }; 118 | 119 | module.exports = Frustum; -------------------------------------------------------------------------------- /lib/gl/FrustumOrtho.js: -------------------------------------------------------------------------------- 1 | var Frustum = require('./Frustum'); 2 | var Vec3 = require('../math/Vec3'); 3 | 4 | function FrustumOrtho(){ 5 | Frustum.call(this); 6 | } 7 | 8 | FrustumOrtho.prototype = Object.create(Frustum.prototype); 9 | FrustumOrtho.prototype.constructor = FrustumOrtho; 10 | 11 | FrustumOrtho.prototype.set = function(camera, frustumScale){ 12 | frustumScale = frustumScale || 1.0; 13 | 14 | var eye = camera.getEye(this._eye); 15 | var frustum = camera.getFrustum(this._frustumCamera); 16 | 17 | var frustumLeft = frustum[2], 18 | frustumTop = frustum[1], 19 | frustumRight = frustum[0], 20 | frustumBottom = frustum[3], 21 | frustumNear = frustum[4] * frustumScale, 22 | frustumFar = frustum[5] * frustumScale; 23 | 24 | var frustumTemp = this._frustumTemp, 25 | vec3Temp = this._vec3Temp; 26 | 27 | var w = camera.getW(vec3Temp), 28 | frustumNearDir = w.scaled(frustumNear,frustumTemp[0]), 29 | frustumFarDir = w.scaled(frustumFar,frustumTemp[1]); 30 | 31 | var v = camera.getV(vec3Temp), 32 | frustumTopV = v.scaled(frustumTop,frustumTemp[2]), 33 | frustumBottomV = v.scaled(frustumBottom,frustumTemp[3]); 34 | 35 | var u = camera.getU(vec3Temp), 36 | frustumLeftU = u.scaled(frustumLeft,frustumTemp[4]), 37 | frustumRightU = u.scaled(frustumRight,frustumTemp[5]); 38 | 39 | var n = this._near, f = this._far; 40 | var fb = eye.added(frustumFarDir), 41 | nb = eye.added(frustumNearDir); 42 | 43 | var ftl = f[0], 44 | ftr = f[1], 45 | fbr = f[2], 46 | fbl = f[3]; 47 | var ntl = n[0], 48 | ntr = n[1], 49 | nbr = n[2], 50 | nbl = n[3]; 51 | 52 | ftl.set(fb).add(frustumTopV).add(frustumLeftU); 53 | ftr.set(fb).add(frustumTopV).add(frustumRightU); 54 | fbr.set(fb).add(frustumBottomV).add(frustumRightU); 55 | fbl.set(fb).add(frustumBottomV).add(frustumLeftU); 56 | 57 | ntl.set(nb).add(frustumTopV).add(frustumLeftU); 58 | ntr.set(nb).add(frustumTopV).add(frustumRightU); 59 | nbr.set(nb).add(frustumBottomV).add(frustumRightU); 60 | nbl.set(nb).add(frustumBottomV).add(frustumLeftU); 61 | 62 | 63 | /* 64 | this._calcPlane(0,ntr,ntl,ftl); 65 | this._calcPlane(1,nbl,nbr,fbr); 66 | this._calcPlane(2,ntl,nbl,fbl); 67 | this._calcPlane(3,ftr,fbr,nbr); 68 | this._calcPlane(4,ntl,ntr,nbr); 69 | this._calcPlane(5,ftr,ftl,fbl);*/ 70 | 71 | var planes = this._planes; 72 | planes[0].setFromPoints(ntr,ntl,ftl); 73 | planes[1].setFromPoints(nbl,nbr,fbr); 74 | planes[2].setFromPoints(ntl,nbl,fbl); 75 | planes[3].setFromPoints(ftr,fbr,nbr); 76 | planes[4].setFromPoints(ntl,ntr,nbr); 77 | planes[5].setFromPoints(ftr,ftl,fbl); 78 | }; 79 | 80 | 81 | 82 | module.exports = FrustumOrtho; -------------------------------------------------------------------------------- /lib/gl/FrustumPersp.js: -------------------------------------------------------------------------------- 1 | var Frustum = require('./Frustum'); 2 | var Vec3 = require('../math/Vec3'); 3 | 4 | function FrustumPersp() { 5 | Frustum.call(this); 6 | } 7 | 8 | FrustumPersp.prototype = Object.create(Frustum.prototype); 9 | FrustumPersp.prototype.constructor = FrustumPersp; 10 | 11 | FrustumPersp.prototype.set = function(camera, frustumScale){ 12 | frustumScale = frustumScale || 1.0; 13 | 14 | var eye = camera.getEye(this._eye); 15 | var frustum = camera.getFrustum(this._frustumCamera); 16 | 17 | var frustumLeft = frustum[2] * frustumScale, 18 | frustumTop = frustum[1] * frustumScale, 19 | frustumRight = frustum[0] * frustumScale, 20 | frustumBottom = frustum[3] * frustumScale, 21 | frustumNear = frustum[4] * frustumScale, 22 | frustumFar = frustum[5] * frustumScale; 23 | 24 | var n = this._near, 25 | f = this._far; 26 | 27 | var ntl = n[0], 28 | ntr = n[1], 29 | nbr = n[2], 30 | nbl = n[3]; 31 | var ftl = f[0], 32 | ftr = f[1], 33 | fbr = f[2], 34 | fbl = f[3]; 35 | 36 | var u = camera.getU(), 37 | v = camera.getV(), 38 | w = camera.getW(); 39 | 40 | var frustumNearW = w.scaled(frustumNear), 41 | frustumFarW = w.scale(frustumFar), 42 | frustumTopV = v.scaled(frustumTop), 43 | frustumBottomV = v.scaled(frustumBottom), 44 | frustumLeftU = u.scaled(frustumLeft), 45 | frustumRightU = u.scaled(frustumRight); 46 | 47 | ntl.set(eye).add(frustumNearW).add(frustumTopV).add(frustumLeftU); 48 | ntr.set(eye).add(frustumNearW).add(frustumTopV).add(frustumRightU); 49 | nbr.set(eye).add(frustumNearW).add(frustumBottomV).add(frustumRightU); 50 | nbl.set(eye).add(frustumNearW).add(frustumBottomV).add(frustumLeftU); 51 | 52 | var ratio = frustumFar / frustumNear; 53 | 54 | frustumTopV.scale(ratio); 55 | frustumBottomV.scale(ratio); 56 | frustumLeftU.scale(ratio); 57 | frustumRightU.scale(ratio); 58 | 59 | ftl.set(eye).add(frustumFarW).add(frustumTopV).add(frustumLeftU); 60 | ftr.set(eye).add(frustumFarW).add(frustumTopV).add(frustumRightU); 61 | fbr.set(eye).add(frustumFarW).add(frustumBottomV).add(frustumRightU); 62 | fbl.set(eye).add(frustumFarW).add(frustumBottomV).add(frustumLeftU); 63 | /* 64 | this._calcPlane(0,ntr,ntl,ftl); 65 | this._calcPlane(1,nbl,nbr,fbr); 66 | this._calcPlane(2,ntl,nbl,fbl); 67 | this._calcPlane(3,ftr,fbr,nbr); 68 | this._calcPlane(4,ntl,ntr,nbr); 69 | this._calcPlane(5,ftr,ftl,fbl);*/ 70 | var planes = this._planes; 71 | planes[0].setFromPoints(ntr,ntl,ftl); 72 | planes[1].setFromPoints(nbl,nbr,fbr); 73 | planes[2].setFromPoints(ntl,nbl,fbl); 74 | planes[3].setFromPoints(ftr,fbr,nbr); 75 | planes[4].setFromPoints(ntl,ntr,nbr); 76 | planes[5].setFromPoints(ftr,ftl,fbl); 77 | }; 78 | 79 | 80 | module.exports = FrustumPersp; -------------------------------------------------------------------------------- /lib/gl/Material.js: -------------------------------------------------------------------------------- 1 | var _gl = require('./gl'), 2 | Color = require('../util/Color'), 3 | Program = require('./Program'); 4 | 5 | function Material(ambient, diffuse, specular, shininess, emission) { 6 | ambient = ambient || Color.black(); 7 | diffuse = diffuse || new Color(0.25,0.25,0.25); 8 | specular = specular || Color.white(); 9 | shininess = shininess || 5.0; 10 | emission = emission || Color.black(); 11 | 12 | this._gl = _gl.get(); 13 | 14 | this._enabled = true; 15 | 16 | this.emission = emission; 17 | this.ambient = ambient; 18 | this.diffuse = diffuse; 19 | this.specular = specular; 20 | this.shininess = shininess; 21 | 22 | this._tempF32 = new Float32Array(4); 23 | 24 | this._uniformLocationEmission = 25 | this._uniformLocationAmbient = 26 | this._uniformLocationDiffuse = 27 | this._uniformLocationSpecular = 28 | this._uniformLocationShininess = null; 29 | 30 | this._programIdLast = null; 31 | } 32 | 33 | Material.prototype.enable = function(){ 34 | this._enabled = true; 35 | }; 36 | 37 | Material.prototype.disable = function(){ 38 | this._enabled = false; 39 | }; 40 | 41 | Material.prototype.apply = function(){ 42 | if(!this._enabled){ 43 | return; 44 | } 45 | var gl = this._gl; 46 | 47 | if(Program.getCurrent().getId() != this._programIdLast){ 48 | var program = Program.getCurrent(); 49 | this._uniformLocationEmission = program.getUniformLocation(Program.UNIFORM_MATERIAL_STRUCT + '.' + Program.UNIFORM_MATERIAL_STRUCT_EMISSION); 50 | this._uniformLocationAmbient = program.getUniformLocation(Program.UNIFORM_MATERIAL_STRUCT + '.' + Program.UNIFORM_MATERIAL_STRUCT_AMBIENT); 51 | this._uniformLocationDiffuse = program.getUniformLocation(Program.UNIFORM_MATERIAL_STRUCT + '.' + Program.UNIFORM_MATERIAL_STRUCT_DIFFUSE); 52 | this._uniformLocationSpecular = program.getUniformLocation(Program.UNIFORM_MATERIAL_STRUCT + '.' + Program.UNIFORM_MATERIAL_STRUCT_SPECULAR); 53 | this._uniformLocationShininess= program.getUniformLocation(Program.UNIFORM_MATERIAL_STRUCT + '.' + Program.UNIFORM_MATERIAL_STRUCT_SHININESS); 54 | this._programIdLast = program.getId(); 55 | } 56 | 57 | var uniformLocationEmission = this._uniformLocationEmission, 58 | uniformLocationAmbient = this._uniformLocationAmbient, 59 | uniformLocationDiffuse = this._uniformLocationDiffuse, 60 | uniformLocationSpecular = this._uniformLocationSpecular, 61 | uniformLocationShininess= this._uniformLocationShininess; 62 | 63 | var emission = this.emission, 64 | ambient = this.ambient, 65 | diffuse = this.diffuse, 66 | specular = this.specular; 67 | 68 | var tempF32 = this._tempF32; 69 | 70 | 71 | if(uniformLocationEmission != -1){ 72 | tempF32[0] = emission.r; 73 | tempF32[1] = emission.g; 74 | tempF32[2] = emission.b; 75 | tempF32[3] = emission.a; 76 | gl.uniform4fv(this._uniformLocationEmission, tempF32); 77 | } 78 | 79 | 80 | if(uniformLocationAmbient != -1){ 81 | tempF32[0] = ambient.r; 82 | tempF32[1] = ambient.g; 83 | tempF32[2] = ambient.b; 84 | tempF32[3] = ambient.a; 85 | gl.uniform4fv(this._uniformLocationAmbient, tempF32); 86 | } 87 | 88 | if(uniformLocationDiffuse != -1){ 89 | tempF32[0] = diffuse.r; 90 | tempF32[1] = diffuse.g; 91 | tempF32[2] = diffuse.b; 92 | tempF32[3] = diffuse.a; 93 | gl.uniform4fv(this._uniformLocationDiffuse, tempF32); 94 | } 95 | 96 | if(uniformLocationSpecular != -1){ 97 | tempF32[0] = specular.r; 98 | tempF32[1] = specular.g; 99 | tempF32[2] = specular.b; 100 | tempF32[3] = specular.a; 101 | gl.uniform4fv(this._uniformLocationSpecular, tempF32); 102 | } 103 | 104 | if(uniformLocationShininess != -1){ 105 | gl.uniform1f(this._uniformLocationShininess, this.shininess); 106 | } 107 | } 108 | 109 | module.exports = Material; 110 | -------------------------------------------------------------------------------- /lib/gl/MeshPrimitive.js: -------------------------------------------------------------------------------- 1 | var Mesh = require('./Mesh'), 2 | PrimitiveScheme = require('./PrimitiveScheme'), 3 | ObjectUtil = require('../util/ObjectUtil'), 4 | _gl = require('./gl'); 5 | 6 | function Plane(numH,numV,format){ 7 | var data = PrimitiveScheme.Plane.create(numH,numV); 8 | Mesh.apply(this,[format]); 9 | 10 | this.setVertices(data.vertices); 11 | this.setNormals(data.normals); 12 | this.setColors(data.colors); 13 | this.setTexcoords(data.texcoords); 14 | 15 | if(data.indices){ 16 | this.setIndices(data.indices); 17 | } 18 | } 19 | 20 | Plane.prototype = Object.create(Mesh.prototype); 21 | Plane.prototype.constructor = Plane; 22 | 23 | Plane.prototype.setSubDivisions = function(numH,numV){ 24 | var data = PrimitiveScheme.Plane.create(numH,numV); 25 | this.setVertices(data.vertices); 26 | this.setNormals(data.normals); 27 | this.setColors(data.colors); 28 | this.setTexcoords(data.texcoords); 29 | 30 | if(data.indices){ 31 | this.setIndices(data.indices); 32 | } 33 | }; 34 | 35 | 36 | function Cube(){ 37 | Mesh.apply(this,[new Mesh.Format(),24]); 38 | var scheme = PrimitiveScheme.Cube; 39 | this.setVertices(scheme.vertices); 40 | this.setNormals(scheme.normals); 41 | this.setTexcoords(scheme.texcoords); 42 | this.setColors(scheme.colors); 43 | 44 | this.indices = new Uint16Array(scheme.indices); 45 | } 46 | 47 | Cube.prototype = Object.create(Mesh.prototype); 48 | Cube.prototype.constructor = Cube; 49 | 50 | function Disk(numSegments,radiusX,radiusY){ 51 | var scheme = PrimitiveScheme.Disk.create(numSegments,radiusX,radiusY); 52 | Mesh.apply(this); 53 | this.setVertices(scheme.vertices); 54 | this.setNormals(scheme.normals); 55 | this.setColors(scheme.colors); 56 | this.setTexcoords(scheme.texcoords); 57 | } 58 | 59 | Disk.prototype = Object.create(Mesh.prototype); 60 | Disk.prototype.constructor = Disk; 61 | 62 | var MeshPrimitive = { 63 | Plane : Plane, 64 | Cube : Cube, 65 | Disk : Disk 66 | }; 67 | 68 | module.exports = MeshPrimitive; -------------------------------------------------------------------------------- /lib/gl/PointLight.js: -------------------------------------------------------------------------------- 1 | var Light = require('./Light'); 2 | 3 | function PointLight(id) { 4 | Light.apply(this, arguments); 5 | } 6 | 7 | PointLight.prototype = Object.create(Light.prototype); 8 | PointLight.prototype.constructor = PointLight; 9 | 10 | module.exports = PointLight; -------------------------------------------------------------------------------- /lib/gl/PrimitiveScheme.js: -------------------------------------------------------------------------------- 1 | var PrimitiveScheme = {}; 2 | 3 | PrimitiveScheme.Disk = { 4 | create : function(numSegments,radiusX,radiusY){ 5 | numSegments = numSegments === undefined ? 20 : numSegments; 6 | radiusX = radiusX === undefined ? 1.0 : radiusX; 7 | radiusY = radiusY === undefined ? 1.0 : radiusY; 8 | 9 | numSegments += 1; 10 | var vertices = [], 11 | normals = [], 12 | colors = [], 13 | texcoords = []; 14 | 15 | var norm = Math.max(radiusX,radiusY); 16 | var radiusXNorm = radiusX / norm, 17 | radiusYNorm = radiusY / norm; 18 | 19 | vertices.push(0,0,0); 20 | normals.push(0,1,0); 21 | colors.push(0,1,0,1); 22 | texcoords.push(0.5,0.5); 23 | 24 | var i = -1; 25 | var step = Math.PI * 2 / (numSegments-1),j; 26 | var x,y; 27 | while(++i < numSegments){ 28 | j = i * step; 29 | x = Math.cos(j) * radiusXNorm; 30 | y = Math.sin(j) * radiusYNorm; 31 | vertices.push(x * norm ,0,y * norm); 32 | normals.push(0,1,0); 33 | colors.push(0,1,0,1); 34 | texcoords.push(0.5 + x * 0.5,0.5 + y * 0.5); 35 | } 36 | 37 | return { 38 | vertices : vertices, 39 | normals : normals, 40 | colors : colors, 41 | texcoords : texcoords 42 | }; 43 | } 44 | }; 45 | 46 | 47 | PrimitiveScheme.Plane = { 48 | create : function(numH,numV){ 49 | var numH_1 = numH - 1, 50 | numV_1 = numV - 1; 51 | var _numH_1 = 1.0 / numH_1, 52 | _numV_1 = 1.0 / numV_1; 53 | var num = numH * numV; 54 | 55 | var vertices = [], 56 | normals = [], 57 | colors = [], 58 | texcoords = [], 59 | indices = null; 60 | 61 | var i, j; 62 | var x, y, z; 63 | i = -1; 64 | while(++i < numV){ 65 | j = -1; 66 | x = i * _numV_1; 67 | while(++j < numH){ 68 | y = 0.0; 69 | z = j * _numH_1; 70 | 71 | vertices.push(x,y,z); 72 | normals.push(0,1,0); 73 | colors.push(1,1,1,1); 74 | texcoords.push(x,z); 75 | } 76 | } 77 | 78 | if(num > 4){ 79 | indices = []; 80 | var a, b, c, d; 81 | i = -1; 82 | while(++i < numV_1){ 83 | j = -1; 84 | while(++j < numH_1){ 85 | a = i * numH + j; 86 | b = a + 1; 87 | c = (i + 1) * numH + j; 88 | d = c + 1; 89 | 90 | indices.push(c,b,a,c,d,b); 91 | } 92 | } 93 | } 94 | 95 | return { 96 | vertices : vertices, 97 | normals : normals, 98 | colors : colors, 99 | texcoords : texcoords, 100 | indices : indices 101 | }; 102 | } 103 | }; 104 | 105 | PrimitiveScheme.Cube = { 106 | vertices : [ 107 | -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, //front 108 | -0.5, -0.5, -0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5, 0.5, -0.5, -0.5, //back 109 | -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, -0.5, //top 110 | -0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, -0.5, 0.5, -0.5, -0.5, 0.5, //bottom 111 | 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, //right 112 | -0.5, -0.5, -0.5, -0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5, 0.5, -0.5 //left 113 | ], 114 | 115 | normals : [ 116 | 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 117 | 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 118 | 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 119 | 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 120 | 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 121 | -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0 122 | ], 123 | 124 | colors : [ 125 | 0, 0.5, 0, 1, 0, 0.5, 0, 1, 0, 0.5, 0, 1, 0, 0.5, 0, 1, 126 | 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 127 | 0.5, 0, 0, 1, 0.5, 0, 0, 1, 0.5, 0, 0, 1, 0.5, 0, 0, 1, 128 | 0, 0, 0.5, 1,0, 0, 0.5, 1,0, 0, 0.5, 1, 0, 0, 0.5, 1, 129 | 0, 0, 1, 1,0, 0, 1, 1,0, 0, 1, 1,0, 0, 1, 1, 130 | 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1 131 | ], 132 | 133 | texcoords : [ 134 | 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 135 | 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 136 | 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 137 | 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 138 | 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 139 | 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0 140 | ], 141 | 142 | indices : [ 143 | 0, 1, 2, 0, 2, 3, 144 | 4, 5, 6, 4, 6, 7, 145 | 8, 9, 10, 8, 10, 11, 146 | 12, 13, 14, 12, 14, 15, 147 | 16, 17, 18, 16, 18, 19, 148 | 20, 21, 22, 20, 22, 23 149 | ] 150 | }; 151 | 152 | 153 | module.exports = PrimitiveScheme; -------------------------------------------------------------------------------- /lib/gl/ProgramPreset.js: -------------------------------------------------------------------------------- 1 | var ProgramPreset = {}; 2 | 3 | ProgramPreset.Basic2d = 4 | "#ifdef VERTEX_SHADER\n" + 5 | "precision highp float;\n" + 6 | "\n" + 7 | "attribute vec3 aVertexPosition;\n" + 8 | "attribute vec4 aVertexColor;\n" + 9 | "attribute vec2 aTexcoord;\n" + 10 | "\n" + 11 | "varying vec4 vVertexColor;\n" + 12 | "varying vec2 vTexcoord;\n" + 13 | "\n" + 14 | "uniform mat4 uProjectionMatrix;\n" + 15 | "uniform mat4 uModelViewMatrix;\n" + 16 | "\n" + 17 | "uniform float uPointSize;\n" + 18 | "\n" + 19 | "void main(){\n" + 20 | " vVertexColor = aVertexColor;\n" + 21 | " vTexcoord = aTexcoord;\n" + 22 | "\n" + 23 | " gl_Position = uProjectionMatrix * uModelViewMatrix * vec4(aVertexPosition,1.0);\n" + 24 | " gl_PointSize = uPointSize;\n" + 25 | "}\n" + 26 | "#endif\n" + 27 | "\n" + 28 | "\n" + 29 | "#ifdef FRAGMENT_SHADER\n" + 30 | "precision highp float;\n" + 31 | "\n" + 32 | "uniform sampler2D uTexture;\n" + 33 | "\n" + 34 | "varying vec4 vVertexColor;\n" + 35 | "varying vec2 vTexcoord;\n" + 36 | "\n" + 37 | "uniform float uUseTexture;\n" + 38 | "\n" + 39 | "uniform vec4 uColor;\n" + 40 | "uniform float uUseUniformColor;\n" + 41 | "\n" + 42 | "void main(){\n" + 43 | " gl_FragColor = (vVertexColor * (1.0 - uUseUniformColor) + uColor * uUseUniformColor) * (1.0 - uUseTexture) + texture2D(uTexture,vTexcoord) * uUseTexture;\n" + 44 | "}\n" + 45 | "#endif"; 46 | 47 | ProgramPreset.Basic3d = 48 | "#ifdef VERTEX_SHADER\n" + 49 | "precision highp float;\n" + 50 | "\n" + 51 | "attribute vec3 aVertexPosition;\n" + 52 | "attribute vec4 aVertexColor;\n" + 53 | "varying vec4 vVertexColor;\n" + 54 | "\n" + 55 | "uniform mat4 uModelViewMatrix;\n" + 56 | "uniform mat4 uProjectionMatrix;\n" + 57 | "\n" + 58 | "uniform float uPointSize;\n" + 59 | "\n" + 60 | "void main(){\n" + 61 | " vVertexColor = aVertexColor;\n" + 62 | " gl_Position = uProjectionMatrix * uModelViewMatrix * vec4(aVertexPosition, 1.0);\n" + 63 | " gl_PointSize = uPointSize;\n" + 64 | "}\n" + 65 | "#endif\n" + 66 | "\n" + 67 | "#ifdef FRAGMENT_SHADER\n" + 68 | "precision highp float;\n" + 69 | "varying vec4 vVertexColor;\n" + 70 | "\n" + 71 | "void main(){\n" + 72 | " gl_FragColor = vVertexColor;\n" + 73 | "}\n" + 74 | "#endif"; 75 | 76 | module.exports = ProgramPreset; -------------------------------------------------------------------------------- /lib/gl/SpotLight.js: -------------------------------------------------------------------------------- 1 | var DirectionalLight = require('./DirectionalLight'); 2 | 3 | function SpotLight(id) { 4 | DirectionalLight.apply(this, arguments); 5 | } 6 | 7 | SpotLight.prototype = Object.create(DirectionalLight.prototype); 8 | SpotLight.prototype.constructor = SpotLight; 9 | 10 | SpotLight.prototype.setExponent = function () { 11 | }; 12 | SpotLight.prototype.setCutOff = function () { 13 | }; 14 | 15 | module.exports = SpotLight; -------------------------------------------------------------------------------- /lib/gl/Vbo.js: -------------------------------------------------------------------------------- 1 | var ObjectUtil = require('../util/ObjectUtil'), 2 | _gl = require('./gl'); 3 | 4 | 5 | var current = null, last = null; 6 | 7 | /** 8 | * Buffer object representation 9 | * @param {Number} [target=gl.ARRAY_BUFFER] - Target buffer, gl.ARRAY_BUFFER, gl.ELEMENT_ARRAY_BUFFER 10 | * @param {Number|ArrayBufferView} [sizeOrData=null] - Size or data 11 | * @param {Number} [usage=gl.STATIC_DRAW] - gl.STREAM_DRAW, gl.STATIC_DRAW, gl.DYNAMIC_DRAW 12 | * @constructor 13 | */ 14 | 15 | function Vbo(target,sizeOrData,usage){ 16 | var gl = this._gl = _gl.get(); 17 | 18 | this._obj = gl.createBuffer(); 19 | this._target = target || gl.ARRAY_BUFFER; 20 | this._size = 0; 21 | 22 | if(!ObjectUtil.isUndefined(sizeOrData) && sizeOrData != 0){ 23 | this.bind(); 24 | gl.bufferData(target,sizeOrData,usage || gl.STATIC_DRAW); 25 | this._size = ObjectUtil.isUndefined(sizeOrData.byteLength) ? sizeOrData : sizeOrData.byteLength; 26 | this.unbind(); 27 | } 28 | } 29 | 30 | /** 31 | * Binds the buffer. 32 | * @returns {Vbo} 33 | */ 34 | 35 | Vbo.prototype.bind = function(){ 36 | //last = current; 37 | //if(last != this){ 38 | // this._obj ? this._gl.bindBuffer(this._target,this._obj) : console.warn('Binding deleted buffer.'); 39 | //} 40 | //current = this; 41 | this._gl.bindBuffer(this._target,this._obj); 42 | return this; 43 | }; 44 | 45 | /** 46 | * Unbinds the buffer. 47 | * @returns {Vbo} 48 | */ 49 | 50 | Vbo.prototype.unbind = function(){ 51 | //if(last != this){ 52 | // this._gl.bindBuffer(this._target,last ? last._obj ? last._obj : null : null); 53 | //} 54 | this._gl.bindBuffer(this._target,null); 55 | return this; 56 | }; 57 | 58 | /** 59 | * Deletes the buffer. 60 | */ 61 | 62 | Vbo.prototype.dispose = function(){ 63 | if(!this._obj){ 64 | return; 65 | } 66 | this._gl.deleteBuffer(this._obj); 67 | this._obj = null; 68 | }; 69 | 70 | 71 | /** 72 | * Modifies or sets some of the buffers data. 73 | * @param {Number} offset - Data offset bytelength 74 | * @param {ArrayBufferView} data - Data to be set. 75 | * @returns {Vbo} 76 | */ 77 | 78 | Vbo.prototype.bufferSubData = function(offset,data){ 79 | this._gl.bufferSubData(this._target,offset,data); 80 | return this; 81 | }; 82 | 83 | /** 84 | * Initializes the buffer. 85 | * @param {Number|ArrayBufferView} sizeOrData - Size or data 86 | * @param {Number} usage - gl.STREAM_DRAW, gl.STATIC_DRAW, gl.DYNAMIC_DRAW 87 | * @returns {Vbo} 88 | */ 89 | 90 | Vbo.prototype.bufferData = function(sizeOrData,usage){ 91 | this._gl.bufferData(this._target,sizeOrData,usage); 92 | this._size = ObjectUtil.isUndefined(sizeOrData.byteLength) ? sizeOrData : sizeOrData.byteLength; 93 | return this; 94 | }; 95 | 96 | /** 97 | * Returns the current byteLength; 98 | * @returns {number} 99 | */ 100 | 101 | Vbo.prototype.getSize = function(){ 102 | return this._size; 103 | }; 104 | 105 | /** 106 | * Returns true if the underlying gl buffer object equals the specified gl buffer object. 107 | * @param {WebGLBuffer} buffer - The buffer 108 | * @returns {boolean} 109 | */ 110 | 111 | Vbo.prototype.equalsGLObject = function(buffer){ 112 | return this._obj == buffer; 113 | }; 114 | 115 | Vbo.dispose = function(){ 116 | if(current){ 117 | current.dispose(); 118 | current = null; 119 | } 120 | if(last){ 121 | last.dispose(); 122 | last = null; 123 | } 124 | }; 125 | 126 | module.exports = Vbo; -------------------------------------------------------------------------------- /lib/gl/VboMeshPrimitive.js: -------------------------------------------------------------------------------- 1 | var VboMesh = require('./VboMesh'), 2 | PrimitiveScheme = require('./PrimitiveScheme'), 3 | ObjectUtil = require('../util/ObjectUtil'), 4 | _gl = require('./gl'); 5 | 6 | function Plane(numH,numV,format,usage){ 7 | var scheme = PrimitiveScheme.Plane.create(numH,numV); 8 | usage = ObjectUtil.isUndefined(usage) ? 9 | (scheme.indices ? _gl.get().TRIANGLES : _gl.get().TRIANGLE_STRIP) : 10 | usage; 11 | VboMesh.apply(this,[usage, format]); 12 | 13 | this.setVertices(scheme.vertices); 14 | this.setNormals(scheme.normals); 15 | this.setColors(scheme.colors); 16 | this.setTexcoords(scheme.texcoords); 17 | 18 | if(scheme.indices){ 19 | this.setIndices(scheme.indices); 20 | } 21 | } 22 | 23 | Plane.prototype = Object.create(VboMesh.prototype); 24 | Plane.prototype.constructor = Plane; 25 | 26 | Plane.prototype.setSubDivisions = function(numH,numV){ 27 | var data = PrimitiveScheme.Plane.create(numH,numV); 28 | this.setVertices(data.vertices); 29 | this.setNormals(data.normals); 30 | this.setColors(data.colors); 31 | this.setTexcoords(data.texcoords); 32 | 33 | if(data.indices){ 34 | this.setIndices(data.indices); 35 | } 36 | }; 37 | 38 | function Cube(usage){ 39 | var scheme = PrimitiveScheme.Cube; 40 | VboMesh.apply(this,[usage,new VboMesh.Format(), scheme.vertices.length / 3]); 41 | this.setVertices(scheme.vertices); 42 | this.setNormals(scheme.normals); 43 | this.setTexcoords(scheme.texcoords); 44 | this.setColors(scheme.colors); 45 | this.setIndices(scheme.indices); 46 | } 47 | 48 | Cube.prototype = Object.create(VboMesh.prototype); 49 | Cube.prototype.constructor = Cube; 50 | 51 | function Disk(usage,numSegments,radiusX,radiusY){ 52 | usage = ObjectUtil.isUndefined(usage) ? _gl.get().TRIANGLE_FAN : usage; 53 | var scheme = PrimitiveScheme.Disk.create(numSegments,radiusX,radiusY); 54 | VboMesh.apply(this,[usage]); 55 | this.setVertices(scheme.vertices); 56 | this.setNormals(scheme.normals); 57 | this.setColors(scheme.colors); 58 | this.setTexcoords(scheme.texcoords); 59 | } 60 | 61 | Disk.prototype = Object.create(VboMesh.prototype); 62 | Disk.prototype.constructor = Disk; 63 | 64 | var VboMeshPrimitive = { 65 | Plane : Plane, 66 | Cube : Cube, 67 | Disk : Disk 68 | }; 69 | 70 | module.exports = VboMeshPrimitive; 71 | -------------------------------------------------------------------------------- /lib/gl/gl.js: -------------------------------------------------------------------------------- 1 | var gl = { 2 | _obj: null, 3 | set : function(gl){ 4 | this._obj = gl; 5 | }, 6 | /** 7 | * Returns the shared gl context. 8 | * @returns {WebGLRenderingContext} 9 | */ 10 | get: function () { 11 | return this._obj; 12 | }, 13 | dispose : function(){ 14 | this._obj = null; 15 | } 16 | }; 17 | module.exports = gl; -------------------------------------------------------------------------------- /lib/gl/glExtensions.js: -------------------------------------------------------------------------------- 1 | var Extensions = {}; 2 | 3 | Extensions.OES_texture_float = null; 4 | Extensions.OES_element_index_uint = null; 5 | Extensions.WEBGL_depth_texture = null; 6 | Extensions.ANGLE_instanced_arrays = null; 7 | Extensions.OES_standard_derivatives = null; 8 | 9 | module.exports = Extensions; 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /lib/gl/glObject.js: -------------------------------------------------------------------------------- 1 | var gl = require('./gl'), 2 | glTrans = require('./glTrans'), 3 | glDraw = require('./glDraw'); 4 | 5 | /** 6 | * Base class for all drawable objects. 7 | * @constructor 8 | */ 9 | 10 | function glObject(){ 11 | /** 12 | * Reference to WebGLRenderingContext 13 | * @type {WebGLRenderingContext} 14 | * @protected 15 | */ 16 | this._gl = gl.get(); 17 | 18 | /** 19 | * Reference to glTrans 20 | * @type {glTrans} 21 | * @protected 22 | */ 23 | 24 | this._glTrans = glTrans; 25 | 26 | 27 | /** 28 | * Reference to glDraw 29 | * @type {glDraw} 30 | * @protected 31 | */ 32 | this._glDraw = glDraw.get(); 33 | } 34 | 35 | module.exports = glObject; 36 | 37 | -------------------------------------------------------------------------------- /lib/gl/glValueType.js: -------------------------------------------------------------------------------- 1 | var ValueType = { 2 | ATTRIB_1f : '1f', 3 | ATTRIB_2f : '2f', 4 | ATTRIB_3f : '3f', 5 | ATTRIB_4f : '3f', 6 | ATTRIB_1i : '1i', 7 | ATTRIB_2i : '2i', 8 | ATTRIB_3i : '3i', 9 | ATTRIB_4i : '4i', 10 | ATTRIB_1fv : '1fv', 11 | ATTRIB_2fv : '2fv', 12 | ATTRIB_3fv : '3fv', 13 | ATTRIB_4fv : '4fv', 14 | ATTRIB_1iv : '1iv', 15 | ATTRIB_2iv : '2iv', 16 | ATTRIB_3iv : '3iv', 17 | ATTRIB_4iv : '4iv' 18 | }; 19 | 20 | module.exports = ValueType; -------------------------------------------------------------------------------- /lib/gl/glu.js: -------------------------------------------------------------------------------- 1 | var Matrix44 = require('../math/Matrix44'); 2 | 3 | module.exports = { 4 | perspective: function (m, fov, aspect, near, far) { 5 | var f = 1.0 / Math.tan(fov * 0.5), 6 | nf = 1.0 / (near - far); 7 | 8 | m[ 1] = m[ 2] = m[ 3] = m[ 4] = m[ 6] = m[ 7] = m[ 8] = m[ 9] = m[12] = m[13] = m[15] = 0; 9 | 10 | m[ 0] = f / aspect; 11 | m[ 5] = f; 12 | m[10] = (far + near) * nf; 13 | m[11] = -1; 14 | m[14] = (2 * far * near) * nf; 15 | 16 | return m; 17 | 18 | }, 19 | 20 | //http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho 21 | ortho : function(m, left, right, bottom, top , near, far) { 22 | var lr = left - right, 23 | bt = bottom - top, 24 | nf = near - far; 25 | 26 | m[ 1] = m[ 2] = m[ 3] = m[ 4] = m[ 6] = m[ 7] = m[ 8] = m[ 9] = m[11] = 0; 27 | 28 | m[ 0] = -2 / lr; 29 | m[ 5] = -2 / bt; 30 | m[10] = 2 / nf; 31 | 32 | m[12] = (left + right) / lr; 33 | m[13] = (top + bottom) / bt; 34 | m[14] = (far + near) / nf; 35 | m[15] = 1; 36 | 37 | return m; 38 | }, 39 | 40 | frustum: function (m, left, right, bottom, top, near, far) { 41 | var rl = 1 / (right - left), 42 | tb = 1 / (top - bottom), 43 | nf = 1 / (near - far); 44 | 45 | 46 | m[ 0] = (near * 2) * rl; 47 | m[ 1] = 0; 48 | m[ 2] = 0; 49 | m[ 3] = 0; 50 | m[ 4] = 0; 51 | m[ 5] = (near * 2) * tb; 52 | m[ 6] = 0; 53 | m[ 7] = 0; 54 | m[ 8] = (right + left) * rl; 55 | m[ 9] = (top + bottom) * tb; 56 | m[10] = (far + near) * nf; 57 | m[11] = -1; 58 | m[12] = 0; 59 | m[13] = 0; 60 | m[14] = (far * near * 2) * nf; 61 | m[15] = 0; 62 | 63 | return m; 64 | }, 65 | 66 | lookAt : function (m, eyex, eyey, eyez, targetx, targety, targetz, upx, upy, upz) { 67 | var x0, x1, x2, y0, y1, y2, z0, z1, z2, len; 68 | 69 | if (Math.abs(eyex - targetx) < 0.000001 && 70 | Math.abs(eyey - targety) < 0.000001 && 71 | Math.abs(eyez - targetz) < 0.000001) { 72 | 73 | m[ 0] = 1; 74 | m[ 1] = m[ 2] = m[ 3] = 0; 75 | m[ 5] = 1; 76 | m[ 4] = m[ 6] = m[ 7] = 0; 77 | m[10] = 1; 78 | m[ 8] = m[ 9] = m[11] = 0; 79 | m[15] = 1; 80 | m[12] = m[13] = m[14] = 0; 81 | 82 | return; 83 | } 84 | 85 | z0 = eyex - targetx; 86 | z1 = eyey - targety; 87 | z2 = eyez - targetz; 88 | 89 | len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2); 90 | z0 *= len; 91 | z1 *= len; 92 | z2 *= len; 93 | 94 | x0 = upy * z2 - upz * z1; 95 | x1 = upz * z0 - upx * z2; 96 | x2 = upx * z1 - upy * z0; 97 | 98 | len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2); 99 | 100 | if(len){ 101 | len = 1.0 / len; 102 | x0 *= len; 103 | x1 *= len; 104 | x2 *= len; 105 | } 106 | 107 | y0 = z1 * x2 - z2 * x1; 108 | y1 = z2 * x0 - z0 * x2; 109 | y2 = z0 * x1 - z1 * x0; 110 | 111 | len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2); 112 | 113 | if(len){ 114 | len = 1.0 / len; 115 | x0 *= len; 116 | x1 *= len; 117 | x2 *= len; 118 | } 119 | 120 | m[ 0] = x0; 121 | m[ 1] = y0; 122 | m[ 2] = z0; 123 | m[ 3] = 0; 124 | m[ 4] = x1; 125 | m[ 5] = y1; 126 | m[ 6] = z1; 127 | m[ 7] = 0; 128 | m[ 8] = x2; 129 | m[ 9] = y2; 130 | m[10] = z2; 131 | m[11] = 0; 132 | m[12] = -(x0 * eyex + x1 * eyey + x2 * eyez); 133 | m[13] = -(y0 * eyex + y1 * eyey + y2 * eyez); 134 | m[14] = -(z0 * eyex + z1 * eyey + z2 * eyez); 135 | m[15] = 1; 136 | } 137 | }; -------------------------------------------------------------------------------- /lib/input/KeyEvent.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Basic key events 3 | * @type {{KEY_DOWN: string, KEY_UP: string, KEY_PRESS: string}} 4 | */ 5 | 6 | var KeyEvent = { 7 | KEY_DOWN : 'keydown', 8 | KEY_UP : 'keyup', 9 | KEY_PRESS : 'keypress' 10 | }; 11 | 12 | module.exports = KeyEvent; -------------------------------------------------------------------------------- /lib/input/Keyboard.js: -------------------------------------------------------------------------------- 1 | var _Error = require('../system/common/Error'), 2 | EventDispatcher = require('../system/EventDispatcher'), 3 | Event = require('../system/Event'); 4 | 5 | /** 6 | * Representation of keyboard input. 7 | * @constructor 8 | */ 9 | 10 | function Keyboard(){ 11 | if (Keyboard.__instance){ 12 | throw new Error(_Error.CLASS_IS_SINGLETON); 13 | } 14 | 15 | EventDispatcher.call(this); 16 | 17 | this._down = false; 18 | this._up = false; 19 | 20 | this._keyCode = null; 21 | this._keyCodePrev = null; 22 | 23 | this._keyStr = null; 24 | this._keyStrPrev = null; 25 | 26 | this._altKey = false; 27 | this._ctrlKey = false; 28 | this._shiftKey = false; 29 | 30 | this._timestamp = null; 31 | this._timestampLast = null; 32 | 33 | Keyboard.__instance = this; 34 | } 35 | 36 | Keyboard.prototype = Object.create(EventDispatcher.prototype); 37 | Keyboard.prototype.constructor = Keyboard; 38 | 39 | /** 40 | * Returns true if a key is down. 41 | * @returns {Boolean} 42 | */ 43 | 44 | Keyboard.prototype.isKeyDown = function(){ 45 | return this._down; 46 | }; 47 | 48 | /** 49 | * Returns true if a key is up. 50 | * @returns {Boolean} 51 | */ 52 | 53 | Keyboard.prototype.isKeyUp = function(){ 54 | return this._up; 55 | }; 56 | 57 | /** 58 | * Return the current key code. 59 | * @returns {null|String} 60 | */ 61 | 62 | Keyboard.prototype.getKeyCode = function(){ 63 | return this._keyCode; 64 | }; 65 | 66 | /** 67 | * Return the current key string. 68 | * @returns {null|String} 69 | */ 70 | 71 | Keyboard.prototype.getKeyStr = function(){ 72 | return this._keyStr; 73 | }; 74 | 75 | /** 76 | * Return the previous key code. 77 | * @returns {null|String} 78 | */ 79 | 80 | Keyboard.prototype.getKeyCodePrev = function(){ 81 | return this._keyCodePrev; 82 | }; 83 | 84 | /** 85 | * Return the previous key string. 86 | * @returns {null|String} 87 | */ 88 | 89 | Keyboard.prototype.getKeyStrPrev = function(){ 90 | return this._keystrPrev; 91 | }; 92 | 93 | /** 94 | * Returns true if the alt-key is pressed. 95 | * @returns {Boolean} 96 | */ 97 | 98 | Keyboard.prototype.isKeyAlt = function(){ 99 | return this._altKey; 100 | }; 101 | 102 | /** 103 | * Returns true if the ctrl-key is pressed. 104 | * @returns {Boolean} 105 | */ 106 | 107 | Keyboard.prototype.isKeyCtrl = function(){ 108 | return this._ctrlKey; 109 | }; 110 | 111 | /** 112 | * Returns true if the shift-key is pressed. 113 | * @returns {Boolean} 114 | */ 115 | 116 | Keyboard.prototype.isKeyShift = function(){ 117 | return this._shiftKey; 118 | }; 119 | 120 | /** 121 | * Returns the singleton. 122 | * @returns {Keyboard} 123 | */ 124 | 125 | Keyboard.getInstance = function() { 126 | return Keyboard.__instance; 127 | }; 128 | 129 | Keyboard.dispose = function(){ 130 | Keyboard.__instance.removeAllEventListeners(); 131 | Keyboard.__instance = null; 132 | }; 133 | 134 | Keyboard.__instance = null; 135 | module.exports = Keyboard; -------------------------------------------------------------------------------- /lib/input/Mouse.js: -------------------------------------------------------------------------------- 1 | var _Error = require('../system/common/Error'), 2 | EventDispatcher = require('../system/EventDispatcher'), 3 | Event = require('../system/Event'), 4 | Vec2 = require('../math/Vec2'); 5 | 6 | /** 7 | * Representation of mouse input. 8 | * @constructor 9 | */ 10 | 11 | function Mouse() { 12 | if (Mouse.__instance){ 13 | throw new Error(_Error.CLASS_IS_SINGLETON); 14 | } 15 | 16 | EventDispatcher.call(this); 17 | 18 | this._position = new Vec2(); 19 | this._positionLast = new Vec2(); 20 | this._positionNormalized = new Vec2(); 21 | this._positionLastNormalized = new Vec2(); 22 | this._down = this._downLast = false; 23 | this._button = null; 24 | this._up = false; 25 | this._move = this._moveLast = false; 26 | this._leave = this._enter = false; 27 | this._wheelDelta = 0; 28 | this._wheelDirection = 0; 29 | 30 | Mouse.__instance = this; 31 | } 32 | 33 | Mouse.prototype = Object.create(EventDispatcher.prototype); 34 | 35 | /** 36 | * Return current mouse position. 37 | * @param {Vec2} [v] - Out position 38 | * @returns {Vec2} 39 | */ 40 | 41 | Mouse.prototype.getPosition = function (v) { 42 | return (v || new Vec2()).set(this._position); 43 | }; 44 | 45 | /** 46 | * Return previous mouse position. 47 | * @param {Vec2} [v] - Out position 48 | * @returns {Vec2} 49 | */ 50 | 51 | Mouse.prototype.getPositionLast = function (v) { 52 | return (v || new Vec2()).set(this._positionLast); 53 | }; 54 | 55 | /** 56 | * Return current mouse position x. 57 | * @returns {Number} 58 | */ 59 | 60 | Mouse.prototype.getX = function () { 61 | return this._position.x; 62 | }; 63 | 64 | /** 65 | * Return current mouse position y. 66 | * @returns {Number} 67 | */ 68 | 69 | Mouse.prototype.getY = function () { 70 | return this._position.y; 71 | }; 72 | 73 | /** 74 | * Return previous mouse position x. 75 | * @returns {Number} 76 | */ 77 | 78 | Mouse.prototype.getXLast = function () { 79 | return this._positionLast.x; 80 | }; 81 | 82 | /** 83 | * Return previous mouse position y. 84 | * @returns {Number} 85 | */ 86 | 87 | Mouse.prototype.getYLast = function () { 88 | return this._positionLast.y; 89 | }; 90 | 91 | /** 92 | * Return current mouse position normaliized. 93 | * @param {Vec2} [v] - Out position 94 | * @returns {Vec2} 95 | */ 96 | 97 | Mouse.prototype.getPositionNormalized = function(v){ 98 | return (v || new Vec2()).set(this._positionNormalized); 99 | } 100 | 101 | /** 102 | * Return previous mouse position normaliized. 103 | * @param {Vec2} [v] - Out position 104 | * @returns {Vec2} 105 | */ 106 | 107 | 108 | Mouse.prototype.getPositionLastNormalized = function (v) { 109 | return (v || new Vec2()).set(this._positionLastNormalized); 110 | }; 111 | 112 | /** 113 | * Return current mouse position x normalized. 114 | * @returns {Number} 115 | */ 116 | 117 | Mouse.prototype.getXNormalized = function () { 118 | return this._positionNormalized.x; 119 | }; 120 | 121 | /** 122 | * Return current mouse position y normalized. 123 | * @returns {Number} 124 | */ 125 | 126 | Mouse.prototype.getYNormalized = function () { 127 | return this._positionNormalized.y; 128 | }; 129 | 130 | /** 131 | * Return previous mouse position x normalized. 132 | * @returns {Number} 133 | */ 134 | 135 | 136 | Mouse.prototype.getXLastNormalized = function () { 137 | return this._positionLastNormalized.x; 138 | }; 139 | 140 | /** 141 | * Return previous mouse position x normalized. 142 | * @returns {Number} 143 | */ 144 | 145 | Mouse.prototype.getYLastNormalized = function () { 146 | return this._positionLastNormalized.y; 147 | }; 148 | 149 | /** 150 | * Return mouse wheel delta. 151 | * @returns {Number} 152 | */ 153 | 154 | Mouse.prototype.getWheelDelta = function () { 155 | return this._wheelDelta; 156 | }; 157 | 158 | /** 159 | * Returns mouse wheel direction -1,1. 160 | * @returns {*} 161 | */ 162 | 163 | Mouse.prototype.getWheelDirection = function(){ 164 | return this._wheelDirection; 165 | } 166 | 167 | /** 168 | * Returns true if the mouse is down. 169 | * @returns {Boolean} 170 | */ 171 | 172 | Mouse.prototype.isDown = function(){ 173 | return this._down; 174 | }; 175 | 176 | /** 177 | * Returns true if the mouse is pressed (hold). 178 | * @returns {Boolean} 179 | */ 180 | 181 | Mouse.prototype.isPressed = function(){ 182 | return this._down && !this._downLast; 183 | } 184 | 185 | /** 186 | * Returns true if the mouse is dragged. 187 | * @returns {Boolean} 188 | */ 189 | 190 | Mouse.prototype.isDragged = function(){ 191 | return this._down && this._move; 192 | }; 193 | 194 | /** 195 | * Returns true if the mouse did move. 196 | * @returns {Boolean} 197 | */ 198 | 199 | Mouse.prototype.didMove = function(){ 200 | return this._move; 201 | }; 202 | 203 | /** 204 | * Returns true if the mouse did enter the window (canvas). 205 | * @returns {Boolean} 206 | */ 207 | 208 | Mouse.prototype.didEnter = function(){ 209 | return this._enter; 210 | }; 211 | 212 | /** 213 | * Returns true if the mouse did leave the window (canvas). 214 | * @returns {Boolean} 215 | */ 216 | 217 | Mouse.prototype.didLeave = function(){ 218 | return this._leave; 219 | }; 220 | 221 | 222 | Mouse.prototype.isLeft = function(){ 223 | return this._button == 1; 224 | }; 225 | 226 | Mouse.prototype.isRight = function(){ 227 | return this._button = 2; 228 | }; 229 | 230 | Mouse.prototype.isMiddle = function(){ 231 | return this._button = 3; 232 | }; 233 | 234 | /** 235 | * Sets the cursor css display property used when over hovering the canvas. 236 | * (See App.js for implementation) 237 | * @param {String} property 238 | */ 239 | 240 | Mouse.prototype.setCursorCSS = function(property){}; 241 | 242 | 243 | /** 244 | * Return the singleton. 245 | * @returns {Mouse|*} 246 | */ 247 | 248 | Mouse.__instance = null; 249 | Mouse.getInstance = function () { 250 | return Mouse.__instance; 251 | }; 252 | 253 | Mouse.dispose = function(){ 254 | Mouse.__instance.removeAllEventListeners(); 255 | Mouse.__instance = null; 256 | }; 257 | 258 | module.exports = Mouse; -------------------------------------------------------------------------------- /lib/input/MouseEvent.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Basic mouse events 3 | * @type {{MOUSE_DOWN: string, MOUSE_PRESSED: string, MOUSE_UP: string, MOUSE_MOVE: string, MOUSE_STOP: string, MOUSE_DRAG: string, MOUSE_OUT: string, MOUSE_ENTER: string, MOUSE_LEAVE: string, MOUSE_WHEEL: string}} 4 | */ 5 | var MouseEvent = { 6 | MOUSE_DOWN : 'mousedown', 7 | MOUSE_PRESSED : 'mousepressed', 8 | MOUSE_UP : 'mouseup', 9 | MOUSE_MOVE : 'mousemove', 10 | MOUSE_STOP : 'mousestop', 11 | MOUSE_DRAG : 'mousedrag', 12 | MOUSE_OUT : 'mouseout', 13 | MOUSE_ENTER : 'mouseenter', 14 | MOUSE_LEAVE : 'mouseleave', 15 | MOUSE_WHEEL : 'mousewheel' 16 | }; 17 | 18 | module.exports = MouseEvent; -------------------------------------------------------------------------------- /lib/math/Ease.js: -------------------------------------------------------------------------------- 1 | function none(a){ 2 | return a; 3 | } 4 | 5 | function stepSmooth(a) { 6 | return a * a * (3 - 2 * a); 7 | } 8 | 9 | function stepSmoothSquared(a) { 10 | a = stepSmooth(a); 11 | return a * a; 12 | } 13 | 14 | function stepSmoothInvSquared(a) { 15 | a = 1.0 - stepSmooth(a); 16 | return 1 - a * a; 17 | } 18 | 19 | function stepSmoothCubed(a) { 20 | a = stepSmooth(a); 21 | return a * a * a * a; 22 | } 23 | 24 | function stepSmoothInvCubed(a) { 25 | a = 1.0 - stepSmooth(a); 26 | return 1 - a * a * a * a; 27 | } 28 | 29 | function stepSquared(a) { 30 | return a * a; 31 | } 32 | 33 | function stepInvSquared(a) { 34 | a = 1.0 - a; 35 | return 1 - a * a; 36 | } 37 | 38 | function stepCubed(a) { 39 | return a * a * a * a; 40 | } 41 | 42 | function stepInvCubed(a) { 43 | a = 1.0 - a; 44 | return 1 - a * a * a * a; 45 | } 46 | 47 | 48 | var Ease = { 49 | none : none, 50 | stepSmooth : stepSmooth, 51 | stepSmoothSquared : stepSmoothSquared, 52 | stepSmoothInvSquared : stepSmoothInvSquared, 53 | stepSmoothCubed : stepSmoothCubed, 54 | stepSmoothInvCubed : stepSmoothInvCubed, 55 | stepSquared : stepSquared, 56 | stepInvSquared : stepInvSquared, 57 | stepCubed: stepCubed, 58 | stepInvCubed : stepInvCubed 59 | }; 60 | 61 | module.exports = Ease; -------------------------------------------------------------------------------- /lib/math/Math.js: -------------------------------------------------------------------------------- 1 | var _Math = { 2 | PI: Math.PI, 3 | HALF_PI: Math.PI * 0.5, 4 | QUARTER_PI: Math.PI * 0.25, 5 | TWO_PI: Math.PI * 2, 6 | EPSILON: 2.2204460492503130808472633361816E-16, 7 | 8 | lerp: function (a, b, v) { 9 | return a + (b - a) * v; 10 | }, 11 | 12 | lerp3 : function(a, b, c, v){ 13 | return a + (b - a) * v + (c - b) * v; 14 | }, 15 | 16 | cosIntrpl: function (a, b, v) { 17 | v = (1 - Math.cos(v * Math.PI)) * 0.5; 18 | return (a * (1 - v) + b * v); 19 | }, 20 | cubicIntrpl: function (a, b, c, d, v) { 21 | var a0, b0, c0, d0, vv; 22 | 23 | vv = v * v; 24 | a0 = d - c - a + b; 25 | b0 = a - b - a0; 26 | c0 = c - a; 27 | d0 = b; 28 | 29 | return a0 * v * vv + b0 * vv + c0 * v + d0; 30 | }, 31 | 32 | hermiteIntrpl: function (a, b, c, d, v, tension, bias) { 33 | var v0, v1, v2, v3, 34 | a0, b0, c0, d0; 35 | 36 | tension = (1.0 - tension) * 0.5; 37 | 38 | var biasp = 1 + bias, 39 | biasn = 1 - bias; 40 | 41 | v2 = v * v; 42 | v3 = v2 * v; 43 | 44 | v0 = (b - a) * biasp * tension; 45 | v0 += (c - b) * biasn * tension; 46 | v1 = (c - b) * biasp * tension; 47 | v1 += (d - c) * biasn * tension; 48 | 49 | a0 = 2 * v3 - 3 * v2 + 1; 50 | b0 = v3 - 2 * v2 + v; 51 | c0 = v3 - v2; 52 | d0 = -2 * v3 + 3 * v2; 53 | 54 | return a0 * b + b0 * v0 + c0 * v1 + d0 * c; 55 | }, 56 | 57 | constrain: function () { 58 | var r; 59 | 60 | switch (arguments.length) { 61 | case 2: 62 | arguments[0] = (arguments[0] > arguments[1]) ? arguments[1] : arguments[0]; 63 | break; 64 | case 3: 65 | arguments[0] = (arguments[0] > arguments[2]) ? arguments[2] : (arguments[0] < arguments[1]) ? arguments[1] : arguments[0]; 66 | break; 67 | } 68 | 69 | return arguments[0]; 70 | }, 71 | 72 | normalize: function (value, start, end) { 73 | return (value - start) / (end - start); 74 | }, 75 | map: function (value, inStart, inEnd, outStart, outEnd) { 76 | return outStart + (outEnd - outStart) * this.normalize(value, inStart, inEnd); 77 | }, 78 | sin: function (value) { 79 | return Math.sin(value); 80 | }, 81 | cos: function (value) { 82 | return Math.cos(value); 83 | }, 84 | clamp: function (value, min, max) { 85 | return Math.max(min, Math.min(max, value)); 86 | }, 87 | saw: function (n) { 88 | return 2 * (n - Math.floor(0.5 + n)); 89 | }, 90 | tri: function (n) { 91 | return 1 - 4 * Math.abs(0.5 - this.frac(0.5 * n + 0.25)); 92 | }, 93 | rect: function (n) { 94 | var a = Math.abs(n); 95 | return (a > 0.5) ? 0 : (a == 0.5) ? 0.5 : (a < 0.5) ? 1 : -1; 96 | }, 97 | frac: function (n) { 98 | return n - Math.floor(n); 99 | }, 100 | sgn: function (n) { 101 | return n / Math.abs(n); 102 | }, 103 | abs: function (n) { 104 | return Math.abs(n); 105 | }, 106 | min: function (n) { 107 | return Math.min(n); 108 | }, 109 | max: function (n) { 110 | return Math.max(n); 111 | }, 112 | atan: function (n) { 113 | return Math.atan(n); 114 | }, 115 | atan2: function (y, x) { 116 | return Math.atan2(y, x); 117 | }, 118 | round: function (n) { 119 | return Math.round(n); 120 | }, 121 | floor: function (n) { 122 | return Math.floor(n); 123 | }, 124 | tan: function (n) { 125 | return Math.tan(n); 126 | }, 127 | rad2deg: function (radians) { 128 | return radians * (180 / Math.PI); 129 | }, 130 | deg2rad: function (degree) { 131 | return degree * (Math.PI / 180); 132 | }, 133 | sqrt: function (value) { 134 | return Math.sqrt(value); 135 | }, 136 | GreatestCommonDivisor: function (a, b) { 137 | return (b == 0) ? a : this.GreatestCommonDivisor(b, a % b); 138 | }, 139 | isFloatEqual: function (a, b) { 140 | return (Math.abs(a - b) < this.EPSILON); 141 | }, 142 | isPowerOfTwo: function (a) { 143 | return (a & (a - 1)) == 0; 144 | }, 145 | swap: function (a, b) { 146 | var t = a; 147 | a = b; 148 | b = a; 149 | }, 150 | pow: function (x, y) { 151 | return Math.pow(x, y); 152 | }, 153 | log: function (n) { 154 | return Math.log(n); 155 | }, 156 | cosh: function (n) { 157 | return (Math.pow(Math.E, n) + Math.pow(Math.E, -n)) * 0.5; 158 | }, 159 | exp: function (n) { 160 | return Math.exp(n); 161 | }, 162 | catmullrom: function (a, b, c, d, i) { 163 | return a * ((-i + 2) * i - 1) * i * 0.5 + 164 | b * (((3 * i - 5) * i) * i + 2) * 0.5 + 165 | c * ((-3 * i + 4) * i + 1) * i * 0.5 + 166 | d * ((i - 1) * i * i) * 0.5; 167 | }, 168 | isPOT : function(a){ 169 | return (a&(a-1))==0; 170 | } 171 | }; 172 | 173 | 174 | module.exports = _Math; -------------------------------------------------------------------------------- /lib/math/Matrix33.js: -------------------------------------------------------------------------------- 1 | var Vec2 = require('./Vec2'); 2 | 3 | /* 4 | * 5 | * 0,1,2, 6 | * 3,4,5, 7 | * 6,7,8 8 | * 9 | */ 10 | 11 | function Matrix33(){ 12 | this.m = [1,0,0, 13 | 0,1,0, 14 | 0,0,1]; 15 | } 16 | 17 | Matrix33.prototype.identity = function(){ 18 | var m = this.m; 19 | m[0] = m[4] = m[8] = 1; 20 | m[1] = m[2] = m[3] = m[5] = m[6] = m[7] = 0; 21 | }; 22 | 23 | Matrix33.prototype.set = function(matrix){ 24 | var m, m_; 25 | 26 | m = this.m; 27 | m_ = matrix.m; 28 | 29 | m[0] = m_[0]; m[1] = m_[1]; m[2] = m_[2]; 30 | m[3] = m_[3]; m[4] = m_[4]; m[5] = m_[5]; 31 | m[6] = m_[6]; m[7] = m_[7]; m[8] = m_[8]; 32 | return this; 33 | }; 34 | 35 | Matrix33.prototype.setf = function(m00,m01,m02, 36 | m10,m11,m12, 37 | m20,m21,m22){ 38 | var m = this.m; 39 | m[0] = m00; m[1] = m01; m[2] = m02; 40 | m[3] = m10; m[4] = m11; m[5] = m12; 41 | m[6] = m20; m[7] = m21; m[8] = m22; 42 | return this; 43 | }; 44 | 45 | Matrix33.prototype.setFromScale = function(scale){ 46 | var m = this.m; 47 | 48 | m[0] = scale.x; 49 | m[4] = scale.y; 50 | 51 | m[1] = m[2] = m[3] = m[5] = m[6] = m[7] = 0; 52 | m[8] = 1; 53 | 54 | return this; 55 | }; 56 | 57 | Matrix33.prototype.setFromScalef = function(x,y){ 58 | var m = this.m; 59 | 60 | m[0] = x; 61 | m[4] = y; 62 | 63 | m[1] = m[2] = m[3] = m[5] = m[6] = m[7] = 0; 64 | m[8] = 1; 65 | 66 | return this; 67 | }; 68 | 69 | Matrix33.prototype.setFromRotation = function(angle){ 70 | var m, cs, ss; 71 | 72 | m = this.m; 73 | cs = Math.cos(angle); 74 | ss = Math.sin(angle); 75 | 76 | m[0] = cs; 77 | m[1] = ss; 78 | m[3] = -ss; 79 | m[4] = cs; 80 | 81 | m[2] = m[5] = m[6] = m[7] = 0; 82 | m[8] = 1.0; 83 | 84 | return this; 85 | }; 86 | 87 | Matrix33.prototype.setFromTranslationf = function(x,y){ 88 | var m = this.m; 89 | 90 | m[0] = m[4] = m[8] = 1; 91 | m[1] = m[3] = m[6] = m[7] 92 | }; 93 | 94 | Matrix33.prototype.multVec2f = function(x,y,out){ 95 | out = out || new Vec2(); 96 | var m = this.m; 97 | 98 | out.x = x * m[0] + y * m[1] + m[2]; 99 | out.y = x * m[3] + y * m[4] + m[5]; 100 | return out; 101 | }; 102 | 103 | Matrix33.prototype.multVec2 = function(v,out){ 104 | out = out || v; 105 | var m,x,y; 106 | 107 | m = this.m; 108 | x = v.x; 109 | y = v.y; 110 | 111 | out.x = x * m[0] + y * m[1] + m[2]; 112 | out.y = x * m[3] + y * m[4] + m[5]; 113 | return out; 114 | }; 115 | 116 | Matrix33.prototype.invert = function(){ 117 | var m, m00, m01, m02, m10, m11, m12, m20, m21, m22, 118 | m01_, m11_, m21_, det; 119 | 120 | m = this.m; 121 | m00 = m[0]; m01 = m[1]; m02 = m[2]; 122 | m10 = m[3]; m11 = m[4]; m12 = m[5]; 123 | m20 = m[6]; m21 = m[7]; m22 = m[8]; 124 | 125 | 126 | m01_ = m22 * m11 - m12 * m21; 127 | m11_ = -m22 * m10 + m12 * m20; 128 | m21_ = m21 * m10 - m11 * m20; 129 | 130 | det = 1.0 / (m00 * m01_ + m01 * m11_ + m02 * m21_); 131 | 132 | m[0] = m01_ * det; 133 | m[1] = (-m22 * m01 + m02 * m21) * det; 134 | m[2] = (m12 * m01 - m02 * m11) * det; 135 | m[3] = m11_ * det; 136 | m[4] = (m22 * m00 - m02 * m20) * det; 137 | m[5] = (-m12 * m00 + m02 * m10) * det; 138 | m[6] = m21_ * det; 139 | m[7] = (-m21 * m00 + m01 * m20) * det; 140 | m[8] = (m11 * m00 - m01 * m10) * det; 141 | return this; 142 | }; 143 | 144 | Matrix33.prototype.transpose = function(){ 145 | var m, m1, m2, m5; 146 | 147 | m = this.m; 148 | m1 = m[1]; 149 | m2 = m[2]; 150 | m5 = m[5]; 151 | 152 | m[1] = m[3]; 153 | m[2] = m[6]; 154 | m[3] = m1; 155 | m[5] = m[7]; 156 | m[6] = m2; 157 | m[7] = m5; 158 | return this; 159 | }; 160 | 161 | Matrix33.prototype.transposed = function(matrix){ 162 | return (matrix || new Matrix33()).set(this).transpose(); 163 | }; 164 | 165 | Matrix33.prototype.toFloat32Array = function(arr){ 166 | arr = arr || new Float32Array(9); 167 | arr.set(this.m); 168 | return arr; 169 | }; 170 | 171 | module.exports = Matrix33; -------------------------------------------------------------------------------- /lib/math/OnB.js: -------------------------------------------------------------------------------- 1 | var Vec3 = require('./Vec3'), 2 | Matrix44 = require('./Matrix44'); 3 | 4 | /** 5 | * Representation of an orthonormal basis. 6 | * @param {Vec3} [u] - tangent 7 | * @param {Vec3} [v] - up 8 | * @param {Vec3} [w] - cotangent 9 | * @constructor 10 | */ 11 | 12 | function OnB(u,v,w){ 13 | this.u = u || Vec3.zAxis(); 14 | this.v = v || Vec3.yAxis(); 15 | this.w = w || Vec3.xAxis(); 16 | } 17 | 18 | /** 19 | * Sets onb from another onb. 20 | * @param {OnB} onb 21 | * @returns {OnB} 22 | */ 23 | 24 | OnB.prototype.set = function(onb){ 25 | this.u.set(onb.u); 26 | this.v.set(onb.v); 27 | this.w.set(onb.w); 28 | return this; 29 | }; 30 | 31 | /** 32 | * Sets u v w from values. 33 | * @param ux 34 | * @param uy 35 | * @param uz 36 | * @param vx 37 | * @param vy 38 | * @param vz 39 | * @param wx 40 | * @param wy 41 | * @param wz 42 | * @returns {OnB} 43 | */ 44 | 45 | OnB.prototype.setf = function(ux,uy,uz,vx,vy,vz,wx,wy,wz){ 46 | this.u.setf(ux,uy,uz); 47 | this.v.setf(vx,vy,vz); 48 | this.w.setf(wx,wy,wz); 49 | return this; 50 | }; 51 | 52 | /** 53 | * Returns a transformation matrix from the onb. 54 | * @param {Matrix44} [mat] - Out matrix 55 | * @returns {Matrix44} 56 | */ 57 | 58 | OnB.prototype.getMatrix = function(mat){ 59 | if(mat){ 60 | mat.identity(); 61 | return Matrix44.fromOnBAxes(this.u,this.v,this.w,mat); 62 | } 63 | return Matrix44.fromOnBAxes(this.u,this.v,this.w); 64 | }; 65 | 66 | module.exports = OnB; 67 | -------------------------------------------------------------------------------- /lib/math/Random.js: -------------------------------------------------------------------------------- 1 | var ObjectUtil = require('../util/ObjectUtil'); 2 | 3 | var seed_ = null; 4 | 5 | function random(){ 6 | if(ObjectUtil.isUndefined(seed_) || seed_ === null){ 7 | return Math.random(); 8 | } 9 | // v8 10 | // http://octane-benchmark.googlecode.com/svn/latest/base.js 11 | // Robert Jenkins' 32 bit integer hash function. 12 | seed_ = ((seed_ + 0x7ed55d16) + (seed_ << 12)) & 0xffffffff; 13 | seed_ = ((seed_ ^ 0xc761c23c) ^ (seed_ >>> 19)) & 0xffffffff; 14 | seed_ = ((seed_ + 0x165667b1) + (seed_ << 5)) & 0xffffffff; 15 | seed_ = ((seed_ + 0xd3a2646c) ^ (seed_ << 9)) & 0xffffffff; 16 | seed_ = ((seed_ + 0xfd7046c5) + (seed_ << 3)) & 0xffffffff; 17 | seed_ = ((seed_ ^ 0xb55a4f09) ^ (seed_ >>> 16)) & 0xffffffff; 18 | return (seed_ & 0xfffffff) / 0x10000000; 19 | } 20 | 21 | var Random = { 22 | /** 23 | * Sets the seed, null if buildin Math.random 24 | * @param seed 25 | */ 26 | setSeed : function(seed){ 27 | seed_ = seed; 28 | }, 29 | 30 | /** 31 | * Returns the current seed 32 | * @param seed 33 | * @returns {*} 34 | */ 35 | 36 | getSeed : function(){ 37 | return seed_; 38 | }, 39 | 40 | /** 41 | * Returns a random float 42 | */ 43 | 44 | random : random, 45 | 46 | /** 47 | * Generate a random float. 48 | * @param {Number} [min=0] - min 49 | * @param {Number} [max=1] - max 50 | * @returns {Number} 51 | */ 52 | randomFloat: function () { 53 | var r; 54 | 55 | switch (arguments.length) { 56 | case 0: 57 | r = random(); 58 | break; 59 | case 1: 60 | r = random() * arguments[0]; 61 | break; 62 | case 2: 63 | r = arguments[0] + (arguments[1] - arguments[0]) * random(); 64 | break; 65 | } 66 | 67 | return r; 68 | }, 69 | 70 | /** 71 | * Generate a random Integer 72 | * @param {Number} [min=0] - min 73 | * @param {Number} [max=1] - max 74 | * @returns {Number} 75 | */ 76 | 77 | randomInteger: function () { 78 | var r; 79 | 80 | switch (arguments.length) { 81 | case 0: 82 | r = 0.5 + random(); 83 | break; 84 | case 1: 85 | r = 0.5 + random() * arguments[0]; 86 | break; 87 | case 2: 88 | r = arguments[0] + ( 1 + arguments[1] - arguments[0]) * random(); 89 | break; 90 | } 91 | 92 | return Math.floor(r); 93 | } 94 | }; 95 | 96 | module.exports = Random; -------------------------------------------------------------------------------- /lib/math/Vec4.js: -------------------------------------------------------------------------------- 1 | function Vec4(x,y,z,w){ 2 | this.x = x || 0; 3 | this.y = y || 0; 4 | this.z = z || 0; 5 | this.w = w === undefined ? 1.0 : w; 6 | } 7 | 8 | Vec4.fromVec3 = function(v,w){ 9 | return new Vec4(v.x, v.y, v.z, w); 10 | }; 11 | 12 | Vec4.zero = function(){ 13 | return new Vec4(); 14 | }; 15 | 16 | Vec4.prototype.set = function (v) { 17 | this.x = v.x; 18 | this.y = v.y; 19 | this.z = v.z; 20 | this.w = v.w; 21 | return this; 22 | }; 23 | 24 | Vec4.prototype.setf = function(x,y,z,w){ 25 | this.x = x || 0; 26 | this.y = y || 0; 27 | this.z = z || 0; 28 | this.w = w === undefined ? this.w : w; 29 | return this; 30 | }; 31 | 32 | Vec4.prototype.setVec3 = function(v,w){ 33 | return this.setf(v.x, v.y, v.z, w); 34 | }; 35 | 36 | module.exports = Vec4; 37 | 38 | -------------------------------------------------------------------------------- /lib/system/Event.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Base class Event. 3 | * @param {EventDispatcher} sender - The sender 4 | * @param {String} type - The type 5 | * @param {Object} [data] - The data 6 | * @constructor 7 | */ 8 | function Event(sender,type,data){ 9 | this.sender = sender; 10 | this.type = type; 11 | this.data = data; 12 | 13 | this.stopPropagation = false; 14 | } 15 | /** 16 | * Returns a copy of the event. 17 | * @returns {Event} 18 | */ 19 | 20 | Event.prototype.copy = function(){ 21 | return new Event(this.sender,this.type,this.data); 22 | }; 23 | 24 | module.exports = Event; 25 | -------------------------------------------------------------------------------- /lib/system/EventDispatcher.js: -------------------------------------------------------------------------------- 1 | var ObjectUtil = require('../util/ObjectUtil'); 2 | 3 | /** 4 | * EventDispatcher base class. 5 | * @constructor 6 | */ 7 | 8 | EventDispatcher = function () { 9 | this._listeners = {}; 10 | }; 11 | 12 | /** 13 | * Register an event callback for a certain type. 14 | * @param {String} type - The event type 15 | * @param {Function} method - Callback if event is raised 16 | */ 17 | 18 | EventDispatcher.prototype.addEventListener = function (type, method) { 19 | this._listeners[type] = this._listeners[type] || []; 20 | this._listeners[type].push(method); 21 | }; 22 | 23 | /** 24 | * Dispatch an event 25 | * @param {Event} event - The event 26 | */ 27 | 28 | EventDispatcher.prototype.dispatchEvent = function (event) { 29 | var type = event.type; 30 | if (!this.hasEventListener(type)){ 31 | return; 32 | } 33 | var methods = this._listeners[type]; 34 | var i = -1, l = methods.length; 35 | while (++i < l) { 36 | methods[i](event); 37 | if(event.stopPropagation){ 38 | break; 39 | } 40 | } 41 | }; 42 | 43 | /** 44 | * Remove a callback from the dispatcher. 45 | * @param {String} type = The type 46 | * @param {Function} [method] - The callback to be removed (if not specified, all callbacks will be removed) 47 | */ 48 | 49 | //TODO: Fix this!, function(){}.bind(context) always returns a new function, so comparison for those will always fail 50 | 51 | EventDispatcher.prototype.removeEventListener = function (type, method) { 52 | if (!this.hasEventListener(type)){ 53 | return; 54 | } 55 | 56 | if(method){ 57 | var methods = this._listeners[type]; 58 | var i = methods.length; 59 | while (--i > -1) { 60 | if (methods[i] == method) { 61 | methods.splice(i, 1); 62 | if (methods.length == 0){ 63 | delete this._listeners[type]; 64 | } 65 | break; 66 | } 67 | } 68 | return; 69 | } 70 | delete this._listeners[type]; 71 | }; 72 | 73 | /** 74 | * Completely remove all listeners. 75 | */ 76 | 77 | EventDispatcher.prototype.removeAllEventListeners = function () { 78 | this._listeners = {}; 79 | }; 80 | 81 | /** 82 | * Returns true there are listeners for a event type. 83 | * @param {String} type - The type 84 | * @returns {Boolean} 85 | */ 86 | 87 | EventDispatcher.prototype.hasEventListener = function (type) { 88 | return this._listeners[type] != undefined && this._listeners[type] != null; 89 | }; 90 | 91 | /** 92 | * Returns the number of listerners for a certain event type. 93 | * @returns {*} 94 | */ 95 | 96 | EventDispatcher.prototype.getNumListerners = function(){ 97 | return ObjectUtil.getNumKeys(this._listeners); 98 | } 99 | 100 | module.exports = EventDispatcher; -------------------------------------------------------------------------------- /lib/system/FileEvent.js: -------------------------------------------------------------------------------- 1 | var FileEvent = { 2 | FILE_ADDED : 'fileadded', 3 | FILE_MODIFIED : 'filemodified', 4 | FILE_REMOVED : 'fileremoved', 5 | FILE_NOT_VALID : 'filenotvalid' 6 | } 7 | 8 | module.exports = FileEvent; -------------------------------------------------------------------------------- /lib/system/Flags.js: -------------------------------------------------------------------------------- 1 | var Flags = 2 | { 3 | __uintTypeAvailable : false, 4 | isUIntTypeAvailable : function(){return this.__uintTypeAvailable;} 5 | }; 6 | 7 | module.exports = Flags; -------------------------------------------------------------------------------- /lib/system/Id.js: -------------------------------------------------------------------------------- 1 | var num = 0; 2 | 3 | module.exports = { 4 | /** 5 | * Get a unique Id within the programs lifetime. 6 | * @returns {Number} 7 | */ 8 | get : function(){ 9 | return num++; 10 | } 11 | }; -------------------------------------------------------------------------------- /lib/system/ObjLoader.js: -------------------------------------------------------------------------------- 1 | var OBJLoader = {}; 2 | 3 | /** 4 | * 5 | * Parses obj file string, returns 6 | * 7 | * {objects : [{vertices,normals,texcoords,indices,materialDesc},...], 8 | * totalTriangles : } 9 | * 10 | */ 11 | 12 | var OBJ_VERTEX = 'v', 13 | OBJ_NORMAL = 'vn', 14 | OBJ_TEX_COORD = 'vt', 15 | OBJ_FACE = 'f', 16 | OBJ_COMMENT = '#', 17 | OBJ_BLANK = '', 18 | OBJ_USE_MTL = 'usemtl', 19 | OBJ_MTL_LIB = 'mtllib', 20 | OBJ_OBJECT = 'o', 21 | OBJ_GROUP = 'g', 22 | OBJ_SCALE = 's'; 23 | 24 | var OBJ_COMP_DIV = '/'; 25 | 26 | function append(a,b){ 27 | b = b.length > 3 ? b.slice(0,3) : b; 28 | Array.prototype.push.apply(a,b); 29 | } 30 | 31 | /** 32 | * 33 | * @param {String} objFileStr - The .obj file string content 34 | * @param {Function} callbackSuccess - callback if done 35 | * @param {Object} [options] 36 | * @param {Boolean} [options.merge] - Indicates whether groups should be ignored 37 | * @param {Boolean} [options.plain] - Indicates whether data is plain, and vertices, normals and texcoords are not sorted by face 38 | * @function 39 | */ 40 | 41 | OBJLoader.Load = function(objFileStr,callbackSuccess,options){ 42 | objFileStr = objFileStr.split('\n'); 43 | options = options || {merge:false}; 44 | options.merge = options.merge || false; 45 | options.plain = options.plain === undefined ? false : options.plain; 46 | 47 | var vertices = [], 48 | normals = [], 49 | texcoords = []; 50 | 51 | var objVertices = [], 52 | objNormals = [], 53 | objTexcoords = [], 54 | objIndices = [], 55 | objMaterial = '', 56 | objIndicesHash = {}, 57 | objIndex = 0; 58 | 59 | var objGroups = []; 60 | 61 | var i = -1, l = objFileStr.length; 62 | var j, k; 63 | var line, tokens, firstToken, dataIndex; 64 | var faceToken, tokens_; 65 | 66 | if(options.plain){ //we expect no faces and groups, just plain unsorted data 67 | vertices = objVertices; 68 | normals = objNormals; 69 | texcoords = objTexcoords; 70 | } 71 | 72 | while(++i < l){ 73 | line = objFileStr[i].trim(); 74 | tokens = line.split(' '); 75 | firstToken = tokens.shift(); 76 | 77 | switch (firstToken){ 78 | // Vertex 79 | case OBJ_VERTEX: 80 | append(vertices,tokens); 81 | break; 82 | 83 | // Normal 84 | case OBJ_NORMAL: 85 | append(normals,tokens); 86 | break; 87 | 88 | // Texcoord 89 | case OBJ_TEX_COORD: 90 | append(texcoords,tokens); 91 | break; 92 | 93 | // Face 94 | case OBJ_FACE: 95 | if(options.plain){ 96 | continue; 97 | } 98 | if(tokens.length != 3){ 99 | throw new Error('Only triangle faces are currently supported'); 100 | } 101 | // face token = per vertex (vertex, normal & texcoord index) 102 | j = -1; k = 3; 103 | while(++j < k){ 104 | // token[0] == vertex index 105 | // token[1] == texture index 106 | // token[2] == normal index 107 | // index = index - 1, as obj format starts at 1 108 | faceToken = tokens[j]; 109 | if(!objIndicesHash[faceToken]){ 110 | tokens_ = faceToken.split(OBJ_COMP_DIV); 111 | 112 | //TODO: move outside 113 | if(tokens_.length == 2){ 114 | dataIndex = (tokens_[0] - 1) * 3; 115 | objVertices.push(vertices[dataIndex++], 116 | vertices[dataIndex++], 117 | vertices[dataIndex ]); 118 | 119 | dataIndex = (tokens_[1] - 1) * 3; 120 | objNormals.push(normals[dataIndex++], 121 | normals[dataIndex++], 122 | normals[dataIndex ]); 123 | 124 | } else { 125 | // vertices 126 | dataIndex = (tokens_[0] - 1) * 3; 127 | objVertices.push(vertices[dataIndex++], 128 | vertices[dataIndex++], 129 | vertices[dataIndex ]); 130 | 131 | 132 | // normals 133 | dataIndex = (tokens_[2] - 1) * 3; 134 | objNormals.push(normals[dataIndex++], 135 | normals[dataIndex++], 136 | normals[dataIndex ]); 137 | 138 | // texcoords 139 | if(texcoords.length != 0){ 140 | dataIndex = (tokens_[1] - 1) * 2; 141 | objTexcoords.push(texcoords[dataIndex++], 142 | texcoords[dataIndex ]); 143 | } 144 | } 145 | 146 | 147 | 148 | 149 | objIndicesHash[faceToken] = objIndex; 150 | objIndices.push(objIndex++); 151 | 152 | } else { //already processed 153 | objIndices.push(objIndicesHash[faceToken]); 154 | } 155 | } 156 | break; 157 | 158 | // Material name for object 159 | case OBJ_USE_MTL: 160 | break; 161 | 162 | // An object group 163 | case OBJ_GROUP: 164 | if(options.merge || options.plain){ 165 | continue; 166 | } 167 | objGroups.push({ 168 | description : tokens.join(' '), 169 | material : null, 170 | indices : [] 171 | }); 172 | objIndices = objGroups[objGroups.length-1].indices; 173 | break; 174 | 175 | // A saperate object 176 | case OBJ_OBJECT: 177 | break; 178 | 179 | // An objects scale 180 | case OBJ_SCALE: 181 | break; 182 | 183 | // A comment – IGNORED 184 | case OBJ_COMMENT: 185 | break; 186 | 187 | // Blank line – IGNORED 188 | case OBJ_BLANK: 189 | break; 190 | 191 | default : 192 | break; 193 | } 194 | } 195 | 196 | 197 | var obj = { 198 | vertices: objVertices, 199 | normals: objNormals, 200 | texcoords: objTexcoords 201 | }; 202 | //if there is just one group, collapse it 203 | if(objGroups.length > 0){ 204 | obj.groups = objGroups; 205 | } else { 206 | obj.indices = objIndices; 207 | } 208 | 209 | callbackSuccess(obj); 210 | }; 211 | 212 | module.exports = OBJLoader; -------------------------------------------------------------------------------- /lib/system/Resource.js: -------------------------------------------------------------------------------- 1 | var ObjectUtil = require('../util/ObjectUtil'), 2 | ResourceType = require('./ResourceType'), 3 | Resources = require('./Resources'); 4 | 5 | var OBJLoader = require('./OBJLoader'); 6 | 7 | function strLogResourceLoadFail(path,type,index){ 8 | return 'Warning: Failed to load Resource ' + "'" + path + "' of type '" + type + "'" + (index != null ? (' at index ' + index + ' .') : '.') ; 9 | } 10 | 11 | function strLogResourceUnsupported(path, type, index) { 12 | return 'Warning: Resource ' + "'" + path + "' of type '" + type + "'" + (index != null ? (' at index ' + index + ' ') : ' ') + 'is not supported.'; 13 | } 14 | 15 | function strLogResourceNoPath(type,index) { 16 | return 'Warning: Resource ' + (type ? ('of type "' + type + '" ') : '') + (index != null ? ( ' at index ' + index ) : '"') + ' has no path.'; 17 | } 18 | 19 | function request__(path,type,callbackSuccess,callbackError){ 20 | var request = new XMLHttpRequest(); 21 | request.open('GET', path); 22 | request.responseType = type; 23 | request.addEventListener('readystatechange', function(){ 24 | if(request.readyState == 4){ 25 | if(request.status == 200){ 26 | callbackSuccess(request.response); 27 | } else if(request.status == 404){ 28 | callbackError(); 29 | } 30 | } 31 | }); 32 | request.send(); 33 | } 34 | 35 | function Load(resource,index,callbackSuccess,callbackError,strict){ 36 | var path = resource.path; 37 | if(!path){ 38 | console.log(strLogResourceNoPath(resource.type,index)); 39 | if(callbackError){ 40 | callbackError(); 41 | } 42 | return; 43 | } 44 | var type = resource.type || 'text', 45 | options = resource.options; 46 | 47 | if(type != ResourceType.IMAGE && 48 | type != ResourceType.ARRAY_BUFFER && 49 | type != ResourceType.BLOB && 50 | type != ResourceType.DOCUMENT && 51 | type != ResourceType.JSON && 52 | type != ResourceType.TEXT && 53 | type != ResourceType.OBJ){ 54 | console.log(strLogResourceUnsupported(path,type,index)); 55 | if(callbackError && strict){ 56 | callbackError(path); 57 | } 58 | return; 59 | } 60 | 61 | function callbackSuccess_(response){ 62 | if (callbackSuccess) { 63 | callbackSuccess(response, index); 64 | } 65 | } 66 | 67 | function callbackError_(){ 68 | console.log(strLogResourceLoadFail(path, type, index)); 69 | if (callbackError && strict) { 70 | callbackError(path); 71 | } 72 | } 73 | 74 | switch (type){ 75 | case ResourceType.IMAGE: 76 | var image = new Image(); 77 | image.addEventListener('load', function () { 78 | if (callbackSuccess) { 79 | callbackSuccess(image, index); 80 | } 81 | }); 82 | image.addEventListener('error', callbackError_); 83 | image.src = path; 84 | break; 85 | 86 | case ResourceType.OBJ: 87 | request__(path, 'text', 88 | function (response) { 89 | OBJLoader.Load(response,callbackSuccess_,options); 90 | },callbackError_); 91 | break; 92 | 93 | default : 94 | request__(path, type, callbackSuccess_,callbackError_); 95 | break; 96 | } 97 | } 98 | 99 | 100 | 101 | var Resource = { 102 | 103 | /** 104 | * Load a resource. 105 | * @param {Object|Object[]} resource - The resource / resource-bundle {path, type} to be loaded 106 | * @param {Function} callbackSuccess - Callback if succesfully loaded (function(resource)) 107 | * @param {Function} [callbackError] - Callback if an error occured 108 | * @param {Function} [callbackProcess] - Callback on load 109 | * @param {bool} [strict=true] - Abort if at least one resource could not be loaded 110 | */ 111 | 112 | load : function(resource, callbackSuccess, callbackError, callbackProcess, strict){ 113 | strict = ObjectUtil.isUndefined(strict) ? true : strict; 114 | var keys = ObjectUtil.getKeys(resource), 115 | numKeys = keys.length; 116 | 117 | if(numKeys == 0){ 118 | console.log('Warning: Invalid Resource.'); 119 | if(callbackError){ 120 | callbackError(); 121 | } 122 | return; 123 | } 124 | 125 | if(numKeys <= 2 && (keys[0] == 'path' || keys[0] == 'type')){ 126 | Load(resource,null,callbackSuccess, callbackError,strict); 127 | return; 128 | } else if(numKeys == 1){ 129 | resource = resource[keys[0]]; 130 | Load(resource,null,function(resource){ 131 | Resources[keys[0]] = resource; 132 | callbackSuccess(Resources); 133 | }, callbackError, strict); 134 | return; 135 | } 136 | 137 | var numFiles = numKeys, 138 | numFilesLoaded = 0; 139 | 140 | var error = false; 141 | 142 | function onFileProcessed(){ 143 | if(numFilesLoaded == numFiles){ 144 | if(callbackSuccess){ 145 | callbackSuccess(Resources); 146 | } 147 | return; 148 | } 149 | if(callbackProcess){ 150 | callbackProcess(numFilesLoaded,numFiles); 151 | } 152 | } 153 | 154 | function onError(){ 155 | if(!strict){ 156 | numFiles--; 157 | onFileProcessed(); 158 | return; 159 | } 160 | if(callbackError){ 161 | callbackError(); 162 | } 163 | error = true; 164 | } 165 | 166 | var index = 0; 167 | for(var key in resource){ 168 | Load(resource[key],index++, 169 | function(resource,index){ 170 | Resources[keys[index]] = resource; 171 | numFilesLoaded++; 172 | onFileProcessed(); 173 | },onError.bind(this)); 174 | if(error){ 175 | return; 176 | } 177 | } 178 | } 179 | }; 180 | 181 | module.exports = Resource; -------------------------------------------------------------------------------- /lib/system/ResourceType.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Type of resource 3 | * @type {{IMAGE: string, ARRAY_BUFFER: string, BLOB: string, DOCUMENT: string, JSON: string, TEXT: string, OBJ: string}} 4 | */ 5 | 6 | var ResourceType = { 7 | IMAGE : 'image', 8 | ARRAY_BUFFER : 'arraybuffer', 9 | BLOB : 'blob', 10 | DOCUMENT : 'document', 11 | JSON : 'json', 12 | TEXT : 'text', 13 | OBJ : 'obj' 14 | }; 15 | 16 | module.exports = ResourceType; -------------------------------------------------------------------------------- /lib/system/Resources.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Global access to all loaded resources. 3 | * @example 4 | * var Resources = Foam.Resources; 5 | * 6 | * function Class(){ 7 | * this._image = Resources.img; 8 | * } 9 | * 10 | * @type {{}} 11 | */ 12 | 13 | var Resources = {}; 14 | 15 | /** 16 | * Dispose all loaded resources. 17 | * @example 18 | * 19 | * function setup(resources){ 20 | * //do something with the loaded data 21 | * this._texture = Texture.fromImage(resources.img); 22 | * resources.dispose(); 23 | * //prints null 24 | * console.log(resources.img); 25 | * } 26 | */ 27 | 28 | Resources.dispose = function(){ 29 | for(var k in this){ 30 | if(k === 'dispose'){ 31 | continue; 32 | } 33 | this[k] = null; 34 | } 35 | }; 36 | 37 | module.exports = Resources; -------------------------------------------------------------------------------- /lib/system/System.js: -------------------------------------------------------------------------------- 1 | var System = {}; 2 | module.exports = System; -------------------------------------------------------------------------------- /lib/system/common/Error.js: -------------------------------------------------------------------------------- 1 | module.exports = 2 | { 3 | METHOD_NOT_IMPLEMENTED: 'Method not implemented in target platform.', 4 | CLASS_IS_SINGLETON: 'App is singleton. Get via getInstance().', 5 | APP_NO_SETUP: 'No setup method added to app.', 6 | APP_NO_UPDATE : 'No update method added to app.', 7 | PLASK_WINDOW_SIZE_SET: 'Plask window size can only be set on startup.', 8 | WRONG_PLATFORM: 'Wrong Platform.', 9 | MATRIX_STACK_POP_ERROR: 'Matrix stack invalid pop.', 10 | VERTICES_IN_WRONG_SIZE: 'Vertices array has wrong length. Should be ', 11 | COLORS_IN_WRONG_SIZE: 'Color array length not equal to number of vertices.', 12 | DIRECTORY_DOESNT_EXIST: 'File target directory does not exist.', 13 | FILE_DOESNT_EXIST: 'File does not exist.', 14 | TEXTURE_WIDTH_NOT_P2: 'Texture imageData is not power of 2.', 15 | TEXTURE_HEIGHT_NOT_P2: 'Texture imageData is not power of 2.', 16 | TEXTURE_IMAGE_DATA_NULL:'Texture imageData is null.' 17 | }; -------------------------------------------------------------------------------- /lib/system/common/Platform.js: -------------------------------------------------------------------------------- 1 | var Platform = {WEB:'WEB',NODE_WEBKIT:'NODE_WEBKIT'}; 2 | Platform.__target = null; 3 | 4 | Platform.getTarget = function(){ 5 | if(!this.__target){ 6 | var bWindow = typeof window !== 'undefined', 7 | bDocument = typeof document !== 'undefined', 8 | bRequireF = typeof require == 'function', 9 | bRequire = !!require, 10 | bNodeWebkit = false; 11 | 12 | //TODO fix 13 | //hm this needs to be fixed -> browserify require vs node-webkit require 14 | //for now this does the job 15 | if(bDocument){ 16 | bNodeWebkit = document.createElement('IFRAME').hasOwnProperty('nwdisable'); 17 | } 18 | 19 | this.__target = (bWindow && bDocument && !bNodeWebkit) ? this.WEB : 20 | (bWindow && bDocument && bNodeWebkit) ? this.NODE_WEBKIT : 21 | null; 22 | 23 | } 24 | 25 | return this.__target; 26 | }; 27 | 28 | module.exports = Platform; -------------------------------------------------------------------------------- /lib/util/ArrayUtil.js: -------------------------------------------------------------------------------- 1 | var ObjectUtil = require('./ObjectUtil'); 2 | 3 | var ArrayUtil = { 4 | /** 5 | * Creates an array of elements of a certain length, 6 | * if only length is passed an array of undefined is created. 7 | * 8 | * var array = createArray(10,0,1,2,3); 9 | * [0,1,2,3,0,1,2,3,0,1,2,3,...] 10 | * 11 | * @param {Number} length - The length 12 | * @param ... objs 13 | * @returns {Array} 14 | */ 15 | createArray: function (length) { 16 | var args = Array.prototype.slice.call(arguments, 1); 17 | 18 | var argsLen = args.length; 19 | var arr = []; 20 | if (argsLen == 0) { 21 | arr.length = length; 22 | return arr; 23 | } 24 | length = length * argsLen; 25 | var i = 0; 26 | while (arr.length != length) { 27 | arr.push(args[(i++) % argsLen]) 28 | } 29 | return arr; 30 | }, 31 | 32 | /** 33 | * Creates an array with obj instances of a certain length. 34 | * @param {Number} length - The length 35 | * @param {Class} classObj - The class 36 | * @returns {Array} 37 | */ 38 | 39 | createObjArray : function(length,classObj){ 40 | var arr = new Array(length); 41 | var i = -1;while(++i < length){ 42 | arr[i] = new classObj(); 43 | } 44 | return arr; 45 | }, 46 | 47 | /** 48 | * Creates an array of obj instances of a certain length. 49 | * Instances are created via factory method. 50 | * @param {Number} length - The length 51 | * @param {Function} factMethod - The factory method 52 | * @returns {Array} 53 | */ 54 | 55 | createFactObjArray : function(length,factMethod){ 56 | var arr = new Array(length); 57 | var i = -1;while(++i < length){ 58 | arr[i] = factMethod(); 59 | } 60 | return arr; 61 | }, 62 | 63 | /** 64 | * Appends an array to another array. 65 | * @param {Array} a - The array 66 | * @param {Array} b - The array to be appended 67 | * @returns {*} 68 | */ 69 | 70 | appendArray: function (a, b) { 71 | a.push.apply(a, b); 72 | return a; 73 | }, 74 | 75 | /** 76 | * Transforms an object to an array. 77 | * @param {Object} a - The object 78 | * @returns {Array} 79 | */ 80 | 81 | toArray: function (a) { 82 | return Array.prototype.slice.call(a); 83 | }, 84 | 85 | /* 86 | setArrayObj : function (arr, index) { 87 | var args = Array.prototype.slice.call(arguments, 2); 88 | var argsLen = args.length; 89 | if(argsLen == 0){ 90 | return; 91 | } 92 | 93 | index *= argsLen; 94 | var i = -1; 95 | while(++i < argsLen){ 96 | arr[index + i] = args[i]; 97 | } 98 | }, 99 | 100 | setArrayObj2: function (arr, index, obj2) { 101 | index *= 2; 102 | arr[index ] = obj2[0]; 103 | arr[index + 1] = obj2[1]; 104 | }, 105 | 106 | setArrayObj3: function (arr, index, obj3) { 107 | index *= 3; 108 | arr[index ] = obj3[0]; 109 | arr[index + 1] = obj3[1]; 110 | arr[index + 2] = obj3[2]; 111 | }, 112 | 113 | setArrayObj4: function (arr, index, obj4) { 114 | index *= 4; 115 | arr[index ] = obj4[0]; 116 | arr[index + 1] = obj4[1]; 117 | arr[index + 2] = obj4[2]; 118 | arr[index + 3] = obj4[3]; 119 | }, 120 | 121 | fillArrayObj4 : function(arr, index, obj4){ 122 | if(index >= arr.length){ 123 | return arr; 124 | } 125 | var i = 0; 126 | var len = arr.length; 127 | while(index < len){ 128 | arr[index++] = obj4[i++%4]; 129 | } 130 | return arr; 131 | }, 132 | 133 | forEachObj2 : function(arr,func,offset,length){ 134 | var i = !offset ? 0 : offset, 135 | l = ObjectUtil.isUndefined(length) ? arr.length : length < offset ? offset : length; 136 | while(i < l){ 137 | func(arr,i); 138 | i += 2; 139 | } 140 | }, 141 | 142 | forEachObj3 : function(arr,func,offset,length){ 143 | var i = !offset ? 0 : offset, 144 | l = ObjectUtil.isUndefined(length) ? arr.length : length < offset ? offset : length; 145 | while(i < l){ 146 | func(arr,i); 147 | i += 3; 148 | } 149 | }, 150 | 151 | forEachObj4 : function(arr,func,offset,length){ 152 | var i = !offset ? 0 : offset, 153 | l = ObjectUtil.isUndefined(length) ? arr.length : length < offset ? offset : length; 154 | while(i < l){ 155 | func(arr,i); 156 | i += 4; 157 | } 158 | }, 159 | */ 160 | 161 | /** 162 | * Returns true if the content of two arrays are equal. 163 | * @param {Array} a - One array 164 | * @param {Array} b - Another array 165 | * @returns {Boolean} 166 | */ 167 | equalContent: function (a, b) { 168 | if (!a || !b || (!a && !b)) { 169 | return false; 170 | } else if (a.length != b.length) { 171 | return false 172 | } else { 173 | var i = -1, l = a.length; 174 | while (++i < l) { 175 | if (a[i] != b[i])return false; 176 | } 177 | } 178 | return true; 179 | }, 180 | 181 | /** 182 | * Transforms an array of vec3s to a flat Float32Array. 183 | * @param vec3Array 184 | * @returns {Float32Array} 185 | */ 186 | toFloat32Array : function(vec3Array){ 187 | var array = new Float32Array(vec3Array.length * 3); 188 | var i = -1, l = vec3Array.length; 189 | var i3, point; 190 | while(++i < l){ 191 | i3 = i * 3; 192 | point = vec3Array[i]; 193 | array[i3 ] = point.x; 194 | array[i3+1] = point.y; 195 | array[i3+2] = point.z; 196 | } 197 | return array; 198 | }, 199 | 200 | /** 201 | * Returns an untyped copy ot the array. 202 | * @param typedArray 203 | * @returns {Array.} 204 | */ 205 | toUntypedArray : function(typedArray){ 206 | return Array.prototype.slice.call(typedArray); 207 | }, 208 | 209 | /** 210 | * Appends the second array to the first, resturns the result. 211 | * @param typedArray0 212 | * @param typedArray1 213 | * @returns {Array.} 214 | */ 215 | 216 | typedArraysAppended : function(typedArray0,typedArray1){ 217 | var arr = new typedArray0.constructor(typedArray0.length + typedArray1.length); 218 | arr.set(typedArray0); 219 | arr.set(typedArray1,typedArray0.length); 220 | return arr; 221 | } 222 | }; 223 | 224 | 225 | module.exports = ArrayUtil; -------------------------------------------------------------------------------- /lib/util/ElementArrayUtil.js: -------------------------------------------------------------------------------- 1 | var ElementArrayUtil = { 2 | /** 3 | * Generate a set of triangle fan indices. 4 | * @param start - The start index 5 | * @param end - The end index 6 | * @param {Array} [out] - The target array 7 | * @returns {Array} 8 | */ 9 | genTriangleFan : function(start,end,out){ 10 | var arr = out || [], 11 | len = end - start; 12 | if(len < 3){ 13 | return arr; 14 | } 15 | arr.length = (len - 1) * 3 - 3; 16 | 17 | var begin = start, 18 | end_2 = end - 2, 19 | index = 0; 20 | while(start < end_2){ 21 | arr[index ] = begin; 22 | arr[index + 1] = start + 1; 23 | arr[index + 2] = start + 2; 24 | start++; 25 | index += 3; 26 | } 27 | 28 | return arr; 29 | }, 30 | /* 31 | genTriangle : function(start, end){ 32 | 33 | }, 34 | 35 | genTriangleStrip : function(start,end){ 36 | 37 | }, 38 | */ 39 | 40 | /** 41 | * Generate a set of indices. 42 | * @param start - The start index 43 | * @param end - The start index 44 | * @returns {Array} 45 | */ 46 | 47 | genPoints : function(start,end){ 48 | var arr = [], 49 | len = end - start; 50 | if(len < 0){ 51 | return arr; 52 | } 53 | arr.length = len; 54 | 55 | while(start < end){ 56 | arr[start++] = start; 57 | } 58 | 59 | return arr; 60 | } 61 | 62 | }; 63 | 64 | module.exports = ElementArrayUtil; -------------------------------------------------------------------------------- /lib/util/ObjectUtil.js: -------------------------------------------------------------------------------- 1 | var ObjectUtil = { 2 | /** 3 | * Returns true if an object is undefined. 4 | * @param {Object} obj - The object 5 | * @returns {Boolean} 6 | */ 7 | isUndefined: function (obj) { 8 | return typeof obj === 'undefined'; 9 | }, 10 | 11 | /** 12 | * Returns true if an object is a Float32Array. 13 | * @param {Object} obj - The object 14 | * @returns {Boolean} 15 | */ 16 | 17 | isFloat32Array: function (obj) { 18 | return obj instanceof Float32Array; 19 | }, 20 | 21 | /** 22 | * Ensures that an array is of type Float32Array. 23 | * @param {Array|Float32Array} arr - The array 24 | * @returns {Float32Array} 25 | */ 26 | 27 | safeFloat32Array: function (arr) { 28 | return arr instanceof Float32Array ? arr : new Float32Array(arr); 29 | }, 30 | 31 | /** 32 | * Ensures that an array is of type Uint16Array. 33 | * @param arr 34 | * @returns {Uint16Array} 35 | */ 36 | 37 | safeUint16Array: function (arr) { 38 | return arr instanceof Uint16Array ? arr : new Uint16Array(arr); 39 | }, 40 | 41 | /** 42 | * Ensures that an array is of type Uint32Array. 43 | * @param arr 44 | * @returns {Uint32Array} 45 | */ 46 | 47 | safeUint32Array : function(arr){ 48 | return arr instanceof Uint32Array ? arr : new Uint32Array(arr); 49 | }, 50 | 51 | /** 52 | * Returns a copy of a Float32Array. (mainly cosmetic) 53 | * @param {Float32Array} arr - The array 54 | * @returns {Float32Array} 55 | */ 56 | 57 | copyFloat32Array: function (arr) { 58 | return new Float32Array(arr); 59 | }, 60 | 61 | /** 62 | * Returns a copy of an array. 63 | * @param {Array} arr - The array 64 | * @param {Array} [out] - Out array 65 | * @returns {Array} 66 | */ 67 | 68 | copyArray: function (arr,out) { 69 | var i = -1, l = arr.length; 70 | out = out || []; 71 | out.length = l; 72 | while (++i < l) { 73 | out[i] = arr[i]; 74 | } 75 | return out; 76 | }, 77 | 78 | /** 79 | * Moves the content of one array to another. 80 | * @param {Array} a - To array 81 | * @param {Array} b - Fform array 82 | */ 83 | 84 | setArray: function (a, b) { 85 | var i = -1, l = a.length; 86 | while (++i < l) { 87 | a[i] = b[i]; 88 | } 89 | }, 90 | 91 | /** 92 | * Shifts the indices within an index array by a certain offset. 93 | * @param {Array} arr - The array 94 | * @param {Nummber} offset - The offset to be shifted 95 | * @param {Array} [len] - The number of elements to be shifted 96 | */ 97 | 98 | shiftIndexArray: function (arr, offset, len) { 99 | var i = -1, l = len || arr.length; 100 | while (++i < l) { 101 | arr[i] += offset; 102 | } 103 | }, 104 | 105 | __toString: function (obj) { 106 | return Object.prototype.toString.call(obj); 107 | }, 108 | 109 | /** 110 | * Returns true if oject is array. 111 | * @param {Object} obj - The object 112 | * @returns {Boolean} 113 | */ 114 | 115 | isArray: function (obj) { 116 | return this.__toString(obj) == '[object Array]'; 117 | }, 118 | 119 | /** 120 | * Returns true if object is object. 121 | * @param {Object} obj - The object 122 | * @returns {Boolean} 123 | */ 124 | 125 | isObject: function (obj) { 126 | return obj === Object(obj) 127 | }, 128 | 129 | /** 130 | * Returns true if object is function. 131 | * @param {Object} obj - The object 132 | * @returns {Boolean} 133 | */ 134 | 135 | isFunction: function (obj) { 136 | return this.__toString(obj) == '[object Function]'; 137 | }, 138 | 139 | /** 140 | * Returns true if object is string.. 141 | * @param {Object} obj - The object 142 | * @returns {Boolean} 143 | */ 144 | 145 | isString: function (obj) { 146 | return this.__toString(obj) == '[object String]'; 147 | }, 148 | 149 | 150 | isNumber : function(obj){ 151 | return this.__toString(obj) == '[object Number]'; 152 | }, 153 | 154 | /** 155 | * Returns true if object is Float64Array. 156 | * @param {Object} obj - The object 157 | * @returns {Boolean} 158 | */ 159 | 160 | isFloat64Array: function (obj) { 161 | return this.__toString(obj) == '[object Float64Array]' 162 | }, 163 | 164 | /** 165 | * Returns true if object is Uint8Array. 166 | * @param {Object} obj - The object 167 | * @returns {Boolean} 168 | */ 169 | 170 | isUint8Array: function (obj) { 171 | return this.__toString(obj) == '[object Uint8Array]'; 172 | }, 173 | 174 | /** 175 | * Returns true if object is Uint16Array. 176 | * @param {Object} obj - The object 177 | * @returns {Boolean} 178 | */ 179 | 180 | isUint16Array: function (obj) { 181 | return this.__toString(obj) == '[object Uint16Array]' 182 | }, 183 | 184 | /** 185 | * Returns true if object is Uint16Array. 186 | * @param {Object} obj - The object 187 | * @returns {Boolean} 188 | */ 189 | 190 | isUint32Array: function (obj) { 191 | return this.__toString(obj) == '[object Uint32Array]' 192 | }, 193 | 194 | /** 195 | * Returns true if object is a typed array. 196 | * @param {Object} obj - The object 197 | * @returns {Boolean} 198 | */ 199 | 200 | isTypedArray: function (obj) { 201 | return this.isUint8Array(obj) || 202 | this.isUint16Array(obj) || 203 | this.isUint32Array(obj) || 204 | this.isFloat32Array(obj) || 205 | this.isFloat32Array(obj); 206 | }, 207 | 208 | /** 209 | * Returns an object keys. 210 | * @param {Object} obj - The object 211 | * @returns {Array} 212 | */ 213 | 214 | getKeys : function(obj){ 215 | if(Object.keys){ 216 | return Object.keys(obj); 217 | } 218 | var keys = []; 219 | for(key in obj){ 220 | if(obj.hasOwnProperty(key)){ 221 | keys.push(key); 222 | } 223 | } 224 | return keys; 225 | }, 226 | 227 | 228 | setVec3Array : function(float32Array, index, vec3){ 229 | index = index * 3; 230 | float32Array[index ] = vec3.x; 231 | float32Array[index+1] = vec3.y; 232 | float32Array[index+2] = vec3.z; 233 | } 234 | }; 235 | 236 | module.exports = ObjectUtil; 237 | -------------------------------------------------------------------------------- /lib/util/StringUtil.js: -------------------------------------------------------------------------------- 1 | var StringUtil = { 2 | /** 3 | * Returns the body of a fucntion as a string. 4 | * @param {Function} func - The function 5 | * @returns {String} 6 | */ 7 | 8 | getFunctionBody: function (func) { 9 | return (func).toString().match(/function[^{]+\{([\s\S]*)\}$/)[1]; 10 | }, 11 | 12 | /** 13 | * Returns a string representation of an object. 14 | * @param {Object} obj - The object 15 | * @returns {String} 16 | */ 17 | 18 | toString: function (obj) { 19 | return this.isFunction(obj) ? this.getFunctionString(obj) : 20 | this.isArray(obj) ? this.getArrayString(obj) : 21 | this.isString(obj) ? this.getString(obj) : 22 | this.isTypedArray(obj) ? this.getTypedArrayString(obj) : 23 | this.isObject(obj) ? this.getObjectString(obj) : 24 | obj; 25 | }, 26 | 27 | /** 28 | * Returns a string representation of a typed array. 29 | * @param {Object} obj - The object 30 | * @returns {String} 31 | */ 32 | 33 | getTypedArrayString: function (obj) { 34 | if (!this.isFloat32Array(obj)) { 35 | throw new TypeError('Object must be of type Float32Array'); 36 | } 37 | 38 | if (obj.byteLength == 0)return '[]'; 39 | var out = '['; 40 | 41 | for (var p in obj) { 42 | out += obj[p] + ','; 43 | } 44 | 45 | return out.substr(0, out.lastIndexOf(',')) + ']'; 46 | }, 47 | 48 | getString: function (obj) { 49 | return '"' + obj + '"'; 50 | }, 51 | 52 | /** 53 | * Returns a string representation of an array. 54 | * @param {Object} obj - The object 55 | * @returns {String} 56 | */ 57 | 58 | getArrayString: function (obj) { 59 | if (!this.isArray(obj)) { 60 | throw new TypeError('Object must be of type array.'); 61 | } 62 | var out = '['; 63 | if (obj.length == 0) { 64 | return out + ']'; 65 | } 66 | 67 | var i = -1; 68 | while (++i < obj.length) { 69 | out += this.toString(obj[i]) + ','; 70 | } 71 | 72 | return out.substr(0, out.lastIndexOf(',')) + ']'; 73 | }, 74 | 75 | /** 76 | * Returns a a string representation of an object. 77 | * @param {Object} obj - The object 78 | * @returns {String} 79 | */ 80 | 81 | getObjectString: function (obj) { 82 | if (!this.isObject(obj)) { 83 | throw new TypeError('Object must be of type object.') 84 | } 85 | var out = '{'; 86 | if (Object.keys(obj).length == 0) { 87 | return out + '}'; 88 | } 89 | 90 | for (var p in obj) { 91 | out += p + ':' + this.toString(obj[p]) + ','; 92 | } 93 | 94 | return out.substr(0, out.lastIndexOf(',')) + '}'; 95 | }, 96 | 97 | 98 | /** 99 | * Returns a string representation of a function or class. 100 | * @param {Function} obj - The function or class 101 | * @returns {string} 102 | * 103 | * If class: 104 | * 105 | * function ClassB(){ 106 | * ClassB.apply(this,arguments);ClassB.call... 107 | * } 108 | * 109 | * ClassB.prototype = Object.create(ClassA.prototype) 110 | * 111 | * ClassB.prototype.method = function(){}; 112 | * 113 | * ClassB.STATIC = 1; 114 | * ClassB.STATIC_OBJ = {}; 115 | * ClassB.STATIC_ARR = []; 116 | * 117 | */ 118 | 119 | getFunctionString: function (obj) { 120 | if (!this.isFunction(obj)) { 121 | throw new TypeError('Object must be of type function.'); 122 | } 123 | 124 | var out = ''; 125 | 126 | var name = obj.name, 127 | constructor = obj.toString(), 128 | inherited = 1 + constructor.indexOf('.call(this') || 1 + constructor.indexOf('.apply(this'); 129 | 130 | out += constructor; 131 | 132 | if (inherited) { 133 | out += '\n\n'; 134 | inherited -= 2; 135 | 136 | var baseClass = ''; 137 | var char = '', 138 | i = 0; 139 | while (char != ' ') { 140 | baseClass = char + baseClass; 141 | char = constructor.substr(inherited - i, 1); 142 | ++i; 143 | } 144 | out += name + '.prototype = Object.create(' + baseClass + '.prototype);'; 145 | } 146 | 147 | for (var p in obj) { 148 | out += '\n\n' + name + '.' + p + ' = ' + this.toString(obj[p]) + ';'; 149 | } 150 | 151 | var prototype = obj.prototype; 152 | for (var p in prototype) { 153 | if (prototype.hasOwnProperty(p)) { 154 | out += '\n\n' + name + '.prototype.' + p + ' = ' + this.toString(prototype[p]) + ';'; 155 | 156 | } 157 | } 158 | 159 | return out; 160 | } 161 | }; 162 | 163 | module.exports = StringUtil; -------------------------------------------------------------------------------- /lib/util/Value1State.js: -------------------------------------------------------------------------------- 1 | function Value1State(){ 2 | this._a = null; 3 | this._b = null; 4 | } 5 | 6 | Value1State.prototype.push = function(a){ 7 | this._b=this._a; 8 | this._a=a; 9 | }; 10 | 11 | Value1State.prototype.peek = function(){ 12 | return this._a; 13 | }; 14 | 15 | Value1State.prototype.isEqual = function(){ 16 | return this._a == this._b; 17 | }; 18 | 19 | Value1State.EMPTY = null; 20 | 21 | module.exports = Value1State; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "foam-gl", 3 | "version": "0.0.9", 4 | "description": "A WebGL toolkit", 5 | "keywords": [ 6 | "webgl" 7 | ], 8 | "homepage" : "https://github.com/automat/foam", 9 | "author": { 10 | "name": "Henryk Wollik", 11 | "email": "hwollik@hotmail.com", 12 | "url": "http://henrykwollik.com" 13 | }, 14 | "main" : "index.js", 15 | "dependencies" : { 16 | "opentype.js" : "0.4.x", 17 | "minimist" : "1.1.x", 18 | "colors" : "1.0.x", 19 | "watchify" : "2.1.x" 20 | }, 21 | "repository": { 22 | "type": "git", 23 | "url": "https://github.com/automat/foam.git" 24 | }, 25 | "bugs" : "https://github.com/automat/foam/issues", 26 | "license": "MIT" 27 | } -------------------------------------------------------------------------------- /resources/basic2d.glsl: -------------------------------------------------------------------------------- 1 | #ifdef VERTEX_SHADER 2 | precision highp float; 3 | 4 | attribute vec3 aVertexPosition; 5 | uniform mat4 uProjectionMatrix; 6 | uniform mat4 uModelViewMatrix; 7 | 8 | 9 | void main(){ 10 | gl_Position = uProjectionMatrix * uModelViewMatrix * vec4(aVertexPosition,1.0); 11 | gl_PointSize = 3.0; 12 | } 13 | #endif 14 | 15 | 16 | #ifdef FRAGMENT_SHADER 17 | precision highp float; 18 | uniform vec4 uColor; 19 | void main(){ 20 | gl_FragColor = uColor; 21 | } 22 | #endif -------------------------------------------------------------------------------- /resources/basic3d.glsl: -------------------------------------------------------------------------------- 1 | #ifdef VERTEX_SHADER 2 | precision highp float; 3 | 4 | attribute vec3 aVertexPosition; 5 | attribute vec4 aVertexColor; 6 | varying vec4 vVertexColor; 7 | 8 | uniform mat4 uModelViewMatrix; 9 | uniform mat4 uProjectionMatrix; 10 | 11 | uniform float uPointSize; 12 | 13 | void main(){ 14 | vVertexColor = aVertexColor; 15 | gl_Position = uProjectionMatrix * uModelViewMatrix * vec4(aVertexPosition, 1.0); 16 | gl_PointSize = uPointSize; 17 | } 18 | #endif 19 | 20 | #ifdef FRAGMENT_SHADER 21 | precision highp float; 22 | varying vec4 vVertexColor; 23 | 24 | void main(){ 25 | gl_FragColor = vVertexColor; 26 | } 27 | #endif -------------------------------------------------------------------------------- /resources/basic3dLight.glsl: -------------------------------------------------------------------------------- 1 | #ifdef VERTEX_SHADER 2 | precision highp float; 3 | 4 | attribute vec3 aVertexPosition; 5 | attribute vec3 aVertexNormal; 6 | attribute vec4 aVertexColor; 7 | 8 | varying vec4 vVertexPosition; 9 | varying vec4 vVertexColor; 10 | varying vec3 vVertexNormal; 11 | 12 | uniform mat4 uModelViewMatrix; 13 | uniform mat4 uProjectionMatrix; 14 | uniform mat3 uNormalMatrix; 15 | 16 | uniform float uPointSize; 17 | 18 | void main(){ 19 | vVertexColor = aVertexColor; 20 | vVertexNormal = normalize(uNormalMatrix * aVertexNormal); 21 | vVertexPosition = uModelViewMatrix * vec4(aVertexPosition, 1.0); 22 | 23 | gl_Position = uProjectionMatrix * vVertexPosition; 24 | gl_PointSize = uPointSize; 25 | } 26 | #endif 27 | 28 | #ifdef FRAGMENT_SHADER 29 | precision highp float; 30 | 31 | #define NUM_LIGHTS 3 32 | 33 | varying vec4 vVertexPosition; 34 | varying vec3 vVertexNormal; 35 | varying vec4 vVertexColor; 36 | 37 | // we just use position and ambient color 38 | struct Light{ 39 | vec4 position; 40 | vec3 ambient; 41 | }; 42 | 43 | // we just use the ambient color 44 | struct Material{ 45 | vec4 ambient; 46 | }; 47 | 48 | uniform Light uLights[NUM_LIGHTS]; 49 | uniform float uUseLighting; 50 | 51 | uniform Material uMaterial; 52 | 53 | void main(){ 54 | // insert your favourite light model here 55 | Light light; 56 | float intensity; 57 | vec4 colorSum = vec4(0,0,0,1.0); 58 | 59 | for (int i = 0; i < NUM_LIGHTS; ++i) { 60 | light = uLights[i]; 61 | intensity = max(dot(vVertexNormal, normalize(light.position.xyz - vVertexPosition.xyz)),0.0); 62 | colorSum += uMaterial.ambient * vec4(light.ambient * intensity,1.0); 63 | } 64 | 65 | gl_FragColor = (1.0 - uUseLighting) * vVertexColor + uUseLighting * colorSum; 66 | } 67 | #endif -------------------------------------------------------------------------------- /resources/basic3dTexture.glsl: -------------------------------------------------------------------------------- 1 | #ifdef VERTEX_SHADER 2 | precision highp float; 3 | 4 | attribute vec3 aVertexPosition; 5 | attribute vec4 aVertexColor; 6 | attribute vec2 aTexcoord; 7 | 8 | varying vec4 vVertexColor; 9 | varying vec2 vTexcoord; 10 | 11 | uniform mat4 uModelViewMatrix; 12 | uniform mat4 uProjectionMatrix; 13 | 14 | uniform float uPointSize; 15 | 16 | void main(){ 17 | vVertexColor = aVertexColor; 18 | vTexcoord = aTexcoord; 19 | gl_Position = uProjectionMatrix * uModelViewMatrix * vec4(aVertexPosition, 1.0); 20 | gl_PointSize = uPointSize; 21 | } 22 | #endif 23 | 24 | #ifdef FRAGMENT_SHADER 25 | precision highp float; 26 | 27 | uniform float uUseTexture; 28 | uniform sampler2D uTexture; 29 | 30 | varying vec4 vVertexColor; 31 | varying vec2 vTexcoord; 32 | 33 | void main(){ 34 | gl_FragColor = texture2D(uTexture,vTexcoord) * uUseTexture + vVertexColor * (1.0 - uUseTexture); 35 | } 36 | #endif -------------------------------------------------------------------------------- /scripts/buildNodeWebkit.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # IDE - shortcut 4 | # buildNodeWebkit - Browserify app.js, gen index.html / package.json, zip all, run NodeWebkit 5 | 6 | ((!$#)) && echo "PATH_TO_APP_JS PATH_TO_TEMP_DIR PATH_TO_NODE_WEBKIT(optional) missing" && exit 1 7 | 8 | args=("$@") 9 | 10 | ((${#args[@]}<2)) && echo "Args missing. Must satisfy PATH_TO_APP_JS PATH_TO_TEMP_DIR PATH_TO_NODE_WEBKIT(optional)" && exit 1 11 | 12 | pathjs=${args[0]} 13 | filejs=$(basename "${pathjs}") 14 | patht=${args[1]} 15 | 16 | if [ "${filejs#*.}" != "js" ] 17 | then 18 | echo "no .js file!" 19 | exit 1 20 | else 21 | if [ -d "$patht" ] 22 | then 23 | 24 | rm -rf "$patht"/* 25 | cd "$patht" 26 | 27 | cat > ./index.html <<- _EOF_ 28 | 29 | 30 | 31 | 32 | 33 | 37 | 38 | 39 | 40 | 41 | _EOF_ 42 | 43 | cat > ./package.json <<- _EOF_ 44 | { 45 | "main" : "index.html", 46 | "name" : "-", 47 | "description" : "-", 48 | "window" : 49 | { 50 | "position" : "center", 51 | "toolbar" : false, 52 | "frame" : false, 53 | "min_width" : 800, 54 | "min_height" : 600 55 | } 56 | } 57 | _EOF_ 58 | 59 | browserify "$pathjs" -i plask > ./bundle.js 60 | 61 | zip app.nw index.html bundle.js package.json 62 | 63 | rm -f index.html 64 | rm -f bundle.js 65 | rm -f package.json 66 | 67 | if [ ${#args[@]} -eq 3 ];then 68 | open -a "${args[2]}" app.nw 69 | fi 70 | 71 | echo "Done!" 72 | exit 0 73 | 74 | else 75 | echo "Temp Directory doesnt exist" 76 | exit 1 77 | fi 78 | fi -------------------------------------------------------------------------------- /scripts/buildProgramPresets.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var fs = require('fs'); 4 | 5 | var path = '../resources', 6 | dir = fs.readdirSync(path); 7 | var name, 8 | content, 9 | file = 'var ProgramPreset = {};\n\n'; 10 | 11 | var i,j,l,m; 12 | 13 | i = -1; l = dir.length; 14 | while(++i < l){ 15 | name = dir[i]; 16 | if(name[0] == '_'){ 17 | continue; 18 | } 19 | content = fs.readFileSync(path + '/' + name,{encoding:'utf8'}).split('\n'); 20 | name = name.slice(0,name.indexOf('.')); 21 | file += 'ProgramPreset.' + name[0].toUpperCase() + name.substring(1) + ' = \n'; 22 | 23 | j = -1; m = content.length-1; 24 | while(++j < m){ 25 | file += '"' + content[j] + '\\n" + \n'; 26 | } 27 | file += '"' + content[m] + '";\n\n'; 28 | } 29 | 30 | file += 'module.exports = ProgramPreset;'; 31 | 32 | fs.writeFile('../lib/gl/ProgramPreset.js',file, function (err) { 33 | if(err){ 34 | console.log(err); 35 | return; 36 | } 37 | console.log('done.'); 38 | }); 39 | -------------------------------------------------------------------------------- /scripts/buildWeb.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # IDE - shortcut 4 | # buildWeb - Browersify app.js, put bundle.js / index.html in clean temp folder, 5 | # open in browser. 6 | 7 | ((!$#)) && echo "PATH_TO_APP_JS PATH_TO_TEMP_DIR PATH_TO_BROWSER_APP(optional) missing" && exit 1 8 | 9 | args=("$@") 10 | 11 | ((${#args[@]}<2)) && echo "Args missing. Must satisfy PATH_TO_APP_JS PATH_TO_TEMP_DIR PATH_TO_BROWSER_APP(optional)." && exit 1 12 | 13 | pathjs=${args[0]} 14 | filejs=$(basename "${pathjs}") 15 | patht=${args[1]} 16 | 17 | (("${filejs#*.}"!="js")) && echo "no .js file" && exit 1 18 | 19 | rm -rf "$patht"/* 20 | 21 | browserify "$pathjs" -i plask > $patht/bundle.js 22 | 23 | cat > $patht/index.html <<- _EOF_ 24 | 25 | 26 | 27 | 28 | 29 | 33 | 34 | 35 | 36 | 37 | _EOF_ 38 | 39 | ((${#args[@]}==3)) && open -a "${args[2]}" "$patht"/index.html -------------------------------------------------------------------------------- /scripts/new.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var colors = require('colors'), 4 | argv = require('minimist')(process.argv.slice(2),{string:['p','t'],boolean:['s','w']}); 5 | 6 | function logUsageAndExit(){ 7 | console.log('Usage: new -p [path] -t [template] [-s]'.blue); 8 | process.exit(); 9 | } 10 | 11 | if(argv.h || argv.help || !argv.p || !argv.t){ 12 | logUsageAndExit(); 13 | } 14 | 15 | if(argv.p.length == 0){ 16 | console.log('✗ No path supplied!'.red); 17 | logUsageAndExit(); 18 | } 19 | 20 | var projectType = argv.t; 21 | var templates = ['basic2d', 'basic3d', 'basic3dTexture', 'basic3dLight']; 22 | 23 | if(!projectType.length){ 24 | console.log('✗ No template type supplied!'.red); 25 | logUsageAndExit(); 26 | } else if(templates.indexOf(projectType) == -1) { 27 | console.log(("✗ Wrong template type '" + projectType + "'!").red); 28 | console.log((' Use ' + templates.join(', ')).red); 29 | process.exit(); 30 | } 31 | 32 | var fs = require('fs'), 33 | path = require('path'); 34 | 35 | function dir(path){ 36 | if(!fs.existsSync(path)){ 37 | fs.mkdirSync(path); 38 | } 39 | return path; 40 | } 41 | 42 | function write(path,src){ 43 | fs.writeFileSync(path,src); 44 | } 45 | 46 | function read(path){ 47 | return fs.readFileSync(path,'utf8'); 48 | } 49 | 50 | function p(path_,add){ 51 | return path.join(path_,add); 52 | } 53 | 54 | var pathProject = dir(path.resolve(argv.p)), 55 | pathProjectSrc = pathProject, 56 | pathTemplates = p(__dirname,'templates'), 57 | pathResources = p(__dirname,'../resources'), 58 | shaderFile, 59 | pathShader, 60 | pathAppjs; 61 | 62 | var srcOnly = argv.s; 63 | 64 | if(!srcOnly){ 65 | write(p(pathProject,'index.html'),read(p(pathTemplates,'index.html'))); 66 | pathProjectSrc = dir(p(pathProject,'src')); 67 | } else { 68 | console.log(' Generating project without index.html.'.blue); 69 | } 70 | 71 | shaderFile = 'program.glsl'; 72 | pathShader = p(pathProjectSrc, shaderFile); 73 | pathAppjs = p(pathProjectSrc, 'app.js'); 74 | 75 | write(pathShader,read(p(pathResources,projectType + '.glsl'))); 76 | write(pathAppjs, read(p(pathTemplates,projectType + '.js')).replace('PATH_TO_SHADER','"' + p(srcOnly ? '.' : 'src',shaderFile) + '"')); 77 | 78 | console.log(('✓ Project of type ' + projectType +' generated at: ' + pathProject).yellow); 79 | 80 | if(argv.w){ 81 | var args = [pathAppjs,'-o',p(pathProject,'bundle.js'),'-d','-v']; 82 | console.log((' watchify ' + args.join(' ')).yellow); 83 | 84 | var child = require('child_process').spawn('watchify',args); 85 | child.stdout.pipe(process.stdout); 86 | child.stderr.pipe(process.stderr); 87 | } -------------------------------------------------------------------------------- /scripts/paths: -------------------------------------------------------------------------------- 1 | # !/bin/bash 2 | 3 | # V8 4 | V8=/Users/automat/Projects/v8 5 | TICK_PROCESSOR=${V8}/tools/mac-tick-processor 6 | PATH_D8=${V8}/out/native 7 | 8 | # PLASK 9 | PLASK=/Users/automat/WebstormProjects/plask/build/Release/Plask.app/Contents/MacOS/Plask 10 | 11 | # TEMP 12 | TEMP=/Users/automat/WebstormProjects/Foam/examples/temp 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /scripts/profilePlaskRun.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | . paths 4 | 5 | ((!$#)) && echo "PATH_TO_APP_JS missing." && exit 1 6 | 7 | filejs=$(basename "$1") 8 | dirjs=$(dirname "$1") 9 | 10 | if [ "${filejs#*.}" != "js" ] 11 | then 12 | echo "no .js file!" 13 | exit 1 14 | else 15 | ${PLASK} --prof "$1" 16 | wait 17 | echo "plask prof done" 18 | 19 | env D8_PATH="${PATH_D8}" "${TICK_PROCESSOR}" v8.log > "${dirjs}"/v8_processed.txt 20 | rm v8.log 21 | echo "prof process done" 22 | fi -------------------------------------------------------------------------------- /scripts/templates/basic2d.js: -------------------------------------------------------------------------------- 1 | var Foam = require('foam-gl'), 2 | Program = Foam.Program; 3 | 4 | Foam.App.newOnLoadWithResource({ 5 | path : PATH_TO_SHADER 6 | },{ 7 | setup: function(resource){ 8 | this.setWindowSize(800,600); 9 | this.setFPS(60); 10 | 11 | this._program = new Program(resource); 12 | this._program.bind(); 13 | 14 | var windowWidth = this.getWindowWidth(), 15 | windowHeight = this.getWindowHeight(); 16 | 17 | this._gl.viewport(0,0,windowWidth,windowHeight); 18 | this._glTrans.setWindowMatrices(windowWidth,windowHeight,true); 19 | }, 20 | update : function(){ 21 | var gl = this._gl, 22 | glTrans = this._glTrans, 23 | glDraw = this._glDraw; 24 | 25 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 26 | gl.clearColor(0.25,0.25,0.25,1.0); 27 | 28 | glTrans.pushMatrix(); 29 | glTrans.translate3f(this.getWindowWidth() * 0.5 - 50, this.getWindowHeight() * 0.5 - 50,0); 30 | glTrans.scale3f(100,100,0); 31 | glDraw.drawRect(); 32 | glTrans.popMatrix(); 33 | } 34 | }); -------------------------------------------------------------------------------- /scripts/templates/basic3d.js: -------------------------------------------------------------------------------- 1 | var Foam = require('foam-gl'), 2 | Program = Foam.Program, 3 | CameraPersp = Foam.CameraPersp; 4 | 5 | Foam.App.newOnLoadWithResource({ 6 | path : PATH_TO_SHADER 7 | },{ 8 | setup : function(resource){ 9 | this.setWindowSize(800, 600); 10 | this.setFPS(60); 11 | 12 | this._program = new Program(resource); 13 | this._program.bind(); 14 | 15 | this._camera = new CameraPersp(); 16 | this._camera.setPerspective(45.0,this.getWindowAspectRatio(),0.00125, 20.0); 17 | 18 | this._program.uniform1f('uPointSize',4.0); 19 | 20 | var gl = this._gl; 21 | 22 | gl.viewport(0,0,this.getWindowWidth(),this.getWindowHeight()); 23 | gl.enable(gl.DEPTH_TEST); 24 | }, 25 | update : function(){ 26 | var gl = this._gl, 27 | glDraw = this._glDraw, 28 | glTrans = this._glTrans; 29 | 30 | var t = this.getSecondsElapsed(); 31 | 32 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 33 | gl.clearColor(0.25,0.25,0.25,1.0); 34 | 35 | this._camera.setEye3f(Math.cos(t) * 3, 3, Math.sin(t) * 3); 36 | this._camera.updateMatrices(); 37 | 38 | glTrans.setMatricesCamera(this._camera); 39 | 40 | glDraw.drawPivot(); 41 | glDraw.drawCubeColored(); 42 | } 43 | } 44 | ); -------------------------------------------------------------------------------- /scripts/templates/basic3dLight.js: -------------------------------------------------------------------------------- 1 | var Foam = require('foam-gl'), 2 | Vec3 = Foam.Vec3, 3 | CameraPersp = Foam.CameraPersp, 4 | Program = Foam.Program, 5 | VboMeshPrimitive = Foam.VboMeshPrimitive, 6 | Light = Foam.Light, 7 | Material = Foam.Material; 8 | 9 | Foam.App.newOnLoadWithResource({ 10 | path: PATH_TO_SHADER 11 | }, { 12 | setup: function (resource) { 13 | this.setWindowSize(800,600); 14 | this.setFPS(60); 15 | 16 | this._program = new Program(resource); 17 | this._program.bind(); 18 | 19 | this._camera = new CameraPersp(60.0, this.getWindowAspectRatio(), 0.01, 20.0); 20 | this._camera.setEye(Vec3.one().scale(3)); 21 | this._camera.updateMatrices(); 22 | 23 | this._light = new Light(0); 24 | this._light.ambient.setf(1,1,1); 25 | 26 | this._material = new Material(); 27 | 28 | this._mesh = new VboMeshPrimitive.Cube(); 29 | 30 | this._program.uniform1f(Program.UNIFORM_POINT_SIZE,3.0); 31 | 32 | var gl = this._gl; 33 | gl.enable(gl.DEPTH_TEST); 34 | gl.viewport(0, 0, this.getWindowWidth(), this.getWindowHeight()); 35 | }, 36 | 37 | update: function () { 38 | var gl = this._gl, 39 | glDraw = this._glDraw, 40 | glTrans = this._glTrans; 41 | 42 | var program = this._program; 43 | 44 | var t = this.getSecondsElapsed(); 45 | 46 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 47 | gl.clearColor(0.25,0.25,0.25,1.0); 48 | 49 | this._camera.setEye3f(Math.cos(t) * 3, 3, Math.sin(t) * 3); 50 | this._camera.updateMatrices(); 51 | 52 | glTrans.setMatricesCamera(this._camera); 53 | 54 | var light = this._light; 55 | 56 | light.position.setf(Math.cos(t),Math.sin(t),Math.sin(t)*0.65); 57 | 58 | program.uniform1f('uUseLighting',0.0); 59 | glDraw.drawPivot(); 60 | light.debugDraw(); 61 | program.uniform1f('uUseLighting',1.0); 62 | 63 | light.draw(); 64 | 65 | this._material.ambient.setf(0.5 + Math.sin(t * 10) * 0.5,0,1); 66 | this._material.apply(); 67 | this._mesh.draw(); 68 | } 69 | } 70 | ); -------------------------------------------------------------------------------- /scripts/templates/basic3dTexture.js: -------------------------------------------------------------------------------- 1 | var Foam = require('foam-gl'), 2 | Program = Foam.Program, 3 | CameraPersp = Foam.CameraPersp, 4 | Texture = Foam.Texture; 5 | 6 | Foam.App.newOnLoadWithResource({ 7 | path : PATH_TO_SHADER 8 | },{ 9 | setup : function(resource){ 10 | this.setWindowSize(800, 600); 11 | this.setFPS(60); 12 | 13 | this._program = new Program(resource); 14 | this._program.bind(); 15 | 16 | this._camera = new CameraPersp(); 17 | this._camera.setPerspective(45.0,this.getWindowAspectRatio(),0.00125, 20.0); 18 | 19 | this._program.uniform1f('uPointSize',4.0); 20 | 21 | this._texture = Texture.fromRandom(100,100); 22 | this._texture.bind(0); 23 | 24 | var gl = this._gl; 25 | 26 | gl.viewport(0,0,this.getWindowWidth(),this.getWindowHeight()); 27 | gl.enable(gl.DEPTH_TEST); 28 | 29 | this._program.uniform1i('uTexture',0); 30 | }, 31 | update : function(){ 32 | var gl = this._gl, 33 | glDraw = this._glDraw, 34 | glTrans = this._glTrans; 35 | 36 | var program = this._program; 37 | 38 | var t = this.getSecondsElapsed(); 39 | 40 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 41 | gl.clearColor(0.25,0.25,0.25,1.0); 42 | 43 | this._camera.setEye3f(Math.cos(t) * 3, 3, Math.sin(t) * 3); 44 | this._camera.updateMatrices(); 45 | 46 | glTrans.setMatricesCamera(this._camera); 47 | 48 | program.uniform1f('uUseTexture',0.0); 49 | glDraw.drawPivot(); 50 | 51 | program.uniform1f('uUseTexture',1.0); 52 | 53 | glTrans.pushMatrix(); 54 | glTrans.translate3f(-0.5,-0.5,0); 55 | glDraw.drawRect(); 56 | glTrans.popMatrix(); 57 | } 58 | } 59 | ); -------------------------------------------------------------------------------- /scripts/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10 | 11 | 12 | 13 | 14 | --------------------------------------------------------------------------------