diff --git a/build/game-lib-min.js b/build/game-lib-min.js index 64b2d72..9a78985 100644 --- a/build/game-lib-min.js +++ b/build/game-lib-min.js @@ -1,2 +1,2 @@ -function GameLib(){}if("undefined"==typeof GameLib.D3&&(GameLib.D3=function(){}),"undefined"==typeof Q){if("undefined"==typeof require)throw console.warn("You need the Q promise library for the GameLib.D3"),new Error("You need the Q promise library for the GameLib.D3");var Q=require("q")}GameLib.D3.BoneWeight=function(e,i){this.boneIndex=e,this.weight=i},GameLib.D3.Bone=function(e,i,t,n,s,o,a,r,h,c){this.id=e,this.name=t,this.boneId=i,"undefined"==typeof n&&(n=[]),this.childBoneIds=n,"undefined"==typeof s&&(s=null),this.parentBoneId=s,"undefined"==typeof o&&(o=new GameLib.D3.Vector4),this.quaternion=o,"undefined"==typeof a&&(a=new GameLib.D3.Vector3(0,0,0)),this.position=a,"undefined"==typeof r&&(r=new GameLib.D3.Vector3(0,0,0)),this.rotation=r,"undefined"==typeof h&&(h=new GameLib.D3.Vector3(1,1,1)),this.scale=h,"undefined"==typeof c&&(c=new GameLib.D3.Vector3(0,1,0)),this.up=c},GameLib.D3.Broadphase=function(e,i,t,n,s){this.id=e,"undefined"==typeof i&&(i="broadphase-"+t),this.name=i,"undefined"==typeof t&&(t=GameLib.D3.Broadphase.BROADPHASE_TYPE_NAIVE),this.broadphaseType=t,"undefined"==typeof n&&(n=null),this.engine=n,this.instance=null,s&&this.createInstance()},GameLib.D3.Broadphase.prototype.createInstance=function(){if(!(this.engine instanceof GameLib.D3.Engine))throw console.warn("No Engine"),new Error("No Engine");this.engine.isNotCannonThrow();var e=null;if(this.broadphaseType==GameLib.D3.Broadphase.BROADPHASE_TYPE_NAIVE)e=new this.engine.instance.NaiveBroadphase;else if(this.broadphaseType==GameLib.D3.Broadphase.BROADPHASE_TYPE_GRID)e=new this.engine.instance.GridBroadphase;else{if(this.broadphaseType!=GameLib.D3.Broadphase.BROADPHASE_TYPE_SAP)throw console.warn("Unsupported broadphase type: "+this.broadphaseType),new Error("Unsupported broadphase type: "+this.broadphaseType);e=new this.engine.instance.SAPBroardphase}return this.instance=e,e},GameLib.D3.Broadphase.BROADPHASE_TYPE_NAIVE=1,GameLib.D3.Broadphase.BROADPHASE_TYPE_GRID=2,GameLib.D3.Broadphase.BROADPHASE_TYPE_SAP=3,GameLib.D3.Color=function(e,i,t,n){this.r=e,this.g=i,this.b=t,this.a=n},GameLib.D3.Engine=function(e,i){this.engineType=e,this.instance=i},GameLib.D3.Engine.prototype.isCannon=function(){return this.engineType==GameLib.D3.Engine.ENGINE_TYPE_CANNON},GameLib.D3.Engine.prototype.isNotCannonThrow=function(){if(this.engineType!=GameLib.D3.Engine.ENGINE_TYPE_CANNON)throw console.warn("Only CANNON supported for this function"),new Error("Only CANNON supported for this function")},GameLib.D3.Engine.prototype.isAmmo=function(){return this.engineType==GameLib.D3.Engine.ENGINE_TYPE_AMMO},GameLib.D3.Engine.prototype.isGoblin=function(){return this.engineType==GameLib.D3.Engine.ENGINE_TYPE_GOBLIN},GameLib.D3.Engine.ENGINE_TYPE_CANNON=1,GameLib.D3.Engine.ENGINE_TYPE_AMMO=2,GameLib.D3.Engine.ENGINE_TYPE_GOBLIN=3,GameLib.D3.FlyControls=function(e,i,t){this.flySpeed=100,this.canvas=t,this.THREE=i,this.yaw=0,this.pitch=0,this.canRotate=!1,this.moveForward=!1,this.moveBackward=!1,this.moveLeft=!1,this.moveRight=!1,this.moveUp=!1,this.moveDown=!1,this.mouseUpCallback=this.onMouseUp.bind(this),this.mouseDownCallback=this.onMouseDown.bind(this),this.mouseMoveCallback=this.onMouseMove.bind(this),this.mouseWheelCallback=this.onMouseWheel.bind(this),this.keyDownCallback=this.onKeyDown.bind(this),this.keyUpCallback=this.onKeyUp.bind(this),this.camera=e,this.canvas.addEventListener("keydown",this.keyDownCallback,!1),this.canvas.addEventListener("keyup",this.keyUpCallback,!1),this.canvas.addEventListener("mousedown",this.mouseDownCallback,!1),this.canvas.addEventListener("mouseup",this.mouseUpCallback,!1),this.canvas.addEventListener("mousewheel",this.mouseWheelCallback,!1),this.havePointerLock="pointerLockElement"in document||"mozPointerLockElement"in document||"webkitPointerLockElement"in document,this.element=document.body,this.havePointerLock&&(this.element.requestPointerLock=this.element.requestPointerLock||this.element.mozRequestPointerLock||this.element.webkitRequestPointerLock,document.exitPointerLock=document.exitPointerLock||document.mozExitPointerLock||document.webkitExitPointerLock)},GameLib.D3.FlyControls.prototype.onMouseWheel=function(e){this.moveForward=!0,this.applyTranslation(.001*e.wheelDelta),e.preventDefault(),this.moveForward=!1},GameLib.D3.FlyControls.prototype.onMouseDown=function(e){1==e.button&&(this.canRotate=!0,this.canvas.addEventListener("mousemove",this.mouseMoveCallback,!1))},GameLib.D3.FlyControls.prototype.onMouseUp=function(e){1==e.button&&(this.canRotate=!1,this.canvas.removeEventListener("mousemove",this.mouseMoveCallback))},GameLib.D3.FlyControls.prototype.applyRotation=function(){this.camera.rotation.set(this.pitch,this.yaw,0,"YXZ")},GameLib.D3.FlyControls.prototype.applyTranslation=function(e){var i=new this.THREE.Vector3(0,0,-1),t=new this.THREE.Euler(0,0,0,"YXZ");t.set(this.pitch,this.yaw,0,"YXZ"),i=i.applyEuler(t);var n=i.normalize(),s=n.cross(new this.THREE.Vector3(0,1,0));this.moveForward?(this.camera.position.x+=n.x*(e*this.flySpeed),this.camera.position.y+=n.y*(e*this.flySpeed),this.camera.position.z+=n.z*(e*this.flySpeed)):this.moveBackward&&(this.camera.position.x-=n.x*(e*this.flySpeed),this.camera.position.y-=n.y*(e*this.flySpeed),this.camera.position.z-=n.z*(e*this.flySpeed)),this.moveLeft?(this.camera.position.x-=s.x*(e*this.flySpeed),this.camera.position.y-=s.y*(e*this.flySpeed),this.camera.position.z-=s.z*(e*this.flySpeed)):this.moveRight&&(this.camera.position.x+=s.x*(e*this.flySpeed),this.camera.position.y+=s.y*(e*this.flySpeed),this.camera.position.z+=s.z*(e*this.flySpeed)),this.moveUp?this.camera.position.y+=e*this.flySpeed:this.moveDown&&(this.camera.position.y-=e*this.flySpeed)},GameLib.D3.FlyControls.prototype.update=function(e){this.applyRotation(),this.applyTranslation(e)},GameLib.D3.FlyControls.prototype.onMouseMove=function(e){if(this.canRotate){var i=e.movementX||e.mozMovementX||e.webkitMovementX||0,t=e.movementY||e.mozMovementY||e.webkitMovementY||0;this.yaw-=.002*i,this.pitch-=.002*t}},GameLib.D3.FlyControls.prototype.onKeyDown=function(e){switch(e.keyCode){case 87:this.moveForward=!0;break;case 65:this.moveLeft=!0;break;case 83:this.moveBackward=!0;break;case 68:this.moveRight=!0;break;case 104:this.moveUp=!0;break;case 98:this.moveDown=!0}},GameLib.D3.FlyControls.prototype.onKeyUp=function(e){switch(e.keyCode){case 38:case 87:this.moveForward=!1;break;case 37:case 65:this.moveLeft=!1;break;case 40:case 83:this.moveBackward=!1;break;case 39:case 68:this.moveRight=!1;break;case 104:this.moveUp=!1;break;case 98:this.moveDown=!1}},GameLib.D3.Game=function(){this.scenes={},this.physicsWorlds=[],this.sceneToPhysicsWorldsMap={}},GameLib.D3.Game.prototype.AddScene=function(e){this.scenes[e.name]=e},GameLib.D3.Game.prototype.AddPhysicsWorld=function(e){this.physicsWorlds.push(e)},GameLib.D3.Game.prototype.LinkPhysicsWorldToScene=function(e,i){this.sceneToPhysicsWorldsMap[i.name]=this.sceneToPhysicsWorldsMap[i.name]||[],this.sceneToPhysicsWorldsMap[i.name].push(e)},GameLib.D3.Game.prototype.GetPhysicsWorldsForScene=function(e){return this.sceneToPhysicsWorldsMap[e.name]},GameLib.D3.Game.prototype.ProcessPhysics=function(e){for(var i in this.sceneToPhysicsWorldsMap){var t=this.sceneToPhysicsWorldsMap[i],n=this.scenes[i];if(n&&t)for(var s=0,o=t.length;s0){var r=GameLib.D3.Texture.loadMaps(e,a,o,i,t,n);Q.all(r).then(function(){s.resolve(o)}).catch(function(e){console.log(e),s.reject(e)})}else s.resolve(o);return s.promise},GameLib.D3.Matrix3=function(e,i,t){this.identity(),e&&(this.rows[0]=e),i&&(this.rows[1]=i),t&&(this.rows[2]=t)},GameLib.D3.Matrix3.prototype.identity=function(){this.rows=[new GameLib.D3.Vector4(1,0,0),new GameLib.D3.Vector4(0,1,0),new GameLib.D3.Vector4(0,0,1)]},GameLib.D3.Matrix4=function(e,i,t,n){this.identity(),e&&(this.rows[0]=e),i&&(this.rows[1]=i),t&&(this.rows[2]=t),n&&(this.rows[3]=n)},GameLib.D3.Matrix4.prototype.rotationMatrixX=function(e){return this.identity(),this.rows[1]=new GameLib.D3.Vector4(0,Math.cos(e),-1*Math.sin(e),0),this.rows[2]=new GameLib.D3.Vector4(0,Math.sin(e),Math.cos(e),0),this},GameLib.D3.Matrix4.prototype.rotationMatrixY=function(e){return this.identity(),this.rows[0]=new GameLib.D3.Vector4(Math.cos(e),0,Math.sin(e),0),this.rows[2]=new GameLib.D3.Vector4(-1*Math.sin(e),0,Math.cos(e),0),this},GameLib.D3.Matrix4.prototype.rotationMatrixZ=function(e){return this.identity(),this.rows[0]=new GameLib.D3.Vector4(Math.cos(e),-1*Math.sin(e),0,0),this.rows[1]=new GameLib.D3.Vector4(Math.sin(e),Math.cos(e),0,0),this},GameLib.D3.Matrix4.prototype.rotateX=function(e,i){return this.identity(),this.rotationMatrixX(e),this.multiply(i)},GameLib.D3.Matrix4.prototype.rotateY=function(e,i){return this.identity(),this.rotationMatrixY(e),this.multiply(i)},GameLib.D3.Matrix4.prototype.rotateZ=function(e,i){return this.identity(),this.rotationMatrixZ(e),this.multiply(i)},GameLib.D3.Matrix4.prototype.multiply=function(e){return e instanceof GameLib.D3.Vector4?new GameLib.D3.Vector4(this.rows[0].x*e.x+this.rows[0].y*e.y+this.rows[0].z*e.z+this.rows[0].w*e.w,this.rows[1].x*e.x+this.rows[1].y*e.y+this.rows[1].z*e.z+this.rows[1].w*e.w,this.rows[2].x*e.x+this.rows[2].y*e.y+this.rows[2].z*e.z+this.rows[2].w*e.w,this.rows[3].x*e.x+this.rows[3].y*e.y+this.rows[3].z*e.z+this.rows[3].w*e.w):e instanceof GameLib.D3.Vector3?new GameLib.D3.Vector3(this.rows[0].x*e.x+this.rows[0].y*e.y+this.rows[0].z*e.z,this.rows[1].x*e.x+this.rows[1].y*e.y+this.rows[1].z*e.z,this.rows[2].x*e.x+this.rows[2].y*e.y+this.rows[2].z*e.z):void 0},GameLib.D3.Matrix4.prototype.identity=function(){this.rows=[new GameLib.D3.Vector4(1,0,0,0),new GameLib.D3.Vector4(0,1,0,0),new GameLib.D3.Vector4(0,0,1,0),new GameLib.D3.Vector4(0,0,0,1)]},GameLib.D3.Matrix4.prototype.lookAt=function(e,i,t){var n=new GameLib.D3.Vector3(e.x,e.y,e.z),s=n.subtract(i).normalize();0===s.squared()&&(s.z=1);var o=t.cross(s).normalize();0===o.squared()&&(s.x+=1e-4,o=t.cross(s).normalize());var a=s.cross(o);return this.rows[0].x=o.x,this.rows[0].y=o.y,this.rows[0].z=o.z,this.rows[1].x=a.x,this.rows[1].y=a.y,this.rows[1].z=a.z,this.rows[2].x=s.x,this.rows[2].y=s.y,this.rows[2].z=s.z,this},GameLib.D3.Mesh=function(e,i,t,n,s,o,a,r,h,c,l,p,m,d,u,y,f,b,L,v){this.id=e,this.path=i,this.name=t,this.meshType=n,this.vertices=s,this.faces=o,"undefined"==typeof a&&(a=null),this.skeleton=a,"undefined"==typeof r&&(r=[]),this.faceVertexUvs=r,"undefined"==typeof h&&(h=[]),this.skinIndices=h,"undefined"==typeof c&&(c=[]),this.skinWeights=c,"undefined"==typeof l&&(l=[]),this.materials=l,"undefined"==typeof p&&(p=new GameLib.D3.Vector3(0,0,0)),this.position=p,"undefined"==typeof m&&new GameLib.D3.Vector4,this.quaternion=m,"undefined"==typeof d&&(d=new GameLib.D3.Vector3(0,0,0)),this.rotation=d,"undefined"==typeof u&&(u=new GameLib.D3.Vector3(1,1,1)),this.scale=u,"undefined"==typeof y&&(y=new GameLib.D3.Vector3(0,1,0)),this.up=y,this.physics=f,this.parentMeshId=b,this.parentSceneId=L,this.rawData=null},GameLib.D3.Mesh.TYPE_NORMAL=0,GameLib.D3.Mesh.TYPE_SKINNED=1,GameLib.D3.Mesh.createInstanceMesh=function(e,i,t,n){var s=null;if(e.meshType==GameLib.D3.Mesh.TYPE_NORMAL&&(s=new n.instance.Mesh(i,t)),e.meshType==GameLib.D3.Mesh.TYPE_SKINNED){for(var o=e.skeleton.bones,a=e.skinIndices,r=e.skinWeights,h=[],c=0;c0;){var a=s.pop();if(a.triangle.v0==a.edge.x&&a.triangle.v1==a.edge.y||a.triangle.v1==a.edge.x&&a.triangle.v2==a.edge.y||a.triangle.v2==a.edge.x&&a.triangle.v0==a.edge.y){var r=a.triangle.v1;a.triangle.v1=a.triangle.v2,a.triangle.v2=r;var h=a.triangle.v1uv;a.triangle.v1uv=a.triangle.v2uv,a.triangle.v2uv=h}o.push(a);for(var c=[new GameLib.D3.Vector2(a.triangle.v0,a.triangle.v1),new GameLib.D3.Vector2(a.triangle.v1,a.triangle.v2),new GameLib.D3.Vector2(a.triangle.v2,a.triangle.v0)],l=0;l9||console.log("The vertices are not in the right length : "+e.length);for(var t=[],n=new GameLib.D3.Vector4.Points,s=0;s0)for(var h=0;h0},GameLib.D3.Vector3.normal=function(e,i,t){var n=i.copy(),s=t.copy();return n.subtract(e).cross(s.subtract(e))},GameLib.D3.Vector3.prototype.lookAt=function(e,i){var t=GameLib.D3.Matrix4.lookAt(this,e,i);this.multiply(t)},GameLib.D3.Vector3.prototype.translate=function(e){return this.x+=e.x,this.y+=e.y,this.z+=e.z,this},GameLib.D3.Vector3.prototype.squared=function(){return this.x*this.x+this.y*this.y+this.z*this.z};GameLib.D3.Vector3.prototype.copy=function(){return new GameLib.D3.Vector3(this.x,this.y,this.z)};GameLib.D3.Vector3.prototype.multiply=function(e){if(e instanceof GameLib.D3.Vector3)this.x*=e.x,this.y*=e.y,this.z*=e.z;else{if(!(e instanceof GameLib.D3.Matrix4))throw console.log("functionality not implemented - please do this"),new Error("not implemented");var i=e.rows[0].x*this.x+e.rows[0].y*this.y+e.rows[0].z*this.z,t=e.rows[1].x*this.x+e.rows[1].y*this.y+e.rows[1].z*this.z,n=e.rows[2].x*this.x+e.rows[2].y*this.y+e.rows[2].z*this.z;this.x=i,this.y=t,this.z=n}return this},GameLib.D3.Vector3.prototype.dot=function(e){return this.x*e.x+this.y*e.y+this.z*e.z},GameLib.D3.Vector3.prototype.normalize=function(){var e=1e-6,i=this.squared();if(io&&(o=h.x,n=i*e)}this.vectors=s;for(var c=(new GameLib.D3.Matrix4).rotationMatrixY(n),l=0;lo&&(o=h.y,n=i*e)}this.vectors=s;for(var c=(new GameLib.D3.Matrix4).rotationMatrixX(n),l=0;ln&&(n=this.vectors[a].x),this.vectors[a].y>s&&(s=this.vectors[a].y),this.vectors[a].z>o&&(o=this.vectors[a].z);return new GameLib.D3.Vector3(Math.abs(n-e),Math.abs(s-i),Math.abs(s-t))},GameLib.D3.Vector4.Points.prototype.average=function(){for(var e=0,i=0,t=0,n=0;n0){var r=GameLib.D3.Texture.loadMaps(e,a,o,t,i,n);Q.all(r).then(function(){s.resolve(o)}).catch(function(e){console.log(e),s.reject(e)})}else s.resolve(o);return s.promise},GameLib.D3.Matrix3=function(e,t,i){this.identity(),e&&(this.rows[0]=e),t&&(this.rows[1]=t),i&&(this.rows[2]=i)},GameLib.D3.Matrix3.prototype.identity=function(){this.rows=[new GameLib.D3.Vector4(1,0,0),new GameLib.D3.Vector4(0,1,0),new GameLib.D3.Vector4(0,0,1)]},GameLib.D3.Matrix4=function(e,t,i,n){this.identity(),e&&(this.rows[0]=e),t&&(this.rows[1]=t),i&&(this.rows[2]=i),n&&(this.rows[3]=n)},GameLib.D3.Matrix4.prototype.rotationMatrixX=function(e){return this.identity(),this.rows[1]=new GameLib.D3.Vector4(0,Math.cos(e),-1*Math.sin(e),0),this.rows[2]=new GameLib.D3.Vector4(0,Math.sin(e),Math.cos(e),0),this},GameLib.D3.Matrix4.prototype.rotationMatrixY=function(e){return this.identity(),this.rows[0]=new GameLib.D3.Vector4(Math.cos(e),0,Math.sin(e),0),this.rows[2]=new GameLib.D3.Vector4(-1*Math.sin(e),0,Math.cos(e),0),this},GameLib.D3.Matrix4.prototype.rotationMatrixZ=function(e){return this.identity(),this.rows[0]=new GameLib.D3.Vector4(Math.cos(e),-1*Math.sin(e),0,0),this.rows[1]=new GameLib.D3.Vector4(Math.sin(e),Math.cos(e),0,0),this},GameLib.D3.Matrix4.prototype.rotateX=function(e,t){return this.identity(),this.rotationMatrixX(e),this.multiply(t)},GameLib.D3.Matrix4.prototype.rotateY=function(e,t){return this.identity(),this.rotationMatrixY(e),this.multiply(t)},GameLib.D3.Matrix4.prototype.rotateZ=function(e,t){return this.identity(),this.rotationMatrixZ(e),this.multiply(t)},GameLib.D3.Matrix4.prototype.multiply=function(e){return e instanceof GameLib.D3.Vector4?new GameLib.D3.Vector4(this.rows[0].x*e.x+this.rows[0].y*e.y+this.rows[0].z*e.z+this.rows[0].w*e.w,this.rows[1].x*e.x+this.rows[1].y*e.y+this.rows[1].z*e.z+this.rows[1].w*e.w,this.rows[2].x*e.x+this.rows[2].y*e.y+this.rows[2].z*e.z+this.rows[2].w*e.w,this.rows[3].x*e.x+this.rows[3].y*e.y+this.rows[3].z*e.z+this.rows[3].w*e.w):e instanceof GameLib.D3.Vector3?new GameLib.D3.Vector3(this.rows[0].x*e.x+this.rows[0].y*e.y+this.rows[0].z*e.z,this.rows[1].x*e.x+this.rows[1].y*e.y+this.rows[1].z*e.z,this.rows[2].x*e.x+this.rows[2].y*e.y+this.rows[2].z*e.z):void 0},GameLib.D3.Matrix4.prototype.identity=function(){this.rows=[new GameLib.D3.Vector4(1,0,0,0),new GameLib.D3.Vector4(0,1,0,0),new GameLib.D3.Vector4(0,0,1,0),new GameLib.D3.Vector4(0,0,0,1)]},GameLib.D3.Matrix4.prototype.lookAt=function(e,t,i){var n=new GameLib.D3.Vector3(e.x,e.y,e.z),s=n.subtract(t).normalize();0===s.squared()&&(s.z=1);var o=i.cross(s).normalize();0===o.squared()&&(s.x+=1e-4,o=i.cross(s).normalize());var a=s.cross(o);return this.rows[0].x=o.x,this.rows[0].y=o.y,this.rows[0].z=o.z,this.rows[1].x=a.x,this.rows[1].y=a.y,this.rows[1].z=a.z,this.rows[2].x=s.x,this.rows[2].y=s.y,this.rows[2].z=s.z,this},GameLib.D3.Mesh=function(e,t,i,n,s,o,a,r,h,c,l,p,d,m,u,f,y,L,b,v){this.id=e,this.path=t,this.name=i,this.meshType=n,this.vertices=s,this.faces=o,"undefined"==typeof a&&(a=null),this.skeleton=a,"undefined"==typeof r&&(r=[]),this.faceVertexUvs=r,"undefined"==typeof h&&(h=[]),this.skinIndices=h,"undefined"==typeof c&&(c=[]),this.skinWeights=c,"undefined"==typeof l&&(l=[]),this.materials=l,"undefined"==typeof p&&(p=new GameLib.D3.Vector3(0,0,0)),this.position=p,"undefined"==typeof d&&new GameLib.D3.Vector4,this.quaternion=d,"undefined"==typeof m&&(m=new GameLib.D3.Vector3(0,0,0)),this.rotation=m,"undefined"==typeof u&&(u=new GameLib.D3.Vector3(1,1,1)),this.scale=u,"undefined"==typeof f&&(f=new GameLib.D3.Vector3(0,1,0)),this.up=f,this.physics=y,this.parentMeshId=L,this.parentSceneId=b,this.rawData=null},GameLib.D3.Mesh.TYPE_NORMAL=0,GameLib.D3.Mesh.TYPE_SKINNED=1,GameLib.D3.Mesh.createInstanceMesh=function(e,t,i,n){var s=null;if(e.meshType==GameLib.D3.Mesh.TYPE_NORMAL&&(s=new n.instance.Mesh(t,i)),e.meshType==GameLib.D3.Mesh.TYPE_SKINNED){for(var o=e.skeleton.bones,a=e.skinIndices,r=e.skinWeights,h=[],c=0;c0;){var a=s.pop();if(a.triangle.v0==a.edge.x&&a.triangle.v1==a.edge.y||a.triangle.v1==a.edge.x&&a.triangle.v2==a.edge.y||a.triangle.v2==a.edge.x&&a.triangle.v0==a.edge.y){var r=a.triangle.v1;a.triangle.v1=a.triangle.v2,a.triangle.v2=r;var h=a.triangle.v1uv;a.triangle.v1uv=a.triangle.v2uv,a.triangle.v2uv=h}o.push(a);for(var c=[new GameLib.D3.Vector2(a.triangle.v0,a.triangle.v1),new GameLib.D3.Vector2(a.triangle.v1,a.triangle.v2),new GameLib.D3.Vector2(a.triangle.v2,a.triangle.v0)],l=0;l9||console.log("The vertices are not in the right length : "+e.length);for(var i=[],n=new GameLib.D3.Vector4.Points,s=0;s0)for(var h=0;h0},GameLib.D3.Vector3.normal=function(e,t,i){var n=t.copy(),s=i.copy();return n.subtract(e).cross(s.subtract(e))},GameLib.D3.Vector3.prototype.lookAt=function(e,t){var i=GameLib.D3.Matrix4.lookAt(this,e,t);this.multiply(i)},GameLib.D3.Vector3.prototype.translate=function(e){return this.x+=e.x,this.y+=e.y,this.z+=e.z,this},GameLib.D3.Vector3.prototype.squared=function(){return this.x*this.x+this.y*this.y+this.z*this.z},GameLib.D3.Vector3.prototype.copy=function(){return new GameLib.D3.Vector3(this.x,this.y,this.z)},GameLib.D3.Vector3.prototype.multiply=function(e){if(e instanceof GameLib.D3.Vector3)this.x*=e.x,this.y*=e.y,this.z*=e.z;else{if(!(e instanceof GameLib.D3.Matrix4))throw console.log("functionality not implemented - please do this"),new Error("not implemented");var t=e.rows[0].x*this.x+e.rows[0].y*this.y+e.rows[0].z*this.z,i=e.rows[1].x*this.x+e.rows[1].y*this.y+e.rows[1].z*this.z,n=e.rows[2].x*this.x+e.rows[2].y*this.y+e.rows[2].z*this.z;this.x=t,this.y=i,this.z=n}return this},GameLib.D3.Vector3.prototype.dot=function(e){return this.x*e.x+this.y*e.y+this.z*e.z},GameLib.D3.Vector3.prototype.normalize=function(){var e=1e-6,t=this.squared();if(to&&(o=h.x,n=t*e)}this.vectors=s;for(var c=(new GameLib.D3.Matrix4).rotationMatrixY(n),l=0;lo&&(o=h.y,n=t*e)}this.vectors=s;for(var c=(new GameLib.D3.Matrix4).rotationMatrixX(n),l=0;ln&&(n=this.vectors[a].x),this.vectors[a].y>s&&(s=this.vectors[a].y),this.vectors[a].z>o&&(o=this.vectors[a].z);return new GameLib.D3.Vector3(Math.abs(n-e),Math.abs(s-t),Math.abs(s-i))},GameLib.D3.Vector4.Points.prototype.average=function(){for(var e=0,t=0,i=0,n=0;n 0) { + var textureMaps = GameLib.D3.Texture.loadMaps( + gameLibMaterial, + blenderMaps, + instanceMaterial, + graphics, + uploadUrl, + progressCallback + ); + Q.all(textureMaps).then( + function(){ + defer.resolve(instanceMaterial); + } + ).catch( + function(error){ + console.log(error); + defer.reject(error); + } + ) + } else { + defer.resolve(instanceMaterial); + } + + return defer.promise; +}; +/** + * Matrix 3 Maths + * @param row0 GameLib.D3.Vector3 + * @param row1 GameLib.D3.Vector3 + * @param row2 GameLib.D3.Vector3 * @constructor */ -GameLib.D3.Skeleton = function( - id, - bones, - boneInverses, - useVertexTexture, - boneTextureWidth, - boneTextureHeight, - boneMatrices, - boneTexture +GameLib.D3.Matrix3 = function( + row0, + row1, + row2 ) { - this.id = id; + this.identity(); - this.bones = bones; - - /** - * An array of Matrix4s that represent the inverse of the matrixWorld of the individual bones. - * @type GameLib.D3.Matrix4[] - */ - if (typeof boneInverses == 'undefined') { - boneInverses = []; - } - this.boneInverses = boneInverses; - - /** - * Use a vertex texture in the shader - allows for more than 4 bones per vertex, not supported by all devices - * @type {boolean} - */ - if (typeof useVertexTexture == 'undefined') { - useVertexTexture = false; - } - this.useVertexTexture = useVertexTexture; - - if (this.useVertexTexture == true) { - console.warn('support for vertex texture bones is not supported yet - something could break somewhere'); + if (row0) { + this.rows[0] = row0; } - if (typeof boneTextureWidth == 'undefined') { - boneTextureWidth = 0; + if (row1) { + this.rows[1] = row1; } - this.boneTextureWidth = boneTextureWidth; - if (typeof boneTextureHeight == 'undefined') { - boneTextureHeight = 0; + if (row2) { + this.rows[2] = row2; } - this.boneTextureHeight = boneTextureHeight; +}; - if (typeof boneMatrices == 'undefined') { - boneMatrices = []; - } - this.boneMatrices = boneMatrices; +/** + * Set matrix to identity + */ +GameLib.D3.Matrix3.prototype.identity = function () { + this.rows = [ + new GameLib.D3.Vector4(1, 0, 0), + new GameLib.D3.Vector4(0, 1, 0), + new GameLib.D3.Vector4(0, 0, 1) + ]; +}; +GameLib.D3.Matrix4 = function( + row0, + row1, + row2, + row3 +) { - if (typeof boneTexture == 'undefined') { - boneTexture = []; + this.identity(); + + if (row0) { + this.rows[0] = row0; } - this.boneTexture = boneTexture; + + if (row1) { + this.rows[1] = row1; + } + + if (row2) { + this.rows[2] = row2; + } + + if (row3) { + this.rows[3] = row3; + } +}; + +GameLib.D3.Matrix4.prototype.rotationMatrixX = function (radians) { + this.identity(); + this.rows[1] = new GameLib.D3.Vector4(0, Math.cos(radians), -1 * Math.sin(radians), 0); + this.rows[2] = new GameLib.D3.Vector4(0, Math.sin(radians), Math.cos(radians), 0); + return this; +}; + +GameLib.D3.Matrix4.prototype.rotationMatrixY = function (radians) { + this.identity(); + this.rows[0] = new GameLib.D3.Vector4( + Math.cos(radians), + 0, + Math.sin(radians), + 0 + ); + this.rows[2] = new GameLib.D3.Vector4( + -1 * Math.sin(radians), + 0, + Math.cos(radians), + 0 + ); + return this; +}; + +GameLib.D3.Matrix4.prototype.rotationMatrixZ = function (radians) { + this.identity(); + this.rows[0] = new GameLib.D3.Vector4(Math.cos(radians), -1 * Math.sin(radians), 0, 0); + this.rows[1] = new GameLib.D3.Vector4(Math.sin(radians), Math.cos(radians), 0, 0); + return this; +}; + +GameLib.D3.Matrix4.prototype.rotateX = function (radians, point) { + this.identity(); + this.rotationMatrixX(radians); + return this.multiply(point); +}; + +GameLib.D3.Matrix4.prototype.rotateY = function (radians, point) { + this.identity(); + this.rotationMatrixY(radians); + return this.multiply(point); +}; + +GameLib.D3.Matrix4.prototype.rotateZ = function (radians, point) { + this.identity(); + this.rotationMatrixZ(radians); + return this.multiply(point); +}; + +GameLib.D3.Matrix4.prototype.multiply = function (mvp) { + if (mvp instanceof GameLib.D3.Vector4) { + return new GameLib.D3.Vector4( + this.rows[0].x * mvp.x + this.rows[0].y * mvp.y + this.rows[0].z * mvp.z + this.rows[0].w * mvp.w, + this.rows[1].x * mvp.x + this.rows[1].y * mvp.y + this.rows[1].z * mvp.z + this.rows[1].w * mvp.w, + this.rows[2].x * mvp.x + this.rows[2].y * mvp.y + this.rows[2].z * mvp.z + this.rows[2].w * mvp.w, + this.rows[3].x * mvp.x + this.rows[3].y * mvp.y + this.rows[3].z * mvp.z + this.rows[3].w * mvp.w + ); + } else if (mvp instanceof GameLib.D3.Vector3) { + return new GameLib.D3.Vector3( + this.rows[0].x * mvp.x + this.rows[0].y * mvp.y + this.rows[0].z * mvp.z, + this.rows[1].x * mvp.x + this.rows[1].y * mvp.y + this.rows[1].z * mvp.z, + this.rows[2].x * mvp.x + this.rows[2].y * mvp.y + this.rows[2].z * mvp.z + ); + } +}; + +GameLib.D3.Matrix4.prototype.identity = function () { + this.rows = [ + new GameLib.D3.Vector4(1, 0, 0, 0), + new GameLib.D3.Vector4(0, 1, 0, 0), + new GameLib.D3.Vector4(0, 0, 1, 0), + new GameLib.D3.Vector4(0, 0, 0, 1) + ]; +}; + +GameLib.D3.Matrix4.prototype.lookAt = function (position, target, up) { + + var pv = new GameLib.D3.Vector3(position.x, position.y, position.z); + + var z = pv.subtract(target).normalize(); + + if (z.squared() === 0) { + z.z = 1; + } + + var x = up.cross(z).normalize(); + + if (x.squared() === 0) { + z.x += 0.0001; + x = up.cross(z).normalize(); + } + + var y = z.cross(x); + + this.rows[0].x = x.x; + this.rows[0].y = x.y; + this.rows[0].z = x.z; + + this.rows[1].x = y.x; + this.rows[1].y = y.y; + this.rows[1].z = y.z; + + this.rows[2].x = z.x; + this.rows[2].y = z.y; + this.rows[2].z = z.z; + + return this; + + // te[ 0 ] = x.x; te[ 4 ] = y.x; te[ 8 ] = z.x; + // te[ 1 ] = x.y; te[ 5 ] = y.y; te[ 9 ] = z.y; + // te[ 2 ] = x.z; te[ 6 ] = y.z; te[ 10 ] = z.z; + + + // var matrix4 = new Matrix4(); + // + // matrix4.rows[0] = side.negative(); + // matrix4.rows[1] = _up; + // matrix4.rows[2] = forward; + + // + // matrix4.setColumn(0, side.negative()); + // matrix4.setColumn(1, _up); + // matrix4.setColumn(2, forward); + + //return matrix4; + + // return new Matrix4( + // new Vector4( + // side.x, + // side.y, + // side.z, + // side.negative().dot(position) + // ), + // new Vector4( + // _up.x, + // _up.y, + // _up.z, + // _up.negative().dot(position) + // ), + // new Vector4( + // forward.negative().x, + // forward.negative().y, + // forward.negative().z, + // forward.dot(position) + // ) + // ) }; /** @@ -1033,6 +1926,7 @@ GameLib.D3.Mesh = function( this.rawData = null;// rawData; }; + /** * Mesh Type * @type {number} @@ -1040,574 +1934,206 @@ GameLib.D3.Mesh = function( GameLib.D3.Mesh.TYPE_NORMAL = 0; GameLib.D3.Mesh.TYPE_SKINNED = 1; -/** - * Bone Superset - * @param id - * @param name string - * @param boneId - * @param childBoneIds - * @param parentBoneId - * @param quaternion - * @param position - * @param rotation - * @param scale GameLib.D3.Vector3 - * @param up - * @param rawData - * @constructor - */ -GameLib.D3.Bone = function( - id, - boneId, - name, - childBoneIds, - parentBoneId, - quaternion, - position, - rotation, - scale, - up, - rawData -) { - this.id = id; - this.name = name; - this.boneId = boneId; - - if (typeof childBoneIds == 'undefined') { - childBoneIds = []; - } - this.childBoneIds = childBoneIds; - - if (typeof parentBoneId == 'undefined') { - parentBoneId = null; - } - this.parentBoneId = parentBoneId; - - if (typeof quaternion == 'undefined') { - quaternion = new GameLib.D3.Vector4(); - } - this.quaternion = quaternion; - - if (typeof position == 'undefined') { - position = new GameLib.D3.Vector3(0,0,0); - } - this.position = position; - - if (typeof rotation == 'undefined') { - rotation = new GameLib.D3.Vector3(0,0,0); - } - this.rotation = rotation; - - if (typeof scale == 'undefined') { - scale = new GameLib.D3.Vector3(1,1,1); - } - this.scale = scale; - - if (typeof up == 'undefined') { - up = new GameLib.D3.Vector3(0,1,0); - } - this.up = up; - - this.rawData = null;//rawData; -}; - -GameLib.D3.Physics = function() {}; /** - * Physics Engine Superset - * @param id - * @param name - * @param engineType - * @param engine - * @constructor + * Creates a THREE Mesh from GameLib.D3.Mesh + * @param gameLibMesh GameLib.D3.Mesh + * @param instanceGeometry + * @param instanceMaterial + * @param graphics + * @returns {*} */ -GameLib.D3.Physics.Engine = function( - id, - name, - engineType, - engine -) { - this.id = id; - this.name = name; - this.engineType = engineType; - this.engine = engine; -}; +GameLib.D3.Mesh.createInstanceMesh = function(gameLibMesh, instanceGeometry, instanceMaterial, graphics) { -/** - * Physics Engine Types - * @type {number} - */ -GameLib.D3.Physics.Engine.TYPE_CANNON = 0x1; -GameLib.D3.Physics.Engine.TYPE_AMMO = 0x2; -GameLib.D3.Physics.Engine.TYPE_GOBLIN = 0x3; + var threeMesh = null; -/** - * Physics World Superset - * @param id - * @param name - * @param gravity - * @param rigidBodies GameLib.D3.Physics.RigidBody[] - * @param engine GameLib.D3.Physics.Engine - * @constructor - */ -GameLib.D3.Physics.World = function( - id, - name, - engineType, - gravity -) { - this.id = id; - - this.name = name; - - this.engineType = engineType; - - if (typeof gravity == 'undefined') { - gravity = new THREE.Vector3(0, -9.81, 0); - } - this.gravity = gravity; - - this.worldObject = null; - - if(this.engineType === GameLib.D3.Physics.Engine.TYPE_CANNON) { - this.worldObject = new CANNON.World(); - this.worldObject.gravity.set(this.gravity.x, this.gravity.y, this.gravity.z); - this.worldObject.broadphase = new CANNON.NaiveBroadphase(); - //this.worldObject.broadphase = new CANNON.SAPBroadphase(); - this.worldObject.solver.iterations = 10; - } -}; - -/** - * Physics Rigid Body Superset - * @param id - * @param name - * @constructor - */ -GameLib.D3.Physics.RigidBody = function( - id, - name -) { - this.bodyObject = null; -}; - -/** - * Physics Rigid Body Vehicle Superset - * @constructor - */ -GameLib.D3.Physics.RigidVehicle = function( -) { - this.vehicleObject = null; -}; - -/** - * Physics Raycast Vehicle Superset - * @constructor - */ -GameLib.D3.Physics.RaycastVehicle = function( -) { - this.vehicleObject = null; -}; - -/** - * Physics Shape Superset - * @constructor - */ -GameLib.D3.Physics.Shape = function( - shapeObject, // Physics engine specific - shapeType -) { - this.shapeObject = shapeObject; - this.shapeType = shapeType; - this.scale = new GameLib.D3.Vector3(1, 1, 1); -}; - -GameLib.D3.Physics.Shape.TYPE_SPHERE = 1; -GameLib.D3.Physics.Shape.TYPE_BOX = 2; -GameLib.D3.Physics.Shape.TYPE_TRIMESH = 3; -GameLib.D3.Physics.Shape.TYPE_CYLINDER = 4; -GameLib.D3.Physics.Shape.TYPE_HEIGHTFIELD = 5; - -/** - * Physics Convex Hull Shape Superset - * @param id - * @param name - * @constructor - */ -GameLib.D3.Physics.Shape.ConvexHull = function( - id, - name -) { - this.id = id; - this.name = name; -}; - -/** - * Physics Triangle Mesh Shape Superset - * @param id - * @param name - * @constructor - */ -GameLib.D3.Physics.Shape.TriangleMesh = function( - id, - name -) { - this.id = id; - this.name = name; -}; - -/** - * TriangleFace - * @param v0 - * @param v1 - * @param v2 - * @param materialIndex - * @param v0uv - * @param v1uv - * @param v2uv - * @param color - * @param vertexColors - * @param vertexNormals - * @param normal - * @constructor - */ -GameLib.D3.TriangleFace = function( - v0, - v1, - v2, - materialIndex, - v0uv, - v1uv, - v2uv, - color, - vertexColors, - vertexNormals, - normal -) { - this.v0 = v0; - this.v1 = v1; - this.v2 = v2; - this.materialIndex = materialIndex; - this.v0uv = v0uv; - this.v1uv = v1uv; - this.v2uv = v2uv; - if (!color) { - color = new GameLib.D3.Color(0xff, 0xff, 0xff, 0xff); - } - this.color = color; - - if (!vertexColors) { - vertexColors = [ - new GameLib.D3.Color(0xff, 0xff, 0xff, 0xff), - new GameLib.D3.Color(0xff, 0xff, 0xff, 0xff), - new GameLib.D3.Color(0xff, 0xff, 0xff, 0xff) - ]; - } - this.vertexColors = vertexColors; - - if (!vertexNormals) { - vertexNormals = [ - new GameLib.D3.Vector3(), - new GameLib.D3.Vector3(), - new GameLib.D3.Vector3() - ] - } - this.vertexNormals = vertexNormals; - - if (!normal) { - normal = new GameLib.D3.Vector3(0); + if (gameLibMesh.meshType == GameLib.D3.Mesh.TYPE_NORMAL) { + threeMesh = new graphics.instance.Mesh(instanceGeometry, instanceMaterial); } - this.normal = normal; -}; + if (gameLibMesh.meshType == GameLib.D3.Mesh.TYPE_SKINNED) { -/** - * TriangleEdge - * @param triangle - * @param edge - * @constructor - */ -GameLib.D3.TriangleEdge = function( - triangle, - edge -) { - this.triangle = triangle; - this.edge = edge; -}; + var bones = gameLibMesh.skeleton.bones; -/** - * Contains a Poly vertex data structure - * @param localIndex - * @param mvertIndex - * @param uv GameLib.D3.Vector2 - * @param materialIndex - * @param edgeIndex - * @constructor - */ -GameLib.D3.PolyVertex = function( - localIndex, - mvertIndex, - uv, - materialIndex, - edgeIndex -) { - this.localIndex = localIndex; - this.mvertIndex = mvertIndex; - this.uv = uv; - this.materialIndex = materialIndex; - this.edgeIndex = edgeIndex; -}; + var skinIndices = gameLibMesh.skinIndices; -/** - * BoneWeight object - associates a vertex to a bone with some weight - * @param boneIndex int - * @param weight float - * @constructor - */ -GameLib.D3.BoneWeight = function( - boneIndex, - weight -) { - this.boneIndex = boneIndex; - this.weight = weight; -}; + var skinWeights = gameLibMesh.skinWeights; -/** - * The normal gets assigned when the face calculates its normal - * @param position - * @param boneWeights GameLib.D3.BoneWeight[] - * @constructor - */ -GameLib.D3.Vertex = function( - position, - boneWeights -) { - this.position = position; - this.boneWeights = boneWeights; -}; + var threeBones = []; -/** - * Image - * @param id - * @param textureLink - * @param filename - * @param uploadPath - * @param apiPath - * @param size - * @param contentType - * @constructor - */ -GameLib.D3.Image = function( - id, - textureLink, - filename, - uploadPath, - apiPath, - size, - contentType -) { - this.id = id; + for (var bi = 0; bi < bones.length; bi++) { - this.filename = filename; + var bone = new graphics.instance.Bone(); - this.textureLink = textureLink; + bone.name = bones[bi].name; - if (typeof uploadPath == 'undefined') { - uploadPath = null; - } - this.uploadPath = uploadPath; + bone.position.x = bones[bi].position.x; + bone.position.y = bones[bi].position.y; + bone.position.z = bones[bi].position.z; - if (typeof apiPath == 'undefined') { - apiPath = null; - } - this.apiPath = apiPath; + bone.rotation.x = bones[bi].rotation.x; + bone.rotation.y = bones[bi].rotation.y; + bone.rotation.z = bones[bi].rotation.z; - if (typeof size == 'undefined') { - size = 0; - } - this.size = size; + bone.quaternion.x = bones[bi].quaternion.x; + bone.quaternion.y = bones[bi].quaternion.y; + bone.quaternion.z = bones[bi].quaternion.z; + bone.quaternion.w = bones[bi].quaternion.w; - if (typeof contentType == 'undefined') { + bone.scale.x = bones[bi].scale.x; + bone.scale.y = bones[bi].scale.y; + bone.scale.z = bones[bi].scale.z; - contentType = 'application/octet-stream'; + bone.up.x = bones[bi].up.x; + bone.up.y = bones[bi].up.y; + bone.up.z = bones[bi].up.z; - if (this.filename.match(/(png)$/i)) { - contentType = 'image/png'; + threeBones.push(bone); } - if (this.filename.match(/(jpg|jpeg)$/i)) { - contentType = 'image/jpeg'; - } - - if (this.filename.match(/(gif)$/i)) { - contentType = 'image/gif'; - } - } - this.contentType = contentType; - - -}; - -/** - * Scenes are objects putting meshes into 'world space' - * @param id - * @param path String - * @param name String - * @param meshes GameLib.D3.Mesh[] - * @param quaternion - * @param position - * @param rotation - * @param scale - * @param parentSceneId - * @param lights - * @constructor - */ -GameLib.D3.Scene = function( - id, - path, - name, - meshes, - quaternion, - position, - rotation, - scale, - parentSceneId, - lights -) { - this.id = id; - this.path = path; - this.name = name; - if (this.name.trim() == "") { - this.name = 'unnamed'; - } - this.meshes = meshes; - - if (typeof quaternion == 'undefined') { - quaternion = new GameLib.D3.Vector4(); - } - this.quaternion = quaternion; - - if (typeof position == 'undefined') { - position = new GameLib.D3.Vector3(0,0,0); - } - this.position = position; - - if (typeof rotation == 'undefined') { - rotation = new GameLib.D3.Vector3(0,0,0); - } - this.rotation = rotation; - - if (typeof scale == 'undefined') { - scale = new GameLib.D3.Vector3(1,1,1); - } - this.scale = scale; - - if (typeof parentSceneId == 'undefined') { - parentSceneId = null; - } - this.parentSceneId = parentSceneId; - - if (typeof lights == 'undefined') { - lights = []; - } - this.lights = lights; -}; - -/** - * Clone a PolyVertex - * @returns {GameLib.D3.PolyVertex} - */ -GameLib.D3.PolyVertex.prototype.clone = function() { - return new GameLib.D3.PolyVertex( - this.localIndex, - this.mvertIndex, - this.uv.copy(), - this.materialIndex, - this.edgeIndex - ) -}; - -/** - * Clone a TriangleFace - * @returns {GameLib.D3.TriangleFace} - */ -GameLib.D3.TriangleFace.prototype.clone = function(){ - return new GameLib.D3.TriangleFace( - this.v0, - this.v1, - this.v2, - this.materialIndex, - this.v0uv.copy(), - this.v1uv.copy(), - this.v2uv.copy() - ); -}; - -/** - * Associates bones with their child bones, based on parent bone references - */ -GameLib.D3.prototype.createChildBoneIds = function() { - for (var bi = 0; bi < this.bones.length; bi++) { - var childBoneIds = []; - - for (var sbi = 0; sbi < this.bones.length; sbi++) { - - if (this.bones[sbi] == this.bones[bi]) { - continue; - } - - if (this.bones[sbi].parentBoneId !== null && - this.bones[sbi].parentBoneId == this.bones[bi].boneId) - { - childBoneIds.push(this.bones[sbi].boneId); + /** + * Setup the bone relationships + */ + for (var br = 0; br < bones.length; br++) { + for (var cbi = 0; cbi < bones[br].childBoneIds.length; cbi++) { + threeBones[br].add(threeBones[bones[br].childBoneIds[cbi]]); } } - this.bones[bi].childBoneIds = childBoneIds; + /** + * Setup bones (indexes) + */ + for (var si = 0; si < skinIndices.length; si++) { + instanceGeometry.skinIndices.push( + new graphics.instance.Vector4( + skinIndices[si].x, + skinIndices[si].y, + skinIndices[si].z, + skinIndices[si].w + ) + ); + } + + /** + * Setup bones (weights) + */ + for (var sw = 0; sw < skinWeights.length; sw++) { + instanceGeometry.skinWeights.push( + new graphics.instance.Vector4( + skinWeights[sw].x, + skinWeights[sw].y, + skinWeights[sw].z, + skinWeights[sw].w + ) + ); + } + + threeMesh = new graphics.instance.SkinnedMesh(instanceGeometry, instanceMaterial); + + var skeleton = new graphics.instance.Skeleton(threeBones); + + skeleton.useVertexTexture = gameLibMesh.skeleton.useVertexTexture; + + for (var i = 0; i < bones.length; i++) { + if (bones[i].parentBoneId === null) { + threeMesh.add(threeBones[i]); + break; + } + } + + threeMesh.bind(skeleton); + + threeMesh.pose(); + + threeMesh.skeleton.skeletonHelper = new graphics.instance.SkeletonHelper(threeMesh); + threeMesh.skeleton.skeletonHelper.material.linewidth = 5; } + + if (threeMesh == null) { + console.log('cannot handle meshes of type ' + gameLibMesh.meshType + ' yet.'); + } + + gameLibMesh.threeMeshId = threeMesh.id; + + return threeMesh; +}; + +GameLib.D3.prototype.invertWindingOrder = function(triangles) { + + for (var i = 0; i < triangles.length; i++) { + var v1 = triangles[i].v1; + triangles[i].v1 = triangles[i].v2; + triangles[i].v2 = v1; + + var backupUV = triangles[i].triangle.v1uv; + triangles[i].triangle.v1uv = triangles[i].triangle.v2uv; + triangles[i].triangle.v2uv = backupUV; + } + + return triangles; }; /** - * This is a work-around function to fix polys which don't triangulate because - * they could lie on Z-plane (XZ or YZ)) - we translate the poly to the origin, systematically rotate the poly around - * Z then Y axis - * @param verticesFlat [] - * @param grain is the amount to systematically rotate the poly by - a finer grain means a more accurate maximum XY - * @return [] + * This function resets a the winding order of a mesh from a reference point V (the average center of the mesh) */ -GameLib.D3.prototype.fixPolyZPlane = function(verticesFlat, grain) { +GameLib.D3.prototype.resetWindingOrder = function(faces, vertices) { - if ((verticesFlat.length % 3) != 0 && !(verticesFlat.length > 9)) { - console.log("The vertices are not in the right length : " + verticesFlat.length); - } + var vertexList = new GameLib.D3.Vector3.Points(); - var vertices = []; - - var points = new GameLib.D3.Vector4.Points(); - - for (var i = 0; i < verticesFlat.length; i += 3) { - points.add(new GameLib.D3.Vector3( - verticesFlat[i], - verticesFlat[i + 1], - verticesFlat[i + 2] + for (var v = 0; v < vertices.length; v++) { + vertexList.add(new GameLib.D3.Vector3( + vertices[v].position.x, + vertices[v].position.y, + vertices[v].position.z )); } - points.toOrigin(); + var V = vertexList.average(); - points.maximizeXDistance(grain); + var triangles = []; - points.maximizeYDistance(grain); + for (var s = 0; s < faces.length; s += 3) { - for (i = 0; i < points.vectors.length; i++) { - vertices.push( - [ - points.vectors[i].x, - points.vectors[i].y - ] + var v0 = faces[s]; + var v1 = faces[s+1]; + var v2 = faces[s+2]; + + triangles.push( + { + v0 : v0, + v1 : v1, + v2 : v2, + edges : [ + {v0: v0, v1: v1}, + {v0: v1, v1: v2}, + {v0: v2, v1: v0} + ], + winding : 0, + edgeIndex : -1, + processed : false + } ); } - return vertices; + for (var i = 0; i < triangles.length; i++) { + if ( + GameLib.D3.Vector3.clockwise( + vertices[triangles[i].v0].position, + vertices[triangles[i].v1].position, + vertices[triangles[i].v2].position, + V + ) + ) { + console.log('clockwise'); + var bv1 = triangles[i].v1; + triangles[i].v1 = triangles[i].v2; + triangles[i].v2 = bv1; + } else { + console.log('not clockwise'); + } + } + + return triangles; }; /** @@ -1635,7 +2161,7 @@ GameLib.D3.prototype.fixPolyZPlane = function(verticesFlat, grain) { * @param orientationEdge GameLib.D3.Vector2 * @returns {Array} */ -GameLib.D3.prototype.fixWindingOrder = function(faces, orientationEdge) { +GameLib.D3.fixWindingOrder = function(faces, orientationEdge) { /** * Checks if a TriangleFace belonging to a TriangleEdge has already been processed @@ -1785,6 +2311,2043 @@ GameLib.D3.prototype.fixWindingOrder = function(faces, orientationEdge) { return triangles; }; +/** + * This is a work-around function to fix polys which don't triangulate because + * they could lie on Z-plane (XZ or YZ)) - we translate the poly to the origin, systematically rotate the poly around + * Z then Y axis + * @param verticesFlat [] + * @param grain is the amount to systematically rotate the poly by - a finer grain means a more accurate maximum XY + * @return [] + */ +GameLib.D3.fixPolyZPlane = function(verticesFlat, grain) { + + if ((verticesFlat.length % 3) != 0 && !(verticesFlat.length > 9)) { + console.log("The vertices are not in the right length : " + verticesFlat.length); + } + + var vertices = []; + + var points = new GameLib.D3.Vector4.Points(); + + for (var i = 0; i < verticesFlat.length; i += 3) { + points.add(new GameLib.D3.Vector3( + verticesFlat[i], + verticesFlat[i + 1], + verticesFlat[i + 2] + )); + } + + points.toOrigin(); + + points.maximizeXDistance(grain); + + points.maximizeYDistance(grain); + + for (i = 0; i < points.vectors.length; i++) { + vertices.push( + [ + points.vectors[i].x, + points.vectors[i].y + ] + ); + } + + return vertices; +}; +/** + * Physics SuperSet Namespace Object + * @param id + * @param name + * @param engine GameLib.D3.Engine + * @param worlds + * @returns {{World: World}} + * @constructor + */ +GameLib.D3.Physics = function( + id, + name, + engine, + worlds +) { + this.id = id; + this.name = name; + this.engine = engine; + + if (typeof worlds == 'undefined') { + worlds = []; + } + this.worlds = worlds; +}; + + +/** + * Solver Types + * @type {number} + */ +GameLib.D3.Physics.SPLIT_SOLVER = 0x1; +GameLib.D3.Physics.GS_SOLVER = 0x2; +/** + * Contains a Poly vertex data structure + * @param localIndex + * @param mvertIndex + * @param uv GameLib.D3.Vector2 + * @param materialIndex + * @param edgeIndex + * @constructor + */ +GameLib.D3.PolyVertex = function( + localIndex, + mvertIndex, + uv, + materialIndex, + edgeIndex +) { + this.localIndex = localIndex; + this.mvertIndex = mvertIndex; + this.uv = uv; + this.materialIndex = materialIndex; + this.edgeIndex = edgeIndex; +}; + +/** + * Clone a PolyVertex + * @returns {GameLib.D3.PolyVertex} + */ +GameLib.D3.PolyVertex.prototype.clone = function() { + return new GameLib.D3.PolyVertex( + this.localIndex, + this.mvertIndex, + this.uv.copy(), + this.materialIndex, + this.edgeIndex + ) +}; +/** + * + * @param engine GamLib.D3.Engine + * @param chassisBody GamLib.D3.RigidBody + * @constructor + */ +GameLib.D3.RaycastVehicle = function( + engine, + chassisBody +) { + this.engine = engine; + this.engine.isNotCannonThrow(); + + this.chassisBody = chassisBody; + + this.instance = this.createInstance(); +}; + +/** + * private + * @returns {GameLib.D3.RaycastVehicle|GameLib.D3.Physics.RaycastVehicle|*} + */ +GameLib.D3.RaycastVehicle.prototype.createInstance = function() { + var instance = new this.engine.instance.RaycastVehicle({ + chassisBody: this.chassisBody.instance + }); + + this.instance = instance; + + return instance; +}; + +/** + * Adds a raycast wheel to this vehicle + * @param wheel GameLib.D3.RaycastWheel + */ +GameLib.D3.RaycastVehicle.prototype.addWheel = function ( + wheel +) { + var options = {}; + + for (var property in wheel) { + if (wheel.hasOwnProperty(property)){ + + if (property == 'engine') { + continue; + } + + options[property] = wheel[property]; + } + } + + this.instance.addWheel(options); +}; + +/** + * Eventually we can wrap wheels + * @returns {*} + * @constructor + */ +GameLib.D3.RaycastVehicle.prototype.getWheelInfo = function() { + return this.instance.wheelInfos; +}; + +GameLib.D3.RaycastWheel = function( + engine, + chassisConnectionPointLocal, + chassisConnectionPointWorld, + directionLocal, + directionWorld, + axleLocal, + axleWorld, + suspensionRestLength, + suspensionMaxLength, + radius, + suspensionStiffness, + dampingCompression, + dampingRelaxation, + frictionSlip, + steering, + rotation, + deltaRotation, + rollInfluence, + maxSuspensionForce, + isFrontWheel, + clippedInvContactDotSuspension, + suspensionRelativeVelocity, + suspensionForce, + skidInfo, + suspensionLength, + maxSuspensionTravel, + useCustomSlidingRotationalSpeed, + customSlidingRotationalSpeed +) { + this.engine = engine; + this.engine.isNotCannonThrow(); + + if(typeof chassisConnectionPointLocal == 'undefined') { + chassisConnectionPointLocal = new this.engine.instance.Vec3(); + } + this.chassisConnectionPointLocal = chassisConnectionPointLocal; + + if(typeof chassisConnectionPointWorld == 'undefined') { + chassisConnectionPointWorld = new this.engine.instance.Vec3(); + } + this.chassisConnectionPointWorld = chassisConnectionPointWorld; + + if(typeof directionLocal == 'undefined') { + directionLocal = new this.engine.instance.Vec3(); + } + this.directionLocal = directionLocal; + + if(typeof directionWorld == 'undefined') { + directionWorld = new this.engine.instance.Vec3(); + } + this.directionWorld = directionWorld; + + if(typeof axleLocal == 'undefined') { + axleLocal = new this.engine.instance.Vec3(); + } + this.axleLocal = axleLocal; + + if(typeof axleWorld == 'undefined') { + axleWorld = new this.engine.instance.Vec3(); + } + this.axleWorld = axleWorld; + + if(typeof suspensionRestLength == 'undefined') { + suspensionRestLength = 1; + } + this.suspensionRestLength = suspensionRestLength; + + if(typeof suspensionMaxLength == 'undefined') { + suspensionMaxLength = 2; + } + this.suspensionMaxLength = suspensionMaxLength; + + if(typeof radius == 'undefined') { + radius = 1; + } + this.radius = radius; + + if(typeof suspensionStiffness == 'undefined') { + suspensionStiffness = 100; + } + this.suspensionStiffness = suspensionStiffness; + + if(typeof dampingCompression == 'undefined') { + dampingCompression = 10; + } + this.dampingCompression = dampingCompression; + + if(typeof dampingRelaxation == 'undefined') { + dampingRelaxation = 10; + } + this.dampingRelaxation = dampingRelaxation; + + if(typeof frictionSlip == 'undefined') { + frictionSlip = 10000; + } + this.frictionSlip = frictionSlip; + + if(typeof steering == 'undefined') { + steering = 0; + } + this.steering = steering; + + if(typeof rotation == 'undefined') { + rotation = 0; + } + this.rotation = rotation; + + if(typeof deltaRotation == 'undefined') { + deltaRotation = 0; + } + this.deltaRotation = deltaRotation; + + if(typeof rollInfluence == 'undefined') { + rollInfluence = 0.01; + } + this.rollInfluence = rollInfluence; + + if(typeof maxSuspensionForce == 'undefined') { + maxSuspensionForce = Number.MAX_VALUE; + } + this.maxSuspensionForce = maxSuspensionForce; + + if(typeof isFrontWheel == 'undefined') { + isFrontWheel = true; + } + this.isFrontWheel = isFrontWheel; + + if(typeof clippedInvContactDotSuspension == 'undefined') { + clippedInvContactDotSuspension = 1; + } + this.clippedInvContactDotSuspension = clippedInvContactDotSuspension; + + if(typeof suspensionRelativeVelocity == 'undefined') { + suspensionRelativeVelocity = 0; + } + this.suspensionRelativeVelocity = suspensionRelativeVelocity; + + if(typeof suspensionForce == 'undefined') { + suspensionForce = 0; + } + this.suspensionForce = suspensionForce; + + if(typeof skidInfo == 'undefined') { + skidInfo = 0; + } + this.skidInfo = skidInfo; + + if(typeof suspensionLength == 'undefined') { + suspensionLength = 0; + } + this.suspensionLength = suspensionLength; + + if(typeof maxSuspensionTravel == 'undefined') { + maxSuspensionTravel = 1; + } + this.maxSuspensionTravel = maxSuspensionTravel; + + if(typeof useCustomSlidingRotationalSpeed == 'undefined') { + useCustomSlidingRotationalSpeed = false; + } + this.useCustomSlidingRotationalSpeed = useCustomSlidingRotationalSpeed; + + if(typeof customSlidingRotationalSpeed == 'undefined') { + customSlidingRotationalSpeed = -0.1; + } + this.customSlidingRotationalSpeed = customSlidingRotationalSpeed; +}; + +/** + * Physics Rigid Body Vehicle Superset + * TODO: body + wheels[] + * @constructor + */ +GameLib.D3.RigidBodyVehicle = function( + engine +) { + this.engine = engine; + + this.engine.isNotCannonThrow(); + + this.instance = null; +}; + +/** + * + * @returns {*} + */ +GameLib.D3.RigidBodyVehicle.prototype.getWheelInfo = function() { + return this.instance.wheelBodies; +}; + +/** + * + * @param chassisBody + * @returns {GameLib.D3.RigidVehicle|GameLib.D3.Physics.RigidVehicle} + */ +GameLib.D3.RigidBodyVehicle.prototype.createInstance = function( + chassisBody // Physics.RigidBody +) { + + var vehicle = new this.engine.instance.RigidVehicle({ + chassisBody: chassisBody.bodyObject + }); + + this.instance = vehicle; + + return vehicle; +}; + +/** + * Adds a wheel to this rigid body vehicle + * @param rigidBody GameLib.D3.RigidBody + * @param position + * @param axis + * @param direction + * @constructor + */ +GameLib.D3.RigidBodyVehicle.prototype.addWheel = function( + rigidBody, + position, + axis, + direction +) { + this.instance.addWheel({ + body: rigidBody.instance, + position: new this.engine.instance.Vec3( + position.x, + position.y, + position.z + ), + axis: new this.engine.instance.Vec3( + axis.x, + axis.y, + axis.z + ), + direction: new this.engine.instance.Vec3( + direction.x, + direction.y, + direction.z + ) + }); +}; + +/** + * RigidBody Superset + * @param engine GameLib.D3.Engine + * @param mass + * @param friction + * @param position + * @param quaternion + * @param velocity + * @param angularVelocity + * @param linearDamping + * @param angularDamping + * @param allowSleep + * @param sleepSpeedLimit + * @param sleepTimeLimit + * @param collisionFilterGroup + * @param collisionFilterMask + * @param fixedRotation + * @param shape GameLib.D3.Shape + * @returns {GameLib.D3.Physics.RigidBody} + * @constructor + */ +GameLib.D3.RigidBody = function( + engine, + mass, + friction, + position, + quaternion, + velocity, + angularVelocity, + linearDamping, + angularDamping, + allowSleep, + sleepSpeedLimit, + sleepTimeLimit, + collisionFilterGroup, + collisionFilterMask, + fixedRotation, + shape +) { + + this.position = position || new GameLib.D3.Vector3(); + this.velocity = velocity || new GameLib.D3.Vector3(); + this.angularVelocity = angularVelocity || new GameLib.D3.Vector3(); + this.quaternion = quaternion || new GameLib.D3.Vector4(0, 0, 0, 1); + this.mass = typeof mass == "undefined" ? 0 : mass; + this.friction = typeof friction == "undefined" ? 5 : friction; + this.linearDamping = typeof linearDamping == "undefined" ? 0.01 : linearDamping; + this.angularDamping = typeof angularDamping == "undefined" ? 0.01 : angularDamping; + this.allowSleep = typeof allowSleep == "undefined" ? true : allowSleep; + this.sleepSpeedLimit = typeof sleepSpeedLimit == "undefined" ? 0.1 : sleepSpeedLimit; + this.sleepTimeLimit = typeof sleepTimeLimit == "undefined" ? 1.0 : sleepTimeLimit; + this.collisionFilterGroup = typeof collisionFilterGroup == "undefined" ? 1 : collisionFilterGroup; + this.collisionFilterMask = typeof collisionFilterMask == "undefined" ? 1 : collisionFilterMask; + this.fixedRotation = typeof fixedRotation == "undefined" ? false : fixedRotation; + this.shape = typeof shape == "undefined" ? null : shape; + + this.engine = engine; + + this.engine.isNotCannonThrow(); + + this.instance = this.createInstance(); +}; + +/** + * private function + * @returns {*} + */ +GameLib.D3.RigidBody.prototype.createInstance = function() { + + var instance = new this.engine.instance.Body({ + mass: mass, + friction: this.friction, + position: new this.engine.instance.Vec3( + this.position.x, + this.position.y, + this.position.z + ), + velocity: new this.engine.instance.Vec3( + this.velocity.x, + this.velocity.y, + this.velocity.z + ), + quaternion: new this.engine.instance.Quaternion( + this.quaternion.x, + this.quaternion.y, + this.quaternion.z, + this.quaternion.w + ), + angularVelocity: new this.engine.instance.Vec3( + this.angularVelocity.x, + this.angularVelocity.y, + this.angularVelocity.z + ), + linearDamping: this.linearDamping, + angularDamping: this.angularDamping, + allowSleep: this.allowSleep, + sleepSpeedLimit: this.sleepSpeedLimit, + sleepTimeLimit: this.sleepTimeLimit, + collisionFilterGroup: this.collisionFilterGroup, + collisionFilterMask: this.collisionFilterMask, + fixedRotation: this.fixedRotation, + shape: this.shape.instance + }); + + this.instance = instance; + + return instance; +}; + +/** + * Adds a shape to this rigid body + * @param shape GameLib.D3.Shape + * @param offset GameLib.D3.Vector3 + * @param orientation GameLib.D3.Vector4 + * @constructor + */ +GameLib.D3.RigidBody.prototype.addShape = function( + shape, + offset, + orientation +) { + if (!offset) { + offset = new GameLib.D3.Vector3(0,0,0); + } + + if (!orientation) { + orientation = new GameLib.D3.Vector4(0,0,0,1); + } + + this.instance.addShape( + shape.instance, + new this.engine.instance.Vec3( + offset.x, + offset.y, + offset.z + ), + new this.engine.instance.Quaternion( + orientation.x, + orientation.y, + orientation.z, + orientation.w + ) + ); +}; + + + +/** + * Scenes are objects putting meshes into 'world space' + * @param id + * @param path String + * @param name String + * @param meshes GameLib.D3.Mesh[] + * @param quaternion + * @param position + * @param rotation + * @param scale + * @param parentSceneId + * @param lights + * @param physics GameLib.D3.Physics + * @constructor + */ +GameLib.D3.Scene = function( + id, + path, + name, + meshes, + quaternion, + position, + rotation, + scale, + parentSceneId, + lights, + physics +) { + this.id = id; + this.path = path; + this.name = name; + if (this.name.trim() == "") { + this.name = 'unnamed'; + } + + if (typeof meshes == 'undefined') { + meshes = []; + } + this.meshes = meshes; + + if (typeof quaternion == 'undefined') { + quaternion = new GameLib.D3.Vector4(); + } + this.quaternion = quaternion; + + if (typeof position == 'undefined') { + position = new GameLib.D3.Vector3(0,0,0); + } + this.position = position; + + if (typeof rotation == 'undefined') { + rotation = new GameLib.D3.Vector3(0,0,0); + } + this.rotation = rotation; + + if (typeof scale == 'undefined') { + scale = new GameLib.D3.Vector3(1,1,1); + } + this.scale = scale; + + if (typeof parentSceneId == 'undefined') { + parentSceneId = null; + } + this.parentSceneId = parentSceneId; + + if (typeof lights == 'undefined') { + lights = []; + } + this.lights = lights; + + if (typeof physics == 'undefined') { + physics = []; + } + this.physics = physics; +}; + +/** + * Loads a scene directly from the API + * @param gameLibScene GameLib.D3.Scene + * @param onLoaded callback + * @param graphics GameLib.D3.Graphics + * @param uploadUrl String + * @param progressCallback callback + * @param apiUrl + */ +GameLib.D3.Scene.loadSceneFromApi = function( + gameLibScene, + onLoaded, + graphics, + uploadUrl, + progressCallback, + apiUrl +) { + + /** + * First check if this is a client or server side request + */ + if (typeof XMLHttpRequest == 'undefined') { + console.warn('implement server side loading from API here'); + return onLoaded(null, new Error('not implemented')); + } + + var xhr = new XMLHttpRequest(); + xhr.open( + 'GET', + apiUrl + '/scene/load' + gameLibScene.path + '/' + gameLibScene.name + ); + + xhr.onreadystatechange = function(xhr) { + return function() { + if (xhr.readyState == 4) { + + var response = JSON.parse(xhr.responseText); + + if (!response.scene || response.scene.length == 0) { + return onLoaded(null, null, new Error('Could not load scene')); + } + + var scene = response.scene[0]; + + var physics3ds = []; + + if (scene.physics && scene.physics.length > 0) { + + for (var p = 0; p < scene.physics.length; p++) { + + var physics = scene.physics[p]; + + var engine = null; + + if (physics.engine.engineType == GameLib.D3.Engine.ENGINE_TYPE_CANNON) { + engine = new GameLib.D3.Engine( + GameLib.D3.Engine.ENGINE_TYPE_CANNON, + CANNON + ); + } + + var physics3d = new GameLib.D3.Physics( + physics.id, + physics.name, + engine, + null + ); + + var worlds3d = []; + + for (var w = 0; w < physics.worlds.length; w++) { + + var world = physics.worlds[w]; + + var broadphase = world.broadphase; + + var broadphase3d = new GameLib.D3.Physics.Broadphase( + broadphase.id, + broadphase.name, + broadphase.broadphaseType + ); + + var solver = world.solver; + + var solver3d = new GameLib.D3.Physics.Solver( + solver.id, + solver.name, + solver.solverType, + solver.iterations, + solver.tolerance + ); + + var bodies = world.rigidBodies; + + var bodies3d = []; + + for (var b = 0; b < bodies.length; b++) { + + var body = bodies[b]; + + //TODO: add all body properties here + var body3d = new GameLib.D3.Physics.RigidBody( + body.id, + body.name + ); + + bodies3d.push(body3d); + } + + var world3d = new GameLib.D3.Physics.World( + null, + world.name, + physics3d, + new GameLib.D3.Vector3( + world.gravity.x, + world.gravity.y, + world.gravity.z + ), + broadphase3d, + solver3d, + bodies3d + ); + + worlds3d.push(world3d); + } + + physics3ds.push(physics3d); + } + } + + var lights3d = []; + + for (var l = 0; l < scene.lights.length; l++) { + + var light = scene.lights[l]; + + var light3d = new GameLib.D3.Light( + light.id, + light.lightType, + light.name, + new GameLib.D3.Color( + light.color.r, + light.color.g, + light.color.b, + light.color.a + ), + light.intensity, + new GameLib.D3.Vector3( + light.position.x, + light.position.y, + light.position.z + ), + new GameLib.D3.Vector3( + light.targetPosition.x, + light.targetPosition.y, + light.targetPosition.z + ), + new GameLib.D3.Vector4( + light.quaternion.x, + light.quaternion.y, + light.quaternion.z, + light.quaternion.w + ), + new GameLib.D3.Vector3( + light.rotation.x, + light.rotation.y, + light.rotation.z + ), + new GameLib.D3.Vector3( + light.scale.x, + light.scale.y, + light.scale.z + ), + light.distance, + light.decay, + light.power, + light.angle, + light.penumbra + ); + + lights3d.push(light3d); + } + + var scene3d = new GameLib.D3.Scene( + scene._id || scene.id, + scene.path, + scene.name, + scene.meshes, + new GameLib.D3.Vector4( + scene.quaternion.x, + scene.quaternion.y, + scene.quaternion.z, + scene.quaternion.w + ), + new GameLib.D3.Vector3( + scene.position.x, + scene.position.y, + scene.position.z + ), + new GameLib.D3.Vector3( + scene.rotation.x, + scene.rotation.y, + scene.rotation.z + ), + new GameLib.D3.Vector3( + scene.scale.x, + scene.scale.y, + scene.scale.z + ), + scene.parentSceneId, + lights3d, + physics3ds + ); + + GameLib.D3.Scene.loadScene( + scene3d, + onLoaded, + false, + graphics, + uploadUrl, + progressCallback + ); + } + } + }(xhr); + + xhr.send(); +}; + +/** + * Loads a GameLib.D3.Scene object into a Graphics Instance Scene object + * @param gameLibScene GameLib.D3.Scene + * @param onLoaded callback when all meshes have loaded + * @param computeNormals set to true to compute new face and vertex normals during load + * @param graphics GameLib.D3.Graphics + * @param uploadUrl + * @param progressCallback + */ +GameLib.D3.Scene.loadScene = function( + gameLibScene, + onLoaded, + computeNormals, + graphics, + uploadUrl, + progressCallback +) { + + console.log("loading scene " + gameLibScene.name); + + graphics.isNotThreeThrow(); + + var meshQ = []; + + for (var m = 0; m < gameLibScene.meshes.length; m++) { + + var mesh = gameLibScene.meshes[m]; + + console.log("loading mesh " + mesh.name); + + var geometry = new graphics.instance.Geometry(); + + var vertices = mesh.vertices; + + var faces = mesh.faces; + + var faceVertexUvs = mesh.faceVertexUvs; + + var materials = mesh.materials; + + /** + * Setup vertices + */ + for (var v = 0; v < vertices.length; v++) { + geometry.vertices.push( + new graphics.instance.Vector3( + vertices[v].position.x, + vertices[v].position.y, + vertices[v].position.z + ) + ) + } + + /** + * Setup faces + */ + for (var f = 0; f < faces.length; f++) { + + var face = new graphics.instance.Face3( + faces[f].v0, + faces[f].v1, + faces[f].v2, + new graphics.instance.Vector3( + faces[f].normal.x, + faces[f].normal.y, + faces[f].normal.z + ), + new graphics.instance.Color( + faces[f].color.r, + faces[f].color.g, + faces[f].color.b + ), + faces[f].materialIndex + ); + + face.vertexColors = [ + new graphics.instance.Color( + faces[f].vertexColors[0].r, + faces[f].vertexColors[0].g, + faces[f].vertexColors[0].b + ), + new graphics.instance.Color( + faces[f].vertexColors[1].r, + faces[f].vertexColors[1].g, + faces[f].vertexColors[1].b + ), + new graphics.instance.Color( + faces[f].vertexColors[2].r, + faces[f].vertexColors[2].g, + faces[f].vertexColors[2].b + ) + ]; + + face.normal = new graphics.instance.Vector3( + faces[f].normal.x, + faces[f].normal.y, + faces[f].normal.z + ); + + face.vertexNormals = [ + new graphics.instance.Vector3( + faces[f].vertexNormals[0].x, + faces[f].vertexNormals[0].y, + faces[f].vertexNormals[0].z + ), + new graphics.instance.Vector3( + faces[f].vertexNormals[1].x, + faces[f].vertexNormals[1].y, + faces[f].vertexNormals[1].z + ), + new graphics.instance.Vector3( + faces[f].vertexNormals[2].x, + faces[f].vertexNormals[2].y, + faces[f].vertexNormals[2].z + ) + ]; + + geometry.faces.push(face); + } + + geometry.faceVertexUvs = []; + + /** + * Setup face UVs + */ + for (var fm = 0; fm < faceVertexUvs.length; fm++) { + + var faceMaterialVertexUvs = faceVertexUvs[fm]; + + geometry.faceVertexUvs[fm] = []; + + for (var fuv = 0; fuv < faceMaterialVertexUvs.length; fuv++) { + geometry.faceVertexUvs[fm][fuv] = []; + geometry.faceVertexUvs[fm][fuv].push( + new graphics.instance.Vector2( + faceMaterialVertexUvs[fuv][0].x, + faceMaterialVertexUvs[fuv][0].y + ), + new graphics.instance.Vector2( + faceMaterialVertexUvs[fuv][1].x, + faceMaterialVertexUvs[fuv][1].y + ), + new graphics.instance.Vector2( + faceMaterialVertexUvs[fuv][2].x, + faceMaterialVertexUvs[fuv][2].y + ) + ); + } + } + + /** + * Re-calculate normals (if we have to) + * @type {Array} + */ + if (computeNormals) { + geometry.computeFaceNormals(); + geometry.computeVertexNormals(); + } + + var instanceMaterialLoaders = []; + + /** + * Setup materials + */ + for (var mi = 0; mi < materials.length; mi++) { + instanceMaterialLoaders.push( + GameLib.D3.Material.createInstanceMaterial( + materials[mi], + graphics, + uploadUrl, + progressCallback + ) + ); + } + + var result = Q.all(instanceMaterialLoaders).then( + function(mesh, geometry) { + return function(materials) { + + console.log("loaded material : " + materials[0].name); + + /** + * We don't support MultiMaterial atm - it doesn't work with raycasting + */ + var material = materials[0]; + + var threeMesh = GameLib.D3.Mesh.createInstanceMesh( + mesh, + geometry, + material, + graphics + ); + threeMesh.name = mesh.name; + + threeMesh.position.x = mesh.position.x; + threeMesh.position.y = mesh.position.y; + threeMesh.position.z = mesh.position.z; + + threeMesh.rotation.x = mesh.rotation.x; + threeMesh.rotation.y = mesh.rotation.y; + threeMesh.rotation.z = mesh.rotation.z; + + threeMesh.scale.x = mesh.scale.x; + threeMesh.scale.y = mesh.scale.y; + threeMesh.scale.z = mesh.scale.z; + + threeMesh.quaternion.x = mesh.quaternion.x; + threeMesh.quaternion.y = mesh.quaternion.y; + threeMesh.quaternion.z = mesh.quaternion.z; + threeMesh.quaternion.w = mesh.quaternion.w; + + return threeMesh; + }; + }(mesh, geometry) + ).catch(function(error){ + console.log(error); + }); + + meshQ.push(result); + } + + Q.all(meshQ).then( + function(instanceMeshes){ + console.log("all meshes have loaded"); + if (typeof onLoaded != 'undefined') { + + var instanceLights = []; + + for (var sli = 0; sli < gameLibScene.lights.length; sli++) { + + var gameLibLight = gameLibScene.lights[sli]; + + var light = null; + + if (gameLibLight.lightType == 'AmbientLight') { + light = new graphics.instance.AmbientLight(gameLibLight.color, gameLibLight.intensity); + } + + if (gameLibLight.lightType == 'DirectionalLight') { + light = new graphics.instance.DirectionalLight(gameLibLight.color, gameLibLight.intensity); + } + + if (gameLibLight.lightType == 'PointLight') { + light = new graphics.instance.PointLight(gameLibLight.color, gameLibLight.intensity); + light.distance = gameLibLight.distance; + light.decay = gameLibLight.decay; + } + + if (gameLibLight.lightType == 'SpotLight') { + light = new graphics.instance.SpotLight(gameLibLight.color, gameLibLight.intensity); + light.distance = gameLibLight.distance; + light.angle = gameLibLight.angle; + light.penumbra = gameLibLight.penumbra; + light.decay = gameLibLight.decay; + } + + light.position.x = gameLibLight.position.x; + light.position.y = gameLibLight.position.y; + light.position.z = gameLibLight.position.z; + + light.rotation.x = gameLibLight.rotation.x; + light.rotation.y = gameLibLight.rotation.y; + light.rotation.z = gameLibLight.rotation.z; + + if (light == null) { + console.warn('Does not support lights of type :' + gameLibLight.lightType + ', not imported'); + } else { + light.name = gameLibLight.name; + instanceLights.push(light); + } + } + + var instanceScene = new graphics.instance.Scene(); + + instanceScene.name = gameLibScene.name; + + instanceScene.position.x = gameLibScene.position.x; + instanceScene.position.y = gameLibScene.position.y; + instanceScene.position.z = gameLibScene.position.z; + + instanceScene.rotation.x = gameLibScene.rotation.x; + instanceScene.rotation.y = gameLibScene.rotation.y; + instanceScene.rotation.z = gameLibScene.rotation.z; + + instanceScene.scale.x = gameLibScene.scale.x; + instanceScene.scale.y = gameLibScene.scale.y; + instanceScene.scale.z = gameLibScene.scale.z; + + instanceScene.quaternion.x = gameLibScene.quaternion.x; + instanceScene.quaternion.y = gameLibScene.quaternion.y; + instanceScene.quaternion.z = gameLibScene.quaternion.z; + instanceScene.quaternion.w = gameLibScene.quaternion.w; + + for (var m = 0; m < instanceMeshes.length; m++) { + instanceScene.add(instanceMeshes[m]); + } + + for (var l = 0; l < instanceLights.length; l++) { + instanceScene.add(instanceLights[l]); + } + + onLoaded( + gameLibScene, + { + scene: instanceScene, + lights: instanceLights, + meshes: instanceMeshes + } + ); + } + }).catch( + function(error){ + console.log(error); + } + ); +}; +/** + * Physics Shape Superset + * @param engine GameLib.D3.Engine + * @param shapeType + * @param scale GameLib.D3.Vector3 + * @param vertices Number[] + * @param indices Number[] + * @param radius Number + * @param halfExtensions GameLib.D3.Vector3 + * @param radiusTop Number + * @param radiusBottom Number + * @param height Number + * @param numSegments Number + * @param heightmap GameLib.D3.Heightmap + * @param elementSize + * @constructor + */ +GameLib.D3.Shape = function( + engine, + shapeType, + scale, + vertices, + indices, + radius, + halfExtensions, + radiusTop, + radiusBottom, + height, + numSegments, + heightmap +) { + this.engine = engine; + + this.engine.isNotCannonThrow(); + + this.shapeType = shapeType; + + this.instance = this.createInstance(); + + if (typeof scale == 'undefined') { + scale = new GameLib.D3.Vector3(1, 1, 1) + } + this.scale = scale; + + if (typeof vertices == 'undefined') { + vertices = []; + } + this.vertices = vertices; + + if (typeof indices == 'undefined') { + indices = []; + } + this.indices = indices; + + if (typeof radius == 'undefined') { + radius = 1; + } + this.radius = radius; + + if (typeof halfExtensions == 'undefined') { + halfExtensions = new GameLib.D3.Vector3(1,1,1); + } + this.halfExtensions = halfExtensions; + + if (typeof radiusTop == 'undefined') { + radiusTop = 1; + } + this.radiusTop = radiusTop; + + if (typeof radiusBottom == 'undefined') { + radiusBottom = 1; + } + this.radiusBottom = radiusBottom; + + if (typeof height == 'undefined') { + height = 1; + } + this.height = height; + + if (typeof numSegments == 'undefined') { + numSegments = 1; + } + this.numSegments = numSegments; + + if (typeof heightmap == 'undefined') { + heightmap = new GameLib.D3.Heightmap(); + } + this.heightmap = heightmap; + +}; + +/** + * Shape constants + * @type {number} + */ +GameLib.D3.Shape.SHAPE_TYPE_SPHERE = 1; +GameLib.D3.Shape.SHAPE_TYPE_BOX = 2; +GameLib.D3.Shape.SHAPE_TYPE_TRIMESH = 3; +GameLib.D3.Shape.SHAPE_TYPE_CYLINDER = 4; +GameLib.D3.Shape.SHAPE_TYPE_HEIGHT_MAP = 5; +GameLib.D3.Shape.SHAPE_TYPE_CONVEX_HULL = 6; + +/** + * + */ +GameLib.D3.Shape.prototype.createInstance = function() { + + var instance = null; + + if (this.shapeType == GameLib.D3.Shape.SHAPE_TYPE_TRIMESH) { + instance = new this.engine.instance.Trimesh( + this.vertices, + this.indices + ); + } else if (this.shapeType == GameLib.D3.Shape.SHAPE_TYPE_SPHERE) { + instance = new this.engine.instance.Sphere( + this.radius + ); + } else if (this.shapeType == GameLib.D3.Shape.SHAPE_TYPE_BOX) { + instance = new this.engine.instance.Box( + new this.engine.instance.Vec3( + this.halfExtensions.x, + this.halfExtensions.y, + this.halfExtensions.z + ) + ); + } else if (this.shapeType == GameLib.D3.Shape.SHAPE_TYPE_CYLINDER) { + instance = new this.engine.instance.Cylinder( + this.radiusTop, + this.radiusBottom, + this.height, + this.numSegments + ); + } else if (this.shapeType == GameLib.D3.Shape.SHAPE_TYPE_HEIGHT_MAP) { + instance = new this.engine.instance.Heightfield( + this.heightmap.matrix, + { + elementSize: this.heightmap.elementSize + } + ); + } else if (this.shapeType == GameLib.D3.Shape.SHAPE_TYPE_CONVEX_HULL) { + console.warn('Shape type not implemented: ' + this.shapeType); + throw new Error('Shape type not implemented: ' + this.shapeType); + } else { + console.warn('Shape type not implemented: ' + this.shapeType); + throw new Error('Shape type not implemented: ' + this.shapeType); + } + + this.instance = instance; + + return instance; +}; + + +/** + * update + */ +GameLib.D3.Shape.prototype.update = function( + engine +) { + engine.isNotCannonThrow(); + + if(this.shapeType === GameLib.D3.Shape.SHAPE_TYPE_TRIMESH) { + this.instance.setScale( + new engine.instance.Vec3( + this.scale.x, + this.scale.y, + this.scale.z + ) + ); + this.instance.updateAABB(); + this.instance.updateNormals(); + this.instance.updateEdges(); + this.instance.updateBoundingSphereRadius(); + this.instance.updateTree(); + } +}; + +/** + * Skeleton Superset + * @param id + * @param bones GameLib.D3.Bone + * @param boneInverses + * @param useVertexTexture + * @param boneTextureWidth + * @param boneTextureHeight + * @param boneMatrices + * @param boneTexture + * @constructor + */ +GameLib.D3.Skeleton = function( + id, + bones, + boneInverses, + useVertexTexture, + boneTextureWidth, + boneTextureHeight, + boneMatrices, + boneTexture +) { + this.id = id; + + this.bones = bones; + + /** + * An array of Matrix4s that represent the inverse of the matrixWorld of the individual bones. + * @type GameLib.D3.Matrix4[] + */ + if (typeof boneInverses == 'undefined') { + boneInverses = []; + } + this.boneInverses = boneInverses; + + /** + * Use a vertex texture in the shader - allows for more than 4 bones per vertex, not supported by all devices + * @type {boolean} + */ + if (typeof useVertexTexture == 'undefined') { + useVertexTexture = false; + } + this.useVertexTexture = useVertexTexture; + + if (this.useVertexTexture == true) { + console.warn('support for vertex texture bones is not supported yet - something could break somewhere'); + } + + if (typeof boneTextureWidth == 'undefined') { + boneTextureWidth = 0; + } + this.boneTextureWidth = boneTextureWidth; + + if (typeof boneTextureHeight == 'undefined') { + boneTextureHeight = 0; + } + this.boneTextureHeight = boneTextureHeight; + + if (typeof boneMatrices == 'undefined') { + boneMatrices = []; + } + this.boneMatrices = boneMatrices; + + if (typeof boneTexture == 'undefined') { + boneTexture = []; + } + this.boneTexture = boneTexture; +}; + + +GameLib.D3.SkyBox = function ( + graphics +) { + this.id = null; + + this.graphics = graphics; + this.graphics.isNotThreeThrow(); + + this.texturesFolder = null; +}; + +GameLib.D3.SkyBox.prototype.load = function ( + texturesFolder +) { + this.texturesFolder = texturesFolder; + this.textures = []; + this.materials = []; + this.mesh = {}; + this.scene = new this.graphics.instance.Scene(); + this.textureCube = null; + + var textureLoader = new this.graphics.instance.TextureLoader(); + + // this textures are used to display the skybox + this.textures.push(textureLoader.load(this.texturesFolder + "px.png")); + this.textures.push(textureLoader.load(this.texturesFolder + "nx.png")); + this.textures.push(textureLoader.load(this.texturesFolder + "py.png")); + this.textures.push(textureLoader.load(this.texturesFolder + "ny.png")); + this.textures.push(textureLoader.load(this.texturesFolder + "pz.png")); + this.textures.push(textureLoader.load(this.texturesFolder + "nz.png")); + + // assign textures to each cube face + for (var i = 0; i < 6; i ++) { + this.materials.push(new this.graphics.instance.MeshBasicMaterial({ map: this.textures[i] })); + } + + // create cube geometry + this.mesh = new this.graphics.instance.Mesh(new this.graphics.instance.CubeGeometry(1, 1, 1), new this.graphics.instance.MeshFaceMaterial(this.materials)); + this.mesh.applyMatrix(new this.graphics.instance.Matrix4().makeScale(1, 1, -1)); + this.scene.add(this.mesh); + + // Load env textureCube + // this is used for reflections on meshes + // mesh.material.envMap = this.textureCube; + this.textureCube = new this.graphics.instance.CubeTextureLoader().load([ + this.texturesFolder + "px.png", this.texturesFolder + "nx.png", + this.texturesFolder + "py.png", this.texturesFolder + "ny.png", + this.texturesFolder + "pz.png", this.texturesFolder + "nz.png" + ]); +}; + +GameLib.D3.SkyBox.prototype.render = function ( + threeRenderer, + threeCamera +) { + var cameraPosition = new this.graphics.instance.Vector3(threeCamera.position.x, threeCamera.position.y, threeCamera.position.z); + + threeCamera.position.set(0, 0, 0); + + var gl = threeRenderer.context; + + gl.disable(gl.DEPTH_TEST); + + threeRenderer.render(this.scene, threeCamera); + + gl.enable(gl.DEPTH_TEST); + + threeCamera.position.copy(cameraPosition); +}; + +/** + * Physics Solver Superset + * @param id + * @param name + * @param solverType + * @param iterations + * @param tolerance + * @constructor + */ +GameLib.D3.Physics.Solver = function( + id, + name, + solverType, + iterations, + tolerance +) { + this.id = id; + if (typeof name == 'undefined') { + if (solverType == GameLib.D3.Physics.SPLIT_SOLVER) { + name = 'split solver'; + } else if (solverType == GameLib.D3.Physics.GS_SOLVER) { + name = 'gs solver'; + } else { + name = 'unknown solver'; + } + } + this.name = name; + this.solverType = solverType; + this.iterations = iterations; + this.tolerance = tolerance; +}; + +/** + * Solver Types + * @type {number} + */ +GameLib.D3.Physics.SPLIT_SOLVER = 0x1; +GameLib.D3.Physics.GS_SOLVER = 0x2; + +/** + * Texture Superset + * @param id + * @param name + * @param image + * @param wrapS + * @param wrapT + * @param repeat + * @param data + * @param format + * @param mapping + * @param magFilter + * @param minFilter + * @param textureType + * @param anisotropy + * @param offset + * @param generateMipmaps + * @param flipY + * @param mipmaps + * @param unpackAlignment + * @param premultiplyAlpha + * @param encoding + * @constructor + */ +GameLib.D3.Texture = function( + id, + name, + image, + wrapS, + wrapT, + repeat, + data, + format, + mapping, + magFilter, + minFilter, + textureType, + anisotropy, + offset, + generateMipmaps, + flipY, + mipmaps, + unpackAlignment, + premultiplyAlpha, + encoding +) { + this.id = id; + this.name = name; + this.image = image; + + if (typeof wrapS == 'undefined') { + wrapS = GameLib.D3.Texture.TYPE_REPEAT_WRAPPING; + } + this.wrapS = wrapS; + + if (typeof wrapT == 'undefined') { + wrapT = GameLib.D3.Texture.TYPE_REPEAT_WRAPPING; + } + this.wrapT = wrapT; + + if (typeof repeat == 'undefined') { + repeat = new GameLib.D3.Vector2(1, 1); + } + this.repeat = repeat; + + if (typeof data == 'undefined') { + data = null; + } + this.data = data; + + if (typeof format == 'undefined') { + format = GameLib.D3.Texture.TYPE_RGBA_FORMAT; + } + this.format = format; + + if (typeof mapping == 'undefined') { + mapping = GameLib.D3.Texture.TYPE_UV_MAPPING; + } + this.mapping = mapping; + + if (typeof magFilter == 'undefined') { + magFilter = GameLib.D3.Texture.TYPE_LINEAR_FILTER; + } + this.magFilter = magFilter; + + if (typeof minFilter == 'undefined') { + minFilter = GameLib.D3.Texture.TYPE_LINEAR_MIPMAP_LINEAR_FILTER; + } + this.minFilter = minFilter; + + if (typeof textureType == 'undefined') { + textureType = GameLib.D3.Texture.TYPE_UNSIGNED_BYTE; + } + this.textureType = textureType; + + if (typeof anisotropy == 'undefined') { + anisotropy = 1; + } + this.anisotropy = anisotropy; + + if (typeof offset == 'undefined') { + offset = new GameLib.D3.Vector2(0, 0); + } + this.offset = offset; + + if (typeof generateMipmaps == 'undefined') { + generateMipmaps = true; + } + this.generateMipmaps = generateMipmaps; + + if (typeof flipY == 'undefined') { + flipY = true; + } + this.flipY = flipY; + + if (typeof mipmaps == 'undefined') { + mipmaps = []; + } + this.mipmaps = mipmaps; + + if (typeof unpackAlignment == 'undefined') { + unpackAlignment = 4; + } + this.unpackAlignment = unpackAlignment; + + if (typeof premultiplyAlpha == 'undefined') { + premultiplyAlpha = false; + } + this.premultiplyAlpha = premultiplyAlpha; + + if (typeof encoding == 'undefined') { + encoding = GameLib.D3.Texture.TYPE_LINEAR_ENCODING; + } + this.encoding = encoding; +}; + +/** + * Texture Formats + * @type {number} + */ +GameLib.D3.Texture.TYPE_ALPHA_FORMAT = 1019; +GameLib.D3.Texture.TYPE_RGB_FORMAT = 1020; +GameLib.D3.Texture.TYPE_RGBA_FORMAT = 1021; +GameLib.D3.Texture.TYPE_LUMINANCE_FORMAT = 1022; +GameLib.D3.Texture.TYPE_LUMINANCE_ALPHA_FORMAT = 1023; +GameLib.D3.Texture.TYPE_DEPTH_FORMAT = 1026; + +/** + * Mapping modes + * @type {number} + */ +GameLib.D3.Texture.TYPE_UV_MAPPING = 300; +GameLib.D3.Texture.TYPE_CUBE_REFLECTION_MAPPING = 301; +GameLib.D3.Texture.TYPE_CUBE_REFRACTION_MAPPING = 302; +GameLib.D3.Texture.TYPE_EQUI_RECTANGULAR_REFLECTION_MAPPING = 303; +GameLib.D3.Texture.TYPE_EQUI_RECTANGULAR_REFRACTION_MAPPING = 304; +GameLib.D3.Texture.TYPE_SPHERICAL_REFLECTION_MAPPING = 305; +GameLib.D3.Texture.TYPE_CUBE_UV_REFLECTION_MAPPING = 306; +GameLib.D3.Texture.TYPE_CUBE_UV_REFRACTION_MAPPING = 307; + +/** + * Wrapping Modes + * @type {number} + */ +GameLib.D3.Texture.TYPE_REPEAT_WRAPPING = 1000; +GameLib.D3.Texture.TYPE_CLAMP_TO_EDGE_WRAPPING = 1001; +GameLib.D3.Texture.TYPE_MIRRORED_REPEAT_WRAPPING = 1002; + +/** + * Mipmap Filters + * @type {number} + */ +GameLib.D3.Texture.TYPE_NEAREST_FILTER = 1003; +GameLib.D3.Texture.TYPE_NEAREST_MIPMAP_NEAREST_FILTER = 1004; +GameLib.D3.Texture.TYPE_NEAREST_MIPMAP_LINEAR_FILTER = 1005; +GameLib.D3.Texture.TYPE_LINEAR_FILTER = 1006; +GameLib.D3.Texture.TYPE_LINEAR_MIPMAP_NEAREST_FILTER = 1007; +GameLib.D3.Texture.TYPE_LINEAR_MIPMAP_LINEAR_FILTER = 1008; + +/** + * Texture Data Types + * @type {number} + */ +GameLib.D3.Texture.TYPE_UNSIGNED_BYTE = 1009; +GameLib.D3.Texture.TYPE_BYTE = 1010; +GameLib.D3.Texture.TYPE_SHORT = 1011; +GameLib.D3.Texture.TYPE_UNSIGNED_SHORT = 1012; +GameLib.D3.Texture.TYPE_INT = 1013; +GameLib.D3.Texture.TYPE_UNSIGNED_INT = 1014; +GameLib.D3.Texture.TYPE_FLOAT = 1015; +GameLib.D3.Texture.TYPE_HALF_FLOAT = 1025; + +/** + * Encoding Modes + * @type {number} + */ +GameLib.D3.Texture.TYPE_LINEAR_ENCODING = 3000; // NO ENCODING AT ALL. +GameLib.D3.Texture.TYPE_SRGB_ENCODING = 3001; +GameLib.D3.Texture.TYPE_GAMMA_ENCODING = 3007; // USES GAMMA_FACTOR, FOR BACKWARDS COMPATIBILITY WITH WEBGLRENDERER.GAMMAINPUT/GAMMAOUTPUT +GameLib.D3.Texture.TYPE_RGBE_ENCODING = 3002; // AKA RADIANCE. +GameLib.D3.Texture.TYPE_LOG_LUV_ENCODING = 3003; +GameLib.D3.Texture.TYPE_RGBM7_ENCODING = 3004; +GameLib.D3.Texture.TYPE_RGBM16_ENCODING = 3005; +GameLib.D3.Texture.TYPE_RGBD_ENCODING = 3006; // MAXRANGE IS 256. + +/** + * Defers loading of an image and resolves once image is loaded + * @param gameLibTexture GameLib.D3.Texture + * @param instanceMaterial + * @param instanceMaterialMapType + * @param graphics GameLib.D3.Graphics + * @param uploadUrl String + * @param progressCallback + * @returns {Promise} + */ +GameLib.D3.Texture.loadMap = function( + gameLibTexture, + instanceMaterial, + instanceMaterialMapType, + graphics, + uploadUrl, + progressCallback +) { + + var defer = Q.defer(); + + var imagePath = null; + + var textureLoader = new graphics.instance.TextureLoader(); + + if (gameLibTexture && gameLibTexture.image && gameLibTexture.image.filename) { + /** + * Else, load from upload source + */ + imagePath = uploadUrl + '/' + gameLibTexture.image.filename; + } + + if (imagePath) { + + textureLoader.crossOrigin = ''; + + textureLoader.load( + imagePath, + function(texture) { + /** + * onLoad + */ + instanceMaterial[instanceMaterialMapType] = texture; + instanceMaterial[instanceMaterialMapType].name = gameLibTexture.name; + instanceMaterial[instanceMaterialMapType].anisotropy = gameLibTexture.anisotropy; + instanceMaterial[instanceMaterialMapType].encoding = gameLibTexture.encoding; + instanceMaterial[instanceMaterialMapType].flipY = gameLibTexture.flipY; + /** + * We don't restore the format since this changing from OS to OS and breaks the implementation sometimes + */ + instanceMaterial[instanceMaterialMapType].generateMipmaps = gameLibTexture.generateMipmaps; + instanceMaterial[instanceMaterialMapType].magFilter = gameLibTexture.magFilter; + instanceMaterial[instanceMaterialMapType].minFilter = gameLibTexture.minFilter; + instanceMaterial[instanceMaterialMapType].mapping = gameLibTexture.mapping; + instanceMaterial[instanceMaterialMapType].mipmaps = gameLibTexture.mipmaps; + instanceMaterial[instanceMaterialMapType].offset = new graphics.instance.Vector2( + gameLibTexture.offset.x, + gameLibTexture.offset.y + ); + instanceMaterial[instanceMaterialMapType].premultiplyAlpha = gameLibTexture.premultiplyAlpha; + instanceMaterial[instanceMaterialMapType].textureType = gameLibTexture.textureType; + instanceMaterial[instanceMaterialMapType].wrapS = gameLibTexture.wrapS; + instanceMaterial[instanceMaterialMapType].wrapT = gameLibTexture.wrapT; + instanceMaterial[instanceMaterialMapType].unpackAlignment = gameLibTexture.unpackAlignment; + instanceMaterial.needsUpdate = true; + defer.resolve(true); + }, + function(xhr) { + /** + * onProgress + */ + if (progressCallback) { + progressCallback(Math.round(xhr.loaded / xhr.total * 100)); + } + }, + function(error) { + /** + * onError + */ + console.log("an error occurred while trying to load the image : " + imagePath); + defer.resolve(null); + } + ); + + } else { + defer.resolve(null); + } + + return defer.promise; +}; + + +/** + * Returns an array of image loading Promises + * @param gameLibMaterial + * @param blenderMaps + * @param instanceMaterial + * @param graphics GameLib.D3.Graphics + * @param uploadUrl String + * @param progressCallback + * @returns Q[] + */ +GameLib.D3.Texture.loadMaps = function( + gameLibMaterial, + blenderMaps, + instanceMaterial, + graphics, + uploadUrl, + progressCallback +) { + + var textureMaps = []; + + for (var ti = 0; ti < blenderMaps.length; ti++) { + + var map = blenderMaps[ti]; + + if (gameLibMaterial.maps.hasOwnProperty(map)) { + + var blenderTexture = gameLibMaterial.maps[map]; + + if ( + blenderTexture && + blenderTexture.image && + blenderTexture.image.filename + ) { + + var instanceMap = null; + + if (map == 'alpha') { + instanceMap = 'alhpaMap'; + } + + if (map == 'ao') { + instanceMap = 'aoMap'; + } + + if (map == 'bump') { + instanceMap = 'bumpMap'; + } + + if (map == 'displacement') { + instanceMap = 'displacementMap'; + } + + if (map == 'emissive') { + instanceMap = 'emissiveMap'; + } + + if (map == 'environment') { + instanceMap = 'envMap'; + } + + if (map == 'light') { + instanceMap = 'lightMap'; + } + + if (map == 'specular') { + instanceMap = 'specularMap'; + } + + if (map == 'diffuse') { + instanceMap = 'map'; + } + + if (map == 'roughness') { + instanceMap = 'roughnessMap'; + } + + if (map == 'metalness') { + instanceMap = 'metalnessMap'; + } + + if (instanceMap == null) { + console.warn("unsupported map type : " + map); + } + + textureMaps.push( + GameLib.D3.Texture.loadMap( + gameLibMaterial.maps[map], + instanceMaterial, + instanceMap, + graphics, + uploadUrl, + progressCallback + ) + ); + } + } + } + + return textureMaps; +}; + +/** + * TriangleEdge + * @param triangle + * @param edge + * @constructor + */ +GameLib.D3.TriangleEdge = function( + triangle, + edge +) { + this.triangle = triangle; + this.edge = edge; +}; +/** + * TriangleFace + * @param v0 + * @param v1 + * @param v2 + * @param materialIndex + * @param v0uv + * @param v1uv + * @param v2uv + * @param color + * @param vertexColors + * @param vertexNormals + * @param normal + * @constructor + */ +GameLib.D3.TriangleFace = function( + v0, + v1, + v2, + materialIndex, + v0uv, + v1uv, + v2uv, + color, + vertexColors, + vertexNormals, + normal +) { + this.v0 = v0; + this.v1 = v1; + this.v2 = v2; + this.materialIndex = materialIndex; + this.v0uv = v0uv; + this.v1uv = v1uv; + this.v2uv = v2uv; + if (!color) { + color = new GameLib.D3.Color(0xff, 0xff, 0xff, 0xff); + } + this.color = color; + + if (!vertexColors) { + vertexColors = [ + new GameLib.D3.Color(0xff, 0xff, 0xff, 0xff), + new GameLib.D3.Color(0xff, 0xff, 0xff, 0xff), + new GameLib.D3.Color(0xff, 0xff, 0xff, 0xff) + ]; + } + this.vertexColors = vertexColors; + + if (!vertexNormals) { + vertexNormals = [ + new GameLib.D3.Vector3(), + new GameLib.D3.Vector3(), + new GameLib.D3.Vector3() + ] + } + this.vertexNormals = vertexNormals; + + if (!normal) { + normal = new GameLib.D3.Vector3(0); + } + + this.normal = normal; +}; + +/** + * Clone a TriangleFace + * @returns {GameLib.D3.TriangleFace} + */ +GameLib.D3.TriangleFace.prototype.clone = function(){ + return new GameLib.D3.TriangleFace( + this.v0, + this.v1, + this.v2, + this.materialIndex, + this.v0uv.copy(), + this.v1uv.copy(), + this.v2uv.copy() + ); +}; + /** * Returns true if two triangles are equal (their vertex indices match in some order) * @param triangle @@ -1829,1107 +4392,637 @@ GameLib.D3.TriangleFace.prototype.equals = function(triangle) { )); }; -GameLib.D3.prototype.invertWindingOrder = function(triangles) { - for (var i = 0; i < triangles.length; i++) { - var v1 = triangles[i].v1; - triangles[i].v1 = triangles[i].v2; - triangles[i].v2 = v1; +GameLib.D3.Vector2 = function(x, y) { - var backupUV = triangles[i].triangle.v1uv; - triangles[i].triangle.v1uv = triangles[i].triangle.v2uv; - triangles[i].triangle.v2uv = backupUV; + this.x = 0; + this.y = 0; + + if (x) { + this.x = x; } - return triangles; + if (y) { + this.y = y; + } }; -/** - * This function resets a the winding order of a mesh from a reference point V (the average center of the mesh) - */ -GameLib.D3.prototype.resetWindingOrder = function(faces, vertices) { - - var vertexList = new GameLib.D3.Vector3.Points(); - - for (var v = 0; v < vertices.length; v++) { - vertexList.add(new GameLib.D3.Vector3( - vertices[v].position.x, - vertices[v].position.y, - vertices[v].position.z - )); - } - - var V = vertexList.average(); - - var triangles = []; - - for (var s = 0; s < faces.length; s += 3) { - - var v0 = faces[s]; - var v1 = faces[s+1]; - var v2 = faces[s+2]; - - triangles.push( - { - v0 : v0, - v1 : v1, - v2 : v2, - edges : [ - {v0: v0, v1: v1}, - {v0: v1, v1: v2}, - {v0: v2, v1: v0} - ], - winding : 0, - edgeIndex : -1, - processed : false - } - ); - } - - for (var i = 0; i < triangles.length; i++) { - if ( - GameLib.D3.Vector3.clockwise( - vertices[triangles[i].v0].position, - vertices[triangles[i].v1].position, - vertices[triangles[i].v2].position, - V - ) - ) { - console.log('clockwise'); - var bv1 = triangles[i].v1; - triangles[i].v1 = triangles[i].v2; - triangles[i].v2 = bv1; - } else { - console.log('not clockwise'); - } - } - - return triangles; -}; - -/** - * Defers loading of an image and resolves once image is loaded - * @param gameLibTexture - * @param threeMaterial - * @param threeMaterialMapType - * @returns {Promise} - */ -GameLib.D3.prototype.loadMap = function(gameLibTexture, threeMaterial, threeMaterialMapType) { - - var q = this.Q.defer(); - - var imagePath = null; - - if (gameLibTexture && gameLibTexture.image && gameLibTexture.image.apiPath && gameLibTexture.image.filename) { - /** - * Load the image from API here if apiPath is defined - */ - imagePath = this.apiUrl + gameLibTexture.image.uploadPath + '/' + gameLibTexture.image.filename; - } - - if (gameLibTexture && gameLibTexture.image && gameLibTexture.image.uploadPath && gameLibTexture.image.filename) { - /** - * Else, load from upload source - */ - imagePath = this.editorUrl + gameLibTexture.image.uploadPath + '/' + gameLibTexture.image.filename; - } - - if (imagePath) { - - this.textureLoader.load( - imagePath, - function(texture) { - /** - * onLoad - */ - threeMaterial[threeMaterialMapType] = texture; - threeMaterial[threeMaterialMapType].name = gameLibTexture.name; - threeMaterial[threeMaterialMapType].anisotropy = gameLibTexture.anisotropy; - threeMaterial[threeMaterialMapType].encoding = gameLibTexture.encoding; - threeMaterial[threeMaterialMapType].flipY = gameLibTexture.flipY; - /** - * We don't restore the format since this changing from OS to OS and breaks the implementation sometimes - */ - threeMaterial[threeMaterialMapType].generateMipmaps = gameLibTexture.generateMipmaps; - threeMaterial[threeMaterialMapType].magFilter = gameLibTexture.magFilter; - threeMaterial[threeMaterialMapType].minFilter = gameLibTexture.minFilter; - threeMaterial[threeMaterialMapType].mapping = gameLibTexture.mapping; - threeMaterial[threeMaterialMapType].mipmaps = gameLibTexture.mipmaps; - threeMaterial[threeMaterialMapType].offset = new this.THREE.Vector2( - gameLibTexture.offset.x, - gameLibTexture.offset.y - ); - threeMaterial[threeMaterialMapType].premultiplyAlpha = gameLibTexture.premultiplyAlpha; - threeMaterial[threeMaterialMapType].textureType = gameLibTexture.textureType; - threeMaterial[threeMaterialMapType].wrapS = gameLibTexture.wrapS; - threeMaterial[threeMaterialMapType].wrapT = gameLibTexture.wrapT; - threeMaterial[threeMaterialMapType].unpackAlignment = gameLibTexture.unpackAlignment; - threeMaterial.needsUpdate = true; - q.resolve(true); - }, - function(xhr) { - /** - * onProgress - */ - if (this.editor) { - this.editor.setServerStatus(Math.round(xhr.loaded / xhr.total * 100) + '% complete', 'success'); - } - }, - function(error) { - /** - * onError - */ - console.log("an error occurred while trying to load the image : " + imagePath); - q.resolve(null); - } - ); - - } else { - q.resolve(null); - } - - return q.promise; -}; - -/** - * Creates a THREE Mesh from GameLib.D3.Mesh - * @param gameLibMesh - * @param threeGeometry - * @param threeMaterial - * @returns {*} - */ -GameLib.D3.prototype.createThreeMesh = function(gameLibMesh, threeGeometry, threeMaterial) { - - var threeMesh = null; - - if (gameLibMesh.meshType == GameLib.D3.Mesh.TYPE_NORMAL) { - threeMesh = new this.THREE.Mesh(threeGeometry, threeMaterial); - } - - if (gameLibMesh.meshType == GameLib.D3.Mesh.TYPE_SKINNED) { - - var bones = gameLibMesh.skeleton.bones; - - var skinIndices = gameLibMesh.skinIndices; - - var skinWeights = gameLibMesh.skinWeights; - - var threeBones = []; - - for (var bi = 0; bi < bones.length; bi++) { - - var bone = new this.THREE.Bone(); - - bone.name = bones[bi].name; - - bone.position.x = bones[bi].position.x; - bone.position.y = bones[bi].position.y; - bone.position.z = bones[bi].position.z; - - bone.rotation.x = bones[bi].rotation.x; - bone.rotation.y = bones[bi].rotation.y; - bone.rotation.z = bones[bi].rotation.z; - - bone.quaternion.x = bones[bi].quaternion.x; - bone.quaternion.y = bones[bi].quaternion.y; - bone.quaternion.z = bones[bi].quaternion.z; - bone.quaternion.w = bones[bi].quaternion.w; - - bone.scale.x = bones[bi].scale.x; - bone.scale.y = bones[bi].scale.y; - bone.scale.z = bones[bi].scale.z; - - bone.up.x = bones[bi].up.x; - bone.up.y = bones[bi].up.y; - bone.up.z = bones[bi].up.z; - - threeBones.push(bone); - } - - /** - * Setup the bone relationships - */ - for (var br = 0; br < bones.length; br++) { - for (var cbi = 0; cbi < bones[br].childBoneIds.length; cbi++) { - threeBones[br].add(threeBones[bones[br].childBoneIds[cbi]]); - } - } - - /** - * Setup bones (indexes) - */ - for (var si = 0; si < skinIndices.length; si++) { - threeGeometry.skinIndices.push( - new this.THREE.Vector4( - skinIndices[si].x, - skinIndices[si].y, - skinIndices[si].z, - skinIndices[si].w - ) - ); - } - - /** - * Setup bones (weights) - */ - for (var sw = 0; sw < skinWeights.length; sw++) { - threeGeometry.skinWeights.push( - new this.THREE.Vector4( - skinWeights[sw].x, - skinWeights[sw].y, - skinWeights[sw].z, - skinWeights[sw].w - ) - ); - } - - threeMesh = new this.THREE.SkinnedMesh(threeGeometry, threeMaterial); - - var skeleton = new this.THREE.Skeleton(threeBones); - - skeleton.useVertexTexture = gameLibMesh.skeleton.useVertexTexture; - - for (var i = 0; i < bones.length; i++) { - if (bones[i].parentBoneId === null) { - threeMesh.add(threeBones[i]); - break; - } - } - - threeMesh.bind(skeleton); - - threeMesh.pose(); - - threeMesh.skeleton.skeletonHelper = new this.THREE.SkeletonHelper(threeMesh); - threeMesh.skeleton.skeletonHelper.material.linewidth = 5; - } - - if (threeMesh == null) { - console.log('cannot handle meshes of type ' + gameLibMesh.meshType + ' yet.'); - } - - gameLibMesh.threeMeshId = threeMesh.id; - - return threeMesh; -}; - -/** - * Returns an array of image loading Promises - * @param blenderMaterial - * @param blenderMaps - * @param threeMaterial - * @returns Q[] - */ -GameLib.D3.prototype.loadMaps = function(blenderMaterial, blenderMaps, threeMaterial) { - - var textureMaps = []; - - for (var ti = 0; ti < blenderMaps.length; ti++) { - - var map = blenderMaps[ti]; - - if (blenderMaterial.maps.hasOwnProperty(map)) { - - var blenderTexture = blenderMaterial.maps[map]; - - if ( - blenderTexture && - blenderTexture.image && - blenderTexture.image.filename && - blenderTexture.image.uploadPath - ) { - - var threeMap = null; - - if (map == 'alpha') { - threeMap = 'alhpaMap'; - } - - if (map == 'ao') { - threeMap = 'aoMap'; - } - - if (map == 'bump') { - threeMap = 'bumpMap'; - } - - if (map == 'displacement') { - threeMap = 'displacementMap'; - } - - if (map == 'emissive') { - threeMap = 'emissiveMap'; - } - - if (map == 'environment') { - threeMap = 'envMap'; - } - - if (map == 'light') { - threeMap = 'lightMap'; - } - - if (map == 'specular') { - threeMap = 'specularMap'; - } - - if (map == 'diffuse') { - threeMap = 'map'; - } - - if (map == 'roughness') { - threeMap = 'roughnessMap'; - } - - if (map == 'metalness') { - threeMap = 'metalnessMap'; - } - - if (threeMap == null) { - console.warn("unsupported map type : " + map); - } - - textureMaps.push(this.loadMap(blenderMaterial.maps[map], threeMaterial, threeMap)); - } - } - } - - return textureMaps; -}; - -/** - * Creates a this.THREE.Material from a GameLib.D3.Material - * @param blenderMaterial GameLib.D3.Material - */ -GameLib.D3.prototype.createThreeMaterial = function(blenderMaterial) { - - var defer = this.Q.defer(); - - var threeMaterial = null; - - var blenderMaps = []; - - if (blenderMaterial.materialType == GameLib.D3.Material.TYPE_MESH_STANDARD) { - - threeMaterial = new this.THREE.MeshStandardMaterial({ - name: blenderMaterial.name, - opacity: blenderMaterial.opacity, - transparent: blenderMaterial.transparent, - blending: blenderMaterial.blending, - blendSrc: blenderMaterial.blendSrc, - blendDst: blenderMaterial.blendDst, - blendEquation: blenderMaterial.blendEquation, - depthTest: blenderMaterial.depthTest, - depthFunc: blenderMaterial.depthFunc, - depthWrite: blenderMaterial.depthWrite, - polygonOffset: blenderMaterial.polygonOffset, - polygonOffsetFactor: blenderMaterial.polygonOffsetFactor, - polygonOffsetUnits: blenderMaterial.polygonOffsetUnits, - alphaTest: blenderMaterial.alphaTest, - clippingPlanes: blenderMaterial.clippingPlanes, - clipShadows: blenderMaterial.clipShadows, - overdraw: blenderMaterial.overdraw, - visible: blenderMaterial.visible, - side: blenderMaterial.side, - color: new this.THREE.Color( - blenderMaterial.color.r, - blenderMaterial.color.g, - blenderMaterial.color.b - ), - roughness: blenderMaterial.roughness, - metalness: blenderMaterial.metalness, - lightMapIntensity: blenderMaterial.lightMapIntensity, - aoMapIntensity: blenderMaterial.aoMapIntensity, - emissive: new this.THREE.Color( - blenderMaterial.emissive.r, - blenderMaterial.emissive.g, - blenderMaterial.emissive.b - ), - emissiveIntensity: blenderMaterial.emissiveIntensity, - bumpScale: blenderMaterial.bumpScale, - normalScale: blenderMaterial.normalScale, - displacementScale: blenderMaterial.displacementScale, - refractionRatio: blenderMaterial.refractionRatio, - fog: blenderMaterial.fog, - shading: blenderMaterial.shading, - wireframe: blenderMaterial.wireframe, - wireframeLinewidth: blenderMaterial.wireframeLineWidth, - wireframeLinecap: blenderMaterial.wireframeLineCap, - wireframeLinejoin: blenderMaterial.wireframeLineJoin, - vertexColors: blenderMaterial.vertexColors, - skinning: blenderMaterial.skinning, - morphTargets: blenderMaterial.morphTargets, - morphNormals: blenderMaterial.morphNormals - }); - - blenderMaps.push( - 'diffuse', - 'light', - 'ao', - 'emissive', - 'bump', - 'normal', - 'displacement', - 'roughness', - 'metalness', - 'alpha', - 'environment' - ); - } else if (blenderMaterial.materialType == GameLib.D3.Material.TYPE_MESH_PHONG) { - - threeMaterial = new this.THREE.MeshPhongMaterial({ - name: blenderMaterial.name, - opacity: blenderMaterial.opacity, - transparent: blenderMaterial.transparent, - blending: blenderMaterial.blending, - blendSrc: blenderMaterial.blendSrc, - blendDst: blenderMaterial.blendDst, - blendEquation: blenderMaterial.blendEquation, - depthTest: blenderMaterial.depthTest, - depthFunc: blenderMaterial.depthFunc, - depthWrite: blenderMaterial.depthWrite, - polygonOffset: blenderMaterial.polygonOffset, - polygonOffsetFactor: blenderMaterial.polygonOffsetFactor, - polygonOffsetUnits: blenderMaterial.polygonOffsetUnits, - alphaTest: blenderMaterial.alphaTest, - clippingPlanes: blenderMaterial.clippingPlanes, - clipShadows: blenderMaterial.clipShadows, - overdraw: blenderMaterial.overdraw, - visible: blenderMaterial.visible, - side: blenderMaterial.side, - color: new this.THREE.Color( - blenderMaterial.color.r, - blenderMaterial.color.g, - blenderMaterial.color.b - ), - specular: new this.THREE.Color( - blenderMaterial.specular.r, - blenderMaterial.specular.g, - blenderMaterial.specular.b - ), - shininess: blenderMaterial.shininess, - lightMapIntensity: blenderMaterial.lightMapIntensity, - aoMapIntensity: blenderMaterial.aoMapIntensity, - emissive: new this.THREE.Color( - blenderMaterial.emissive.r, - blenderMaterial.emissive.g, - blenderMaterial.emissive.b - ), - emissiveIntensity: blenderMaterial.emissiveIntensity, - bumpScale: blenderMaterial.bumpScale, - normalScale: blenderMaterial.normalScale, - displacementScale: blenderMaterial.displacementScale, - combine: blenderMaterial.combine, - refractionRatio: blenderMaterial.refractionRatio, - fog: blenderMaterial.fog, - shading: blenderMaterial.shading, - wireframe: blenderMaterial.wireframe, - wireframeLinewidth: blenderMaterial.wireframeLineWidth, - wireframeLinecap: blenderMaterial.wireframeLineCap, - wireframeLinejoin: blenderMaterial.wireframeLineJoin, - vertexColors: blenderMaterial.vertexColors, - skinning: blenderMaterial.skinning, - morphTargets: blenderMaterial.morphTargets, - morphNormals: blenderMaterial.morphNormals - }); - - blenderMaps.push( - 'diffuse', - 'light', - 'ao', - 'emissive', - 'bump', - 'normal', - 'displacement', - 'specular', - 'alpha', - 'environment' - ); - - } else { - console.log("material type is not implemented yet: " + blenderMaterial.materialType + " - material indexes could be screwed up"); - } - - if (blenderMaps.length > 0) { - var textureMaps = this.loadMaps(blenderMaterial, blenderMaps, threeMaterial); - Q.all(textureMaps).then( - function(){ - defer.resolve(threeMaterial); - } - ).catch( - function(error){ - console.log(error); - defer.reject(error); - } - ) - } else { - defer.resolve(threeMaterial); - } - - return defer.promise; -}; - -/** - * Loads a scene directly from the API - * @param sceneName - * @param onLoaded callback - */ -GameLib.D3.prototype.loadSceneFromApi = function(sceneName, onLoaded) { - /** - * First check if this is a client or server side request - */ - if (typeof XMLHttpRequest == 'undefined') { - console.warn('implement server side loading from API here'); - return onLoaded(null, new Error('not implemented')); - } - - var xhr = new XMLHttpRequest(); - xhr.open( - 'GET', - this.apiUrl + '/scene/pong%20latest' +GameLib.D3.Vector2.prototype.copy = function() { + return new GameLib.D3.Vector2( + this.x, + this.y ); +}; - xhr.onreadystatechange = function(xhr, gameLibD3) { - return function() { - if (xhr.readyState == 4) { - var response = JSON.parse(xhr.responseText); - gameLibD3.loadScene(response.scene[0], onLoaded, false); - } +GameLib.D3.Vector2.prototype.equals = function(v) { + return !!(((this.x == v.x) && + (this.y == v.y)) || + ((this.y == v.x) && + (this.x == v.y))); +}; + +GameLib.D3.Vector3 = function(x, y, z) { + + this.x = 0; + this.y = 0; + this.z = 0; + + if (x) { + this.x = x; + } + + if (y) { + this.y = y; + } + + if (z) { + this.z = z; + } +}; + +GameLib.D3.Vector3.prototype.subtract = function (v) { + + if (v instanceof GameLib.D3.Vector3) { + this.x -= v.x; + this.y -= v.y; + this.z -= v.z; + } + + if (v instanceof GameLib.D3.Vector4) { + console.warn("trying to subtract vector of bigger length (4 vs 3))"); + } + + return this; +}; + +GameLib.D3.Vector3.prototype.cross = function (v) { + return new GameLib.D3.Vector3( + this.y * v.z - this.z * v.y, + this.z * v.x - this.x * v.z, + this.x * v.y - this.y * v.x + ); +}; + +GameLib.D3.Vector3.prototype.negative = function () { + this.x *= -1; + this.y *= -1; + this.z *= -1; + return this; +}; + +GameLib.D3.Vector3.clockwise = function (u, v, w, viewPoint) { + + var normal = GameLib.D3.Vector3.normal(u, v, w); + + var uv = u.copy(); + + var winding = normal.dot(uv.subtract(viewPoint)); + + return (winding > 0); +}; + +GameLib.D3.Vector3.normal = function (u, v, w) { + var vv = v.copy(); + var wv = w.copy(); + return vv.subtract(u).cross(wv.subtract(u)); +}; + +GameLib.D3.Vector3.prototype.lookAt = function (at, up) { + + var lookAtMatrix = GameLib.D3.Matrix4.lookAt(this, at, up); + + this.multiply(lookAtMatrix); +}; + +GameLib.D3.Vector3.prototype.translate = function (v) { + this.x += v.x; + this.y += v.y; + this.z += v.z; + return this; +}; + +GameLib.D3.Vector3.prototype.squared = function () { + return this.x * this.x + this.y * this.y + this.z * this.z; +}; + +GameLib.D3.Vector3.prototype.copy = function () { + return new GameLib.D3.Vector3( + this.x, + this.y, + this.z + ); +}; + +GameLib.D3.Vector3.prototype.multiply = function (s) { + if (s instanceof GameLib.D3.Vector3) { + this.x *= s.x; + this.y *= s.y; + this.z *= s.z; + } else if (s instanceof GameLib.D3.Matrix4) { + var x = s.rows[0].x * this.x + s.rows[0].y * this.y + s.rows[0].z * this.z; + var y = s.rows[1].x * this.x + s.rows[1].y * this.y + s.rows[1].z * this.z; + var z = s.rows[2].x * this.x + s.rows[2].y * this.y + s.rows[2].z * this.z; + this.x = x; + this.y = y; + this.z = z; + } else { + console.log("functionality not implemented - please do this"); + throw new Error("not implemented"); + } + return this; +}; + + +GameLib.D3.Vector3.prototype.dot = function (v) { + return (this.x * v.x) + (this.y * v.y) + (this.z * v.z); +}; + +GameLib.D3.Vector3.prototype.normalize = function () { + + var EPSILON = 0.000001; + + var v2 = this.squared(); + + if (v2 < EPSILON) { + return this; //do nothing for zero vector + } + + var invLength = 1 / Math.sqrt(v2); + + this.x *= invLength; + this.y *= invLength; + this.z *= invLength; + + return this; +}; + +GameLib.D3.Vector4 = function(x, y, z, w) { + + this.x = 0; + this.y = 0; + this.z = 0; + this.w = 0; + + if (x) { + this.x = x; + } + + if (y) { + this.y = y; + } + + if (z) { + this.z = z; + } + + if (w) { + this.w = w; + } +}; + +GameLib.D3.Vector4.prototype.translate = function (v) { + this.x += v.x; + this.y += v.y; + this.z += v.z; + return this; +}; + +GameLib.D3.Vector4.prototype.copy = function () { + return new GameLib.D3.Vector4( + this.x, + this.y, + this.z, + this.w + ); +}; + +GameLib.D3.Vector4.prototype.multiply = function (s) { + if (s instanceof GameLib.D3.Vector3) { + this.x *= s.x; + this.y *= s.y; + this.z *= s.z; + } else if (s instanceof GameLib.D3.Matrix4) { + var x = s.rows[0].x * this.x + s.rows[0].y * this.y + s.rows[0].z * this.z + s.rows[0].w * this.w; + var y = s.rows[1].x * this.x + s.rows[1].y * this.y + s.rows[1].z * this.z + s.rows[1].w * this.w; + var z = s.rows[2].x * this.x + s.rows[2].y * this.y + s.rows[2].z * this.z + s.rows[2].w * this.w; + var w = s.rows[3].x * this.x + s.rows[3].y * this.y + s.rows[3].z * this.z + s.rows[3].w * this.w; + this.x = x; + this.y = y; + this.z = z; + this.w = w; + } else { + console.log("functionality not implemented - please do this"); + throw new Error("not implemented"); + } +}; + + +GameLib.D3.Vector4.prototype.normalize = function () { + + // note - leave w untouched + var EPSILON = 0.000001; + + var v2 = this.x * this.x + this.y * this.y + this.z * this.z; + + if (v2 < EPSILON) { + return this; //do nothing for zero vector + } + + var invLength = 1 / Math.sqrt(v2); + + this.x *= invLength; + this.y *= invLength; + this.z *= invLength; + + return this; +}; + +GameLib.D3.Vector4.prototype.subtract = function (v) { + + if (v instanceof GameLib.D3.Vector3) { + this.x -= v.x; + this.y -= v.y; + this.z -= v.z; + } + + if (v instanceof GameLib.D3.Vector4) { + this.x -= v.x; + this.y -= v.y; + this.z -= v.z; + this.w -= v.w; + } + + return this; +}; + +GameLib.D3.Vector4.Points = function () { + this.vectors = []; +}; + +GameLib.D3.Vector4.Points.prototype.add = function (vector) { + + if (vector instanceof GameLib.D3.Vector3) { + vector = new GameLib.D3.Vector4( + vector.x, + vector.y, + vector.z, + 1 + ) + } + + if (!vector instanceof GameLib.D3.Vector4) { + console.warn("Vector needs to be of type Vector4"); + throw new Error("Vector needs to be of type Vector4"); + } + + this.vectors.push(vector); + + return this; +}; + +GameLib.D3.Vector4.Points.prototype.copy = function () { + + var vectors = []; + + for (var i = 0; i < this.vectors.length; i++) { + vectors.push(this.vectors[i].copy()); + } + + return vectors; +}; + +GameLib.D3.Vector4.Points.prototype.maximizeXDistance = function (grain) { + +// console.log("vectors (before): " + JSON.stringify(this.vectors, null, 2)); + + var multiplier = 0; + + var rotationMatrixY = new GameLib.D3.Matrix4().rotationMatrixY(grain); + + var totalRadians = 0; + + var backupVectors = this.copy(); + + var maxXDistance = 0; + + for (var i = 0; i < Math.PI * 2; i += grain) { + + multiplier++; + + for (var j = 0; j < this.vectors.length; j++) { + this.vectors[j] = rotationMatrixY.multiply(this.vectors[j]); } - }(xhr, this); - xhr.send(); + var distances = this.distances(); + + if (distances.x > maxXDistance) { + + maxXDistance = distances.x; + totalRadians = multiplier * grain; + } + } + + this.vectors = backupVectors; + +// console.log("distance: " + maxXDistance + " radians : " + totalRadians); + + var maxRotationMatrix = new GameLib.D3.Matrix4().rotationMatrixY(totalRadians); + + for (var k = 0; k < this.vectors.length; k++) { + this.vectors[k] = maxRotationMatrix.multiply(this.vectors[k]); + } + +// console.log("vectors (after): " + JSON.stringify(this.vectors, null, 2)); + +}; + +GameLib.D3.Vector4.Points.prototype.maximizeYDistance = function (grain) { + +// console.log("vectors (before): " + JSON.stringify(this.vectors, null, 2)); + + var multiplier = 0; + + var rotationMatrixX = new GameLib.D3.Matrix4().rotationMatrixX(grain); + + var totalRadians = 0; + + var backupVectors = this.copy(); + + var maxYDistance = 0; + + for (var i = 0; i < Math.PI * 2; i += grain) { + + multiplier++; + + for (var j = 0; j < this.vectors.length; j++) { + this.vectors[j] = rotationMatrixX.multiply(this.vectors[j]); + } + + var distances = this.distances(); + + if (distances.y > maxYDistance) { + maxYDistance = distances.y; + totalRadians = multiplier * grain; + } + } + + this.vectors = backupVectors; + +// console.log("distance: " + maxYDistance + " radians : " + totalRadians); + + var maxRotationMatrix = new GameLib.D3.Matrix4().rotationMatrixX(totalRadians); + + for (var k = 0; k < this.vectors.length; k++) { + this.vectors[k] = maxRotationMatrix.multiply(this.vectors[k]); + } + +// console.log("vectors (after): " + JSON.stringify(this.vectors, null, 2)); + +}; + + +GameLib.D3.Vector4.Points.prototype.lookAt = function (at, up) { + + var polyCenter = this.average(); + + console.log("poly center : " + JSON.stringify(polyCenter)); + + var lookAtMatrix = new GameLib.D3.Matrix4().lookAt(polyCenter, at, up); + + lookAtMatrix.rows[0] = new GameLib.D3.Vector4(1, 0, 0, 0); + lookAtMatrix.rows[1] = new GameLib.D3.Vector4(0, 0, 1, 0); + lookAtMatrix.rows[2] = new GameLib.D3.Vector4(0, 1, 0, 0); + + console.log("look at matrix : " + JSON.stringify(lookAtMatrix, null, 2)); + + for (var i = 0; i < this.vectors.length; i++) { + console.log("vector " + i + " (before): " + JSON.stringify(this.vectors[i])); + this.vectors[i] = lookAtMatrix.multiply(this.vectors[i]); + console.log("vector " + i + " (after) : " + JSON.stringify(this.vectors[i])); + } +}; + +GameLib.D3.Vector4.Points.prototype.distances = function () { + + var minX = this.vectors[0].x; + var minY = this.vectors[0].y; + var minZ = this.vectors[0].z; + + var maxX = this.vectors[0].x; + var maxY = this.vectors[0].y; + var maxZ = this.vectors[0].z; + + for (var i = 0; i < this.vectors.length; i++) { + if (this.vectors[i].x < minX) { + minX = this.vectors[i].x; + } + if (this.vectors[i].y < minY) { + minY = this.vectors[i].y; + } + if (this.vectors[i].z < minZ) { + minZ = this.vectors[i].z; + } + + if (this.vectors[i].x > maxX) { + maxX = this.vectors[i].x; + } + if (this.vectors[i].y > maxY) { + maxY = this.vectors[i].y; + } + if (this.vectors[i].z > maxZ) { + maxZ = this.vectors[i].z; + } + } + + return new GameLib.D3.Vector3( + Math.abs(maxX - minX), + Math.abs(maxY - minY), + Math.abs(maxY - minZ) + ) +}; + +GameLib.D3.Vector4.Points.prototype.average = function () { + var averageX = 0; + var averageY = 0; + var averageZ = 0; + + for (var i = 0; i < this.vectors.length; i++) { + averageX += this.vectors[i].x; + averageY += this.vectors[i].y; + averageZ += this.vectors[i].z; + } + + return new GameLib.D3.Vector3( + averageX / this.vectors.length, + averageY / this.vectors.length, + averageZ / this.vectors.length + ); +}; + +GameLib.D3.Vector4.Points.prototype.negative = function () { + + for (var i = 0; i < this.vectors.length; i++) { + this.vectors[i].x *= -1; + this.vectors[i].y *= -1; + this.vectors[i].z *= -1; + } + + return this; +}; + + +GameLib.D3.Vector4.Points.prototype.toOrigin = function () { + + var distanceFromOrigin = this.average().negative(); + + for (var i = 0; i < this.vectors.length; i++) { + this.vectors[i].translate(distanceFromOrigin); + } }; /** - * Loads a GameLib.D3.Scene object into a ThreeJS Scene object - * @param gameLibScene GameLib.D3.Scene - * @param onLoaded callback when all meshes have loaded - * @param computeNormals set to true to compute new face and vertex normals during load + * The normal gets assigned when the face calculates its normal + * @param position + * @param boneWeights GameLib.D3.BoneWeight[] + * @constructor */ -GameLib.D3.prototype.loadScene = function(gameLibScene, onLoaded, computeNormals) { - - console.log("loading scene " + gameLibScene.name); - - var meshQ = []; - - for (var m = 0; m < gameLibScene.meshes.length; m++) { - - var mesh = gameLibScene.meshes[m]; - - console.log("loading mesh " + mesh.name); - - var geometry = new this.THREE.Geometry(); - - var vertices = mesh.vertices; - - var faces = mesh.faces; - - var faceVertexUvs = mesh.faceVertexUvs; - - var materials = mesh.materials; - - /** - * Setup vertices - */ - for (var v = 0; v < vertices.length; v++) { - geometry.vertices.push( - new this.THREE.Vector3( - vertices[v].position.x, - vertices[v].position.y, - vertices[v].position.z - ) - ) - } - - /** - * Setup faces - */ - for (var f = 0; f < faces.length; f++) { - - var face = new this.THREE.Face3( - faces[f].v0, - faces[f].v1, - faces[f].v2, - new this.THREE.Vector3( - faces[f].normal.x, - faces[f].normal.y, - faces[f].normal.z - ), - new this.THREE.Color( - faces[f].color.r, - faces[f].color.g, - faces[f].color.b - ), - faces[f].materialIndex - ); - - face.vertexColors = [ - new this.THREE.Color( - faces[f].vertexColors[0].r, - faces[f].vertexColors[0].g, - faces[f].vertexColors[0].b - ), - new this.THREE.Color( - faces[f].vertexColors[1].r, - faces[f].vertexColors[1].g, - faces[f].vertexColors[1].b - ), - new this.THREE.Color( - faces[f].vertexColors[2].r, - faces[f].vertexColors[2].g, - faces[f].vertexColors[2].b - ) - ]; - - face.normal = new this.THREE.Vector3( - faces[f].normal.x, - faces[f].normal.y, - faces[f].normal.z - ); - - face.vertexNormals = [ - new this.THREE.Vector3( - faces[f].vertexNormals[0].x, - faces[f].vertexNormals[0].y, - faces[f].vertexNormals[0].z - ), - new this.THREE.Vector3( - faces[f].vertexNormals[1].x, - faces[f].vertexNormals[1].y, - faces[f].vertexNormals[1].z - ), - new this.THREE.Vector3( - faces[f].vertexNormals[2].x, - faces[f].vertexNormals[2].y, - faces[f].vertexNormals[2].z - ) - ]; - - geometry.faces.push(face); - } - - geometry.faceVertexUvs = []; - - /** - * Setup face UVs - */ - for (var fm = 0; fm < faceVertexUvs.length; fm++) { - - var faceMaterialVertexUvs = faceVertexUvs[fm]; - - geometry.faceVertexUvs[fm] = []; - - for (var fuv = 0; fuv < faceMaterialVertexUvs.length; fuv++) { - geometry.faceVertexUvs[fm][fuv] = []; - geometry.faceVertexUvs[fm][fuv].push( - new this.THREE.Vector2( - faceMaterialVertexUvs[fuv][0].x, - faceMaterialVertexUvs[fuv][0].y - ), - new this.THREE.Vector2( - faceMaterialVertexUvs[fuv][1].x, - faceMaterialVertexUvs[fuv][1].y - ), - new this.THREE.Vector2( - faceMaterialVertexUvs[fuv][2].x, - faceMaterialVertexUvs[fuv][2].y - ) - ); - } - } - - /** - * Re-calculate normals (if we have to) - * @type {Array} - */ - if (computeNormals) { - geometry.computeFaceNormals(); - geometry.computeVertexNormals(); - } - - var threeMaterialLoaders = []; - - /** - * Setup materials - */ - for (var mi = 0; mi < materials.length; mi++) { - threeMaterialLoaders.push(this.createThreeMaterial(materials[mi])); - } - - var result = this.Q.all(threeMaterialLoaders).then( - function(gl3d, mesh, geometry) { - return function(materials) { - - console.log("loaded all materials maps (" + materials.length + ")"); - - /** - * We don't support MultiMaterial atm - it doesn't work with raycasting - */ - var material = materials[0]; - - var threeMesh = gl3d.createThreeMesh(mesh, geometry, material); - threeMesh.name = mesh.name; - - threeMesh.position.x = mesh.position.x; - threeMesh.position.y = mesh.position.y; - threeMesh.position.z = mesh.position.z; - - threeMesh.rotation.x = mesh.rotation.x; - threeMesh.rotation.y = mesh.rotation.y; - threeMesh.rotation.z = mesh.rotation.z; - - threeMesh.scale.x = mesh.scale.x; - threeMesh.scale.y = mesh.scale.y; - threeMesh.scale.z = mesh.scale.z; - - threeMesh.quaternion.x = mesh.quaternion.x; - threeMesh.quaternion.y = mesh.quaternion.y; - threeMesh.quaternion.z = mesh.quaternion.z; - threeMesh.quaternion.w = mesh.quaternion.w; - - return threeMesh; - }; - }(this, mesh, geometry) - ).catch(function(error){ - console.log(error); - }); - - meshQ.push(result); - } - - this.Q.all(meshQ).then(function(threeMeshes){ - console.log("all meshes have loaded"); - if (typeof onLoaded != 'undefined') { - - var threeLights = []; - - for (var sli = 0; sli < gameLibScene.lights.length; sli++) { - - var blenderLight = gameLibScene.lights[sli]; - - var light = null; - - if (blenderLight.lightType == 'AmbientLight') { - light = new this.THREE.AmbientLight(blenderLight.color, blenderLight.intensity); - } - - if (blenderLight.lightType == 'DirectionalLight') { - light = new this.THREE.DirectionalLight(blenderLight.color, blenderLight.intensity); - } - - if (blenderLight.lightType == 'PointLight') { - light = new this.THREE.PointLight(blenderLight.color, blenderLight.intensity); - light.distance = blenderLight.distance; - light.decay = blenderLight.decay; - } - - if (blenderLight.lightType == 'SpotLight') { - light = new this.THREE.SpotLight(blenderLight.color, blenderLight.intensity); - light.distance = blenderLight.distance; - light.angle = blenderLight.angle; - light.penumbra = blenderLight.penumbra; - light.decay = blenderLight.decay; - } - - light.position.x = blenderLight.position.x; - light.position.y = blenderLight.position.y; - light.position.z = blenderLight.position.z; - - light.rotation.x = blenderLight.rotation.x; - light.rotation.y = blenderLight.rotation.y; - light.rotation.z = blenderLight.rotation.z; - - // light.scale.x = blenderLight.scale.x; - // light.scale.y = blenderLight.scale.y; - // light.scale.z = blenderLight.scale.z; - - if (light == null) { - console.warn('Does not support lights of type :' + blenderLight.lightType + ', not imported'); - } else { - light.name = blenderLight.name; - threeLights.push(light); - } - } - - onLoaded(threeMeshes, threeLights); - } - }).catch(function(error){ - console.log(error); - }); -}; - -// --------------- -// Physics -// --------------- - -GameLib.D3.Physics.Shape.prototype.Update = function( - physicsWorld -) { - if(physicsWorld.engineType === GameLib.D3.Physics.Engine.TYPE_CANNON) { - if(this.shapeType === GameLib.D3.Physics.Shape.TYPE_TRIMESH) { - this.shapeObject.setScale(new CANNON.Vec3(this.scale.x, this.scale.y, this.scale.z)); - this.shapeObject.scale.x = this.scale.x; - this.shapeObject.scale.y = this.scale.y; - this.shapeObject.scale.z = this.scale.z; - this.shapeObject.updateAABB(); - this.shapeObject.updateNormals(); - this.shapeObject.updateEdges(); - this.shapeObject.updateBoundingSphereRadius(); - this.shapeObject.updateTree(); - } - } -}; - -GameLib.D3.Physics.World.prototype.AddShape = function( - shape, // d3.physics.shape - rigidBody, - offset, // vec3 - orientation //quaternion -) { - shape.shape = shape; - - if(this.engineType === GameLib.D3.Physics.Engine.TYPE_CANNON) { - - var _offset = null; - var _orientation = null; - - if(offset != null && typeof offset !== 'undefined') { - _offset = new CANNON.Vec3(offset.x, offset.y, offset.z); - } - - if(orientation != null && typeof orientation !== 'undefined') { - _orientation = new CANNON.Quaternion(orientation.x, orientation.y, orientation.z, orientation.w); - } - - rigidBody.bodyObject.addShape(shape.shapeObject, _offset, _orientation); - } -}; - -GameLib.D3.Physics.World.prototype.CreateRigidVehicle = function( - chassisBody // Physics.RigidBody -) { - var rigidVehicle = new GameLib.D3.Physics.RigidVehicle(); - - if(this.engineType == GameLib.D3.Physics.Engine.TYPE_CANNON) { - var vehicle = new CANNON.RigidVehicle({ - chassisBody: chassisBody.bodyObject - }); - rigidVehicle.vehicleObject = vehicle; - return rigidVehicle; - } -}; - -GameLib.D3.Physics.World.prototype.CreateRaycastVehicle = function( - chassisBody // Physics.RigidBody -) { - var raycastVehicle = new GameLib.D3.Physics.RaycastVehicle(); - if(this.engineType == GameLib.D3.Physics.Engine.TYPE_CANNON) { - var vehicle = new CANNON.RaycastVehicle({ - chassisBody: chassisBody.bodyObject - }); - raycastVehicle.vehicleObject = vehicle; - return raycastVehicle; - } -}; - -GameLib.D3.Physics.World.prototype.AddWheelToRigidVehicle = function( - vehicle, - rigidBody, +GameLib.D3.Vertex = function( position, - axis, - direction + boneWeights ) { - if(this.engineType == GameLib.D3.Physics.Engine.TYPE_CANNON) { - vehicle.vehicleObject.addWheel({ - body: rigidBody.bodyObject, - position: new CANNON.Vec3(position.x, position.y, position.z), - axis: new CANNON.Vec3(axis.x, axis.y, axis.z), - direction: new CANNON.Vec3(direction.x, direction.y, direction.z) - }); + this.position = position; + this.boneWeights = boneWeights; +}; +/** + * World SuperSet - contains the custom world instance + * @param id + * @param name + * @param engine + * @param gravity + * @param broadphase + * @param solver + * @param rigidBodies + * @constructor + */ +GameLib.D3.World = function( + id, + name, + engine, + gravity, + broadphase, + solver, + rigidBodies +) { + + this.id = id; + + this.name = name; + + if (typeof gravity == 'undefined') { + gravity = new GameLib.D3.Vector3(0, -9.81, 0); } -}; + this.gravity = gravity; -GameLib.D3.Physics.World.prototype.AddWheelToRaycastVehicle = function ( - vehicle, // physics.raycastvehicle - options // cannon options -) { - if (this.engineType == GameLib.D3.Physics.Engine.TYPE_CANNON) { - vehicle.vehicleObject.addWheel(options); - } else { - console.log("function for engine not implemented"); - } -}; - -GameLib.D3.Physics.RigidVehicle.prototype.GetWheelInfo = function( - -) { - // note: need a way to determine which engine we are currently using - return this.vehicleObject.wheelBodies; -}; - -GameLib.D3.Physics.RaycastVehicle.prototype.GetWheelInfo = function( - -) { - // note: need a way to determine which engine we are currently using - return this.vehicleObject.wheelInfos; -}; - - -GameLib.D3.Physics.World.prototype.CreateRigidBody = function( - mass, - friction, - position, - quaternion, - velocity, - angularVelocity, - linearDamping, - angularDamping, - allowSleep, - sleepSpeedLimit, - sleepTimeLimit, - collisionFilterGroup, - collisionFilterMask, - fixedRotation, - shape -) { - - var rigidBody = new GameLib.D3.Physics.RigidBody(0, "null"); - - position = position || new GameLib.D3.Vector3(); - velocity = velocity || new GameLib.D3.Vector3(); - angularVelocity = angularVelocity || new GameLib.D3.Vector3(); - quaternion = quaternion || new GameLib.D3.Vector4(0, 0, 0, 1); - mass = typeof mass == "undefined" ? 0 : mass; - friction = typeof friction == "undefined" ? 5 : friction; - linearDamping = typeof linearDamping == "undefined" ? 0.01 : linearDamping; - angularDamping = typeof angularDamping == "undefined" ? 0.01 : angularDamping; - allowSleep = typeof allowSleep == "undefined" ? true : allowSleep; - sleepSpeedLimit = typeof sleepSpeedLimit == "undefined" ? 0.1 : sleepSpeedLimit; - sleepTimeLimit = typeof sleepTimeLimit == "undefined" ? 1.0 : sleepTimeLimit; - collisionFilterGroup = typeof collisionFilterGroup == "undefined" ? 1 : collisionFilterGroup; - collisionFilterMask = typeof collisionFilterMask == "undefined" ? 1 : collisionFilterMask; - fixedRotation = typeof fixedRotation == "undefined" ? false : fixedRotation; - shape = typeof shape == "undefined" ? null : shape; - - - // Create the bodyObject - if(this.engineType == GameLib.D3.Physics.Engine.TYPE_CANNON) { - rigidBody.bodyObject = new CANNON.Body( - { - mass: mass, - friction: friction, - position: new CANNON.Vec3(position.x, position.y, position.z), - velocity: new CANNON.Vec3(velocity.x, velocity.y, velocity.z), - quaternion: new CANNON.Quaternion(quaternion.x, quaternion.y, quaternion.z, quaternion.w), - angularVelocity: new CANNON.Vec3(angularVelocity.x, angularVelocity.y, angularVelocity.z), - linearDamping: linearDamping, - angularDamping: angularDamping, - allowSleep: allowSleep, - sleepSpeedLimit: sleepSpeedLimit, - sleepTimeLimit: sleepTimeLimit, - collisionFilterGroup: collisionFilterGroup, - collisionFilterMask: collisionFilterMask, - fixedRotation: fixedRotation, - shape: shape - } + if (typeof broadphase == 'undefined') { + broadphase = new GameLib.D3.Physics.Broadphase( + null, + 'broadPhaseNaive', + GameLib.D3.Physics.BROADPHASE_TYPE_NAIVE ); - - return rigidBody; } + this.broadphase = broadphase; + + if (typeof solver == 'undefined') { + solver = new GameLib.D3.Physics.Solver( + null, + 'GSSolver', + GameLib.D3.Physics.GS_SOLVER + ); + } + this.solver = solver; + + if (typeof rigidBodies == 'undefined') { + rigidBodies = []; + } + this.rigidBodies = rigidBodies; + + this.engine = engine; + + this.engine.isNotCannonThrow(); + + this.instance = this.createInstance(); }; -GameLib.D3.Physics.World.prototype.CreateTriMeshShape = function( - vertices, // flat list of floats - indices // float list of floats +/** + * private + * @returns {GameLib.D3.World|GameLib.D3.Physics.World|*} + */ +GameLib.D3.World.prototype.createInstance = function() { + + var instance = new this.engine.instance.World(); + + instance.broadphase = this.broadphase.instance; + + instance.solver = this.solver.instance; + + instance.gravity.x = this.gravity.x; + instance.gravity.y = this.gravity.y; + instance.gravity.z = this.gravity.z; + + instance.name = this.name; + + return instance; +}; + +/** + * + * @param rigidBody GameLib.D3.RigidBody + * @constructor + */ +GameLib.D3.World.prototype.addRigidBody = function( + rigidBody ) { - if(this.engineType == GameLib.D3.Physics.Engine.TYPE_CANNON) { - return new GameLib.D3.Physics.Shape(new CANNON.Trimesh(vertices, indices), GameLib.D3.Physics.Shape.TYPE_TRIMESH); - } + this.instance.addBody(rigidBody.instance); }; -GameLib.D3.Physics.World.prototype.CreateSphereShape = function ( - radius -) { - if(this.engineType == GameLib.D3.Physics.Engine.TYPE_CANNON) { - return new GameLib.D3.Physics.Shape(new CANNON.Sphere(radius), GameLib.D3.Physics.Shape.TYPE_SPHERE); - } -}; - -GameLib.D3.Physics.World.prototype.CreateBoxShape = function( - halfExtensions // vec3 -) { - if(this.engineType == GameLib.D3.Physics.Engine.TYPE_CANNON) { - return new GameLib.D3.Physics.Shape(new CANNON.Box(new CANNON.Vec3(halfExtensions.x, halfExtensions.y, halfExtensions.z)), GameLib.D3.Physics.Shape.TYPE_BOX); - } -}; - -GameLib.D3.Physics.World.prototype.CreateCylinderShape = function( - radiusTop, - radiusBottom, - height, - numSegments -) { - if(this.engineType == GameLib.D3.Physics.Engine.TYPE_CANNON) { - return new GameLib.D3.Physics.Shape(new CANNON.Cylinder(radiusTop, radiusBottom, height, numSegments), GameLib.D3.Physics.Shape.TYPE_CYLINDER); - } -}; - -GameLib.D3.Physics.World.prototype.CreateHeightfieldShape = function ( - heightmapData, - elementSize -) { - if(this.engineType == GameLib.D3.Physics.Engine.TYPE_CANNON) { - return new GameLib.D3.Physics.Shape(new CANNON.Heightfield(heightmapData.matrix, { elementSize: elementSize }), GameLib.D3.Physics.Shape.TYPE_HEIGHTFIELD); - } -}; - -GameLib.D3.Physics.World.prototype.AddRigidBody = function( - rigidBody // Physics.RigidBody -) { - if(this.engineType === GameLib.D3.Physics.Engine.TYPE_CANNON) { - this.worldObject.addBody(rigidBody.bodyObject); - } -}; - -GameLib.D3.Physics.World.prototype.AddVehicle = function( +/** + * + * @param vehicle (GameLib.D3.RigidBodyVehicle | GameLib.D3.RaycastVehicle) + * @constructor + */ +GameLib.D3.World.prototype.addVehicle = function( vehicle // note: physics.vehicle ) { - if(this.engineType == GameLib.D3.Physics.Engine.TYPE_CANNON) { - vehicle.vehicleObject.addToWorld(this.worldObject); - } + vehicle.instance.addToWorld(this.world.instance); }; -GameLib.D3.Physics.World.prototype.Step = function( +GameLib.D3.World.prototype.step = function( timeStep ) { - if(this.engineType == GameLib.D3.Physics.Engine.TYPE_CANNON) { - - // todo: figure out, why this call to internal step is more stable for trimesh collisions..... - //this.worldObject.internalStep(timeStep); - //return; - - var now = performance.now() / 1000; - if(!this.lastCallTime){ - // last call time not saved, cant guess elapsed time. Take a simple step. - this.worldObject.step(timeStep); - this.lastCallTime = now; - return; - } - - var timeSinceLastCall = now - this.lastCallTime; - - this.worldObject.step(timeStep, timeSinceLastCall); + // todo: figure out, why this call to internal step is more stable for trimesh collisions..... + //this.worldObject.internalStep(timeStep); + //return; + var now = performance.now() / 1000; + if(!this.lastCallTime){ + // last call time not saved, cant guess elapsed time. Take a simple step. + this.instance.step(timeStep); this.lastCallTime = now; + return; } + + var timeSinceLastCall = now - this.lastCallTime; + + this.instance.step(timeStep, timeSinceLastCall); + + this.lastCallTime = now; }; -GameLib.D3.Physics.World.prototype.GetIndexedVertices = function( +GameLib.D3.World.prototype.GetIndexedVertices = function( triangleMeshShape ) { - if(this.engine.engineType == GameLib.D3.Physics.Engine.TYPE_CANNON) { + if(this.engine.engineType == GameLib.D3.Physics.TYPE_CANNON) { return { vertices : triangleMeshShape.vertices, @@ -2943,7 +5036,17 @@ GameLib.D3.Physics.World.prototype.GetIndexedVertices = function( }; -GameLib.D3.Physics.World.prototype.GenerateWireframeViewMesh = function( +/** + * TODO: FIX + * @param triangleMeshShape + * @param normalLength + * @param scale + * @param opacity + * @param wireframeColor + * @returns {THREE.Mesh|this.meshes} + * @constructor + */ +GameLib.D3.World.GenerateWireframeViewMesh = function( triangleMeshShape, normalLength, scale, @@ -2984,8 +5087,8 @@ GameLib.D3.Physics.World.prototype.GenerateWireframeViewMesh = function( .divideScalar(3); var normal = null; - if(this.engine.engineType == GameLib.D3.Physics.Engine.TYPE_CANNON) { - var normal = new CANNON.Vec3(); + if(this.engine.engineType == GameLib.D3.Physics.TYPE_CANNON) { + var normal = new this.physics.CANNON.Vec3(); triangleMeshShape.getNormal(i, normal); } else { // todo: calculate the normal for v0, v1 & v2 here. @@ -3002,7 +5105,18 @@ GameLib.D3.Physics.World.prototype.GenerateWireframeViewMesh = function( return wireframeTHREEMesh; }; -GameLib.D3.Physics.World.prototype.GenerateTriangleCollisionMesh = function( +/** + * TODO: FIX + * @param threeMesh + * @param mass + * @param friction + * @param createCollisionSubMeshes + * @param facesPerSubsection + * @param subsectionsToMerge + * @returns {Array} + * @constructor + */ +GameLib.D3.World.GenerateTriangleCollisionMesh = function( threeMesh, mass, // default = 0 friction, // default = 10 @@ -3026,17 +5140,17 @@ GameLib.D3.Physics.World.prototype.GenerateTriangleCollisionMesh = function( var body = null; - if(this.engine.engineType == GameLib.D3.Physics.Engine.TYPE_CANNON) { + if(this.engine.engineType == GameLib.D3.Physics.TYPE_CANNON) { - var meshShape = new CANNON.Trimesh(vertices, indicies); - meshShape.setScale(new CANNON.Vec3(threeMesh.scale.x, threeMesh.scale.y, threeMesh.scale.z)); + var meshShape = new this.physics.CANNON.Trimesh(vertices, indicies); + meshShape.setScale(new this.physics.CANNON.Vec3(threeMesh.scale.x, threeMesh.scale.y, threeMesh.scale.z)); meshShape.updateAABB(); meshShape.updateNormals(); meshShape.updateEdges(); meshShape.updateBoundingSphereRadius(); meshShape.updateTree(); - body = new CANNON.Body({ mass: mass ? mass : 0, friction: friction ? friction : 10 }); + body = new this.physics.CANNON.Body({ mass: mass ? mass : 0, friction: friction ? friction : 10 }); body.addShape(meshShape); } else if (this.engine.engineType == GameLib.D3.Physics.Engine.TYPE_AMMO) { @@ -3076,287 +5190,6 @@ GameLib.D3.Physics.World.prototype.GenerateTriangleCollisionMesh = function( } }; -// ----------- -// SkyBox -// ----------- - -GameLib.D3.SkyBox = function ( - -) { - this.id = null; - this.texturesFolder = null; -}; - -GameLib.D3.SkyBox.prototype.Load = function ( - texturesFolder -) { - this.texturesFolder = texturesFolder; - this.textures = []; - this.materials = []; - this.mesh = {}; - this.scene = new THREE.Scene(); - this.textureCube = null; - - var textureLoader = new THREE.TextureLoader(); - - // this textures are used to display the skybox - this.textures.push(textureLoader.load(this.texturesFolder + "px.png")); - this.textures.push(textureLoader.load(this.texturesFolder + "nx.png")); - this.textures.push(textureLoader.load(this.texturesFolder + "py.png")); - this.textures.push(textureLoader.load(this.texturesFolder + "ny.png")); - this.textures.push(textureLoader.load(this.texturesFolder + "pz.png")); - this.textures.push(textureLoader.load(this.texturesFolder + "nz.png")); - - // assign textures to each cube face - for (var i = 0; i < 6; i ++) { - this.materials.push(new THREE.MeshBasicMaterial({ map: this.textures[i] })); - } - - // create cube geometry - this.mesh = new THREE.Mesh(new THREE.CubeGeometry(1, 1, 1), new THREE.MeshFaceMaterial(this.materials)); - this.mesh.applyMatrix(new THREE.Matrix4().makeScale(1, 1, -1)); - this.scene.add(this.mesh); - - // Load env textureCube - // this is used for reflections on meshes - // mesh.material.envMap = this.textureCube; - this.textureCube = new THREE.CubeTextureLoader().load([ - this.texturesFolder + "px.png", this.texturesFolder + "nx.png", - this.texturesFolder + "py.png", this.texturesFolder + "ny.png", - this.texturesFolder + "pz.png", this.texturesFolder + "nz.png" - ]); -}; - -GameLib.D3.SkyBox.prototype.Render = function ( - threeRenderer, - threeCamera -) { - var cameraPosition = new THREE.Vector3(threeCamera.position.x, threeCamera.position.y, threeCamera.position.z); - - threeCamera.position.set(0, 0, 0); - - var gl = threeRenderer.context; - - gl.disable(gl.DEPTH_TEST); - - threeRenderer.render(this.scene, threeCamera); - - gl.enable(gl.DEPTH_TEST); - - threeCamera.position.copy(cameraPosition); -}; - - -// --------- -// Game -// --------- -GameLib.D3.Game = function ( - -) { - this.scenes = {}; - this.physicsWorlds = []; - this.sceneToPhysicsWorldsMap = {}; -}; - -GameLib.D3.Game.prototype.AddScene = function( - scene -) { - this.scenes[scene.name] = scene; -}; - -GameLib.D3.Game.prototype.AddPhysicsWorld = function( - physicsWorld -) { - this.physicsWorlds.push(physicsWorld); -}; - -GameLib.D3.Game.prototype.LinkPhysicsWorldToScene = function( - physicsWorld, - scene -) { - this.sceneToPhysicsWorldsMap[scene.name] = this.sceneToPhysicsWorldsMap[scene.name] || []; - this.sceneToPhysicsWorldsMap[scene.name].push(physicsWorld); -}; - -GameLib.D3.Game.prototype.GetPhysicsWorldsForScene = function ( - scene -) { - return this.sceneToPhysicsWorldsMap[scene.name]; -}; - -GameLib.D3.Game.prototype.ProcessPhysics = function ( - timestep -) { - for(var s in this.sceneToPhysicsWorldsMap) { - - var physicsWorldArray = this.sceneToPhysicsWorldsMap[s]; - var scene = this.scenes[s]; - - if(scene && physicsWorldArray) { - - for(var i = 0, l = physicsWorldArray.length; i < l; i++) { - - var physicsWorld = physicsWorldArray[i]; - physicsWorld.Step(timestep); - - for(var p in physicsWorld.linkedPairs) { - var pair = physicsWorld.linkedPairs[p]; - var mesh = pair.threeMesh; - var body = pair.physicsBody; - - if(mesh) { - if(physicsWorld.engineType === GameLib.D3.Physics.Engine.TYPE_CANNON) { - - var quaternion = new THREE.Quaternion(); - quaternion.copy(body.bodyObject.quaternion); - - var quaternionCopy = quaternion.clone(); - - var position = new THREE.Vector3(); - position.copy(body.bodyObject.position); - - if(mesh.permutate) { - - if(mesh.permutate.offset) { - if(mesh.permutate.offset.quaternion) { - var offsetQuaternion = new THREE.Quaternion(); - offsetQuaternion.copy(mesh.permutate.offset.quaternion); - quaternion = quaternion.multiply(offsetQuaternion).normalize(); - } - - if(mesh.permutate.offset.position) { - var offsetPosition = new THREE.Vector3(); - offsetPosition.copy(mesh.permutate.offset.position); - //position = position.add(offsetPosition); - position = position.add(offsetPosition.applyQuaternion(quaternionCopy)); - } - } - } - - mesh.position.copy(position); - mesh.quaternion.copy(quaternion); - } - } - } - } - } - - } -}; - -GameLib.D3.Game.prototype.LinkPair = function ( - threeMesh, - physicsBody, - physicsWorld -) { - physicsWorld.linkedPairs = physicsWorld.linkedPairs || []; - - physicsWorld.linkedPairs.push({ - threeMesh : threeMesh, - physicsBody : physicsBody - }); -}; - - -/* * * * * * * * * * - * Heightmap Tools - * * * * * * * * * */ - -GameLib.D3.HeightmapData = function ( - sizeX, - sizeY, - matrix -) { - this.sizeX = sizeX || 0; - this.sizeY = sizeY || 0; - - // 2D Array with height data - // Column-major - this.matrix = matrix || []; -}; - -GameLib.D3.GenerateThreeMeshFromHeightField = function ( - heightFieldShape -) { - - var geometry = new THREE.Geometry(); - - var v0 = new THREE.Vector3(); - var v1 = new THREE.Vector3(); - var v2 = new THREE.Vector3(); - - var shape = heightFieldShape.shapeObject; - for (var xi = 0; xi < shape.data.length - 1; xi++) { - for (var yi = 0; yi < shape.data[xi].length - 1; yi++) { - for (var k = 0; k < 2; k++) { - shape.getConvexTrianglePillar(xi, yi, k===0); - v0.copy(shape.pillarConvex.vertices[0]); - v1.copy(shape.pillarConvex.vertices[1]); - v2.copy(shape.pillarConvex.vertices[2]); - v0.add(shape.pillarOffset); - v1.add(shape.pillarOffset); - v2.add(shape.pillarOffset); - geometry.vertices.push( - new THREE.Vector3(v0.x, v0.y, v0.z), - new THREE.Vector3(v1.x, v1.y, v1.z), - new THREE.Vector3(v2.x, v2.y, v2.z) - ); - var i = geometry.vertices.length - 3; - geometry.faces.push(new THREE.Face3(i, i+1, i+2)); - } - } - } - geometry.computeBoundingSphere(); - geometry.computeFaceNormals(); - - return new THREE.Mesh(geometry, new THREE.MeshNormalMaterial({ wireframe : false, shading : THREE.SmoothShading })); -}; - -GameLib.D3.GenerateHeightmapDataFromImage = function ( - imagePath, - heightScale, - callback // receives HeightmapData instance as the first argument -) { - var img = new Image(); - - img.onload = function () { - - var canvas = document.createElement('canvas'); - canvas.width = img.width; - canvas.height = img.height; - - var context = canvas.getContext('2d'); - context.drawImage(img, 0, 0); - - var imgd = context.getImageData(0, 0, img.width, img.height); - var pixels = imgd.data; - - var heightList = []; - for (var i = 0, n = pixels.length; i < n; i += (4)) { - heightList.push(pixels[i]); - } - - var matrix = []; - var sizeX = img.width, - sizeY = img.height; - - for (var i = 0; i < sizeX; i++) { - matrix.push([]); - for (var j = 0; j < sizeY; j++) { - var height = (heightList[(sizeX - i) + j * sizeY] / 255) * heightScale; - matrix[i].push(height); - } - } - - - // todo: delete canvas here - - callback(new GameLib.D3.HeightmapData(sizeX, sizeY, matrix)); - }; - - img.src = imagePath; -}; - -if (typeof module != 'undefined') { - module.exports = GameLib.D3; +if (typeof module !== 'undefined') { + module.exports = GameLib; } \ No newline at end of file