diff --git a/Babylon/Animations/babylon.animation.js b/Babylon/Animations/babylon.animation.js index 27c75181af7..f01dd4860e4 100644 --- a/Babylon/Animations/babylon.animation.js +++ b/Babylon/Animations/babylon.animation.js @@ -19,6 +19,18 @@ var BABYLON = BABYLON || {}; }; // Methods + BABYLON.Animation.prototype.floatInterpolateFunction = function (startValue, endValue, gradient) { + return startValue + (endValue - startValue) * gradient; + }; + + BABYLON.Animation.prototype.quaternionInterpolateFunction = function (startValue, endValue, gradient) { + return BABYLON.Quaternion.Slerp(startValue, endValue, gradient); + }; + + BABYLON.Animation.prototype.vector3InterpolateFunction = function (startValue, endValue, gradient) { + return BABYLON.Vector3.Lerp(startValue, endValue, gradient); + }; + BABYLON.Animation.prototype.clone = function() { var clone = new BABYLON.Animation(this.name, this.targetPropertyPath.join("."), this.framePerSecond, this.dataType, this.loopMode); @@ -37,6 +49,8 @@ var BABYLON = BABYLON || {}; if (loopMode === BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT && repeatCount > 0) { return highLimitValue.clone ? highLimitValue.clone() : highLimitValue; } + + this.currentFrame = currentFrame; for (var key = 0; key < this._keys.length; key++) { if (this._keys[key + 1].frame >= currentFrame) { @@ -50,9 +64,9 @@ var BABYLON = BABYLON || {}; switch (loopMode) { case BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE: case BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT: - return startValue + (endValue - startValue) * gradient; + return this.floatInterpolateFunction(startValue, endValue, gradient); case BABYLON.Animation.ANIMATIONLOOPMODE_RELATIVE: - return offsetValue * repeatCount + (startValue + (endValue - startValue) * gradient); + return offsetValue * repeatCount + this.floatInterpolateFunction(startValue, endValue, gradient); } break; // Quaternion @@ -61,10 +75,10 @@ var BABYLON = BABYLON || {}; switch (loopMode) { case BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE: case BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT: - quaternion = BABYLON.Quaternion.Slerp(startValue, endValue, gradient); + quaternion = this.quaternionInterpolateFunction(startValue, endValue, gradient); break; case BABYLON.Animation.ANIMATIONLOOPMODE_RELATIVE: - quaternion = BABYLON.Quaternion.Slerp(startValue, endValue, gradient).add(offsetValue.scale(repeatCount)); + quaternion = this.quaternionInterpolateFunction(startValue, endValue, gradient).add(offsetValue.scale(repeatCount)); break; } @@ -74,9 +88,9 @@ var BABYLON = BABYLON || {}; switch (loopMode) { case BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE: case BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT: - return BABYLON.Vector3.Lerp(startValue, endValue, gradient); + return this.vector3InterpolateFunction(startValue, endValue, gradient); case BABYLON.Animation.ANIMATIONLOOPMODE_RELATIVE: - return BABYLON.Vector3.Lerp(startValue, endValue, gradient).add(offsetValue.scale(repeatCount)); + return this.vector3InterpolateFunction(startValue, endValue, gradient).add(offsetValue.scale(repeatCount)); } // Matrix case BABYLON.Animation.ANIMATIONTYPE_MATRIX: diff --git a/Babylon/Cameras/babylon.camera.js b/Babylon/Cameras/babylon.camera.js index 1432bd8e8d6..e4c84612635 100644 --- a/Babylon/Cameras/babylon.camera.js +++ b/Babylon/Cameras/babylon.camera.js @@ -37,7 +37,6 @@ var BABYLON = BABYLON || {}; BABYLON.Camera.ORTHOGRAPHIC_CAMERA = 1; // Members - BABYLON.Camera.prototype.fov = 0.8; BABYLON.Camera.prototype.orthoLeft = null; BABYLON.Camera.prototype.orthoRight = null; BABYLON.Camera.prototype.orthoBottom = null; diff --git a/Babylon/Cameras/babylon.freeCamera.js b/Babylon/Cameras/babylon.freeCamera.js index f7aa532acc2..9e46bb8d74f 100644 --- a/Babylon/Cameras/babylon.freeCamera.js +++ b/Babylon/Cameras/babylon.freeCamera.js @@ -45,7 +45,7 @@ var BABYLON = BABYLON || {}; BABYLON.FreeCamera.prototype.noRotationConstraint = false; BABYLON.FreeCamera.prototype.angularSensibility = 2000.0; BABYLON.FreeCamera.prototype.lockedTarget = null; - + BABYLON.FreeCamera.prototype.onCollide = null; // Methods BABYLON.FreeCamera.prototype._computeLocalCameraSpeed = function () { @@ -228,6 +228,9 @@ var BABYLON = BABYLON || {}; if (this._diffPosition.length() > BABYLON.Engine.collisionsEpsilon) { this.position.addInPlace(this._diffPosition); + if (this.onCollide) { + this.onCollide(this._collider.collidedMesh); + } } }; diff --git a/Babylon/Collisions/babylon.collider.js b/Babylon/Collisions/babylon.collider.js index 4bef6d5fbf0..06a8831f348 100644 --- a/Babylon/Collisions/babylon.collider.js +++ b/Babylon/Collisions/babylon.collider.js @@ -308,6 +308,7 @@ var BABYLON = BABYLON || {}; } this.nearestDistance = distToCollision; this.collisionFound = true; + this.collidedMesh = subMesh.getMesh(); } } }; diff --git a/Babylon/Lights/babylon.pointLight.js b/Babylon/Lights/babylon.pointLight.js index 6975cb20c02..c607f1b4233 100644 --- a/Babylon/Lights/babylon.pointLight.js +++ b/Babylon/Lights/babylon.pointLight.js @@ -14,7 +14,7 @@ var BABYLON = BABYLON || {}; BABYLON.PointLight.prototype = Object.create(BABYLON.Light.prototype); // Methods - BABYLON.Light.prototype.transferToEffect = function (effect, positionUniformName) { + BABYLON.PointLight.prototype.transferToEffect = function (effect, positionUniformName) { if (this.parent && this.parent.getWorldMatrix) { if (!this._transformedPosition) { this._transformedPosition = BABYLON.Vector3.Zero(); diff --git a/Babylon/Materials/textures/babylon.baseTexture.js b/Babylon/Materials/textures/babylon.baseTexture.js index 446db081d14..c6fb3efade3 100644 --- a/Babylon/Materials/textures/babylon.baseTexture.js +++ b/Babylon/Materials/textures/babylon.baseTexture.js @@ -11,7 +11,6 @@ var BABYLON = BABYLON || {}; // Members BABYLON.BaseTexture.prototype.delayLoadState = BABYLON.Engine.DELAYLOADSTATE_NONE; BABYLON.BaseTexture.prototype.hasAlpha = false; - BABYLON.BaseTexture.prototype.hasAlpha = false; BABYLON.BaseTexture.prototype.level = 1; BABYLON.BaseTexture.prototype._texture = null; diff --git a/Babylon/Mesh/babylon.mesh.js b/Babylon/Mesh/babylon.mesh.js index 416a07e34fb..ebbfa3ed3d2 100644 --- a/Babylon/Mesh/babylon.mesh.js +++ b/Babylon/Mesh/babylon.mesh.js @@ -801,6 +801,78 @@ var BABYLON = BABYLON || {}; this.onDispose(); } }; + + // Physics + BABYLON.Mesh.prototype.setPhysicsState = function(options) { + if (!this._scene._physicsEngine) { + return; + } + + options.impostor = options.impostor || BABYLON.PhysicsEngine.NoImpostor; + options.mass = options.mass || 0; + options.friction = options.friction || 0.0; + options.restitution = options.restitution || 0.9; + + this._physicImpostor = options.impostor; + this._physicsMass = options.mass; + this._physicsFriction = options.friction; + this._physicRestitution = options.restitution; + + if (options.impostor === BABYLON.PhysicsEngine.NoImpostor) { + this._scene._physicsEngine._unregisterMesh(this); + return; + } + + this._scene._physicsEngine._registerMesh(this, options); + }; + + BABYLON.Mesh.prototype.getPhysicsImpostor = function() { + if (!this._physicImpostor) { + return BABYLON.PhysicsEngine.NoImpostor; + } + + return this._physicImpostor; + }; + + BABYLON.Mesh.prototype.getPhysicsMass = function() { + if (!this._physicsMass) { + return 0; + } + + return this._physicsMass; + }; + + BABYLON.Mesh.prototype.getPhysicsFriction = function () { + if (!this._physicsFriction) { + return 0; + } + + return this._physicsFriction; + }; + + BABYLON.Mesh.prototype.getPhysicsRestitution = function () { + if (!this._physicRestitution) { + return 0; + } + + return this._physicRestitution; + }; + + BABYLON.Mesh.prototype.applyImpulse = function(force, contactPoint) { + if (!this._physicImpostor) { + return; + } + + this._scene._physicsEngine._applyImpulse(this, force, contactPoint); + }; + + BABYLON.Mesh.prototype.setPhysicsLinkWith = function(otherMesh, pivot1, pivot2) { + if (!this._physicImpostor) { + return; + } + + this._scene._physicsEngine._createLink(this, otherMesh, pivot1, pivot2); + }; // Statics BABYLON.Mesh.CreateBox = function (name, size, scene, updatable) { diff --git a/Babylon/Physics/babylon.physicsEngine.js b/Babylon/Physics/babylon.physicsEngine.js new file mode 100644 index 00000000000..23d563166e3 --- /dev/null +++ b/Babylon/Physics/babylon.physicsEngine.js @@ -0,0 +1,172 @@ +"use strict"; + +var BABYLON = BABYLON || {}; + +(function () { + BABYLON.PhysicsEngine = function (gravity) { + this.gravity = gravity || new BABYLON.Vector3(0, 0, -9.82); + + this._world = new CANNON.World(); + this._world.broadphase = new CANNON.NaiveBroadphase(); + this._world.gravity.set(this.gravity.x, this.gravity.y, this.gravity.z); + + this._registeredMeshes = []; + this._physicsMaterials = []; + }; + + BABYLON.PhysicsEngine.prototype._runOneStep = function (delta) { + if (delta > 1.0) { + delta = 1.0; + } + + this._world.step(delta); + + for (var index = 0; index < this._registeredMeshes.length; index++) { + var registeredMesh = this._registeredMeshes[index]; + + registeredMesh.mesh.position.x = registeredMesh.body.position.x; + registeredMesh.mesh.position.y = registeredMesh.body.position.z; + registeredMesh.mesh.position.z = registeredMesh.body.position.y; + + if (!registeredMesh.mesh.rotationQuaternion) { + registeredMesh.mesh.rotationQuaternion = new BABYLON.Quaternion(0, 0, 0, 1); + } + + registeredMesh.mesh.rotationQuaternion.x = registeredMesh.body.quaternion.x; + registeredMesh.mesh.rotationQuaternion.y = registeredMesh.body.quaternion.z; + registeredMesh.mesh.rotationQuaternion.z = registeredMesh.body.quaternion.y; + registeredMesh.mesh.rotationQuaternion.w = -registeredMesh.body.quaternion.w; + } + }; + + BABYLON.PhysicsEngine.prototype._addMaterial = function (friction, restitution) { + var index; + var mat; + + for (index = 0; index < this._physicsMaterials.length; index++) { + mat = this._physicsMaterials[index]; + + if (mat.friction === friction && mat.restitution === restitution) { + return mat; + } + } + + var currentMat = new CANNON.Material(); + currentMat.friction = friction; + currentMat.restitution = restitution; + this._physicsMaterials.push(currentMat); + + for (index = 0; index < this._physicsMaterials.length; index++) { + mat = this._physicsMaterials[index]; + + var contactMaterial = new CANNON.ContactMaterial(mat, currentMat, Math.max(mat.friction, currentMat.friction), mat.restitution * currentMat.restitution); + this._world.addContactMaterial(contactMaterial); + } + + return currentMat; + }; + + BABYLON.PhysicsEngine.prototype._setGravity = function (gravity) { + this._world.gravity.set(this.gravity.x, this.gravity.y, this.gravity.z); + }; + + BABYLON.PhysicsEngine.prototype._registerMesh = function (mesh, options) { + var shape = null; + + this._unregisterMesh(mesh); + + mesh.computeWorldMatrix(true); + + switch (options.impostor) { + case BABYLON.PhysicsEngine.SphereImpostor: + var bbox = mesh.getBoundingInfo().boundingBox; + var radiusX = bbox.maximumWorld.x - bbox.minimumWorld.x; + var radiusY = bbox.maximumWorld.y - bbox.minimumWorld.y; + var radiusZ = bbox.maximumWorld.z - bbox.minimumWorld.z; + + shape = new CANNON.Sphere(Math.max(radiusX, radiusY, radiusZ) / 2); + break; + case BABYLON.PhysicsEngine.BoxImpostor: + var bbox = mesh.getBoundingInfo().boundingBox; + var min = bbox.minimumWorld; + var max = bbox.maximumWorld; + var box = max.subtract(min).scale(0.5); + shape = new CANNON.Box(new CANNON.Vec3(box.x, box.z, box.y)); + break; + case BABYLON.PhysicsEngine.PlaneImpostor: + shape = new CANNON.Plane(); + break; + } + + var material = this._addMaterial(options.friction, options.restitution); + var body = new CANNON.RigidBody(options.mass, shape, material); + + body.position.set(mesh.position.x, mesh.position.z, mesh.position.y); + this._world.add(body); + + this._registeredMeshes.push({ mesh: mesh, body: body, material:material}); + }; + + BABYLON.PhysicsEngine.prototype._unregisterMesh = function (mesh) { + for (var index = 0; index < this._registeredMeshes.length; index++) { + var registeredMesh = this._registeredMeshes[index]; + + if (registeredMesh.mesh === mesh) { + // Remove + this._world.remove(registeredMesh.body); + this._registeredMeshes.splice(index, 1); + return; + } + } + }; + + BABYLON.PhysicsEngine.prototype._applyImpulse = function (mesh, force, contactPoint) { + var worldPoint = new CANNON.Vec3(contactPoint.x, contactPoint.z, contactPoint.y); + var impulse = new CANNON.Vec3(force.x, force.z, force.y); + + for (var index = 0; index < this._registeredMeshes.length; index++) { + var registeredMesh = this._registeredMeshes[index]; + + if (registeredMesh.mesh === mesh) { + registeredMesh.body.applyImpulse(impulse, worldPoint); + return; + } + } + }; + + BABYLON.PhysicsEngine.prototype._createLink = function (mesh1, mesh2, pivot1, pivot2) { + var body1, body2; + for (var index = 0; index < this._registeredMeshes.length; index++) { + var registeredMesh = this._registeredMeshes[index]; + + if (registeredMesh.mesh === mesh1) { + body1 = registeredMesh.body; + } else if (registeredMesh.mesh === mesh2) { + body2 = registeredMesh.body; + } + } + + if (!body1 || !body2) { + return; + } + + var constraint = new CANNON.PointToPointConstraint(body1, new CANNON.Vec3(pivot1.x, pivot1.z, pivot1.y), body2, new CANNON.Vec3(pivot2.x, pivot2.z, pivot2.y)); + this._world.addConstraint(constraint); + }; + + BABYLON.PhysicsEngine.prototype.dispose = function () { + while (this._registeredMeshes.length) { + this._unregisterMesh(this._registeredMeshes[0].mesh); + } + }; + + // Statics + BABYLON.PhysicsEngine.IsSupported = function() { + return CANNON !== undefined; + }; + + BABYLON.PhysicsEngine.NoImpostor = 0; + BABYLON.PhysicsEngine.SphereImpostor = 1; + BABYLON.PhysicsEngine.BoxImpostor = 2; + BABYLON.PhysicsEngine.PlaneImpostor = 3; +})(); diff --git a/Babylon/Shaders/shadowMap.fragment.fx b/Babylon/Shaders/shadowMap.fragment.fx index 65f9dc39d9c..90d57e12016 100644 --- a/Babylon/Shaders/shadowMap.fragment.fx +++ b/Babylon/Shaders/shadowMap.fragment.fx @@ -22,14 +22,17 @@ vec2 packHalf(float depth) return color - (color.yy * bitOffset); } +#ifndef VSM +varying vec4 vPosition; +#endif void main(void) { #ifdef VSM - float moment1 = gl_FragCoord.z / gl_FragCoord.w; + float moment1 = gl_FragCoord.z / gl_FragCoord.w; float moment2 = moment1 * moment1; gl_FragColor = vec4(packHalf(moment1), packHalf(moment2)); #else - gl_FragColor = pack(gl_FragCoord.z / gl_FragCoord.w); + gl_FragColor = pack(vPosition.z / vPosition.w); #endif } \ No newline at end of file diff --git a/Babylon/Shaders/shadowMap.vertex.fx b/Babylon/Shaders/shadowMap.vertex.fx index f2cafb7ef78..a599b7a7715 100644 --- a/Babylon/Shaders/shadowMap.vertex.fx +++ b/Babylon/Shaders/shadowMap.vertex.fx @@ -18,6 +18,10 @@ uniform mat4 viewProjection; uniform mat4 worldViewProjection; #endif +#ifndef VSM +varying vec4 vPosition; +#endif + void main(void) { #ifdef BONES @@ -28,6 +32,9 @@ void main(void) mat4 finalWorld = world * (m0 + m1 + m2 + m3); gl_Position = viewProjection * finalWorld * vec4(position, 1.0); #else +#ifndef VSM + vPosition = worldViewProjection * vec4(position, 1.0); +#endif gl_Position = worldViewProjection * vec4(position, 1.0); #endif } \ No newline at end of file diff --git a/Babylon/Tools/babylon.sceneLoader.js b/Babylon/Tools/babylon.sceneLoader.js index a6af93744e7..fc58e6df8a6 100644 --- a/Babylon/Tools/babylon.sceneLoader.js +++ b/Babylon/Tools/babylon.sceneLoader.js @@ -1,6 +1,6 @@ "use strict"; -var BABYLON = BABYLON || {}; +var BABYLON = BABYLON || {}; (function () { var loadCubeTexture = function (rootUrl, parsedTexture, scene) { @@ -415,6 +415,22 @@ var BABYLON = BABYLON || {}; if (parsedMesh.skeletonId > -1) { mesh.skeleton = scene.getLastSkeletonByID(parsedMesh.skeletonId); } + + // Physics + if (parsedMesh.physicsImpostor) { + if (!scene.isPhysicsEnabled()) { + scene.enablePhysics(); + } + + switch (parsedMesh.physicsImpostor) { + case 1: // BOX + mesh.setPhysicsState({ impostor: BABYLON.PhysicsEngine.BoxImpostor, mass: parsedMesh.physicsMass, friction: parsedMesh.physicsFriction, restitution: parsedMesh.physicsRestitution }); + break; + case 2: // SPHERE + mesh.setPhysicsState({ impostor: BABYLON.PhysicsEngine.SphereImpostor, mass: parsedMesh.physicsMass, friction: parsedMesh.physicsFriction, restitution: parsedMesh.physicsRestitution }); + break; + } + } // Animations if (parsedMesh.animations) { diff --git a/Babylon/babylon.engine.js b/Babylon/babylon.engine.js index f1150c79d71..9e6ac384626 100644 --- a/Babylon/babylon.engine.js +++ b/Babylon/babylon.engine.js @@ -845,7 +845,7 @@ var BABYLON = BABYLON || {}; var that = this; cascadeLoad(rootUrl, 0, [], scene, function (imgs) { - var width = getExponantOfTwo(imgs[0].width); + var width = getExponantOfTwo(imgs[0].width, that._caps.maxCubemapTextureSize); var height = width; that._workingCanvas.width = width; diff --git a/Babylon/babylon.scene.js b/Babylon/babylon.scene.js index 5b12df26e9a..e1260b53a57 100644 --- a/Babylon/babylon.scene.js +++ b/Babylon/babylon.scene.js @@ -121,10 +121,6 @@ var BABYLON = BABYLON || {}; return this._activeVertices; }; - BABYLON.Scene.prototype.getTotalVertices = function () { - return this._totalVertices; - }; - BABYLON.Scene.prototype.getActiveParticles = function () { return this._activeParticles; }; @@ -690,9 +686,15 @@ var BABYLON = BABYLON || {}; } // Animations - this._animationRatio = BABYLON.Tools.GetDeltaTime() * (60.0 / 1000.0); + var deltaTime = BABYLON.Tools.GetDeltaTime(); + this._animationRatio = deltaTime * (60.0 / 1000.0); this._animate(); + // Physics + if (this._physicsEngine) { + this._physicsEngine._runOneStep(deltaTime / 1000.0); + } + // Clear this._engine.clear(this.clearColor, this.autoClear || this.forceWireframe, true); @@ -788,6 +790,11 @@ var BABYLON = BABYLON || {}; // Post-processes this.postProcessManager.dispose(); + + // Physics + if (this._physicsEngine) { + this.disablePhysicsEngine(); + } // Remove from engine index = this._engine.scenes.indexOf(this); @@ -951,6 +958,42 @@ var BABYLON = BABYLON || {}; return BABYLON.Ray.Transform(ray, that._pickWithRayInverseMatrix); }, predicate, fastCheck); }; + + // Physics + BABYLON.Scene.prototype.enablePhysics = function(gravity) { + if (this._physicsEngine) { + return true; + } + + if (!BABYLON.PhysicsEngine.IsSupported()) { + return false; + } + + this._physicsEngine = new BABYLON.PhysicsEngine(gravity); + + return true; + }; + + BABYLON.Scene.prototype.disablePhysicsEngine = function() { + if (!this._physicsEngine) { + return; + } + + this._physicsEngine.dispose(); + this._physicsEngine = undefined; + }; + + BABYLON.Scene.prototype.isPhysicsEnabled = function() { + return this._physicsEngine !== undefined; + }; + + BABYLON.Scene.prototype.setGravity = function (gravity) { + if (!this._physicsEngine) { + return; + } + + this._physicsEngine._setGravity(gravity); + }; // Statics BABYLON.Scene.FOGMODE_NONE = 0; diff --git a/Babylon/jscompaktor.bat b/Babylon/jscompaktor.bat index dc420a4b662..914d45d3de5 100644 --- a/Babylon/jscompaktor.bat +++ b/Babylon/jscompaktor.bat @@ -1 +1 @@ -JSKompactor.exe /i:"Babylon/Tools/babylon.math.js,Babylon/Tools/babylon.tools.js,Babylon/babylon.engine.js,Babylon/babylon.node.js,Babylon/Culling/babylon.boundingSphere.js,Babylon/Culling/babylon.boundingBox.js,Babylon/Culling/babylon.boundingInfo.js,Babylon/Lights/babylon.light.js,Babylon/Lights/babylon.pointLight.js,Babylon/Lights/babylon.spotlight.js,Babylon/Lights/babylon.directionalLight.js,Babylon/Lights//Shadows/babylon.shadowGenerator.js,Babylon/Lights/babylon.hemisphericLight.js,Babylon/Collisions/babylon.collider.js,Babylon/Cameras/babylon.camera.js,Babylon/Cameras/babylon.freeCamera.js,Babylon/Cameras/babylon.touchCamera.js,Babylon/Cameras/babylon.deviceOrientationCamera.js,Babylon/Cameras/babylon.arcRotateCamera.js,Babylon/babylon.scene.js,Babylon/Mesh/babylon.vertexBuffer.js,Babylon/Mesh/babylon.mesh.js,Babylon/Mesh/babylon.subMesh.js,Babylon/Materials/textures/babylon.baseTexture.js,Babylon/Rendering/babylon.renderingGroup.js,Babylon/Rendering/babylon.renderingManager.js,Babylon/Materials/textures/babylon.texture.js,Babylon/Materials/textures/babylon.cubeTexture.js,Babylon/Materials/textures/babylon.renderTargetTexture.js,Babylon/Materials/textures/babylon.mirrorTexture.js,Babylon/Materials/textures/babylon.dynamicTexture.js,Babylon/Materials/textures/babylon.videoTexture.js,Babylon/Materials/babylon.effect.js,Babylon/Materials/babylon.material.js,Babylon/Materials/babylon.standardMaterial.js,Babylon/Materials/babylon.multiMaterial.js,Babylon/Tools/babylon.database.js,Babylon/Tools/babylon.sceneLoader.js,Babylon/Sprites/babylon.spriteManager.js,Babylon/Sprites/babylon.sprite.js,Babylon/Layer/babylon.layer.js,Babylon/Particles/babylon.particle.js,Babylon/Particles/babylon.particleSystem.js,Babylon/Animations/babylon.animation.js,Babylon/Animations/babylon.animatable.js,Babylon/Culling/Octrees/babylon.octree.js,Babylon/Culling/Octrees/babylon.octreeBlock.js,Babylon/Bones/babylon.bone.js,Babylon/Bones/babylon.skeleton.js,Babylon/PostProcess/babylon.postProcess.js,Babylon/PostProcess/babylon.postProcessManager.js,Babylon/PostProcess/babylon.passPostProcess.js,Babylon/PostProcess/babylon.blurPostProcess.js,Babylon/PostProcess/babylon.fxaaPostProcess.js,Babylon/PostProcess/babylon.refractionPostProcess.js,Babylon/PostProcess/babylon.blackAndWhitePostProcess.js,Babylon/PostProcess/babylon.convolutionPostProcess.js,Babylon/PostProcess/babylon.fxaaPostProcess.js,Babylon/LensFlare/babylon.lensFlare.js,Babylon/LensFlare/babylon.lensFlareSystem.js,Babylon/Collisions/babylon.pickingInfo.js,Babylon/Tools/babylon.filesInput.js" /o:"..\babylon.js" /w:".." /s:"Babylon/Shaders" \ No newline at end of file +JSKompactor.exe /i:"Babylon/Tools/babylon.math.js,Babylon/Tools/babylon.tools.js,Babylon/babylon.engine.js,Babylon/babylon.node.js,Babylon/Culling/babylon.boundingSphere.js,Babylon/Culling/babylon.boundingBox.js,Babylon/Culling/babylon.boundingInfo.js,Babylon/Lights/babylon.light.js,Babylon/Lights/babylon.pointLight.js,Babylon/Lights/babylon.spotlight.js,Babylon/Lights/babylon.directionalLight.js,Babylon/Lights//Shadows/babylon.shadowGenerator.js,Babylon/Lights/babylon.hemisphericLight.js,Babylon/Collisions/babylon.collider.js,Babylon/Cameras/babylon.camera.js,Babylon/Cameras/babylon.freeCamera.js,Babylon/Cameras/babylon.touchCamera.js,Babylon/Cameras/babylon.deviceOrientationCamera.js,Babylon/Cameras/babylon.arcRotateCamera.js,Babylon/babylon.scene.js,Babylon/Mesh/babylon.vertexBuffer.js,Babylon/Mesh/babylon.mesh.js,Babylon/Mesh/babylon.subMesh.js,Babylon/Materials/textures/babylon.baseTexture.js,Babylon/Rendering/babylon.renderingGroup.js,Babylon/Rendering/babylon.renderingManager.js,Babylon/Materials/textures/babylon.texture.js,Babylon/Materials/textures/babylon.cubeTexture.js,Babylon/Materials/textures/babylon.renderTargetTexture.js,Babylon/Materials/textures/babylon.mirrorTexture.js,Babylon/Materials/textures/babylon.dynamicTexture.js,Babylon/Materials/textures/babylon.videoTexture.js,Babylon/Materials/babylon.effect.js,Babylon/Materials/babylon.material.js,Babylon/Materials/babylon.standardMaterial.js,Babylon/Materials/babylon.multiMaterial.js,Babylon/Tools/babylon.database.js,Babylon/Tools/babylon.sceneLoader.js,Babylon/Sprites/babylon.spriteManager.js,Babylon/Sprites/babylon.sprite.js,Babylon/Layer/babylon.layer.js,Babylon/Particles/babylon.particle.js,Babylon/Particles/babylon.particleSystem.js,Babylon/Animations/babylon.animation.js,Babylon/Animations/babylon.animatable.js,Babylon/Culling/Octrees/babylon.octree.js,Babylon/Culling/Octrees/babylon.octreeBlock.js,Babylon/Bones/babylon.bone.js,Babylon/Bones/babylon.skeleton.js,Babylon/PostProcess/babylon.postProcess.js,Babylon/PostProcess/babylon.postProcessManager.js,Babylon/PostProcess/babylon.passPostProcess.js,Babylon/PostProcess/babylon.blurPostProcess.js,Babylon/PostProcess/babylon.fxaaPostProcess.js,Babylon/PostProcess/babylon.refractionPostProcess.js,Babylon/PostProcess/babylon.blackAndWhitePostProcess.js,Babylon/PostProcess/babylon.convolutionPostProcess.js,Babylon/PostProcess/babylon.fxaaPostProcess.js,Babylon/LensFlare/babylon.lensFlare.js,Babylon/LensFlare/babylon.lensFlareSystem.js,Babylon/Collisions/babylon.pickingInfo.js,Babylon/Tools/babylon.filesInput.js,Babylon/Physics/babylon.physicsEngine.js" /o:"..\babylon.js" /w:".." /s:"Babylon/Shaders" \ No newline at end of file diff --git a/Exporters/Blender/io_export_babylon.py b/Exporters/Blender/io_export_babylon.py index 89595696278..61656b0b65e 100644 --- a/Exporters/Blender/io_export_babylon.py +++ b/Exporters/Blender/io_export_babylon.py @@ -601,6 +601,17 @@ def export_mesh(object, scene, file_handler, multiMaterials): Export_babylon.write_bool(file_handler, "checkCollisions", object.data.checkCollisions) Export_babylon.write_int(file_handler, "billboardMode", billboardMode) Export_babylon.write_bool(file_handler, "receiveShadows", object.data.receiveShadows) + + # Export Physics + if object.rigid_body != None: + shape_items = {'BOX': 1, 'SPHERE': 2} + shape_type = shape_items[object.rigid_body.collision_shape] + Export_babylon.write_int(file_handler, "physicsImpostor", shape_type) + Export_babylon.write_float(file_handler, "physicsMass", object.rigid_body.mass) + Export_babylon.write_float(file_handler, "physicsFriction", object.rigid_body.friction) + Export_babylon.write_float(file_handler, "physicsRestitution", object.rigid_body.restitution) + + # Geometry if hasSkeleton: i = 0 for obj in [object for object in scene.objects if object.is_visible(scene)]: @@ -644,7 +655,7 @@ def export_mesh(object, scene, file_handler, multiMaterials): file_handler.write("}") first = False file_handler.write("]") - + #Export Animations rotAnim = False diff --git a/Samples/Assets/amiga.jpg b/Samples/Assets/amiga.jpg new file mode 100644 index 00000000000..e65f977b495 Binary files /dev/null and b/Samples/Assets/amiga.jpg differ diff --git a/Samples/Assets/mosaic.jpg b/Samples/Assets/mosaic.jpg new file mode 100644 index 00000000000..e565e02989c Binary files /dev/null and b/Samples/Assets/mosaic.jpg differ diff --git a/Samples/Assets/wood.jpg b/Samples/Assets/wood.jpg new file mode 100644 index 00000000000..9a61e629c12 Binary files /dev/null and b/Samples/Assets/wood.jpg differ diff --git a/Samples/Scenes/Customs/physics.js b/Samples/Scenes/Customs/physics.js new file mode 100644 index 00000000000..7ad57e124ac --- /dev/null +++ b/Samples/Scenes/Customs/physics.js @@ -0,0 +1,121 @@ +var CreatePhysicsScene = function(engine) { + var scene = new BABYLON.Scene(engine); + var camera = new BABYLON.FreeCamera("Camera", new BABYLON.Vector3(0, 0, -20), scene); + camera.checkCollisions = true; + camera.applyGravity = true; + + var light = new BABYLON.DirectionalLight("dir02", new BABYLON.Vector3(0.2, -1, 0), scene); + light.position = new BABYLON.Vector3(0, 80, 0); + + // Material + var materialAmiga = new BABYLON.StandardMaterial("amiga", scene); + materialAmiga.diffuseTexture = new BABYLON.Texture("assets/amiga.jpg", scene); + materialAmiga.emissiveColor = new BABYLON.Color3(0.5, 0.5, 0.5); + materialAmiga.diffuseTexture.uScale = 5; + materialAmiga.diffuseTexture.vScale = 5; + + var materialAmiga2 = new BABYLON.StandardMaterial("amiga", scene); + materialAmiga2.diffuseTexture = new BABYLON.Texture("assets/mosaic.jpg", scene); + materialAmiga2.emissiveColor = new BABYLON.Color3(0.5, 0.5, 0.5); + + // Shadows + var shadowGenerator = new BABYLON.ShadowGenerator(2048, light); + shadowGenerator.getShadowMap().renderList.push(box0); + + // Physics + scene.enablePhysics(); + + // Spheres + var y = 0; + for (var index = 0; index < 32; index++) { + var sphere = BABYLON.Mesh.CreateSphere("Sphere0", 16, 3, scene); + sphere.material = materialAmiga; + + sphere.position = new BABYLON.Vector3(Math.random() * 20 - 10, y, Math.random() * 10 - 5); + + shadowGenerator.getShadowMap().renderList.push(sphere); + + sphere.setPhysicsState({ impostor: BABYLON.PhysicsEngine.SphereImpostor, mass: 1 }); + + y += 2; + } + + // Link + var spheres = []; + for (var index = 0; index < 10; index++) { + var sphere = BABYLON.Mesh.CreateSphere("Sphere0", 16, 1, scene); + spheres.push(sphere); + sphere.material = materialAmiga2; + sphere.position = new BABYLON.Vector3(Math.random() * 20 - 10, y, Math.random() * 10 - 5); + + shadowGenerator.getShadowMap().renderList.push(sphere); + + sphere.setPhysicsState({ impostor: BABYLON.PhysicsEngine.SphereImpostor, mass: 1 }); + } + + for (var index = 0; index < 10; index++) { + spheres[index].setPhysicsLinkWith(spheres[index + 1], new BABYLON.Vector3(0, 0.5, 0), new BABYLON.Vector3(0, -0.5, 0)); + } + + // Box + var box0 = BABYLON.Mesh.CreateBox("Box0", 3, scene); + box0.position = new BABYLON.Vector3(3, 30, 0); + var materialWood = new BABYLON.StandardMaterial("wood", scene); + materialWood.diffuseTexture = new BABYLON.Texture("assets/wood.jpg", scene); + materialWood.emissiveColor = new BABYLON.Color3(0.5, 0.5, 0.5); + box0.material = materialWood; + + shadowGenerator.getShadowMap().renderList.push(box0); + + // Playground + var ground = BABYLON.Mesh.CreateBox("Ground", 1, scene); + ground.scaling = new BABYLON.Vector3(100, 1, 100); + ground.position.y = -5.0; + ground.checkCollisions = true; + + var border0 = BABYLON.Mesh.CreateBox("border0", 1, scene); + border0.scaling = new BABYLON.Vector3(1, 100, 100); + border0.position.y = -5.0; + border0.position.x = -50.0; + border0.checkCollisions = true; + + var border1 = BABYLON.Mesh.CreateBox("border1", 1, scene); + border1.scaling = new BABYLON.Vector3(1, 100, 100); + border1.position.y = -5.0; + border1.position.x = 50.0; + border1.checkCollisions = true; + + var border2 = BABYLON.Mesh.CreateBox("border2", 1, scene); + border2.scaling = new BABYLON.Vector3(100, 100, 1); + border2.position.y = -5.0; + border2.position.z = 50.0; + border2.checkCollisions = true; + + var border3 = BABYLON.Mesh.CreateBox("border3", 1, scene); + border3.scaling = new BABYLON.Vector3(100, 100, 1); + border3.position.y = -5.0; + border3.position.z = -50.0; + border3.checkCollisions = true; + + camera.setTarget(new BABYLON.Vector3(0, 0, 0)); + + var groundMat = new BABYLON.StandardMaterial("groundMat", scene); + groundMat.diffuseColor = new BABYLON.Color3(0.5, 0.5, 0.5); + groundMat.emissiveColor = new BABYLON.Color3(0.2, 0.2, 0.2); + ground.material = groundMat; + border0.material = groundMat; + border1.material = groundMat; + border2.material = groundMat; + border3.material = groundMat; + ground.receiveShadows = true; + + // Physics + box0.setPhysicsState({ impostor: BABYLON.PhysicsEngine.BoxImpostor, mass: 2, friction: 0.4, restitution: 0.3 }); + ground.setPhysicsState({ impostor: BABYLON.PhysicsEngine.BoxImpostor, mass: 0, friction: 0.5, restitution: 0.7 }); + border0.setPhysicsState({ impostor: BABYLON.PhysicsEngine.BoxImpostor, mass: 0 }); + border1.setPhysicsState({ impostor: BABYLON.PhysicsEngine.BoxImpostor, mass: 0 }); + border2.setPhysicsState({ impostor: BABYLON.PhysicsEngine.BoxImpostor, mass: 0 }); + border3.setPhysicsState({ impostor: BABYLON.PhysicsEngine.BoxImpostor, mass: 0 }); + + return scene; +}; \ No newline at end of file diff --git a/Samples/Scenes/Espilit/debug.txt b/Samples/Scenes/Espilit/debug.txt new file mode 100644 index 00000000000..ad5dbcdeaed --- /dev/null +++ b/Samples/Scenes/Espilit/debug.txt @@ -0,0 +1 @@ +Generation of c:\Export\Espilit\Espilit.babylon successfullGeneration of c:\Export\espilit\espilit.babylon successfull \ No newline at end of file diff --git a/Samples/Scenes/Sandbox/Assets/BtnDragdrop.png b/Samples/Scenes/Sandbox/Assets/BtnDragdrop.png new file mode 100644 index 00000000000..f3b86caa14c Binary files /dev/null and b/Samples/Scenes/Sandbox/Assets/BtnDragdrop.png differ diff --git a/Samples/Scenes/Sandbox/Assets/BtnFullscreen.png b/Samples/Scenes/Sandbox/Assets/BtnFullscreen.png new file mode 100644 index 00000000000..e7231312fe0 Binary files /dev/null and b/Samples/Scenes/Sandbox/Assets/BtnFullscreen.png differ diff --git a/Samples/Scenes/Sandbox/Assets/BtnPerf.png b/Samples/Scenes/Sandbox/Assets/BtnPerf.png new file mode 100644 index 00000000000..fbc7be5ab91 Binary files /dev/null and b/Samples/Scenes/Sandbox/Assets/BtnPerf.png differ diff --git a/Samples/Scenes/Sandbox/Assets/FlecheDown.png b/Samples/Scenes/Sandbox/Assets/FlecheDown.png new file mode 100644 index 00000000000..9ab230e9298 Binary files /dev/null and b/Samples/Scenes/Sandbox/Assets/FlecheDown.png differ diff --git a/Samples/Scenes/Sandbox/Assets/FlecheTuto.png b/Samples/Scenes/Sandbox/Assets/FlecheTuto.png new file mode 100644 index 00000000000..c3b1786e0c7 Binary files /dev/null and b/Samples/Scenes/Sandbox/Assets/FlecheTuto.png differ diff --git a/Samples/Scenes/Sandbox/Assets/Interface-Sandbox.jpg b/Samples/Scenes/Sandbox/Assets/Interface-Sandbox.jpg new file mode 100644 index 00000000000..f026f765a46 Binary files /dev/null and b/Samples/Scenes/Sandbox/Assets/Interface-Sandbox.jpg differ diff --git a/Samples/Scenes/Sandbox/Assets/LogoSandbox.png b/Samples/Scenes/Sandbox/Assets/LogoSandbox.png new file mode 100644 index 00000000000..800a119253e Binary files /dev/null and b/Samples/Scenes/Sandbox/Assets/LogoSandbox.png differ diff --git a/Samples/Scenes/Sandbox/Assets/WideLogo.png b/Samples/Scenes/Sandbox/Assets/WideLogo.png new file mode 100644 index 00000000000..c4ba39c5c9c Binary files /dev/null and b/Samples/Scenes/Sandbox/Assets/WideLogo.png differ diff --git a/Samples/Scenes/Sandbox/Assets/arrow.png b/Samples/Scenes/Sandbox/Assets/arrow.png new file mode 100644 index 00000000000..fee979e15aa Binary files /dev/null and b/Samples/Scenes/Sandbox/Assets/arrow.png differ diff --git a/Samples/Scenes/Sandbox/Assets/down.png b/Samples/Scenes/Sandbox/Assets/down.png new file mode 100644 index 00000000000..a401bae0871 Binary files /dev/null and b/Samples/Scenes/Sandbox/Assets/down.png differ diff --git a/Samples/Scenes/Sandbox/Assets/sep.png b/Samples/Scenes/Sandbox/Assets/sep.png new file mode 100644 index 00000000000..1734133a7cb Binary files /dev/null and b/Samples/Scenes/Sandbox/Assets/sep.png differ diff --git a/Samples/Scenes/Sandbox/Assets/up.png b/Samples/Scenes/Sandbox/Assets/up.png new file mode 100644 index 00000000000..cbb62b4d082 Binary files /dev/null and b/Samples/Scenes/Sandbox/Assets/up.png differ diff --git a/Samples/Scenes/Sandbox/Assets/video.png b/Samples/Scenes/Sandbox/Assets/video.png new file mode 100644 index 00000000000..c3e6f07e80d Binary files /dev/null and b/Samples/Scenes/Sandbox/Assets/video.png differ diff --git a/Samples/Scenes/Sandbox/index.css b/Samples/Scenes/Sandbox/index.css new file mode 100644 index 00000000000..b584d39a614 --- /dev/null +++ b/Samples/Scenes/Sandbox/index.css @@ -0,0 +1,232 @@ +html, body { + width: 100%; + height: 100%; + padding: 0; + margin: 0; + overflow: hidden; + font-family: "Segoe WP", "Segoe UI", "Verdana", "Arial"; +} + +a { + color: white; +} + + a:visited { + color: white; + } + +.hidden { + display: none; +} + +#renderCanvas { + position: absolute; + width: 100%; + height: 100%; + top: 0; + margin-bottom: 70px; + touch-action: none; + -ms-touch-action: none; +} + +.help { + position: absolute; + background-color: #988DB5; + right: 0; + bottom: 70px; + color: white; + padding-right: 10px; + width: 360px; + height: 30px; + transition: all 0.5s ease; + -webkit-transition: all 0.5s ease; + transform: translateX(400px); + -webkit-transform: translateX(400px); + text-align: center; +} + + .help.shown { + transform: translateX(-100px); + -webkit-transform: translateX(-100px); + } + + .help2 { + position: absolute; + background-color: #988DB5; + right: 0; + bottom: 70px; + color: white; + padding-right: 10px; + width: 360px; + height: 30px; + transition: all 0.5s ease; + -webkit-transition: all 0.5s ease; + transform: translateX(400px); + -webkit-transform: translateX(400px); + text-align: center; +} + + .help2.shown { + transform: translateX(0px); + -webkit-transform: translateX(0px); + } + +#helpArrow { + position: absolute; + right: -65px; + bottom: 10px; +} + +#fps { + position: absolute; + font-size: 30px; + color: white; + bottom: 15px; + right: 85px; + width: 85px; +} + +.footer { + position: absolute; + width: 100%; + height: 60px; + bottom: 0; + background-color: #59448F; + padding-top: 5px; + padding-left: 15px; +} + +.perffooter { + position: absolute; + width: 100%; + height: 60px; + bottom: 0px; + background-color: #988DB5; + padding-top: 5px; + padding-left: 15px; + transition: all 0.5s ease; + -webkit-transition: all 0.5s ease; +} + + .perffooter.shown { + transform: translateY(-65px); + -webkit-transform: translateY(-65px); + } + +.footerRight { + display: inline; + position: absolute; + bottom: 0; + right: 10px; +} + +.footerLeft { + position: absolute; + bottom: 20px; + left: 15px; + color: white; +} + +.custom-upload { + position: relative; + background:url(./Assets/BtnDragdrop.png) center right no-repeat; + height: 56px; + width: 56px; + margin: 10px 20px 5px 5px; +} + +.custom-upload input[type=file] +{ + outline:none; + position: relative; + text-align: right; + -moz-opacity:0 ; + filter:alpha(opacity: 0); + opacity: 0; + z-index: 2; + width:100%; + height:100%; + +} + +#logo { + width: 100%; + height: 100%; + background: url('./Assets/LogoSandbox.png') no-repeat 0 0; + background-position: center; +} + +#btnFullscreen { +} + +#btnFullscreen { + margin-top: 10px; + margin-right: 25px; +} + +#btnPerf { + margin-top: 10px; + margin-right: 15px; +} + +ul { + padding:0; + margin:0; + list-style-type:none; + } + +li { + float:left; + } + +#btnDownArrow { + position: absolute; + bottom: 35px; + right: 30px; +} + +#miscCounters { + position: relative; + top: 18px; + height: 60px; + -webkit-column-width: 150px; + -moz-column-width: 150px; + -ms-column-width: 150px; + -o-column-width: 150px; + column-width: 150px; + + font-size: 14px; +} + +#loadingText { + width: 100%; + height: 60px; + position: absolute; + top: 50%; + left: 0; + margin-top: -30px; + color: white; + text-align: center; + padding-top: 10px; + font-size: 30px; + transition: transform 0.25s ease-in-out; + -webkit-transition: -webkit-transform 0.25s ease-in-out; + z-index: 3; + cursor: default; + background-color: #988DB5; +} + +.loadingText { + transform: translateX(120%); + -webkit-transform: translateX(120%); +} + +#btnFullscreen, #btnPerf, #btnFiles { + -webkit-transition: -webkit-transform 0.15s ease-in-out; + transition: transform 0.15s ease-in-out; +} + +#btnFullscreen:hover, #btnPerf:hover, #btnFiles:hover { + -webkit-transform: scale(0.9); + transform: scale(0.9); +} \ No newline at end of file diff --git a/Samples/Scenes/Sandbox/index.html b/Samples/Scenes/Sandbox/index.html new file mode 100644 index 00000000000..9eb9bb4f1f2 --- /dev/null +++ b/Samples/Scenes/Sandbox/index.html @@ -0,0 +1,52 @@ + + + + BabylonJS - Sandbox + + + + + + + + +
+ Press this button to open your assets' files + +
+
+ Or directly drag'n'drop your files in the browser +
+
+
+
+
+
+
+ +
+
+ +
+ + \ No newline at end of file diff --git a/Samples/Scenes/Sandbox/index.js b/Samples/Scenes/Sandbox/index.js new file mode 100644 index 00000000000..72df4d85c9c --- /dev/null +++ b/Samples/Scenes/Sandbox/index.js @@ -0,0 +1,103 @@ +/// + +document.addEventListener("DOMContentLoaded", startGame, false); + +function startGame() { + if (BABYLON.Engine.isSupported()) { + var canvas = document.getElementById("renderCanvas"); + var engine = new BABYLON.Engine(canvas, true); + var divFps = document.getElementById("fps"); + var htmlInput = document.getElementById("files"); + var btnFullScreen = document.getElementById("btnFullscreen"); + var btnDownArrow = document.getElementById("btnDownArrow"); + var perffooter = document.getElementById("perf"); + var btnPerf = document.getElementById("btnPerf"); + var miscCounters = document.getElementById("miscCounters"); + var help01 = document.getElementById("help01"); + var help02 = document.getElementById("help02"); + var loadingText = document.getElementById("loadingText"); + var filesInput; + var currentHelpCounter; + var currentScene; + var perffooterEnable = false; + + currentHelpCounter = localStorage.getItem("helpcounter"); + + if (!currentHelpCounter) currentHelpCounter = 0; + + // Resize + window.addEventListener("resize", function () { + engine.resize(); + }); + + var sceneLoaded = function (sceneFile, babylonScene) { + currentScene = babylonScene; + document.title = "BabylonJS - " + sceneFile.name; + // Fix for IE, otherwise it will change the default filter for files selection after first use + htmlInput.value = ""; + document.getElementById("logo").className = "hidden"; + loadingText.className = "loadingText"; + }; + + var progressCallback = function (evt) { + if (evt.lengthComputable) { + loadingText.innerHTML = "Loading, please wait..." + (evt.loaded * 100 / evt.total).toFixed() + "%"; + } else { + dlCount = evt.loaded / (1024 * 1024); + loadingText.innerHTML = "Loading, please wait..." + Math.floor(dlCount * 100.0) / 100.0 + " MB already loaded."; + } + }; + + var textureLoadingCallback = function (remainingTextures) { + loadingText.innerHTML = "Streaming items..." + (remainingTextures ? (remainingTextures + " remaining") : ""); + }; + + var startingProcessingFilesCallback = function () { + loadingText.className = ""; + loadingText.innerHTML = "Loading, please wait..."; + }; + + var additionnalRenderLoopLogic = function () { + divFps.innerHTML = BABYLON.Tools.GetFps().toFixed() + " fps"; + if (currentScene) { + miscCounters.innerHTML = "Total vertices: " + currentScene.getTotalVertices() + "
" + + "Active vertices: " + currentScene.getActiveVertices() + "
" + + "Active particles: " + currentScene.getActiveParticles() + "
" + + "Frame duration: " + currentScene.getLastFrameDuration() + " ms" + "
" + + "Evaluate Active Meshes duration: " + currentScene.getEvaluateActiveMeshesDuration() + " ms" + "
" + + "Render Targets duration: " + currentScene.getRenderTargetsDuration() + " ms" + "
" + + "Particles duration: " + currentScene.getParticlesDuration() + " ms" + "
" + + "Sprites duration: " + currentScene.getSpritesDuration() + " ms" + "
" + + "Render duration: " + currentScene.getRenderDuration() + " ms"; + } + }; + + filesInput = new BABYLON.FilesInput(engine, null, canvas, sceneLoaded, progressCallback, additionnalRenderLoopLogic, textureLoadingCallback, startingProcessingFilesCallback); + filesInput.monitorElementForDragNDrop(canvas); + + htmlInput.addEventListener('change', filesInput.loadFiles, false); + btnFullScreen.addEventListener('click', function () { + engine.switchFullscreen(true); + }, false); + btnPerf.addEventListener('click', function () { + perffooter.className = "perffooter shown"; + }, false); + btnDownArrow.addEventListener('click', function () { + perffooter.className = "perffooter"; + }, false); + + // The help tips will be displayed only 5 times + if (currentHelpCounter < 5) { + help01.className = "help shown"; + + setTimeout(function () { + help01.className = "help"; + help02.className = "help2 shown"; + setTimeout(function () { + help02.className = "help2"; + localStorage.setItem("helpcounter", currentHelpCounter + 1); + }, 5000); + }, 5000); + } + } +} \ No newline at end of file diff --git a/Samples/Screenshots/Train.jpg b/Samples/Screenshots/Train.jpg index 423f5afa39d..38df651dd90 100644 Binary files a/Samples/Screenshots/Train.jpg and b/Samples/Screenshots/Train.jpg differ diff --git a/Samples/Screenshots/bing3D.jpg b/Samples/Screenshots/bing3D.jpg new file mode 100644 index 00000000000..3a15f56c794 Binary files /dev/null and b/Samples/Screenshots/bing3D.jpg differ diff --git a/Samples/Screenshots/physics.jpg b/Samples/Screenshots/physics.jpg new file mode 100644 index 00000000000..b3958f81761 Binary files /dev/null and b/Samples/Screenshots/physics.jpg differ diff --git a/Samples/babylon.js b/Samples/babylon.js index a500694c641..ea9f87be043 100644 --- a/Samples/babylon.js +++ b/Samples/babylon.js @@ -1,11 +1,11 @@ -var BABYLON=BABYLON||{};(function(){BABYLON.Ray=function(origin,direction){this.origin=origin;this.direction=direction;};BABYLON.Ray.prototype.intersectsBox=function(box){var d=0.0;var maxValue=Number.MAX_VALUE;if(Math.abs(this.direction.x)<0.0000001){if(this.origin.xbox.maximum.x){return false;}}else{var inv=1.0/this.direction.x;var min=(box.minimum.x-this.origin.x)*inv;var max=(box.maximum.x-this.origin.x)*inv;if(min>max){var temp=min;min=max;max=temp;}d=Math.max(min,d);maxValue=Math.min(max,maxValue);if(d>maxValue){return false;}}if(Math.abs(this.direction.y)<0.0000001){if(this.origin.ybox.maximum.y){return false;}}else{var inv=1.0/this.direction.y;var min=(box.minimum.y-this.origin.y)*inv;var max=(box.maximum.y-this.origin.y)*inv;if(min>max){var temp=min;min=max;max=temp;}d=Math.max(min,d);maxValue=Math.min(max,maxValue);if(d>maxValue){return false;}}if(Math.abs(this.direction.z)<0.0000001){if(this.origin.zbox.maximum.z){return false;}}else{var inv=1.0/this.direction.z;var min=(box.minimum.z-this.origin.z)*inv;var max=(box.maximum.z-this.origin.z)*inv;if(min>max){var temp=min;min=max;max=temp;}d=Math.max(min,d);maxValue=Math.min(max,maxValue);if(d>maxValue){return false;}}return true;};BABYLON.Ray.prototype.intersectsSphere=function(sphere){var x=sphere.center.x-this.origin.x;var y=sphere.center.y-this.origin.y;var z=sphere.center.z-this.origin.z;var pyth=(x*x)+(y*y)+(z*z);var rr=sphere.radius*sphere.radius;if(pyth<=rr){return true;}var dot=(x*this.direction.x)+(y*this.direction.y)+(z*this.direction.z);if(dot<0.0){return false;}var temp=pyth-(dot*dot);return temp<=rr;};BABYLON.Ray.prototype.intersectsTriangle=function(vertex0,vertex1,vertex2){if(!this._edge1){this._edge1=BABYLON.Vector3.Zero();this._edge2=BABYLON.Vector3.Zero();this._pvec=BABYLON.Vector3.Zero();this._tvec=BABYLON.Vector3.Zero();this._qvec=BABYLON.Vector3.Zero();}vertex1.subtractToRef(vertex0,this._edge1);vertex2.subtractToRef(vertex0,this._edge2);BABYLON.Vector3.CrossToRef(this.direction,this._edge2,this._pvec);var det=BABYLON.Vector3.Dot(this._edge1,this._pvec);if(det===0){return 0;}var invdet=1/det;this.origin.subtractToRef(vertex0,this._tvec);var bu=BABYLON.Vector3.Dot(this._tvec,this._pvec)*invdet;if(bu<0||bu>1.0){return 0;}BABYLON.Vector3.CrossToRef(this._tvec,this._edge1,this._qvec);var bv=BABYLON.Vector3.Dot(this.direction,this._qvec)*invdet;if(bv<0||bu+bv>1.0){return 0;}return BABYLON.Vector3.Dot(this._edge2,this._qvec)*invdet;};BABYLON.Ray.CreateNew=function(x,y,viewportWidth,viewportHeight,world,view,projection){var start=BABYLON.Vector3.Unproject(new BABYLON.Vector3(x,y,0),viewportWidth,viewportHeight,world,view,projection);var end=BABYLON.Vector3.Unproject(new BABYLON.Vector3(x,y,1),viewportWidth,viewportHeight,world,view,projection);var direction=end.subtract(start);direction.normalize();return new BABYLON.Ray(start,direction);};BABYLON.Ray.Transform=function(ray,matrix){var newOrigin=BABYLON.Vector3.TransformCoordinates(ray.origin,matrix);var newDirection=BABYLON.Vector3.TransformNormal(ray.direction,matrix);return new BABYLON.Ray(newOrigin,newDirection);};BABYLON.Color3=function(initialR,initialG,initialB){this.r=initialR;this.g=initialG;this.b=initialB;};BABYLON.Color3.prototype.toString=function(){return"{R: "+this.r+" G:"+this.g+" B:"+this.b+"}";};BABYLON.Color3.prototype.multiply=function(otherColor){return new BABYLON.Color3(this.r*otherColor.r,this.g*otherColor.g,this.b*otherColor.b);};BABYLON.Color3.prototype.multiplyToRef=function(otherColor,result){result.r=this.r*otherColor.r;result.g=this.g*otherColor.g;result.b=this.b*otherColor.b;};BABYLON.Color3.prototype.equals=function(otherColor){return this.r===otherColor.r&&this.g===otherColor.g&&this.b===otherColor.b;};BABYLON.Color3.prototype.scale=function(scale){return new BABYLON.Color3(this.r*scale,this.g*scale,this.b*scale);};BABYLON.Color3.prototype.scaleToRef=function(scale,result){result.r=this.r*scale;result.g=this.g*scale;result.b=this.b*scale;};BABYLON.Color3.prototype.clone=function(){return new BABYLON.Color3(this.r,this.g,this.b);};BABYLON.Color3.prototype.copyFrom=function(source){this.r=source.r;this.g=source.g;this.b=source.b;};BABYLON.Color3.prototype.copyFromFloats=function(r,g,b){this.r=r;this.g=g;this.b=b;};BABYLON.Color3.FromArray=function(array){return new BABYLON.Color3(array[0],array[1],array[2]);};BABYLON.Color4=function(initialR,initialG,initialB,initialA){this.r=initialR;this.g=initialG;this.b=initialB;this.a=initialA;};BABYLON.Color4.prototype.addInPlace=function(right){this.r+=right.r;this.g+=right.g;this.b+=right.b;this.a+=right.a;};BABYLON.Color4.prototype.add=function(right){return new BABYLON.Color4(this.r+right.r,this.g+right.g,this.b+right.b,this.a+right.a);};BABYLON.Color4.prototype.subtract=function(right){return new BABYLON.Color4(this.r-right.r,this.g-right.g,this.b-right.b,this.a-right.a);};BABYLON.Color4.prototype.subtractToRef=function(right,result){result.r=this.r-right.r;result.g=this.g-right.g;result.b=this.b-right.b;result.a=this.a-right.a;};BABYLON.Color4.prototype.scale=function(scale){return new BABYLON.Color4(this.r*scale,this.g*scale,this.b*scale,this.a*scale);};BABYLON.Color4.prototype.scaleToRef=function(scale,result){result.r=this.r*scale;result.g=this.g*scale;result.b=this.b*scale;result.a=this.a*scale;};BABYLON.Color4.prototype.toString=function(){return"{R: "+this.r+" G:"+this.g+" B:"+this.b+" A:"+this.a+"}";};BABYLON.Color4.prototype.clone=function(){return new BABYLON.Color4(this.r,this.g,this.b,this.a);};BABYLON.Color4.Lerp=function(left,right,amount){var result=new BABYLON.Color4(0,0,0,0);BABYLON.Color4.LerpToRef(left,right,amount,result);return result;};BABYLON.Color4.LerpToRef=function(left,right,amount,result){result.r=left.r+(right.r-left.r)*amount;result.g=left.g+(right.g-left.g)*amount;result.b=left.b+(right.b-left.b)*amount;result.a=left.a+(right.a-left.a)*amount;};BABYLON.Color4.FromArray=function(array,offset){if(!offset){offset=0;}return new BABYLON.Color4(array[offset],array[offset+1],array[offset+2],array[offset+3]);};BABYLON.Vector2=function(initialX,initialY){this.x=initialX;this.y=initialY;};BABYLON.Vector2.prototype.toString=function(){return"{X: "+this.x+" Y:"+this.y+"}";};BABYLON.Vector2.prototype.add=function(otherVector){return new BABYLON.Vector2(this.x+otherVector.x,this.y+otherVector.y);};BABYLON.Vector2.prototype.subtract=function(otherVector){return new BABYLON.Vector2(this.x-otherVector.x,this.y-otherVector.y);};BABYLON.Vector2.prototype.negate=function(){return new BABYLON.Vector2(-this.x,-this.y);};BABYLON.Vector2.prototype.scaleInPlace=function(scale){this.x*=scale;this.y*=scale;};BABYLON.Vector2.prototype.scale=function(scale){return new BABYLON.Vector2(this.x*scale,this.y*scale);};BABYLON.Vector2.prototype.equals=function(otherVector){return this.x===otherVector.x&&this.y===otherVector.y;};BABYLON.Vector2.prototype.length=function(){return Math.sqrt(this.x*this.x+this.y*this.y);};BABYLON.Vector2.prototype.lengthSquared=function(){return(this.x*this.x+this.y*this.y);};BABYLON.Vector2.prototype.normalize=function(){var len=this.length();if(len===0)return;var num=1.0/len;this.x*=num;this.y*=num;};BABYLON.Vector2.prototype.clone=function(){return new BABYLON.Vector2(this.x,this.y);};BABYLON.Vector2.Zero=function(){return new BABYLON.Vector2(0,0);};BABYLON.Vector2.CatmullRom=function(value1,value2,value3,value4,amount){var squared=amount*amount;var cubed=amount*squared;var x=0.5*((((2.0*value2.x)+((-value1.x+value3.x)*amount))+(((((2.0*value1.x)-(5.0*value2.x))+(4.0*value3.x))-value4.x)*squared))+((((-value1.x+(3.0*value2.x))-(3.0*value3.x))+value4.x)*cubed));var y=0.5*((((2.0*value2.y)+((-value1.y+value3.y)*amount))+(((((2.0*value1.y)-(5.0*value2.y))+(4.0*value3.y))-value4.y)*squared))+((((-value1.y+(3.0*value2.y))-(3.0*value3.y))+value4.y)*cubed));return new BABYLON.Vector2(x,y);};BABYLON.Vector2.Clamp=function(value,min,max){var x=value.x;x=(x>max.x)?max.x:x;x=(xmax.y)?max.y:y;y=(yright.x)?left.x:right.x;var y=(left.y>right.y)?left.y:right.y;return new BABYLON.Vector2(x,y);};BABYLON.Vector2.Transform=function(vector,transformation){var x=(vector.x*transformation.m[0])+(vector.y*transformation.m[4]);var y=(vector.x*transformation.m[1])+(vector.y*transformation.m[5]);return new BABYLON.Vector2(x,y);};BABYLON.Vector2.Distance=function(value1,value2){return Math.sqrt(BABYLON.Vector2.DistanceSquared(value1,value2));};BABYLON.Vector2.DistanceSquared=function(value1,value2){var x=value1.x-value2.x;var y=value1.y-value2.y;return(x*x)+(y*y);};BABYLON.Vector3=function(initialX,initialY,initialZ){this.x=initialX;this.y=initialY;this.z=initialZ;};BABYLON.Vector3.prototype.toString=function(){return"{X: "+this.x+" Y:"+this.y+" Z:"+this.z+"}";};BABYLON.Vector3.prototype.toArray=function(array,index){array[index]=this.x;array[index+1]=this.y;array[index+2]=this.z;};BABYLON.Vector3.prototype.addInPlace=function(otherVector){this.x+=otherVector.x;this.y+=otherVector.y;this.z+=otherVector.z;};BABYLON.Vector3.prototype.add=function(otherVector){return new BABYLON.Vector3(this.x+otherVector.x,this.y+otherVector.y,this.z+otherVector.z);};BABYLON.Vector3.prototype.addToRef=function(otherVector,result){result.x=this.x+otherVector.x;result.y=this.y+otherVector.y;result.z=this.z+otherVector.z;};BABYLON.Vector3.prototype.subtractInPlace=function(otherVector){this.x-=otherVector.x;this.y-=otherVector.y;this.z-=otherVector.z;};BABYLON.Vector3.prototype.subtract=function(otherVector){return new BABYLON.Vector3(this.x-otherVector.x,this.y-otherVector.y,this.z-otherVector.z);};BABYLON.Vector3.prototype.subtractToRef=function(otherVector,result){result.x=this.x-otherVector.x;result.y=this.y-otherVector.y;result.z=this.z-otherVector.z;};BABYLON.Vector3.prototype.subtractFromFloats=function(x,y,z){return new BABYLON.Vector3(this.x-x,this.y-y,this.z-z);};BABYLON.Vector3.prototype.subtractFromFloatsToRef=function(x,y,z,result){result.x=this.x-x;result.y=this.y-y;result.z=this.z-z;};BABYLON.Vector3.prototype.negate=function(){return new BABYLON.Vector3(-this.x,-this.y,-this.z);};BABYLON.Vector3.prototype.scaleInPlace=function(scale){this.x*=scale;this.y*=scale;this.z*=scale;};BABYLON.Vector3.prototype.scale=function(scale){return new BABYLON.Vector3(this.x*scale,this.y*scale,this.z*scale);};BABYLON.Vector3.prototype.scaleToRef=function(scale,result){result.x=this.x*scale;result.y=this.y*scale;result.z=this.z*scale;};BABYLON.Vector3.prototype.equals=function(otherVector){return this.x===otherVector.x&&this.y===otherVector.y&&this.z===otherVector.z;};BABYLON.Vector3.prototype.equalsToFloats=function(x,y,z){return this.x===x&&this.y===y&&this.z===z;};BABYLON.Vector3.prototype.multiplyInPlace=function(otherVector){this.x*=otherVector.x;this.y*=otherVector.y;this.z*=otherVector.z;};BABYLON.Vector3.prototype.multiply=function(otherVector){return new BABYLON.Vector3(this.x*otherVector.x,this.y*otherVector.y,this.z*otherVector.z);};BABYLON.Vector3.prototype.multiplyToRef=function(otherVector,result){result.x=this.x*otherVector.x;result.y=this.y*otherVector.y;result.z=this.z*otherVector.z;};BABYLON.Vector3.prototype.multiplyByFloats=function(x,y,z){return new BABYLON.Vector3(this.x*x,this.y*y,this.z*z);};BABYLON.Vector3.prototype.divide=function(otherVector){return new BABYLON.Vector3(this.x/otherVector.x,this.y/otherVector.y,this.z/otherVector.z);};BABYLON.Vector3.prototype.divideToRef=function(otherVector,result){result.x=this.x/otherVector.x;result.y=this.y/otherVector.y;result.z=this.z/otherVector.z;};BABYLON.Vector3.prototype.length=function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z);};BABYLON.Vector3.prototype.lengthSquared=function(){return(this.x*this.x+this.y*this.y+this.z*this.z);};BABYLON.Vector3.prototype.normalize=function(){var len=this.length();if(len===0)return;var num=1.0/len;this.x*=num;this.y*=num;this.z*=num;};BABYLON.Vector3.prototype.clone=function(){return new BABYLON.Vector3(this.x,this.y,this.z);};BABYLON.Vector3.prototype.copyFrom=function(source){this.x=source.x;this.y=source.y;this.z=source.z;};BABYLON.Vector3.prototype.copyFromFloats=function(x,y,z){this.x=x;this.y=y;this.z=z;};BABYLON.Vector3.FromArray=function(array,offset){if(!offset){offset=0;}return new BABYLON.Vector3(array[offset],array[offset+1],array[offset+2]);};BABYLON.Vector3.FromArrayToRef=function(array,offset,result){if(!offset){offset=0;}result.x=array[offset];result.y=array[offset+1];result.z=array[offset+2];};BABYLON.Vector3.FromFloatsToRef=function(x,y,z,result){result.x=x;result.y=y;result.z=z;};BABYLON.Vector3.Zero=function(){return new BABYLON.Vector3(0,0,0);};BABYLON.Vector3.Up=function(){return new BABYLON.Vector3(0,1.0,0);};BABYLON.Vector3.TransformCoordinates=function(vector,transformation){var result=BABYLON.Vector3.Zero();BABYLON.Vector3.TransformCoordinatesToRef(vector,transformation,result);return result;};BABYLON.Vector3.TransformCoordinatesToRef=function(vector,transformation,result){var x=(vector.x*transformation.m[0])+(vector.y*transformation.m[4])+(vector.z*transformation.m[8])+transformation.m[12];var y=(vector.x*transformation.m[1])+(vector.y*transformation.m[5])+(vector.z*transformation.m[9])+transformation.m[13];var z=(vector.x*transformation.m[2])+(vector.y*transformation.m[6])+(vector.z*transformation.m[10])+transformation.m[14];var w=(vector.x*transformation.m[3])+(vector.y*transformation.m[7])+(vector.z*transformation.m[11])+transformation.m[15];result.x=x/w;result.y=y/w;result.z=z/w;};BABYLON.Vector3.TransformCoordinatesFromFloatsToRef=function(x,y,z,transformation,result){var rx=(x*transformation.m[0])+(y*transformation.m[4])+(z*transformation.m[8])+transformation.m[12];var ry=(x*transformation.m[1])+(y*transformation.m[5])+(z*transformation.m[9])+transformation.m[13];var rz=(x*transformation.m[2])+(y*transformation.m[6])+(z*transformation.m[10])+transformation.m[14];var rw=(x*transformation.m[3])+(y*transformation.m[7])+(z*transformation.m[11])+transformation.m[15];result.x=rx/rw;result.y=ry/rw;result.z=rz/rw;};BABYLON.Vector3.TransformNormal=function(vector,transformation){var result=BABYLON.Vector3.Zero();BABYLON.Vector3.TransformNormalToRef(vector,transformation,result);return result;};BABYLON.Vector3.TransformNormalToRef=function(vector,transformation,result){result.x=(vector.x*transformation.m[0])+(vector.y*transformation.m[4])+(vector.z*transformation.m[8]);result.y=(vector.x*transformation.m[1])+(vector.y*transformation.m[5])+(vector.z*transformation.m[9]);result.z=(vector.x*transformation.m[2])+(vector.y*transformation.m[6])+(vector.z*transformation.m[10]);};BABYLON.Vector3.TransformNormalFromFloatsToRef=function(x,y,z,transformation,result){result.x=(x*transformation.m[0])+(y*transformation.m[4])+(z*transformation.m[8]);result.y=(x*transformation.m[1])+(y*transformation.m[5])+(z*transformation.m[9]);result.z=(x*transformation.m[2])+(y*transformation.m[6])+(z*transformation.m[10]);};BABYLON.Vector3.CatmullRom=function(value1,value2,value3,value4,amount){var squared=amount*amount;var cubed=amount*squared;var x=0.5*((((2.0*value2.x)+((-value1.x+value3.x)*amount))+(((((2.0*value1.x)-(5.0*value2.x))+(4.0*value3.x))-value4.x)*squared))+((((-value1.x+(3.0*value2.x))-(3.0*value3.x))+value4.x)*cubed));var y=0.5*((((2.0*value2.y)+((-value1.y+value3.y)*amount))+(((((2.0*value1.y)-(5.0*value2.y))+(4.0*value3.y))-value4.y)*squared))+((((-value1.y+(3.0*value2.y))-(3.0*value3.y))+value4.y)*cubed));var z=0.5*((((2.0*value2.z)+((-value1.z+value3.z)*amount))+(((((2.0*value1.z)-(5.0*value2.z))+(4.0*value3.z))-value4.z)*squared))+((((-value1.z+(3.0*value2.z))-(3.0*value3.z))+value4.z)*cubed));return new BABYLON.Vector3(x,y,z);};BABYLON.Vector3.Clamp=function(value,min,max){var x=value.x;x=(x>max.x)?max.x:x;x=(xmax.y)?max.y:y;y=(ymax.z)?max.z:z;z=(zright.x)?left.x:right.x;var y=(left.y>right.y)?left.y:right.y;var z=(left.z>right.z)?left.z:right.z;return new BABYLON.Vector3(x,y,z);};BABYLON.Vector3.Distance=function(value1,value2){return Math.sqrt(BABYLON.Vector3.DistanceSquared(value1,value2));};BABYLON.Vector3.DistanceSquared=function(value1,value2){var x=value1.x-value2.x;var y=value1.y-value2.y;var z=value1.z-value2.z;return(x*x)+(y*y)+(z*z);};BABYLON.Quaternion=function(initialX,initialY,initialZ,initialW){this.x=initialX;this.y=initialY;this.z=initialZ;this.w=initialW;};BABYLON.Quaternion.prototype.toString=function(){return"{X: "+this.x+" Y:"+this.y+" Z:"+this.z+" W:"+this.w+"}";};BABYLON.Quaternion.prototype.equals=function(otherQuaternion){return this.x===otherQuaternion.x&&this.y===otherQuaternion.y&&this.z===otherQuaternion.z&&this.w===otherQuaternion.w;};BABYLON.Quaternion.prototype.clone=function(){return new BABYLON.Quaternion(this.x,this.y,this.z,this.w);};BABYLON.Quaternion.prototype.copyFrom=function(other){this.x=other.x;this.y=other.y;this.z=other.z;this.w=other.w;};BABYLON.Quaternion.prototype.add=function(other){return new BABYLON.Quaternion(this.x+other.x,this.y+other.y,this.z+other.z,this.w+other.w);};BABYLON.Quaternion.prototype.scale=function(value){return new BABYLON.Quaternion(this.x*value,this.y*value,this.z*value,this.w*value);};BABYLON.Quaternion.prototype.multiply=function(q1){var result=new BABYLON.Quaternion(0,0,0,1.0);this.multiplyToRef(q1,result);return result;};BABYLON.Quaternion.prototype.multiplyToRef=function(q1,result){result.x=this.x*q1.w+this.y*q1.z-this.z*q1.y+this.w*q1.x;result.y=-this.x*q1.z+this.y*q1.w+this.z*q1.x+this.w*q1.y;result.z=this.x*q1.y-this.y*q1.x+this.z*q1.w+this.w*q1.z;result.w=-this.x*q1.x-this.y*q1.y-this.z*q1.z+this.w*q1.w;};BABYLON.Quaternion.prototype.length=function(){return Math.sqrt((this.x*this.x)+(this.y*this.y)+(this.z*this.z)+(this.w*this.w));};BABYLON.Quaternion.prototype.normalize=function(){var length=1.0/this.length();this.x*=length;this.y*=length;this.z*=length;this.w*=length;};BABYLON.Quaternion.prototype.toEulerAngles=function(){var qx=this.x;var qy=this.y;var qz=this.z;var qw=this.w;var sqx=qx*qx;var sqy=qy*qy;var sqz=qz*qz;var yaw=Math.atan2(2.0*(qy*qw-qx*qz),1.0-2.0*(sqy+sqz));var pitch=Math.asin(2.0*(qx*qy+qz*qw));var roll=Math.atan2(2.0*(qx*qw-qy*qz),1.0-2.0*(sqx+sqz));var gimbaLockTest=qx*qy+qz*qw;if(gimbaLockTest>0.499){yaw=2.0*Math.atan2(qx,qw);roll=0;}else if(gimbaLockTest<-0.499){yaw=-2.0*Math.atan2(qx,qw);roll=0;}return new BABYLON.Vector3(pitch,yaw,roll);};BABYLON.Quaternion.prototype.toRotationMatrix=function(result){var xx=this.x*this.x;var yy=this.y*this.y;var zz=this.z*this.z;var xy=this.x*this.y;var zw=this.z*this.w;var zx=this.z*this.x;var yw=this.y*this.w;var yz=this.y*this.z;var xw=this.x*this.w;result.m[0]=1.0-(2.0*(yy+zz));result.m[1]=2.0*(xy+zw);result.m[2]=2.0*(zx-yw);result.m[3]=0;result.m[4]=2.0*(xy-zw);result.m[5]=1.0-(2.0*(zz+xx));result.m[6]=2.0*(yz+xw);result.m[7]=0;result.m[8]=2.0*(zx+yw);result.m[9]=2.0*(yz-xw);result.m[10]=1.0-(2.0*(yy+xx));result.m[11]=0;result.m[12]=0;result.m[13]=0;result.m[14]=0;result.m[15]=1.0;};BABYLON.Quaternion.FromArray=function(array,offset){if(!offset){offset=0;}return new BABYLON.Quaternion(array[offset],array[offset+1],array[offset+2],array[offset+3]);};BABYLON.Quaternion.RotationYawPitchRoll=function(yaw,pitch,roll){var result=new BABYLON.Quaternion();BABYLON.Quaternion.RotationYawPitchRollToRef(yaw,pitch,roll,result);return result;};BABYLON.Quaternion.RotationYawPitchRollToRef=function(yaw,pitch,roll,result){var halfRoll=roll*0.5;var halfPitch=pitch*0.5;var halfYaw=yaw*0.5;var sinRoll=Math.sin(halfRoll);var cosRoll=Math.cos(halfRoll);var sinPitch=Math.sin(halfPitch);var cosPitch=Math.cos(halfPitch);var sinYaw=Math.sin(halfYaw);var cosYaw=Math.cos(halfYaw);result.x=(cosYaw*sinPitch*cosRoll)+(sinYaw*cosPitch*sinRoll);result.y=(sinYaw*cosPitch*cosRoll)-(cosYaw*sinPitch*sinRoll);result.z=(cosYaw*cosPitch*sinRoll)-(sinYaw*sinPitch*cosRoll);result.w=(cosYaw*cosPitch*cosRoll)+(sinYaw*sinPitch*sinRoll);};BABYLON.Quaternion.Slerp=function(left,right,amount){var num2;var num3;var num=amount;var num4=(((left.x*right.x)+(left.y*right.y))+(left.z*right.z))+(left.w*right.w);var flag=false;if(num4<0){flag=true;num4=-num4;}if(num4>0.999999){num3=1-num;num2=flag?-num:num;}else{var num5=Math.acos(num4);var num6=(1.0/Math.sin(num5));num3=(Math.sin((1.0-num)*num5))*num6;num2=flag?((-Math.sin(num*num5))*num6):((Math.sin(num*num5))*num6);}return new BABYLON.Quaternion((num3*left.x)+(num2*right.x),(num3*left.y)+(num2*right.y),(num3*left.z)+(num2*right.z),(num3*left.w)+(num2*right.w));};if(!BABYLON.MatrixType){BABYLON.MatrixType=(typeof Float32Array!=='undefined')?Float32Array:Array;}BABYLON.Matrix=function(){this.m=new BABYLON.MatrixType(16);};BABYLON.Matrix.prototype.isIdentity=function(){if(this.m[0]!=1.0||this.m[5]!=1.0||this.m[10]!=1.0||this.m[15]!=1.0)return false;if(this.m[1]!=0.0||this.m[2]!=0.0||this.m[3]!=0.0||this.m[4]!=0.0||this.m[6]!=0.0||this.m[7]!=0.0||this.m[8]!=0.0||this.m[9]!=0.0||this.m[11]!=0.0||this.m[12]!=0.0||this.m[13]!=0.0||this.m[14]!=0.0)return false;return true;};BABYLON.Matrix.prototype.determinant=function(){var temp1=(this.m[10]*this.m[15])-(this.m[11]*this.m[14]);var temp2=(this.m[9]*this.m[15])-(this.m[11]*this.m[13]);var temp3=(this.m[9]*this.m[14])-(this.m[10]*this.m[13]);var temp4=(this.m[8]*this.m[15])-(this.m[11]*this.m[12]);var temp5=(this.m[8]*this.m[14])-(this.m[10]*this.m[12]);var temp6=(this.m[8]*this.m[13])-(this.m[9]*this.m[12]);return((((this.m[0]*(((this.m[5]*temp1)-(this.m[6]*temp2))+(this.m[7]*temp3)))-(this.m[1]*(((this.m[4]*temp1)-(this.m[6]*temp4))+(this.m[7]*temp5))))+(this.m[2]*(((this.m[4]*temp2)-(this.m[5]*temp4))+(this.m[7]*temp6))))-(this.m[3]*(((this.m[4]*temp3)-(this.m[5]*temp5))+(this.m[6]*temp6))));};BABYLON.Matrix.prototype.toArray=function(){return this.m;};BABYLON.Matrix.prototype.invert=function(){this.invertToRef(this);};BABYLON.Matrix.prototype.invertToRef=function(other){var l1=this.m[0];var l2=this.m[1];var l3=this.m[2];var l4=this.m[3];var l5=this.m[4];var l6=this.m[5];var l7=this.m[6];var l8=this.m[7];var l9=this.m[8];var l10=this.m[9];var l11=this.m[10];var l12=this.m[11];var l13=this.m[12];var l14=this.m[13];var l15=this.m[14];var l16=this.m[15];var l17=(l11*l16)-(l12*l15);var l18=(l10*l16)-(l12*l14);var l19=(l10*l15)-(l11*l14);var l20=(l9*l16)-(l12*l13);var l21=(l9*l15)-(l11*l13);var l22=(l9*l14)-(l10*l13);var l23=((l6*l17)-(l7*l18))+(l8*l19);var l24=-(((l5*l17)-(l7*l20))+(l8*l21));var l25=((l5*l18)-(l6*l20))+(l8*l22);var l26=-(((l5*l19)-(l6*l21))+(l7*l22));var l27=1.0/((((l1*l23)+(l2*l24))+(l3*l25))+(l4*l26));var l28=(l7*l16)-(l8*l15);var l29=(l6*l16)-(l8*l14);var l30=(l6*l15)-(l7*l14);var l31=(l5*l16)-(l8*l13);var l32=(l5*l15)-(l7*l13);var l33=(l5*l14)-(l6*l13);var l34=(l7*l12)-(l8*l11);var l35=(l6*l12)-(l8*l10);var l36=(l6*l11)-(l7*l10);var l37=(l5*l12)-(l8*l9);var l38=(l5*l11)-(l7*l9);var l39=(l5*l10)-(l6*l9);other.m[0]=l23*l27;other.m[4]=l24*l27;other.m[8]=l25*l27;other.m[12]=l26*l27;other.m[1]=-(((l2*l17)-(l3*l18))+(l4*l19))*l27;other.m[5]=(((l1*l17)-(l3*l20))+(l4*l21))*l27;other.m[9]=-(((l1*l18)-(l2*l20))+(l4*l22))*l27;other.m[13]=(((l1*l19)-(l2*l21))+(l3*l22))*l27;other.m[2]=(((l2*l28)-(l3*l29))+(l4*l30))*l27;other.m[6]=-(((l1*l28)-(l3*l31))+(l4*l32))*l27;other.m[10]=(((l1*l29)-(l2*l31))+(l4*l33))*l27;other.m[14]=-(((l1*l30)-(l2*l32))+(l3*l33))*l27;other.m[3]=-(((l2*l34)-(l3*l35))+(l4*l36))*l27;other.m[7]=(((l1*l34)-(l3*l37))+(l4*l38))*l27;other.m[11]=-(((l1*l35)-(l2*l37))+(l4*l39))*l27;other.m[15]=(((l1*l36)-(l2*l38))+(l3*l39))*l27;};BABYLON.Matrix.prototype.setTranslation=function(vector3){this.m[12]=vector3.x;this.m[13]=vector3.y;this.m[14]=vector3.z;};BABYLON.Matrix.prototype.multiply=function(other){var result=new BABYLON.Matrix();this.multiplyToRef(other,result);return result;};BABYLON.Matrix.prototype.copyFrom=function(other){for(var index=0;index<16;index++){this.m[index]=other.m[index];}};BABYLON.Matrix.prototype.multiplyToRef=function(other,result){this.multiplyToArray(other,result.m,0);};BABYLON.Matrix.prototype.multiplyToArray=function(other,result,offset){result[offset]=this.m[0]*other.m[0]+this.m[1]*other.m[4]+this.m[2]*other.m[8]+this.m[3]*other.m[12];result[offset+1]=this.m[0]*other.m[1]+this.m[1]*other.m[5]+this.m[2]*other.m[9]+this.m[3]*other.m[13];result[offset+2]=this.m[0]*other.m[2]+this.m[1]*other.m[6]+this.m[2]*other.m[10]+this.m[3]*other.m[14];result[offset+3]=this.m[0]*other.m[3]+this.m[1]*other.m[7]+this.m[2]*other.m[11]+this.m[3]*other.m[15];result[offset+4]=this.m[4]*other.m[0]+this.m[5]*other.m[4]+this.m[6]*other.m[8]+this.m[7]*other.m[12];result[offset+5]=this.m[4]*other.m[1]+this.m[5]*other.m[5]+this.m[6]*other.m[9]+this.m[7]*other.m[13];result[offset+6]=this.m[4]*other.m[2]+this.m[5]*other.m[6]+this.m[6]*other.m[10]+this.m[7]*other.m[14];result[offset+7]=this.m[4]*other.m[3]+this.m[5]*other.m[7]+this.m[6]*other.m[11]+this.m[7]*other.m[15];result[offset+8]=this.m[8]*other.m[0]+this.m[9]*other.m[4]+this.m[10]*other.m[8]+this.m[11]*other.m[12];result[offset+9]=this.m[8]*other.m[1]+this.m[9]*other.m[5]+this.m[10]*other.m[9]+this.m[11]*other.m[13];result[offset+10]=this.m[8]*other.m[2]+this.m[9]*other.m[6]+this.m[10]*other.m[10]+this.m[11]*other.m[14];result[offset+11]=this.m[8]*other.m[3]+this.m[9]*other.m[7]+this.m[10]*other.m[11]+this.m[11]*other.m[15];result[offset+12]=this.m[12]*other.m[0]+this.m[13]*other.m[4]+this.m[14]*other.m[8]+this.m[15]*other.m[12];result[offset+13]=this.m[12]*other.m[1]+this.m[13]*other.m[5]+this.m[14]*other.m[9]+this.m[15]*other.m[13];result[offset+14]=this.m[12]*other.m[2]+this.m[13]*other.m[6]+this.m[14]*other.m[10]+this.m[15]*other.m[14];result[offset+15]=this.m[12]*other.m[3]+this.m[13]*other.m[7]+this.m[14]*other.m[11]+this.m[15]*other.m[15];};BABYLON.Matrix.prototype.equals=function(value){return(this.m[0]===value.m[0]&&this.m[1]===value.m[1]&&this.m[2]===value.m[2]&&this.m[3]===value.m[3]&&this.m[4]===value.m[4]&&this.m[5]===value.m[5]&&this.m[6]===value.m[6]&&this.m[7]===value.m[7]&&this.m[8]===value.m[8]&&this.m[9]===value.m[9]&&this.m[10]===value.m[10]&&this.m[11]===value.m[11]&&this.m[12]===value.m[12]&&this.m[13]===value.m[13]&&this.m[14]===value.m[14]&&this.m[15]===value.m[15]);};BABYLON.Matrix.prototype.clone=function(){return BABYLON.Matrix.FromValues(this.m[0],this.m[1],this.m[2],this.m[3],this.m[4],this.m[5],this.m[6],this.m[7],this.m[8],this.m[9],this.m[10],this.m[11],this.m[12],this.m[13],this.m[14],this.m[15]);};BABYLON.Matrix.FromArray=function(array,offset){var result=new BABYLON.Matrix();BABYLON.Matrix.FromArrayToRef(array,offset,result);return result;};BABYLON.Matrix.FromArrayToRef=function(array,offset,result){if(!offset){offset=0;}for(var index=0;index<16;index++){result.m[index]=array[index+offset];}};BABYLON.Matrix.FromValuesToRef=function(initialM11,initialM12,initialM13,initialM14,initialM21,initialM22,initialM23,initialM24,initialM31,initialM32,initialM33,initialM34,initialM41,initialM42,initialM43,initialM44,result){result.m[0]=initialM11;result.m[1]=initialM12;result.m[2]=initialM13;result.m[3]=initialM14;result.m[4]=initialM21;result.m[5]=initialM22;result.m[6]=initialM23;result.m[7]=initialM24;result.m[8]=initialM31;result.m[9]=initialM32;result.m[10]=initialM33;result.m[11]=initialM34;result.m[12]=initialM41;result.m[13]=initialM42;result.m[14]=initialM43;result.m[15]=initialM44;};BABYLON.Matrix.FromValues=function(initialM11,initialM12,initialM13,initialM14,initialM21,initialM22,initialM23,initialM24,initialM31,initialM32,initialM33,initialM34,initialM41,initialM42,initialM43,initialM44){var result=new BABYLON.Matrix();result.m[0]=initialM11;result.m[1]=initialM12;result.m[2]=initialM13;result.m[3]=initialM14;result.m[4]=initialM21;result.m[5]=initialM22;result.m[6]=initialM23;result.m[7]=initialM24;result.m[8]=initialM31;result.m[9]=initialM32;result.m[10]=initialM33;result.m[11]=initialM34;result.m[12]=initialM41;result.m[13]=initialM42;result.m[14]=initialM43;result.m[15]=initialM44;return result;};BABYLON.Matrix.Identity=function(){return BABYLON.Matrix.FromValues(1.0,0,0,0,0,1.0,0,0,0,0,1.0,0,0,0,0,1.0);};BABYLON.Matrix.IdentityToRef=function(result){BABYLON.Matrix.FromValuesToRef(1.0,0,0,0,0,1.0,0,0,0,0,1.0,0,0,0,0,1.0,result);};BABYLON.Matrix.Zero=function(){return BABYLON.Matrix.FromValues(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);};BABYLON.Matrix.RotationX=function(angle){var result=new BABYLON.Matrix();BABYLON.Matrix.RotationXToRef(angle,result);return result;};BABYLON.Matrix.RotationXToRef=function(angle,result){var s=Math.sin(angle);var c=Math.cos(angle);result.m[0]=1.0;result.m[15]=1.0;result.m[5]=c;result.m[10]=c;result.m[9]=-s;result.m[6]=s;result.m[1]=0;result.m[2]=0;result.m[3]=0;result.m[4]=0;result.m[7]=0;result.m[8]=0;result.m[11]=0;result.m[12]=0;result.m[13]=0;result.m[14]=0;};BABYLON.Matrix.RotationY=function(angle){var result=new BABYLON.Matrix();BABYLON.Matrix.RotationYToRef(angle,result);return result;};BABYLON.Matrix.RotationYToRef=function(angle,result){var s=Math.sin(angle);var c=Math.cos(angle);result.m[5]=1.0;result.m[15]=1.0;result.m[0]=c;result.m[2]=-s;result.m[8]=s;result.m[10]=c;result.m[1]=0;result.m[3]=0;result.m[4]=0;result.m[6]=0;result.m[7]=0;result.m[9]=0;result.m[11]=0;result.m[12]=0;result.m[13]=0;result.m[14]=0;};BABYLON.Matrix.RotationZ=function(angle){var result=new BABYLON.Matrix();BABYLON.Matrix.RotationZToRef(angle,result);return result;};BABYLON.Matrix.RotationZToRef=function(angle,result){var s=Math.sin(angle);var c=Math.cos(angle);result.m[10]=1.0;result.m[15]=1.0;result.m[0]=c;result.m[1]=s;result.m[4]=-s;result.m[5]=c;result.m[2]=0;result.m[3]=0;result.m[6]=0;result.m[7]=0;result.m[8]=0;result.m[9]=0;result.m[11]=0;result.m[12]=0;result.m[13]=0;result.m[14]=0;};BABYLON.Matrix.RotationAxis=function(axis,angle){var s=Math.sin(-angle);var c=Math.cos(-angle);var c1=1-c;axis.normalize();var result=BABYLON.Matrix.Zero();result.m[0]=(axis.x*axis.x)*c1+c;result.m[1]=(axis.x*axis.y)*c1-(axis.z*s);result.m[2]=(axis.x*axis.z)*c1+(axis.y*s);result.m[3]=0.0;result.m[4]=(axis.y*axis.x)*c1+(axis.z*s);result.m[5]=(axis.y*axis.y)*c1+c;result.m[6]=(axis.y*axis.z)*c1-(axis.x*s);result.m[7]=0.0;result.m[8]=(axis.z*axis.x)*c1-(axis.y*s);result.m[9]=(axis.z*axis.y)*c1+(axis.x*s);result.m[10]=(axis.z*axis.z)*c1+c;result.m[11]=0.0;result.m[15]=1.0;return result;};BABYLON.Matrix.RotationYawPitchRoll=function(yaw,pitch,roll){var result=new BABYLON.Matrix();BABYLON.Matrix.RotationYawPitchRollToRef(yaw,pitch,roll,result);return result;};var tempQuaternion=new BABYLON.Quaternion();BABYLON.Matrix.RotationYawPitchRollToRef=function(yaw,pitch,roll,result){BABYLON.Quaternion.RotationYawPitchRollToRef(yaw,pitch,roll,tempQuaternion);tempQuaternion.toRotationMatrix(result);};BABYLON.Matrix.Scaling=function(x,y,z){var result=BABYLON.Matrix.Zero();BABYLON.Matrix.ScalingToRef(x,y,z,result);return result;};BABYLON.Matrix.ScalingToRef=function(x,y,z,result){result.m[0]=x;result.m[1]=0;result.m[2]=0;result.m[3]=0;result.m[4]=0;result.m[5]=y;result.m[6]=0;result.m[7]=0;result.m[8]=0;result.m[9]=0;result.m[10]=z;result.m[11]=0;result.m[12]=0;result.m[13]=0;result.m[14]=0;result.m[15]=1.0;};BABYLON.Matrix.Translation=function(x,y,z){var result=BABYLON.Matrix.Identity();BABYLON.Matrix.TranslationToRef(x,y,z,result);return result;};BABYLON.Matrix.TranslationToRef=function(x,y,z,result){BABYLON.Matrix.FromValuesToRef(1.0,0,0,0,0,1.0,0,0,0,0,1.0,0,x,y,z,1.0,result);};BABYLON.Matrix.LookAtLH=function(eye,target,up){var result=BABYLON.Matrix.Zero();BABYLON.Matrix.LookAtLHToRef(eye,target,up,result);return result;};var xAxis=BABYLON.Vector3.Zero();var yAxis=BABYLON.Vector3.Zero();var zAxis=BABYLON.Vector3.Zero();BABYLON.Matrix.LookAtLHToRef=function(eye,target,up,result){target.subtractToRef(eye,zAxis);zAxis.normalize();BABYLON.Vector3.CrossToRef(up,zAxis,xAxis);xAxis.normalize();BABYLON.Vector3.CrossToRef(zAxis,xAxis,yAxis);yAxis.normalize();var ex=-BABYLON.Vector3.Dot(xAxis,eye);var ey=-BABYLON.Vector3.Dot(yAxis,eye);var ez=-BABYLON.Vector3.Dot(zAxis,eye);return BABYLON.Matrix.FromValuesToRef(xAxis.x,yAxis.x,zAxis.x,0,xAxis.y,yAxis.y,zAxis.y,0,xAxis.z,yAxis.z,zAxis.z,0,ex,ey,ez,1,result);};BABYLON.Matrix.OrthoLH=function(width,height,znear,zfar){var hw=2.0/width;var hh=2.0/height;var id=1.0/(zfar-znear);var nid=znear/(znear-zfar);return BABYLON.Matrix.FromValues(hw,0,0,0,0,hh,0,0,0,0,id,0,0,0,nid,1);};BABYLON.Matrix.OrthoOffCenterLH=function(left,right,bottom,top,znear,zfar){var matrix=BABYLON.Matrix.Zero();BABYLON.Matrix.OrthoOffCenterLHToRef(left,right,bottom,top,znear,zfar,matrix);return matrix;};BABYLON.Matrix.OrthoOffCenterLHToRef=function(left,right,bottom,top,znear,zfar,result){result.m[0]=2.0/(right-left);result.m[1]=result.m[2]=result.m[3]=0;result.m[5]=2.0/(top-bottom);result.m[4]=result.m[6]=result.m[7]=0;result.m[10]=-1.0/(znear-zfar);result.m[8]=result.m[9]=result.m[11]=0;result.m[12]=(left+right)/(left-right);result.m[13]=(top+bottom)/(bottom-top);result.m[14]=znear/(znear-zfar);result.m[15]=1.0;};BABYLON.Matrix.PerspectiveLH=function(width,height,znear,zfar){var matrix=BABYLON.Matrix.Zero();matrix.m[0]=(2.0*znear)/width;matrix.m[1]=matrix.m[2]=matrix.m[3]=0.0;matrix.m[5]=(2.0*znear)/height;matrix.m[4]=matrix.m[6]=matrix.m[7]=0.0;matrix.m[10]=-zfar/(znear-zfar);matrix.m[8]=matrix.m[9]=0.0;matrix.m[11]=1.0;matrix.m[12]=matrix.m[13]=matrix.m[15]=0.0;matrix.m[14]=(znear*zfar)/(znear-zfar);return matrix;};BABYLON.Matrix.PerspectiveFovLH=function(fov,aspect,znear,zfar){var matrix=BABYLON.Matrix.Zero();BABYLON.Matrix.PerspectiveFovLHToRef(fov,aspect,znear,zfar,matrix);return matrix;};BABYLON.Matrix.PerspectiveFovLHToRef=function(fov,aspect,znear,zfar,result){var tan=1.0/(Math.tan(fov*0.5));result.m[0]=tan/aspect;result.m[1]=result.m[2]=result.m[3]=0.0;result.m[5]=tan;result.m[4]=result.m[6]=result.m[7]=0.0;result.m[8]=result.m[9]=0.0;result.m[10]=-zfar/(znear-zfar);result.m[11]=1.0;result.m[12]=result.m[13]=result.m[15]=0.0;result.m[14]=(znear*zfar)/(znear-zfar);};BABYLON.Matrix.AffineTransformation=function(scaling,rotationCenter,rotation,translation){return BABYLON.Matrix.Scaling(scaling,scaling,scaling)*BABYLON.Matrix.Translation(-rotationCenter)*BABYLON.Matrix.RotationQuaternion(rotation)*BABYLON.Matrix.Translation(rotationCenter)*BABYLON.Matrix.Translation(translation);};BABYLON.Matrix.GetFinalMatrix=function(viewport,world,view,projection,zmin,zmax){var cw=viewport.width;var ch=viewport.height;var cx=viewport.x;var cy=viewport.y;var viewportMatrix=new BABYLON.Matrix(cw/2.0,0,0,0,0,-ch/2.0,0,0,0,0,zmax-zmin,0,cx+cw/2.0,ch/2.0+cy,zmin,1);return world.multiply(view).multiply(projection).multiply(viewportMatrix);};BABYLON.Matrix.Transpose=function(matrix){var result=new BABYLON.Matrix();result.m[0]=matrix.m[0];result.m[1]=matrix.m[4];result.m[2]=matrix.m[8];result.m[3]=matrix.m[12];result.m[4]=matrix.m[1];result.m[5]=matrix.m[5];result.m[6]=matrix.m[9];result.m[7]=matrix.m[13];result.m[8]=matrix.m[2];result.m[9]=matrix.m[6];result.m[10]=matrix.m[10];result.m[11]=matrix.m[14];result.m[12]=matrix.m[3];result.m[13]=matrix.m[7];result.m[14]=matrix.m[11];result.m[15]=matrix.m[15];return result;};BABYLON.Matrix.Reflection=function(plane){var matrix=new BABYLON.Matrix();BABYLON.Matrix.ReflectionToRef(plane,matrix);return matrix;};BABYLON.Matrix.ReflectionToRef=function(plane,result){plane.normalize();var x=plane.normal.x;var y=plane.normal.y;var z=plane.normal.z;var temp=-2*x;var temp2=-2*y;var temp3=-2*z;result.m[0]=(temp*x)+1;result.m[1]=temp2*x;result.m[2]=temp3*x;result.m[3]=0.0;result.m[4]=temp*y;result.m[5]=(temp2*y)+1;result.m[6]=temp3*y;result.m[7]=0.0;result.m[8]=temp*z;result.m[9]=temp2*z;result.m[10]=(temp3*z)+1;result.m[11]=0.0;result.m[12]=temp*plane.d;result.m[13]=temp2*plane.d;result.m[14]=temp3*plane.d;result.m[15]=1.0;};BABYLON.Plane=function(a,b,c,d){this.normal=new BABYLON.Vector3(a,b,c);this.d=d;};BABYLON.Plane.prototype.normalize=function(){var norm=(Math.sqrt((this.normal.x*this.normal.x)+(this.normal.y*this.normal.y)+(this.normal.z*this.normal.z)));var magnitude=0;if(norm!=0){magnitude=1.0/norm;}this.normal.x*=magnitude;this.normal.y*=magnitude;this.normal.z*=magnitude;this.d*=magnitude;};BABYLON.Plane.prototype.transform=function(transformation){var transposedMatrix=BABYLON.Matrix.Transpose(transformation);var x=this.normal.x;var y=this.normal.y;var z=this.normal.z;var d=this.d;var normalX=(((x*transposedMatrix.m[0])+(y*transposedMatrix.m[1]))+(z*transposedMatrix.m[2]))+(d*transposedMatrix.m[3]);var normalY=(((x*transposedMatrix.m[4])+(y*transposedMatrix.m[5]))+(z*transposedMatrix.m[6]))+(d*transposedMatrix.m[7]);var normalZ=(((x*transposedMatrix.m[8])+(y*transposedMatrix.m[9]))+(z*transposedMatrix.m[10]))+(d*transposedMatrix.m[11]);var finalD=(((x*transposedMatrix.m[12])+(y*transposedMatrix.m[13]))+(z*transposedMatrix.m[14]))+(d*transposedMatrix.m[15]);return new BABYLON.Plane(normalX,normalY,normalZ,finalD);};BABYLON.Plane.prototype.dotCoordinate=function(point){return((((this.normal.x*point.x)+(this.normal.y*point.y))+(this.normal.z*point.z))+this.d);};BABYLON.Plane.prototype.copyFromPoints=function(point1,point2,point3){var x1=point2.x-point1.x;var y1=point2.y-point1.y;var z1=point2.z-point1.z;var x2=point3.x-point1.x;var y2=point3.y-point1.y;var z2=point3.z-point1.z;var yz=(y1*z2)-(z1*y2);var xz=(z1*x2)-(x1*z2);var xy=(x1*y2)-(y1*x2);var pyth=(Math.sqrt((yz*yz)+(xz*xz)+(xy*xy)));var invPyth;if(pyth!=0)invPyth=1.0/pyth;elseinvPyth=0;this.normal.x=yz*invPyth;this.normal.y=xz*invPyth;this.normal.z=xy*invPyth;this.d=-((this.normal.x*point1.x)+(this.normal.y*point1.y)+(this.normal.z*point1.z));};BABYLON.Plane.prototype.isFrontFacingTo=function(direction,epsilon){var dot=BABYLON.Vector3.Dot(this.normal,direction);return(dot<=epsilon);};BABYLON.Plane.prototype.signedDistanceTo=function(point){return BABYLON.Vector3.Dot(point,this.normal)+this.d;};BABYLON.Plane.FromArray=function(array){return new BABYLON.Plane(array[0],array[1],array[2],array[3]);};BABYLON.Plane.FromPoints=function(point1,point2,point3){var result=new BABYLON.Plane(0,0,0,0);result.copyFromPoints(point1,point2,point3);return result;};BABYLON.Plane.FromPositionAndNormal=function(origin,normal){var result=new BABYLON.Plane(0,0,0,0);normal.normalize();result.normal=normal;result.d=-(normal.x*origin.x+normal.y*origin.y+normal.z*origin.z);return result;};BABYLON.Plane.SignedDistanceToPlaneFromPositionAndNormal=function(origin,normal,point){var d=-(normal.x*origin.x+normal.y*origin.y+normal.z*origin.z);return BABYLON.Vector3.Dot(point,normal)+d;};BABYLON.Frustum={};BABYLON.Frustum.GetPlanes=function(transform){var frustumPlanes=[];for(var index=0;index<6;index++){frustumPlanes.push(new BABYLON.Plane(0,0,0,0));}BABYLON.Frustum.GetPlanesToRef(transform,frustumPlanes);return frustumPlanes;};BABYLON.Frustum.GetPlanesToRef=function(transform,frustumPlanes){frustumPlanes[0].normal.x=transform.m[3]+transform.m[2];frustumPlanes[0].normal.y=transform.m[7]+transform.m[6];frustumPlanes[0].normal.z=transform.m[10]+transform.m[10];frustumPlanes[0].d=transform.m[15]+transform.m[14];frustumPlanes[0].normalize();frustumPlanes[1].normal.x=transform.m[3]-transform.m[2];frustumPlanes[1].normal.y=transform.m[7]-transform.m[6];frustumPlanes[1].normal.z=transform.m[11]-transform.m[10];frustumPlanes[1].d=transform.m[15]-transform.m[14];frustumPlanes[1].normalize();frustumPlanes[2].normal.x=transform.m[3]+transform.m[0];frustumPlanes[2].normal.y=transform.m[7]+transform.m[4];frustumPlanes[2].normal.z=transform.m[11]+transform.m[8];frustumPlanes[2].d=transform.m[15]+transform.m[12];frustumPlanes[2].normalize();frustumPlanes[3].normal.x=transform.m[3]-transform.m[0];frustumPlanes[3].normal.y=transform.m[7]-transform.m[4];frustumPlanes[3].normal.z=transform.m[11]-transform.m[8];frustumPlanes[3].d=transform.m[15]-transform.m[12];frustumPlanes[3].normalize();frustumPlanes[4].normal.x=transform.m[3]-transform.m[1];frustumPlanes[4].normal.y=transform.m[7]-transform.m[5];frustumPlanes[4].normal.z=transform.m[11]-transform.m[9];frustumPlanes[4].d=transform.m[15]-transform.m[13];frustumPlanes[4].normalize();frustumPlanes[5].normal.x=transform.m[3]+transform.m[1];frustumPlanes[5].normal.y=transform.m[7]+transform.m[5];frustumPlanes[5].normal.z=transform.m[11]+transform.m[9];frustumPlanes[5].d=transform.m[15]+transform.m[13];frustumPlanes[5].normalize();};BABYLON.Viewport={};BABYLON.Viewport=function(x,y,width,height){this.width=width;this.height=height;this.x=x;this.y=y;};BABYLON.Viewport.prototype.toGlobal=function(engine){var width=engine.getRenderWidth()*engine.getHardwareScalingLevel();var height=engine.getRenderHeight()*engine.getHardwareScalingLevel();return new BABYLON.Viewport(this.x*width,this.y*height,this.width*width,this.height*height);};})();var BABYLON=BABYLON||{};(function(){BABYLON.Tools={};BABYLON.Tools.ExtractMinAndMax=function(positions,start,count){var minimum=new BABYLON.Vector3(Number.MAX_VALUE,Number.MAX_VALUE,Number.MAX_VALUE);var maximum=new BABYLON.Vector3(-Number.MAX_VALUE,-Number.MAX_VALUE,-Number.MAX_VALUE);for(var index=start;indexthis.data.length){this.data.length*=2;}};BABYLON.Tools.SmartArray.prototype.pushNoDuplicate=function(value){if(this.indexOf(value)>-1){return;}this.push(value);};BABYLON.Tools.SmartArray.prototype.sort=function(compareFn){this.data.sort(compareFn);};BABYLON.Tools.SmartArray.prototype.reset=function(){this.length=0;};BABYLON.Tools.SmartArray.prototype.concat=function(array){if(array.length===0){return;}if(this.length+array.length>this.data.length){this.data.length=(this.length+array.length)*2;}for(var index=0;indexthis.data.length){this.data.length=(this.length+array.length)*2;}for(var index=0;index=this.length){this.data[this.length++]=item;}}};BABYLON.Tools.SmartArray.prototype.indexOf=function(value){var position=this.data.indexOf(value);if(position>=this.length){return-1;}return position;};BABYLON.Tools.GetPointerPrefix=function(){var eventPrefix="pointer";if(!navigator.pointerEnabled){eventPrefix="mouse";}return eventPrefix;};BABYLON.Tools.QueueNewFrame=function(func){if(window.requestAnimationFrame)window.requestAnimationFrame(func);else if(window.msRequestAnimationFrame)window.msRequestAnimationFrame(func);else if(window.webkitRequestAnimationFrame)window.webkitRequestAnimationFrame(func);else if(window.mozRequestAnimationFrame)window.mozRequestAnimationFrame(func);else if(window.oRequestAnimationFrame)window.oRequestAnimationFrame(func);else{window.setTimeout(func,16);}};BABYLON.Tools.RequestFullscreen=function(element){if(element.requestFullscreen)element.requestFullscreen();else if(element.msRequestFullscreen)element.msRequestFullscreen();else if(element.webkitRequestFullscreen)element.webkitRequestFullscreen();else if(element.mozRequestFullScreen)element.mozRequestFullScreen();};BABYLON.Tools.ExitFullscreen=function(){if(document.exitFullscreen){document.exitFullscreen();}else if(document.mozCancelFullScreen){document.mozCancelFullScreen();}else if(document.webkitCancelFullScreen){document.webkitCancelFullScreen();}else if(document.msCancelFullScreen){document.msCancelFullScreen();}};BABYLON.Tools.BaseUrl="";BABYLON.Tools.LoadImage=function(url,onload,onerror,database){var img=new Image();img.onload=function(){onload(img);};img.onerror=function(err){onerror(img,err);};var noIndexedDB=function(){img.src=url;};var loadFromIndexedDB=function(){database.loadImageFromDB(url,img);};if(database&&database.enableTexturesOffline&&BABYLON.Database.isUASupportingBlobStorage){database.openAsync(loadFromIndexedDB,noIndexedDB);}else{noIndexedDB();}return img;};BABYLON.Tools.LoadFile=function(url,callback,progressCallBack,database){var noIndexedDB=function(){var request=new XMLHttpRequest();var loadUrl=BABYLON.Tools.BaseUrl+url;request.open('GET',loadUrl,true);request.onprogress=progressCallBack;request.onreadystatechange=function(){if(request.readyState==4){if(request.status==200){callback(request.responseText);}else{throw new Error(request.status,"Unable to load "+loadUrl);}}};request.send(null);};var loadFromIndexedDB=function(){database.loadSceneFromDB(url,callback,progressCallBack,noIndexedDB);};if(database&&url.indexOf(".babylon")!==-1&&(database.enableSceneOffline)){database.openAsync(loadFromIndexedDB,noIndexedDB);}else{noIndexedDB();}};BABYLON.Tools.isIE=function(){return window.ActiveXObject!==undefined;};BABYLON.Tools.WithinEpsilon=function(a,b){var num=a-b;return-1.401298E-45<=num&&num<=1.401298E-45;};var cloneValue=function(source,destinationObject){if(!source)return null;if(source instanceof BABYLON.Mesh){return null;}if(source instanceof BABYLON.SubMesh){return source.clone(destinationObject);}else if(source.clone){return source.clone();}return null;};BABYLON.Tools.DeepCopy=function(source,destination,doNotCopyList,mustCopyList){for(var prop in source){if(prop[0]==="_"&&(!mustCopyList||mustCopyList.indexOf(prop)===-1)){continue;}if(doNotCopyList&&doNotCopyList.indexOf(prop)!==-1){continue;}var sourceValue=source[prop];var typeOfSourceValue=typeof sourceValue;if(typeOfSourceValue=="function"){continue;}if(typeOfSourceValue=="object"){if(sourceValue instanceof Array){destination[prop]=[];if(sourceValue.length>0){if(typeof sourceValue[0]=="object"){for(var index=0;index=2){deltaTime=previousFramesDuration[length-1]-previousFramesDuration[length-2];}if(length>=fpsRange){if(length>fpsRange){previousFramesDuration.splice(0,1);length=previousFramesDuration.length;}var sum=0;for(var id=0;id=0){this._gl.vertexAttribPointer(order,vertexDeclaration[index],this._gl.FLOAT,false,vertexStrideSize,offset);}offset+=vertexDeclaration[index]*4;}}if(this._cachedIndexBuffer!==indexBuffer){this._cachedIndexBuffer=indexBuffer;this._gl.bindBuffer(this._gl.ELEMENT_ARRAY_BUFFER,indexBuffer);}};BABYLON.Engine.prototype.bindMultiBuffers=function(vertexBuffers,indexBuffer,effect){if(this._cachedVertexBuffers!==vertexBuffers||this._cachedEffectForVertexBuffers!==effect){this._cachedVertexBuffers=vertexBuffers;this._cachedEffectForVertexBuffers=effect;var attributes=effect.getAttributesNames();for(var index=0;index=0){var vertexBuffer=vertexBuffers[attributes[index]];var stride=vertexBuffer.getStrideSize();this._gl.bindBuffer(this._gl.ARRAY_BUFFER,vertexBuffer._buffer);this._gl.vertexAttribPointer(order,stride,this._gl.FLOAT,false,stride*4,0);}}}if(this._cachedIndexBuffer!==indexBuffer){this._cachedIndexBuffer=indexBuffer;this._gl.bindBuffer(this._gl.ELEMENT_ARRAY_BUFFER,indexBuffer);}};BABYLON.Engine.prototype._releaseBuffer=function(buffer){buffer.references--;if(buffer.references===0){this._gl.deleteBuffer(buffer);}};BABYLON.Engine.prototype.draw=function(useTriangles,indexStart,indexCount){this._gl.drawElements(useTriangles?this._gl.TRIANGLES:this._gl.LINES,indexCount,this._gl.UNSIGNED_SHORT,indexStart*2);};BABYLON.Engine.prototype.createEffect=function(baseName,attributesNames,uniformsNames,samplers,defines,optionalDefines){var vertex=baseName.vertex||baseName;var fragment=baseName.fragment||baseName;var name=vertex+"+"+fragment+"@"+defines;if(this._compiledEffects[name]){return this._compiledEffects[name];}var effect=new BABYLON.Effect(baseName,attributesNames,uniformsNames,samplers,this,defines,optionalDefines);this._compiledEffects[name]=effect;return effect;};var compileShader=function(gl,source,type,defines){var shader=gl.createShader(type==="vertex"?gl.VERTEX_SHADER:gl.FRAGMENT_SHADER);gl.shaderSource(shader,(defines?defines+"\n":"")+source);gl.compileShader(shader);if(!gl.getShaderParameter(shader,gl.COMPILE_STATUS)){throw new Error(gl.getShaderInfoLog(shader));}return shader;};BABYLON.Engine.prototype.createShaderProgram=function(vertexCode,fragmentCode,defines){var vertexShader=compileShader(this._gl,vertexCode,"vertex",defines);var fragmentShader=compileShader(this._gl,fragmentCode,"fragment",defines);var shaderProgram=this._gl.createProgram();this._gl.attachShader(shaderProgram,vertexShader);this._gl.attachShader(shaderProgram,fragmentShader);this._gl.linkProgram(shaderProgram);var error=this._gl.getProgramInfoLog(shaderProgram);if(error){throw new Error(error);}this._gl.deleteShader(vertexShader);this._gl.deleteShader(fragmentShader);return shaderProgram;};BABYLON.Engine.prototype.getUniforms=function(shaderProgram,uniformsNames){var results=[];for(var index=0;index=0){this._gl.enableVertexAttribArray(effect.getAttribute(index));}}this._currentEffect=effect;};BABYLON.Engine.prototype.setMatrices=function(uniform,matrices){if(!uniform)return;this._gl.uniformMatrix4fv(uniform,false,matrices);};BABYLON.Engine.prototype.setMatrix=function(uniform,matrix){if(!uniform)return;this._gl.uniformMatrix4fv(uniform,false,matrix.toArray());};BABYLON.Engine.prototype.setFloat=function(uniform,value){if(!uniform)return;this._gl.uniform1f(uniform,value);};BABYLON.Engine.prototype.setFloat2=function(uniform,x,y){if(!uniform)return;this._gl.uniform2f(uniform,x,y);};BABYLON.Engine.prototype.setFloat3=function(uniform,x,y,z){if(!uniform)return;this._gl.uniform3f(uniform,x,y,z);};BABYLON.Engine.prototype.setBool=function(uniform,bool){if(!uniform)return;this._gl.uniform1i(uniform,bool);};BABYLON.Engine.prototype.setFloat4=function(uniform,x,y,z,w){if(!uniform)return;this._gl.uniform4f(uniform,x,y,z,w);};BABYLON.Engine.prototype.setColor3=function(uniform,color3){if(!uniform)return;this._gl.uniform3f(uniform,color3.r,color3.g,color3.b);};BABYLON.Engine.prototype.setColor4=function(uniform,color3,alpha){if(!uniform)return;this._gl.uniform4f(uniform,color3.r,color3.g,color3.b,alpha);};BABYLON.Engine.prototype.setState=function(culling){if(this._currentState.culling!==culling){if(culling){this._gl.cullFace(this.cullBackFaces?this._gl.BACK:this._gl.FRONT);this._gl.enable(this._gl.CULL_FACE);}else{this._gl.disable(this._gl.CULL_FACE);}this._currentState.culling=culling;}};BABYLON.Engine.prototype.setDepthBuffer=function(enable){if(enable){this._gl.enable(this._gl.DEPTH_TEST);}else{this._gl.disable(this._gl.DEPTH_TEST);}};BABYLON.Engine.prototype.setDepthWrite=function(enable){this._gl.depthMask(enable);};BABYLON.Engine.prototype.setColorWrite=function(enable){this._gl.colorMask(enable,enable,enable,enable);};BABYLON.Engine.prototype.setAlphaMode=function(mode){switch(mode){case BABYLON.Engine.ALPHA_DISABLE:this.setDepthWrite(true);this._gl.disable(this._gl.BLEND);break;case BABYLON.Engine.ALPHA_COMBINE:this.setDepthWrite(false);this._gl.blendFuncSeparate(this._gl.SRC_ALPHA,this._gl.ONE_MINUS_SRC_ALPHA,this._gl.ZERO,this._gl.ONE);this._gl.enable(this._gl.BLEND);break;case BABYLON.Engine.ALPHA_ADD:this.setDepthWrite(false);this._gl.blendFuncSeparate(this._gl.ONE,this._gl.ONE,this._gl.ZERO,this._gl.ONE);this._gl.enable(this._gl.BLEND);break;}};BABYLON.Engine.prototype.setAlphaTesting=function(enable){this._alphaTest=enable;};BABYLON.Engine.prototype.getAlphaTesting=function(){return this._alphaTest;};BABYLON.Engine.prototype.wipeCaches=function(){this._activeTexturesCache=[];this._currentEffect=null;this._currentState={culling:null};this._cachedVertexBuffers=null;this._cachedVertexBuffers=null;this._cachedEffectForVertexBuffers=null;};var getExponantOfTwo=function(value,max){var count=1;do{count*=2;}while(countmax)count=max;return count;};BABYLON.Engine.prototype.createTexture=function(url,noMipmap,invertY,scene){var texture=this._gl.createTexture();var that=this;var onload=function(img){var potWidth=getExponantOfTwo(img.width,that._caps.maxTextureSize);var potHeight=getExponantOfTwo(img.height,that._caps.maxTextureSize);var isPot=(img.width==potWidth&&img.height==potHeight);if(!isPot){that._workingCanvas.width=potWidth;that._workingCanvas.height=potHeight;that._workingContext.drawImage(img,0,0,img.width,img.height,0,0,potWidth,potHeight);};that._gl.bindTexture(that._gl.TEXTURE_2D,texture);that._gl.pixelStorei(that._gl.UNPACK_FLIP_Y_WEBGL,invertY===undefined?true:invertY);that._gl.texImage2D(that._gl.TEXTURE_2D,0,that._gl.RGBA,that._gl.RGBA,that._gl.UNSIGNED_BYTE,isPot?img:that._workingCanvas);that._gl.texParameteri(that._gl.TEXTURE_2D,that._gl.TEXTURE_MAG_FILTER,that._gl.LINEAR);if(noMipmap){that._gl.texParameteri(that._gl.TEXTURE_2D,that._gl.TEXTURE_MIN_FILTER,that._gl.LINEAR);}else{that._gl.texParameteri(that._gl.TEXTURE_2D,that._gl.TEXTURE_MIN_FILTER,that._gl.LINEAR_MIPMAP_LINEAR);that._gl.generateMipmap(that._gl.TEXTURE_2D);}that._gl.bindTexture(that._gl.TEXTURE_2D,null);that._activeTexturesCache=[];texture._baseWidth=img.width;texture._baseHeight=img.height;texture._width=potWidth;texture._height=potHeight;texture.isReady=true;scene._removePendingData(texture);};var onerror=function(){scene._removePendingData(texture);};scene._addPendingData(texture);BABYLON.Tools.LoadImage(url,onload,onerror,scene.database);texture.url=url;texture.noMipmap=noMipmap;texture.references=1;this._loadedTexturesCache.push(texture);return texture;};BABYLON.Engine.prototype.createDynamicTexture=function(width,height,generateMipMaps){var texture=this._gl.createTexture();width=getExponantOfTwo(width,this._caps.maxTextureSize);height=getExponantOfTwo(height,this._caps.maxTextureSize);this._gl.bindTexture(this._gl.TEXTURE_2D,texture);this._gl.texParameteri(this._gl.TEXTURE_2D,this._gl.TEXTURE_MAG_FILTER,this._gl.LINEAR);if(!generateMipMaps){this._gl.texParameteri(this._gl.TEXTURE_2D,this._gl.TEXTURE_MIN_FILTER,this._gl.LINEAR);}else{this._gl.texParameteri(this._gl.TEXTURE_2D,this._gl.TEXTURE_MIN_FILTER,this._gl.LINEAR_MIPMAP_LINEAR);}this._gl.bindTexture(this._gl.TEXTURE_2D,null);this._activeTexturesCache=[];texture._baseWidth=width;texture._baseHeight=height;texture._width=width;texture._height=height;texture.isReady=false;texture.generateMipMaps=generateMipMaps;texture.references=1;this._loadedTexturesCache.push(texture);return texture;};BABYLON.Engine.prototype.updateDynamicTexture=function(texture,canvas,invertY){this._gl.bindTexture(this._gl.TEXTURE_2D,texture);this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL,invertY);this._gl.texImage2D(this._gl.TEXTURE_2D,0,this._gl.RGBA,this._gl.RGBA,this._gl.UNSIGNED_BYTE,canvas);if(texture.generateMipMaps){this._gl.generateMipmap(this._gl.TEXTURE_2D);}this._gl.bindTexture(this._gl.TEXTURE_2D,null);this._activeTexturesCache=[];texture.isReady=true;};BABYLON.Engine.prototype.updateVideoTexture=function(texture,video){this._gl.bindTexture(this._gl.TEXTURE_2D,texture);this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL,false);if(video.videoWidth!==texture._width||video.videoHeight!==texture._height){if(!texture._workingCanvas){texture._workingCanvas=document.createElement("canvas");texture._workingContext=texture._workingCanvas.getContext("2d");texture._workingCanvas.width=texture._width;texture._workingCanvas.height=texture._height;}texture._workingContext.drawImage(video,0,0,video.videoWidth,video.videoHeight,0,0,texture._width,texture._height);this._gl.texImage2D(this._gl.TEXTURE_2D,0,this._gl.RGBA,this._gl.RGBA,this._gl.UNSIGNED_BYTE,texture._workingCanvas);}else{this._gl.texImage2D(this._gl.TEXTURE_2D,0,this._gl.RGBA,this._gl.RGBA,this._gl.UNSIGNED_BYTE,video);}if(texture.generateMipMaps){this._gl.generateMipmap(this._gl.TEXTURE_2D);}this._gl.bindTexture(this._gl.TEXTURE_2D,null);this._activeTexturesCache=[];texture.isReady=true;};BABYLON.Engine.prototype.createRenderTargetTexture=function(size,options){var generateMipMaps=false;var generateDepthBuffer=true;var samplingMode=BABYLON.Texture.TRILINEAR_SAMPLINGMODE;if(options!==undefined){generateMipMaps=options.generateMipMaps===undefined?options:options.generateMipmaps;generateDepthBuffer=options.generateDepthBuffer===undefined?true:options.generateDepthBuffer;if(options.samplingMode!==undefined){samplingMode=options.samplingMode;}}var gl=this._gl;var texture=gl.createTexture();gl.bindTexture(gl.TEXTURE_2D,texture);var width=size.width||size;var height=size.height||size;var magFilter=gl.NEAREST;var minFilter=gl.NEAREST;if(samplingMode===BABYLON.Texture.BILINEAR_SAMPLINGMODE){magFilter=gl.LINEAR;if(generateMipMaps){minFilter=gl.LINEAR_MIPMAP_NEAREST;}else{minFilter=gl.LINEAR;}}else if(samplingMode===BABYLON.Texture.TRILINEAR_SAMPLINGMODE){magFilter=gl.LINEAR;if(generateMipMaps){minFilter=gl.LINEAR_MIPMAP_LINEAR;}else{minFilter=gl.LINEAR;}}gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,magFilter);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,minFilter);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.CLAMP_TO_EDGE);gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,width,height,0,gl.RGBA,gl.UNSIGNED_BYTE,null);var depthBuffer;if(generateDepthBuffer){depthBuffer=gl.createRenderbuffer();gl.bindRenderbuffer(gl.RENDERBUFFER,depthBuffer);gl.renderbufferStorage(gl.RENDERBUFFER,gl.DEPTH_COMPONENT16,width,height);}var framebuffer=gl.createFramebuffer();gl.bindFramebuffer(gl.FRAMEBUFFER,framebuffer);gl.framebufferTexture2D(gl.FRAMEBUFFER,gl.COLOR_ATTACHMENT0,gl.TEXTURE_2D,texture,0);if(generateDepthBuffer){gl.framebufferRenderbuffer(gl.FRAMEBUFFER,gl.DEPTH_ATTACHMENT,gl.RENDERBUFFER,depthBuffer);}gl.bindTexture(gl.TEXTURE_2D,null);gl.bindRenderbuffer(gl.RENDERBUFFER,null);gl.bindFramebuffer(gl.FRAMEBUFFER,null);texture._framebuffer=framebuffer;if(generateDepthBuffer){texture._depthBuffer=depthBuffer;}texture._width=width;texture._height=height;texture.isReady=true;texture.generateMipMaps=generateMipMaps;texture.references=1;this._activeTexturesCache=[];this._loadedTexturesCache.push(texture);return texture;};var extensions=["_px.jpg","_py.jpg","_pz.jpg","_nx.jpg","_ny.jpg","_nz.jpg"];var cascadeLoad=function(rootUrl,index,loadedImages,scene,onfinish){var img;var onload=function(){loadedImages.push(img);scene._removePendingData(img);if(index!=extensions.length-1){cascadeLoad(rootUrl,index+1,loadedImages,scene,onfinish);}else{onfinish(loadedImages);}};var onerror=function(){scene._removePendingData(img);};img=BABYLON.Tools.LoadImage(rootUrl+extensions[index],onload,onerror,scene.database);scene._addPendingData(img);};BABYLON.Engine.prototype.createCubeTexture=function(rootUrl,scene){var gl=this._gl;var texture=gl.createTexture();texture.isCube=true;texture.url=rootUrl;texture.references=1;this._loadedTexturesCache.push(texture);var that=this;cascadeLoad(rootUrl,0,[],scene,function(imgs){var width=getExponantOfTwo(imgs[0].width);var height=width;that._workingCanvas.width=width;that._workingCanvas.height=height;var faces=[gl.TEXTURE_CUBE_MAP_POSITIVE_X,gl.TEXTURE_CUBE_MAP_POSITIVE_Y,gl.TEXTURE_CUBE_MAP_POSITIVE_Z,gl.TEXTURE_CUBE_MAP_NEGATIVE_X,gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,gl.TEXTURE_CUBE_MAP_NEGATIVE_Z];gl.bindTexture(gl.TEXTURE_CUBE_MAP,texture);gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,false);for(var index=0;indexthis.maximumWorld.x)this.maximumWorld.x=v.x;if(v.y>this.maximumWorld.y)this.maximumWorld.y=v.y;if(v.z>this.maximumWorld.z)this.maximumWorld.z=v.z;}this.maximumWorld.addToRef(this.minimumWorld,this.center);this.center.scaleInPlace(0.5);BABYLON.Vector3.FromArrayToRef(world.m,0,this.directions[0]);BABYLON.Vector3.FromArrayToRef(world.m,4,this.directions[1]);BABYLON.Vector3.FromArrayToRef(world.m,8,this.directions[2]);};BABYLON.BoundingBox.prototype.isInFrustrum=function(frustumPlanes){return BABYLON.BoundingBox.IsInFrustrum(this.vectorsWorld,frustumPlanes);};BABYLON.BoundingBox.prototype.intersectsPoint=function(point){if(this.maximumWorld.xpoint.x)return false;if(this.maximumWorld.ypoint.y)return false;if(this.maximumWorld.zpoint.z)return false;return true;};BABYLON.BoundingBox.prototype.intersectsSphere=function(sphere){var vector=BABYLON.Vector3.Clamp(sphere.centerWorld,this.minimumWorld,this.maximumWorld);var num=BABYLON.Vector3.DistanceSquared(sphere.centerWorld,vector);return(num<=(sphere.radiusWorld*sphere.radiusWorld));};BABYLON.BoundingBox.prototype.intersectsMinMax=function(min,max){if(this.maximumWorld.xmax.x)return false;if(this.maximumWorld.ymax.y)return false;if(this.maximumWorld.zmax.z)return false;return true;};BABYLON.BoundingBox.intersects=function(box0,box1){if(box0.maximumWorld.xbox1.maximumWorld.x)return false;if(box0.maximumWorld.ybox1.maximumWorld.y)return false;if(box0.maximumWorld.zbox1.maximumWorld.z)return false;return true;};BABYLON.BoundingBox.IsInFrustrum=function(boundingVectors,frustumPlanes){for(var p=0;p<6;p++){var inCount=8;for(var i=0;i<8;i++){if(frustumPlanes[p].dotCoordinate(boundingVectors[i])<0){--inCount;}else{break;}}if(inCount==0)return false;}return true;};})();var BABYLON=BABYLON||{};(function(){BABYLON.BoundingInfo=function(minimum,maximum){this.boundingBox=new BABYLON.BoundingBox(minimum,maximum);this.boundingSphere=new BABYLON.BoundingSphere(minimum,maximum);};BABYLON.BoundingInfo.prototype._update=function(world,scale){this.boundingBox._update(world);this.boundingSphere._update(world,scale);};var extentsOverlap=function(min0,max0,min1,max1){return!(min0>max1||min1>max0);};var computeBoxExtents=function(axis,box){var p=BABYLON.Vector3.Dot(box.center,axis);var r0=Math.abs(BABYLON.Vector3.Dot(box.directions[0],axis))*box.extends.x;var r1=Math.abs(BABYLON.Vector3.Dot(box.directions[1],axis))*box.extends.y;var r2=Math.abs(BABYLON.Vector3.Dot(box.directions[2],axis))*box.extends.z;var r=r0+r1+r2;return{min:p-r,max:p+r};};var axisOverlap=function(axis,box0,box1){var result0=computeBoxExtents(axis,box0);var result1=computeBoxExtents(axis,box1);return extentsOverlap(result0.min,result0.max,result1.min,result1.max);};BABYLON.BoundingInfo.prototype.isInFrustrum=function(frustumPlanes){if(!this.boundingSphere.isInFrustrum(frustumPlanes))return false;return this.boundingBox.isInFrustrum(frustumPlanes);};BABYLON.BoundingInfo.prototype._checkCollision=function(collider){return collider._canDoCollision(this.boundingSphere.centerWorld,this.boundingSphere.radiusWorld,this.boundingBox.minimumWorld,this.boundingBox.maximumWorld);};BABYLON.BoundingInfo.prototype.intersectsPoint=function(point){if(!this.boundingSphere.centerWorld){return false;}if(!this.boundingSphere.intersectsPoint(point)){return false;}if(!this.boundingBox.intersectsPoint(point)){return false;}return true;};BABYLON.BoundingInfo.prototype.intersects=function(boundingInfo,precise){if(!this.boundingSphere.centerWorld||!boundingInfo.boundingSphere.centerWorld){return false;}if(!BABYLON.BoundingSphere.intersects(this.boundingSphere,boundingInfo.boundingSphere)){return false;}if(!BABYLON.BoundingBox.intersects(this.boundingBox,boundingInfo.boundingBox)){return false;}if(!precise){return true;}var box0=this.boundingBox;var box1=boundingInfo.boundingBox;if(!axisOverlap(box0.directions[0],box0,box1))return false;if(!axisOverlap(box0.directions[1],box0,box1))return false;if(!axisOverlap(box0.directions[2],box0,box1))return false;if(!axisOverlap(box1.directions[0],box0,box1))return false;if(!axisOverlap(box1.directions[1],box0,box1))return false;if(!axisOverlap(box1.directions[2],box0,box1))return false;if(!axisOverlap(BABYLON.Vector3.Cross(box0.directions[0],box1.directions[0]),box0,box1))return false;if(!axisOverlap(BABYLON.Vector3.Cross(box0.directions[0],box1.directions[1]),box0,box1))return false;if(!axisOverlap(BABYLON.Vector3.Cross(box0.directions[0],box1.directions[2]),box0,box1))return false;if(!axisOverlap(BABYLON.Vector3.Cross(box0.directions[1],box1.directions[0]),box0,box1))return false;if(!axisOverlap(BABYLON.Vector3.Cross(box0.directions[1],box1.directions[1]),box0,box1))return false;if(!axisOverlap(BABYLON.Vector3.Cross(box0.directions[1],box1.directions[2]),box0,box1))return false;if(!axisOverlap(BABYLON.Vector3.Cross(box0.directions[2],box1.directions[0]),box0,box1))return false;if(!axisOverlap(BABYLON.Vector3.Cross(box0.directions[2],box1.directions[1]),box0,box1))return false;if(!axisOverlap(BABYLON.Vector3.Cross(box0.directions[2],box1.directions[2]),box0,box1))return false;return true;};})();var BABYLON=BABYLON||{};(function(){BABYLON.Light=function(name,scene){this.name=name;this.id=name;this._childrenFlag=true;this._scene=scene;scene.lights.push(this);this.animations=[];this.excludedMeshes=[];};BABYLON.Light.prototype=Object.create(BABYLON.Node.prototype);BABYLON.Light.prototype.intensity=1.0;BABYLON.Light.prototype.getScene=function(){return this._scene;};BABYLON.Light.prototype.getShadowGenerator=function(){return this._shadowGenerator;};BABYLON.Light.prototype.transferToEffect=function(){};BABYLON.Light.prototype.getWorldMatrix=function(){var worldMatrix=this._getWorldMatrix();if(this.parent&&this.parent.getWorldMatrix){if(!this._parentedWorldMatrix){this._parentedWorldMatrix=BABYLON.Matrix.Identity();}worldMatrix.multiplyToRef(this.parent.getWorldMatrix(),this._parentedWorldMatrix);return this._parentedWorldMatrix;}return worldMatrix;};BABYLON.Light.prototype.dispose=function(){if(this._shadowGenerator){this._shadowGenerator.dispose();this._shadowGenerator=null;}var index=this._scene.lights.indexOf(this);this._scene.lights.splice(index,1);};})();var BABYLON=BABYLON||{};(function(){BABYLON.PointLight=function(name,position,scene){BABYLON.Light.call(this,name,scene);this.position=position;this.diffuse=new BABYLON.Color3(1.0,1.0,1.0);this.specular=new BABYLON.Color3(1.0,1.0,1.0);};BABYLON.PointLight.prototype=Object.create(BABYLON.Light.prototype);BABYLON.Light.prototype.transferToEffect=function(effect,positionUniformName){if(this.parent&&this.parent.getWorldMatrix){if(!this._transformedPosition){this._transformedPosition=BABYLON.Vector3.Zero();}BABYLON.Vector3.TransformCoordinatesToRef(this.position,this.parent.getWorldMatrix(),this._transformedPosition);effect.setFloat4(positionUniformName,this._transformedPosition.x,this._transformedPosition.y,this._transformedPosition.z,0);return;}effect.setFloat4(positionUniformName,this.position.x,this.position.y,this.position.z,0);};BABYLON.PointLight.prototype.getShadowGenerator=function(){return null;};BABYLON.PointLight.prototype._getWorldMatrix=function(){if(!this._worldMatrix){this._worldMatrix=BABYLON.Matrix.Identity();}BABYLON.Matrix.TranslationToRef(this.position.x,this.position.y,this.position.z,this._worldMatrix);return this._worldMatrix;};})();var BABYLON=BABYLON||{};(function(){BABYLON.SpotLight=function(name,position,direction,angle,exponent,scene){BABYLON.Light.call(this,name,scene);this.position=position;this.direction=direction;this.angle=angle;this.exponent=exponent;this.diffuse=new BABYLON.Color3(1.0,1.0,1.0);this.specular=new BABYLON.Color3(1.0,1.0,1.0);};BABYLON.SpotLight.prototype=Object.create(BABYLON.Light.prototype);BABYLON.SpotLight.prototype.transferToEffect=function(effect,positionUniformName,directionUniformName){var normalizeDirection;if(this.parent&&this.parent.getWorldMatrix){if(!this._transformedDirection){this._transformedDirection=BABYLON.Vector3.Zero();}if(!this._transformedPosition){this._transformedPosition=BABYLON.Vector3.Zero();}var parentWorldMatrix=this.parent.getWorldMatrix();BABYLON.Vector3.TransformCoordinatesToRef(this.position,parentWorldMatrix,this._transformedPosition);BABYLON.Vector3.TransformNormalToRef(this.direction,parentWorldMatrix,this._transformedDirection);effect.setFloat4(positionUniformName,this._transformedPosition.x,this._transformedPosition.y,this._transformedPosition.z,this.exponent);normalizeDirection=BABYLON.Vector3.Normalize(this._transformedDirection);}else{effect.setFloat4(positionUniformName,this.position.x,this.position.y,this.position.z,this.exponent);normalizeDirection=BABYLON.Vector3.Normalize(this.direction);}effect.setFloat4(directionUniformName,normalizeDirection.x,normalizeDirection.y,normalizeDirection.z,Math.cos(this.angle*0.5));};BABYLON.SpotLight.prototype._getWorldMatrix=function(){if(!this._worldMatrix){this._worldMatrix=BABYLON.Matrix.Identity();}BABYLON.Matrix.TranslationToRef(this.position.x,this.position.y,this.position.z,this._worldMatrix);return this._worldMatrix;};})();var BABYLON=BABYLON||{};(function(){BABYLON.DirectionalLight=function(name,direction,scene){BABYLON.Light.call(this,name,scene);this.position=direction.scale(-1);this.direction=direction;this.diffuse=new BABYLON.Color3(1.0,1.0,1.0);this.specular=new BABYLON.Color3(1.0,1.0,1.0);};BABYLON.DirectionalLight.prototype=Object.create(BABYLON.Light.prototype);BABYLON.DirectionalLight.prototype._computeTransformedPosition=function(){if(this.parent&&this.parent.getWorldMatrix){if(!this._transformedPosition){this._transformedPosition=BABYLON.Vector3.Zero();}BABYLON.Vector3.TransformCoordinatesToRef(this.position,this.parent.getWorldMatrix(),this._transformedPosition);return true;}return false;};BABYLON.DirectionalLight.prototype.transferToEffect=function(effect,directionUniformName){if(this.parent&&this.parent.getWorldMatrix){if(!this._transformedDirection){this._transformedDirection=BABYLON.Vector3.Zero();}BABYLON.Vector3.TransformNormalToRef(this.direction,this.parent.getWorldMatrix(),this._transformedDirection);effect.setFloat4(directionUniformName,this._transformedDirection.x,this._transformedDirection.y,this._transformedDirection.z,1);return;}effect.setFloat4(directionUniformName,this.direction.x,this.direction.y,this.direction.z,1);};BABYLON.DirectionalLight.prototype._getWorldMatrix=function(){if(!this._worldMatrix){this._worldMatrix=BABYLON.Matrix.Identity();}BABYLON.Matrix.TranslationToRef(this.position.x,this.position.y,this.position.z,this._worldMatrix);return this._worldMatrix;};})();var BABYLON=BABYLON||{};(function(){BABYLON.ShadowGenerator=function(mapSize,light){this._light=light;this._scene=light.getScene();light._shadowGenerator=this;this._shadowMap=new BABYLON.RenderTargetTexture(light.name+"_shadowMap",mapSize,this._scene,false);this._shadowMap.wrapU=BABYLON.Texture.CLAMP_ADDRESSMODE;this._shadowMap.wrapV=BABYLON.Texture.CLAMP_ADDRESSMODE;this._shadowMap.renderParticles=false;var that=this;var renderSubMesh=function(subMesh){var mesh=subMesh.getMesh();var world=mesh.getWorldMatrix();var engine=that._scene.getEngine();if(that.isReady(mesh)){engine.enableEffect(that._effect);if(mesh.skeleton&&mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind)&&mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind)){that._effect.setMatrix("world",world);that._effect.setMatrix("viewProjection",that.getTransformMatrix());that._effect.setMatrices("mBones",mesh.skeleton.getTransformMatrices());}else{world.multiplyToRef(that.getTransformMatrix(),that._worldViewProjection);that._effect.setMatrix("worldViewProjection",that._worldViewProjection);}mesh.bindAndDraw(subMesh,that._effect,false);}};this._shadowMap.customRenderFunction=function(opaqueSubMeshes,alphaTestSubMeshes){var index;for(index=0;index=0;};var intersectBoxAASphere=function(boxMin,boxMax,sphereCenter,sphereRadius){if(boxMin.x>sphereCenter.x+sphereRadius)return false;if(sphereCenter.x-sphereRadius>boxMax.x)return false;if(boxMin.y>sphereCenter.y+sphereRadius)return false;if(sphereCenter.y-sphereRadius>boxMax.y)return false;if(boxMin.z>sphereCenter.z+sphereRadius)return false;if(sphereCenter.z-sphereRadius>boxMax.z)return false;return true;};var getLowestRoot=function(a,b,c,maxR){var determinant=b*b-4.0*a*c;var result={root:0,found:false};if(determinant<0)return result;var sqrtD=Math.sqrt(determinant);var r1=(-b-sqrtD)/(2.0*a);var r2=(-b+sqrtD)/(2.0*a);if(r1>r2){var temp=r2;r2=r1;r1=temp;}if(r1>0&&r10&&r2this.velocityWorldLength+max+sphereRadius){return false;}if(!intersectBoxAASphere(vecMin,vecMax,this.basePointWorld,this.velocityWorldLength+max))return false;return true;};BABYLON.Collider.prototype._testTriangle=function(faceIndex,subMesh,p1,p2,p3){var t0;var embeddedInPlane=false;if(!subMesh._trianglePlanes){subMesh._trianglePlanes=[];}if(!subMesh._trianglePlanes[faceIndex]){subMesh._trianglePlanes[faceIndex]=new BABYLON.Plane(0,0,0,0);subMesh._trianglePlanes[faceIndex].copyFromPoints(p1,p2,p3);}var trianglePlane=subMesh._trianglePlanes[faceIndex];if((!subMesh.getMaterial())&&!trianglePlane.isFrontFacingTo(this.normalizedVelocity,0))return;var signedDistToTrianglePlane=trianglePlane.signedDistanceTo(this.basePoint);var normalDotVelocity=BABYLON.Vector3.Dot(trianglePlane.normal,this.velocity);if(normalDotVelocity==0){if(Math.abs(signedDistToTrianglePlane)>=1.0)return;embeddedInPlane=true;t0=0;}else{t0=(-1.0-signedDistToTrianglePlane)/normalDotVelocity;var t1=(1.0-signedDistToTrianglePlane)/normalDotVelocity;if(t0>t1){var temp=t1;t1=t0;t0=temp;}if(t0>1.0||t1<0.0)return;if(t0<0)t0=0;if(t0>1.0)t0=1.0;}this._collisionPoint.copyFromFloats(0,0,0);var found=false;var t=1.0;if(!embeddedInPlane){this.basePoint.subtractToRef(trianglePlane.normal,this._planeIntersectionPoint);this.velocity.scaleToRef(t0,this._tempVector);this._planeIntersectionPoint.addInPlace(this._tempVector);if(this._checkPointInTriangle(this._planeIntersectionPoint,p1,p2,p3,trianglePlane.normal)){found=true;t=t0;this._collisionPoint.copyFrom(this._planeIntersectionPoint);}}if(!found){var velocitySquaredLength=this.velocity.lengthSquared();var a=velocitySquaredLength;this.basePoint.subtractToRef(p1,this._tempVector);var b=2.0*(BABYLON.Vector3.Dot(this.velocity,this._tempVector));var c=this._tempVector.lengthSquared-1.0;var lowestRoot=getLowestRoot(a,b,c,t);if(lowestRoot.found){t=lowestRoot.root;found=true;this._collisionPoint.copyFrom(p1);}this.basePoint.subtractToRef(p2,this._tempVector);b=2.0*(BABYLON.Vector3.Dot(this.velocity,this._tempVector));c=this._tempVector.lengthSquared-1.0;lowestRoot=getLowestRoot(a,b,c,t);if(lowestRoot.found){t=lowestRoot.root;found=true;this._collisionPoint.copyFrom(p2);}this.basePoint.subtractToRef(p3,this._tempVector);b=2.0*(BABYLON.Vector3.Dot(this.velocity,this._tempVector));c=this._tempVector.lengthSquared-1.0;lowestRoot=getLowestRoot(a,b,c,t);if(lowestRoot.found){t=lowestRoot.root;found=true;this._collisionPoint.copyFrom(p3);}p2.subtractToRef(p1,this._edge);p1.subtractToRef(this.basePoint,this._baseToVertex);var edgeSquaredLength=this._edge.lengthSquared();var edgeDotVelocity=BABYLON.Vector3.Dot(this._edge,this.velocity);var edgeDotBaseToVertex=BABYLON.Vector3.Dot(this._edge,this._baseToVertex);a=edgeSquaredLength*(-velocitySquaredLength)+edgeDotVelocity*edgeDotVelocity;b=edgeSquaredLength*(2.0*BABYLON.Vector3.Dot(this.velocity,this._baseToVertex))-2.0*edgeDotVelocity*edgeDotBaseToVertex;c=edgeSquaredLength*(1.0-this._baseToVertex.lengthSquared())+edgeDotBaseToVertex*edgeDotBaseToVertex;lowestRoot=getLowestRoot(a,b,c,t);if(lowestRoot.found){var f=(edgeDotVelocity*lowestRoot.root-edgeDotBaseToVertex)/edgeSquaredLength;if(f>=0.0&&f<=1.0){t=lowestRoot.root;found=true;this._edge.scaleInPlace(f);p1.addToRef(this._edge,this._collisionPoint);}}p3.subtractToRef(p2,this._edge);p2.subtractToRef(this.basePoint,this._baseToVertex);edgeSquaredLength=this._edge.lengthSquared();edgeDotVelocity=BABYLON.Vector3.Dot(this._edge,this.velocity);edgeDotBaseToVertex=BABYLON.Vector3.Dot(this._edge,this._baseToVertex);a=edgeSquaredLength*(-velocitySquaredLength)+edgeDotVelocity*edgeDotVelocity;b=edgeSquaredLength*(2.0*BABYLON.Vector3.Dot(this.velocity,this._baseToVertex))-2.0*edgeDotVelocity*edgeDotBaseToVertex;c=edgeSquaredLength*(1.0-this._baseToVertex.lengthSquared())+edgeDotBaseToVertex*edgeDotBaseToVertex;lowestRoot=getLowestRoot(a,b,c,t);if(lowestRoot.found){var f=(edgeDotVelocity*lowestRoot.root-edgeDotBaseToVertex)/edgeSquaredLength;if(f>=0.0&&f<=1.0){t=lowestRoot.root;found=true;this._edge.scaleInPlace(f);p2.addToRef(this._edge,this._collisionPoint);}}p1.subtractToRef(p3,this._edge);p3.subtractToRef(this.basePoint,this._baseToVertex);edgeSquaredLength=this._edge.lengthSquared();edgeDotVelocity=BABYLON.Vector3.Dot(this._edge,this.velocity);edgeDotBaseToVertex=BABYLON.Vector3.Dot(this._edge,this._baseToVertex);a=edgeSquaredLength*(-velocitySquaredLength)+edgeDotVelocity*edgeDotVelocity;b=edgeSquaredLength*(2.0*BABYLON.Vector3.Dot(this.velocity,this._baseToVertex))-2.0*edgeDotVelocity*edgeDotBaseToVertex;c=edgeSquaredLength*(1.0-this._baseToVertex.lengthSquared())+edgeDotBaseToVertex*edgeDotBaseToVertex;lowestRoot=getLowestRoot(a,b,c,t);if(lowestRoot.found){var f=(edgeDotVelocity*lowestRoot.root-edgeDotBaseToVertex)/edgeSquaredLength;if(f>=0.0&&f<=1.0){t=lowestRoot.root;found=true;this._edge.scaleInPlace(f);p3.addToRef(this._edge,this._collisionPoint);}}}if(found){var distToCollision=t*this.velocity.length();if(!this.collisionFound||distToCollision=0.0){this.rotation.y=(-Math.atan(vDir.z/vDir.x)+Math.PI/2.0);}else{this.rotation.y=(-Math.atan(vDir.z/vDir.x)-Math.PI/2.0);}this.rotation.z=-Math.acos(BABYLON.Vector3.Dot(new BABYLON.Vector3(0,1.0,0),this.upVector));if(isNaN(this.rotation.x))this.rotation.x=0;if(isNaN(this.rotation.y))this.rotation.y=0;if(isNaN(this.rotation.z))this.rotation.z=0;};BABYLON.FreeCamera.prototype.attachControl=function(canvas,noPreventDefault){var previousPosition;var that=this;var engine=this._scene.getEngine();if(this._attachedCanvas){return;}this._attachedCanvas=canvas;if(this._onMouseDown===undefined){this._onMouseDown=function(evt){previousPosition={x:evt.clientX,y:evt.clientY};if(!noPreventDefault){evt.preventDefault();}};this._onMouseUp=function(evt){previousPosition=null;if(!noPreventDefault){evt.preventDefault();}};this._onMouseOut=function(evt){previousPosition=null;that._keys=[];if(!noPreventDefault){evt.preventDefault();}};this._onMouseMove=function(evt){if(!previousPosition&&!engine.isPointerLock){return;}var offsetX;var offsetY;if(!engine.isPointerLock){offsetX=evt.clientX-previousPosition.x;offsetY=evt.clientY-previousPosition.y;}else{offsetX=evt.movementX||evt.mozMovementX||evt.webkitMovementX||evt.msMovementX||0;offsetY=evt.movementY||evt.mozMovementY||evt.webkitMovementY||evt.msMovementY||0;}that.cameraRotation.y+=offsetX/that.angularSensibility;that.cameraRotation.x+=offsetY/that.angularSensibility;previousPosition={x:evt.clientX,y:evt.clientY};if(!noPreventDefault){evt.preventDefault();}};this._onKeyDown=function(evt){if(that.keysUp.indexOf(evt.keyCode)!==-1||that.keysDown.indexOf(evt.keyCode)!==-1||that.keysLeft.indexOf(evt.keyCode)!==-1||that.keysRight.indexOf(evt.keyCode)!==-1){var index=that._keys.indexOf(evt.keyCode);if(index===-1){that._keys.push(evt.keyCode);}if(!noPreventDefault){evt.preventDefault();}}};this._onKeyUp=function(evt){if(that.keysUp.indexOf(evt.keyCode)!==-1||that.keysDown.indexOf(evt.keyCode)!==-1||that.keysLeft.indexOf(evt.keyCode)!==-1||that.keysRight.indexOf(evt.keyCode)!==-1){var index=that._keys.indexOf(evt.keyCode);if(index>=0){that._keys.splice(index,1);}if(!noPreventDefault){evt.preventDefault();}}};this._onLostFocus=function(){that._keys=[];};this._reset=function(){that._keys=[];previousPosition=null;that.cameraDirection=new BABYLON.Vector3(0,0,0);that.cameraRotation=new BABYLON.Vector2(0,0);};}canvas.addEventListener("mousedown",this._onMouseDown,false);canvas.addEventListener("mouseup",this._onMouseUp,false);canvas.addEventListener("mouseout",this._onMouseOut,false);canvas.addEventListener("mousemove",this._onMouseMove,false);window.addEventListener("keydown",this._onKeyDown,false);window.addEventListener("keyup",this._onKeyUp,false);window.addEventListener("blur",this._onLostFocus,false);};BABYLON.FreeCamera.prototype.detachControl=function(canvas){if(this._attachedCanvas!=canvas){return;}canvas.removeEventListener("mousedown",this._onMouseDown);canvas.removeEventListener("mouseup",this._onMouseUp);canvas.removeEventListener("mouseout",this._onMouseOut);canvas.removeEventListener("mousemove",this._onMouseMove);window.removeEventListener("keydown",this._onKeyDown);window.removeEventListener("keyup",this._onKeyUp);window.removeEventListener("blur",this._onLostFocus);this._attachedCanvas=null;if(this._reset){this._reset();}};BABYLON.FreeCamera.prototype._collideWithWorld=function(velocity){this.position.subtractFromFloatsToRef(0,this.ellipsoid.y,0,this._oldPosition);this._collider.radius=this.ellipsoid;this._scene._getNewPosition(this._oldPosition,velocity,this._collider,3,this._newPosition);this._newPosition.subtractToRef(this._oldPosition,this._diffPosition);if(this._diffPosition.length()>BABYLON.Engine.collisionsEpsilon){this.position.addInPlace(this._diffPosition);}};BABYLON.FreeCamera.prototype._checkInputs=function(){if(!this._localDirection){this._localDirection=BABYLON.Vector3.Zero();this._transformedDirection=BABYLON.Vector3.Zero();}for(var index=0;index0||Math.abs(this.cameraDirection.y)>0||Math.abs(this.cameraDirection.z)>0;var needToRotate=Math.abs(this.cameraRotation.x)>0||Math.abs(this.cameraRotation.y)>0;if(needToMove){if(this.checkCollisions&&this._scene.collisionsEnabled){this._collideWithWorld(this.cameraDirection);if(this.applyGravity){var oldPosition=this.position;this._collideWithWorld(this._scene.gravity);this._needMoveForGravity=(BABYLON.Vector3.DistanceSquared(oldPosition,this.position)!=0);}}else{this.position.addInPlace(this.cameraDirection);}}if(needToRotate){this.rotation.x+=this.cameraRotation.x;this.rotation.y+=this.cameraRotation.y;if(!this.noRotationConstraint){var limit=(Math.PI/2)*0.95;if(this.rotation.x>limit)this.rotation.x=limit;if(this.rotation.x<-limit)this.rotation.x=-limit;}}if(needToMove){this.cameraDirection.scaleInPlace(this.inertia);}if(needToRotate){this.cameraRotation.scaleInPlace(this.inertia);}};BABYLON.FreeCamera.prototype._getViewMatrix=function(){BABYLON.Vector3.FromFloatsToRef(0,0,1,this._referencePoint);if(!this.lockedTarget){if(this.upVector.x!=0||this.upVector.y!=1.0||this.upVector.z!=0){BABYLON.Matrix.LookAtLHToRef(BABYLON.Vector3.Zero(),this._referencePoint,this.upVector,this._lookAtTemp);BABYLON.Matrix.RotationYawPitchRollToRef(this.rotation.y,this.rotation.x,this.rotation.z,this._cameraRotationMatrix);this._lookAtTemp.multiplyToRef(this._cameraRotationMatrix,this._tempMatrix);this._lookAtTemp.invert();this._tempMatrix.multiplyToRef(this._lookAtTemp,this._cameraRotationMatrix);}else{BABYLON.Matrix.RotationYawPitchRollToRef(this.rotation.y,this.rotation.x,this.rotation.z,this._cameraRotationMatrix);}BABYLON.Vector3.TransformCoordinatesToRef(this._referencePoint,this._cameraRotationMatrix,this._transformedReferencePoint);this.position.addToRef(this._transformedReferencePoint,this._currentTarget);}else{if(this.lockedTarget.position){this._currentTarget.copyFrom(this.lockedTarget.position);}else{this._currentTarget.copyFrom(this.lockedTarget);}}BABYLON.Matrix.LookAtLHToRef(this.position,this._currentTarget,this.upVector,this._viewMatrix);return this._viewMatrix;};})();"use strict";var BABYLON=BABYLON||{};(function(){BABYLON.TouchCamera=function(name,position,scene){BABYLON.FreeCamera.call(this,name,position,scene);this._offsetX=null;this._offsetY=null;this._pointerCount=0;this._pointerPressed=[];};BABYLON.TouchCamera.prototype=Object.create(BABYLON.FreeCamera.prototype);BABYLON.TouchCamera.prototype.angularSensibility=200000.0;BABYLON.TouchCamera.prototype.moveSensibility=500.0;BABYLON.TouchCamera.prototype.attachControl=function(canvas,noPreventDefault){var previousPosition;var that=this;if(this._attachedCanvas){return;}this._attachedCanvas=canvas;if(this._onPointerDown===undefined){this._onPointerDown=function(evt){if(!noPreventDefault){evt.preventDefault();}that._pointerPressed.push(evt.pointerId);if(that._pointerPressed.length!==1){return;}previousPosition={x:evt.clientX,y:evt.clientY};};this._onPointerUp=function(evt){if(!noPreventDefault){evt.preventDefault();}var index=that._pointerPressed.indexOf(evt.pointerId);if(index===-1){return;}that._pointerPressed.splice(index,1);if(index!=0){return;}previousPosition=null;that._offsetX=null;that._offsetY=null;};this._onPointerMove=function(evt){if(!noPreventDefault){evt.preventDefault();}if(!previousPosition){return;}var index=that._pointerPressed.indexOf(evt.pointerId);if(index!=0){return;}that._offsetX=evt.clientX-previousPosition.x;that._offsetY=-(evt.clientY-previousPosition.y);};this._onLostFocus=function(){that._offsetX=null;that._offsetY=null;};}canvas.addEventListener("pointerdown",this._onPointerDown);canvas.addEventListener("pointerup",this._onPointerUp);canvas.addEventListener("pointerout",this._onPointerUp);canvas.addEventListener("pointermove",this._onPointerMove);window.addEventListener("blur",this._onLostFocus);};BABYLON.TouchCamera.prototype.detachControl=function(canvas){if(this._attachedCanvas!=canvas){return;}canvas.removeEventListener("pointerdown",this._onPointerDown);canvas.removeEventListener("pointerup",this._onPointerUp);canvas.removeEventListener("pointerout",this._onPointerUp);canvas.removeEventListener("pointermove",this._onPointerMove);window.removeEventListener("blur",this._onLostFocus);this._attachedCanvas=null;};BABYLON.TouchCamera.prototype._checkInputs=function(){if(!this._offsetX){return;}this.cameraRotation.y+=this._offsetX/this.angularSensibility;if(this._pointerPressed.length>1){this.cameraRotation.x+=-this._offsetY/this.angularSensibility;}else{var speed=this._computeLocalCameraSpeed();var direction=new BABYLON.Vector3(0,0,speed*this._offsetY/this.moveSensibility);BABYLON.Matrix.RotationYawPitchRollToRef(this.rotation.y,this.rotation.x,0,this._cameraRotationMatrix);this.cameraDirection.addInPlace(BABYLON.Vector3.TransformCoordinates(direction,this._cameraRotationMatrix));}};})();"use strict";var BABYLON=BABYLON||{};(function(){BABYLON.DeviceOrientationCamera=function(name,position,scene){BABYLON.FreeCamera.call(this,name,position,scene);this._offsetX=null;this._offsetY=null;this._orientationGamma=0;this._orientationBeta=0;this._initialOrientationGamma=0;this._initialOrientationBeta=0;};BABYLON.DeviceOrientationCamera.prototype=Object.create(BABYLON.FreeCamera.prototype);BABYLON.DeviceOrientationCamera.prototype.angularSensibility=10000.0;BABYLON.DeviceOrientationCamera.prototype.moveSensibility=50.0;BABYLON.DeviceOrientationCamera.prototype.attachControl=function(canvas,noPreventDefault){if(this._attachedCanvas){return;}this._attachedCanvas=canvas;var that=this;if(!this._orientationChanged){this._orientationChanged=function(evt){if(!that._initialOrientationGamma){that._initialOrientationGamma=evt.gamma;that._initialOrientationBeta=evt.beta;}that._orientationGamma=evt.gamma;that._orientationBeta=evt.beta;that._offsetY=(that._initialOrientationBeta-that._orientationBeta);that._offsetX=(that._initialOrientationGamma-that._orientationGamma);};}window.addEventListener("deviceorientation",this._orientationChanged);};BABYLON.DeviceOrientationCamera.prototype.detachControl=function(canvas){if(this._attachedCanvas!=canvas){return;}window.removeEventListener("deviceorientation",this._orientationChanged);this._attachedCanvas=null;this._orientationGamma=0;this._orientationBeta=0;this._initialOrientationGamma=0;this._initialOrientationBeta=0;};BABYLON.DeviceOrientationCamera.prototype._checkInputs=function(){if(!this._offsetX){return;}this.cameraRotation.y-=this._offsetX/this.angularSensibility;var speed=this._computeLocalCameraSpeed();var direction=new BABYLON.Vector3(0,0,speed*this._offsetY/this.moveSensibility);BABYLON.Matrix.RotationYawPitchRollToRef(this.rotation.y,this.rotation.x,0,this._cameraRotationMatrix);this.cameraDirection.addInPlace(BABYLON.Vector3.TransformCoordinates(direction,this._cameraRotationMatrix));};})();"use strict";var BABYLON=BABYLON||{};(function(){var eventPrefix=BABYLON.Tools.GetPointerPrefix();BABYLON.ArcRotateCamera=function(name,alpha,beta,radius,target,scene){BABYLON.Camera.call(this,name,BABYLON.Vector3.Zero(),scene);this.alpha=alpha;this.beta=beta;this.radius=radius;this.target=target;this._keys=[];this.keysUp=[38];this.keysDown=[40];this.keysLeft=[37];this.keysRight=[39];this._viewMatrix=new BABYLON.Matrix();this.getViewMatrix();};BABYLON.ArcRotateCamera.prototype=Object.create(BABYLON.Camera.prototype);BABYLON.ArcRotateCamera.prototype.inertialAlphaOffset=0;BABYLON.ArcRotateCamera.prototype.inertialBetaOffset=0;BABYLON.ArcRotateCamera.prototype.lowerAlphaLimit=null;BABYLON.ArcRotateCamera.prototype.upperAlphaLimit=null;BABYLON.ArcRotateCamera.prototype.lowerBetaLimit=null;BABYLON.ArcRotateCamera.prototype.upperBetaLimit=null;BABYLON.ArcRotateCamera.prototype.lowerRadiusLimit=null;BABYLON.ArcRotateCamera.prototype.upperRadiusLimit=null;BABYLON.ArcRotateCamera.prototype.angularSensibility=1000.0;BABYLON.ArcRotateCamera.prototype.attachControl=function(canvas,noPreventDefault){var previousPosition;var that=this;var pointerId;if(this._attachedCanvas){return;}this._attachedCanvas=canvas;var engine=this._scene.getEngine();if(this._onPointerDown===undefined){this._onPointerDown=function(evt){if(pointerId){return;}pointerId=evt.pointerId;previousPosition={x:evt.clientX,y:evt.clientY};if(!noPreventDefault){evt.preventDefault();}};this._onPointerUp=function(evt){previousPosition=null;pointerId=null;if(!noPreventDefault){evt.preventDefault();}};this._onPointerMove=function(evt){if(!previousPosition){return;}if(pointerId!==evt.pointerId){return;}var offsetX=evt.clientX-previousPosition.x;var offsetY=evt.clientY-previousPosition.y;that.inertialAlphaOffset-=offsetX/that.angularSensibility;that.inertialBetaOffset-=offsetY/that.angularSensibility;previousPosition={x:evt.clientX,y:evt.clientY};if(!noPreventDefault){evt.preventDefault();}};this._onMouseMove=function(evt){if(!engine.isPointerLock){return;}var offsetX=evt.movementX||evt.mozMovementX||evt.webkitMovementX||evt.msMovementX||0;var offsetY=evt.movementY||evt.mozMovementY||evt.webkitMovementY||evt.msMovementY||0;that.inertialAlphaOffset-=offsetX/that.angularSensibility;that.inertialBetaOffset-=offsetY/that.angularSensibility;if(!noPreventDefault){evt.preventDefault();}};this._wheel=function(event){var delta=0;if(event.wheelDelta){delta=event.wheelDelta/120;}else if(event.detail){delta=-event.detail/3;}if(delta)that.radius-=delta;if(event.preventDefault){if(!noPreventDefault){event.preventDefault();}}};this._onKeyDown=function(evt){if(that.keysUp.indexOf(evt.keyCode)!==-1||that.keysDown.indexOf(evt.keyCode)!==-1||that.keysLeft.indexOf(evt.keyCode)!==-1||that.keysRight.indexOf(evt.keyCode)!==-1){var index=that._keys.indexOf(evt.keyCode);if(index===-1){that._keys.push(evt.keyCode);}if(evt.preventDefault){if(!noPreventDefault){evt.preventDefault();}}}};this._onKeyUp=function(evt){if(that.keysUp.indexOf(evt.keyCode)!==-1||that.keysDown.indexOf(evt.keyCode)!==-1||that.keysLeft.indexOf(evt.keyCode)!==-1||that.keysRight.indexOf(evt.keyCode)!==-1){var index=that._keys.indexOf(evt.keyCode);if(index>=0){that._keys.splice(index,1);}if(evt.preventDefault){if(!noPreventDefault){evt.preventDefault();}}}};this._onLostFocus=function(){that._keys=[];pointerId=null;};this._onGestureStart=function(e){if(!that._MSGestureHandler){that._MSGestureHandler=new MSGesture();that._MSGestureHandler.target=canvas;}that._MSGestureHandler.addPointer(e.pointerId);};this._onGesture=function(e){that.radius*=e.scale;if(e.preventDefault){if(!noPreventDefault){e.stopPropagation();e.preventDefault();}}};this._reset=function(){that._keys=[];that.inertialAlphaOffset=0;that.inertialBetaOffset=0;previousPosition=null;pointerId=null;};}canvas.addEventListener(eventPrefix+"down",this._onPointerDown,false);canvas.addEventListener(eventPrefix+"up",this._onPointerUp,false);canvas.addEventListener(eventPrefix+"out",this._onPointerUp,false);canvas.addEventListener(eventPrefix+"move",this._onPointerMove,false);canvas.addEventListener("mousemove",this._onMouseMove,false);canvas.addEventListener("MSPointerDown",this._onGestureStart,false);canvas.addEventListener("MSGestureChange",this._onGesture,false);window.addEventListener("keydown",this._onKeyDown,false);window.addEventListener("keyup",this._onKeyUp,false);window.addEventListener('mousewheel',this._wheel,false);window.addEventListener("blur",this._onLostFocus,false);};BABYLON.ArcRotateCamera.prototype.detachControl=function(canvas){if(this._attachedCanvas!=canvas){return;}canvas.removeEventListener(eventPrefix+"down",this._onPointerDown);canvas.removeEventListener(eventPrefix+"up",this._onPointerUp);canvas.removeEventListener(eventPrefix+"out",this._onPointerUp);canvas.removeEventListener(eventPrefix+"move",this._onPointerMove);canvas.removeEventListener("mousemove",this._onMouseMove);canvas.removeEventListener("MSPointerDown",this._onGestureStart);canvas.removeEventListener("MSGestureChange",this._onGesture);window.removeEventListener("keydown",this._onKeyDown);window.removeEventListener("keyup",this._onKeyUp);window.removeEventListener('mousewheel',this._wheel);window.removeEventListener("blur",this._onLostFocus);this._MSGestureHandler=null;this._attachedCanvas=null;if(this._reset){this._reset();}};BABYLON.ArcRotateCamera.prototype._update=function(){for(var index=0;indexthis.upperAlphaLimit){this.alpha=this.upperAlphaLimit;}if(this.lowerBetaLimit&&this.betathis.upperBetaLimit){this.beta=this.upperBetaLimit;}if(this.lowerRadiusLimit&&this.radiusthis.upperRadiusLimit){this.radius=this.upperRadiusLimit;}};BABYLON.ArcRotateCamera.prototype.setPosition=function(position){var radiusv3=position.subtract(this.target.position?this.target.position:this.target);this.radius=radiusv3.length();this.alpha=Math.atan(radiusv3.z/radiusv3.x);this.beta=Math.acos(radiusv3.y/this.radius);};BABYLON.ArcRotateCamera.prototype._getViewMatrix=function(){if(this.beta>Math.PI)this.beta=Math.PI;if(this.beta<=0)this.beta=0.01;var cosa=Math.cos(this.alpha);var sina=Math.sin(this.alpha);var cosb=Math.cos(this.beta);var sinb=Math.sin(this.beta);this.target.addToRef(new BABYLON.Vector3(this.radius*cosa*sinb,this.radius*cosb,this.radius*sina*sinb),this.position);BABYLON.Matrix.LookAtLHToRef(this.position,this.target,this.upVector,this._viewMatrix);return this._viewMatrix;};})();"use strict";var BABYLON=BABYLON||{};(function(){BABYLON.Scene=function(engine){this._engine=engine;this.autoClear=true;this.clearColor=new BABYLON.Color3(0.2,0.2,0.3);this.ambientColor=new BABYLON.Color3(0,0,0);engine.scenes.push(this);this._totalVertices=0;this._activeVertices=0;this._activeParticles=0;this._lastFrameDuration=0;this._evaluateActiveMeshesDuration=0;this._renderTargetsDuration=0;this._renderDuration=0;this._renderId=0;this._executeWhenReadyTimeoutId=-1;this._toBeDisposed=new BABYLON.Tools.SmartArray(256);this._onReadyCallbacks=[];this._pendingData=[];this._onBeforeRenderCallbacks=[];this.fogMode=BABYLON.Scene.FOGMODE_NONE;this.fogColor=new BABYLON.Color3(0.2,0.2,0.3);this.fogDensity=0.1;this.fogStart=0;this.fogEnd=1000.0;this.lights=[];this.cameras=[];this.activeCamera=null;this.meshes=[];this._activeMeshes=new BABYLON.Tools.SmartArray(256);this._processedMaterials=new BABYLON.Tools.SmartArray(256);this._renderTargets=new BABYLON.Tools.SmartArray(256);this._activeParticleSystems=new BABYLON.Tools.SmartArray(256);this._activeSkeletons=new BABYLON.Tools.SmartArray(32);this._renderingManager=new BABYLON.RenderingManager(this);this.materials=[];this.multiMaterials=[];this.defaultMaterial=new BABYLON.StandardMaterial("default material",this);this.textures=[];this.particlesEnabled=true;this.particleSystems=[];this.spriteManagers=[];this.layers=[];this.skeletons=[];this.lensFlareSystems=[];this.collisionsEnabled=true;this.gravity=new BABYLON.Vector3(0,-9.0,0);this._activeAnimatables=[];this._transformMatrix=BABYLON.Matrix.Zero();this._scaledPosition=BABYLON.Vector3.Zero();this._scaledVelocity=BABYLON.Vector3.Zero();this.postProcessesEnabled=true;this.postProcessManager=new BABYLON.PostProcessManager(this);this.customRenderTargets=[];this.activeCameras=[];};BABYLON.Scene.prototype.getEngine=function(){return this._engine;};BABYLON.Scene.prototype.getTotalVertices=function(){return this._totalVertices;};BABYLON.Scene.prototype.getActiveVertices=function(){return this._activeVertices;};BABYLON.Scene.prototype.getTotalVertices=function(){return this._totalVertices;};BABYLON.Scene.prototype.getActiveParticles=function(){return this._activeParticles;};BABYLON.Scene.prototype.getLastFrameDuration=function(){return this._lastFrameDuration;};BABYLON.Scene.prototype.getEvaluateActiveMeshesDuration=function(){return this._evaluateActiveMeshesDuration;};BABYLON.Scene.prototype.getRenderTargetsDuration=function(){return this._renderTargetsDuration;};BABYLON.Scene.prototype.getRenderDuration=function(){return this._renderDuration;};BABYLON.Scene.prototype.getParticlesDuration=function(){return this._particlesDuration;};BABYLON.Scene.prototype.getSpritesDuration=function(){return this._spritesDuration;};BABYLON.Scene.prototype.getAnimationRatio=function(){return this._animationRatio;};BABYLON.Scene.prototype.getRenderId=function(){return this._renderId;};BABYLON.Scene.prototype.isReady=function(){if(this._pendingData.length>0){return false;}for(var index=0;index-1){this._onBeforeRenderCallbacks.splice(index,1);}};BABYLON.Scene.prototype._addPendingData=function(data){this._pendingData.push(data);};BABYLON.Scene.prototype._removePendingData=function(data){var index=this._pendingData.indexOf(data);if(index!==-1){this._pendingData.splice(index,1);}};BABYLON.Scene.prototype.getWaitingItemsCount=function(){return this._pendingData.length;};BABYLON.Scene.prototype.executeWhenReady=function(func){this._onReadyCallbacks.push(func);if(this._executeWhenReadyTimeoutId!==-1){return;}var that=this;this._executeWhenReadyTimeoutId=setTimeout(function(){that._checkIsReady();},150);};BABYLON.Scene.prototype._checkIsReady=function(){if(this.isReady()){this._onReadyCallbacks.forEach(function(func){func();});this._onReadyCallbacks=[];this._executeWhenReadyTimeoutId=-1;return;}var that=this;this._executeWhenReadyTimeoutId=setTimeout(function(){that._checkIsReady();},150);};BABYLON.Scene.prototype.beginAnimation=function(target,from,to,loop,speedRatio,onAnimationEnd){if(speedRatio===undefined){speedRatio=1.0;}if(target.animations){this.stopAnimation(target);var animatable=new BABYLON._Animatable(target,from,to,loop,speedRatio,onAnimationEnd);this._activeAnimatables.push(animatable);}if(target.getAnimatables){var animatables=target.getAnimatables();for(var index=0;index=0;index--){if(this.meshes[index].id===id){return this.meshes[index];}}return null;};BABYLON.Scene.prototype.getLastEntryByID=function(id){for(var index=this.meshes.length-1;index>=0;index--){if(this.meshes[index].id===id){return this.meshes[index];}}for(var index=this.cameras.length-1;index>=0;index--){if(this.cameras[index].id===id){return this.cameras[index];}}for(var index=this.lights.length-1;index>=0;index--){if(this.lights[index].id===id){return this.lights[index];}}return null;};BABYLON.Scene.prototype.getMeshByName=function(name){for(var index=0;index=0;index--){if(this.skeletons[index].id===id){return this.skeletons[index];}}return null;};BABYLON.Scene.prototype.getSkeletonById=function(id){for(var index=0;index0&&mesh.isInFrustrum(this._frustumPlanes))){if(mesh._renderId===0){this._activeMeshes.push(mesh);}mesh._renderId=this._renderId;if(mesh.skeleton){this._activeSkeletons.pushNoDuplicate(mesh.skeleton);}var subMeshes=block.subMeshes[meshIndex];for(var subIndex=0;subIndex0&&mesh.isInFrustrum(this._frustumPlanes)){this._activeMeshes.push(mesh);if(mesh.skeleton){this._activeSkeletons.pushNoDuplicate(mesh.skeleton);}for(var subIndex=0;subIndex0){engine.restoreDefaultFramebuffer();}this._renderTargetsDuration=new Date()-beforeRenderTargetDate;this.postProcessManager._prepareFrame();var beforeRenderDate=new Date();if(this.layers.length){engine.setDepthBuffer(false);var layerIndex;var layer;for(layerIndex=0;layerIndex0){var currentRenderId=this._renderId;for(var cameraIndex=0;cameraIndex=maximumRetry){finalPosition.copyFrom(position);return;}collider._initialize(position,velocity,closeDistance);for(var index=0;indexmax.x)max.x=v.x;if(v.y>max.y)max.y=v.y;if(v.z>max.z)max.z=v.z;};var min=new BABYLON.Vector3(Number.MAX_VALUE,Number.MAX_VALUE,Number.MAX_VALUE);var max=new BABYLON.Vector3(-Number.MAX_VALUE,-Number.MAX_VALUE,-Number.MAX_VALUE);for(var index=0;index=pickingInfo.distance)continue;pickingInfo=result;if(fastCheck){break;}}return pickingInfo||new BABYLON.PickingInfo();};BABYLON.Scene.prototype.pick=function(x,y,predicate,fastCheck){var that=this;return this._internalPick(function(world){return that.createPickingRay(x,y,world);},predicate,fastCheck);};BABYLON.Scene.prototype.pickWithRay=function(ray,predicate,fastCheck){var that=this;return this._internalPick(function(world){if(!that._pickWithRayInverseMatrix){that._pickWithRayInverseMatrix=BABYLON.Matrix.Identity();}world.invertToRef(that._pickWithRayInverseMatrix);return BABYLON.Ray.Transform(ray,that._pickWithRayInverseMatrix);},predicate,fastCheck);};BABYLON.Scene.FOGMODE_NONE=0;BABYLON.Scene.FOGMODE_EXP=1;BABYLON.Scene.FOGMODE_EXP2=2;BABYLON.Scene.FOGMODE_LINEAR=3;})();var BABYLON=BABYLON||{};(function(){BABYLON.VertexBuffer=function(mesh,data,kind,updatable){this._mesh=mesh;this._engine=mesh.getScene().getEngine();this._updatable=updatable;if(updatable){this._buffer=this._engine.createDynamicVertexBuffer(data.length*4);this._engine.updateDynamicVertexBuffer(this._buffer,data);}else{this._buffer=this._engine.createVertexBuffer(data);}this._data=data;this._kind=kind;switch(kind){case BABYLON.VertexBuffer.PositionKind:this._strideSize=3;this._mesh._resetPointsArrayCache();break;case BABYLON.VertexBuffer.NormalKind:this._strideSize=3;break;case BABYLON.VertexBuffer.UVKind:this._strideSize=2;break;case BABYLON.VertexBuffer.UV2Kind:this._strideSize=2;break;case BABYLON.VertexBuffer.ColorKind:this._strideSize=3;break;case BABYLON.VertexBuffer.MatricesIndicesKind:this._strideSize=4;break;case BABYLON.VertexBuffer.MatricesWeightsKind:this._strideSize=4;break;}};BABYLON.VertexBuffer.prototype.isUpdatable=function(){return this._updatable;};BABYLON.VertexBuffer.prototype.getData=function(){return this._data;};BABYLON.VertexBuffer.prototype.getStrideSize=function(){return this._strideSize;};BABYLON.VertexBuffer.prototype.update=function(data){this._engine.updateDynamicVertexBuffer(this._buffer,data);this._data=data;if(this._kind===BABYLON.VertexBuffer.PositionKind){this._mesh._resetPointsArrayCache();}};BABYLON.VertexBuffer.prototype.dispose=function(){this._engine._releaseBuffer(this._buffer);};BABYLON.VertexBuffer.PositionKind="position";BABYLON.VertexBuffer.NormalKind="normal";BABYLON.VertexBuffer.UVKind="uv";BABYLON.VertexBuffer.UV2Kind="uv2";BABYLON.VertexBuffer.ColorKind="color";BABYLON.VertexBuffer.MatricesIndicesKind="matricesIndices";BABYLON.VertexBuffer.MatricesWeightsKind="matricesWeights";})();var BABYLON=BABYLON||{};(function(){BABYLON.Mesh=function(name,scene){this.name=name;this.id=name;this._scene=scene;this._totalVertices=0;this._worldMatrix=BABYLON.Matrix.Identity();scene.meshes.push(this);this.position=new BABYLON.Vector3(0,0,0);this.rotation=new BABYLON.Vector3(0,0,0);this.rotationQuaternion=null;this.scaling=new BABYLON.Vector3(1,1,1);this._pivotMatrix=BABYLON.Matrix.Identity();this._indices=[];this.subMeshes=[];this._renderId=0;this._onBeforeRenderCallbacks=[];this.animations=[];this._positions=null;this._cache={localMatrixUpdated:false,infiniteDistance:true,position:BABYLON.Vector3.Zero(),scaling:BABYLON.Vector3.Zero(),rotation:BABYLON.Vector3.Zero(),rotationQuaternion:new BABYLON.Quaternion(0,0,0,0)};this._childrenFlag=false;this._localScaling=BABYLON.Matrix.Zero();this._localRotation=BABYLON.Matrix.Zero();this._localTranslation=BABYLON.Matrix.Zero();this._localBillboard=BABYLON.Matrix.Zero();this._localPivotScaling=BABYLON.Matrix.Zero();this._localPivotScalingRotation=BABYLON.Matrix.Zero();this._localWorld=BABYLON.Matrix.Zero();this._worldMatrix=BABYLON.Matrix.Zero();this._rotateYByPI=BABYLON.Matrix.RotationY(Math.PI);this._collisionsTransformMatrix=BABYLON.Matrix.Zero();this._collisionsScalingMatrix=BABYLON.Matrix.Zero();this._absolutePosition=BABYLON.Vector3.Zero();};BABYLON.Mesh.prototype=Object.create(BABYLON.Node.prototype);BABYLON.Mesh.BILLBOARDMODE_NONE=0;BABYLON.Mesh.BILLBOARDMODE_X=1;BABYLON.Mesh.BILLBOARDMODE_Y=2;BABYLON.Mesh.BILLBOARDMODE_Z=4;BABYLON.Mesh.BILLBOARDMODE_ALL=7;BABYLON.Mesh.prototype.delayLoadState=BABYLON.Engine.DELAYLOADSTATE_NONE;BABYLON.Mesh.prototype.material=null;BABYLON.Mesh.prototype.isVisible=true;BABYLON.Mesh.prototype.isPickable=true;BABYLON.Mesh.prototype.visibility=1.0;BABYLON.Mesh.prototype.billboardMode=BABYLON.Mesh.BILLBOARDMODE_NONE;BABYLON.Mesh.prototype.checkCollisions=false;BABYLON.Mesh.prototype.receiveShadows=false;BABYLON.Mesh.prototype._isDisposed=false;BABYLON.Mesh.prototype.onDispose=null;BABYLON.Mesh.prototype.skeleton=null;BABYLON.Mesh.prototype.renderingGroupId=0;BABYLON.Mesh.prototype.infiniteDistance=false;BABYLON.Mesh.prototype.getBoundingInfo=function(){return this._boundingInfo;};BABYLON.Mesh.prototype.getScene=function(){return this._scene;};BABYLON.Mesh.prototype.getWorldMatrix=function(){if(this._currentRenderId!==this._scene.getRenderId()){this.computeWorldMatrix();}return this._worldMatrix;};BABYLON.Mesh.prototype.getAbsolutePosition=function(){return this._absolutePosition;};BABYLON.Mesh.prototype.getTotalVertices=function(){return this._totalVertices;};BABYLON.Mesh.prototype.getVerticesData=function(kind){return this._vertexBuffers[kind].getData();};BABYLON.Mesh.prototype.isVerticesDataPresent=function(kind){if(!this._vertexBuffers&&this._delayInfo){return this._delayInfo.indexOf(kind)!==-1;}return this._vertexBuffers[kind]!==undefined;};BABYLON.Mesh.prototype.getTotalIndices=function(){return this._indices.length;};BABYLON.Mesh.prototype.getIndices=function(){return this._indices;};BABYLON.Mesh.prototype.getVertexStrideSize=function(){return this._vertexStrideSize;};BABYLON.Mesh.prototype.setPivotMatrix=function(matrix){this._pivotMatrix=matrix;this._cache.pivotMatrixUpdated=true;};BABYLON.Mesh.prototype.getPivotMatrix=function(){return this._localMatrix;};BABYLON.Mesh.prototype.isSynchronized=function(){if(this.billboardMode!==BABYLON.Mesh.BILLBOARDMODE_NONE)return false;if(this._cache.pivotMatrixUpdated){return false;}if(this._cache.infiniteDistance!==this.infiniteDistance){return false;}if(!this._cache.position.equals(this.position))return false;if(this.rotationQuaternion){if(!this._cache.rotationQuaternion.equals(this.rotationQuaternion))return false;}else{if(!this._cache.rotation.equals(this.rotation))return false;}if(!this._cache.scaling.equals(this.scaling))return false;if(this.parent)return!this.parent._needToSynchonizeChildren();return true;};BABYLON.Mesh.prototype.isReady=function(){return this._isReady;};BABYLON.Mesh.prototype.isAnimated=function(){return this._animationStarted;};BABYLON.Mesh.prototype.isDisposed=function(){return this._isDisposed;};BABYLON.Mesh.prototype.markAsDirty=function(property){if(property==="rotation"){this.rotationQuaternion=null;}this._childrenFlag=true;};BABYLON.Mesh.prototype.refreshBoundingInfo=function(){var data=this.getVerticesData(BABYLON.VertexBuffer.PositionKind);if(!data){return;}var extend=BABYLON.Tools.ExtractMinAndMax(data,0,this._totalVertices);this._boundingInfo=new BABYLON.BoundingInfo(extend.minimum,extend.maximum);for(var index=0;index-1){this._onBeforeRenderCallbacks.splice(index,1);}};BABYLON.Mesh.prototype.render=function(subMesh){if(!this._vertexBuffers||!this._indexBuffer){return;}for(var callbackIndex=0;callbackIndex1&&!subMesh._checkCollision(collider))continue;this._collideForSubMesh(subMesh,transformMatrix,collider);}};BABYLON.Mesh.prototype._checkCollision=function(collider){if(!this._boundingInfo._checkCollision(collider))return;BABYLON.Matrix.ScalingToRef(1.0/collider.radius.x,1.0/collider.radius.y,1.0/collider.radius.z,this._collisionsScalingMatrix);this._worldMatrix.multiplyToRef(this._collisionsScalingMatrix,this._collisionsTransformMatrix);this._processCollisionsForSubModels(collider,this._collisionsTransformMatrix);};BABYLON.Mesh.prototype.intersectsMesh=function(mesh,precise){if(!this._boundingInfo||!mesh._boundingInfo){return false;}return this._boundingInfo.intersects(mesh._boundingInfo,precise);};BABYLON.Mesh.prototype.intersectsPoint=function(point){if(!this._boundingInfo){return false;}return this._boundingInfo.intersectsPoint(point);};BABYLON.Mesh.prototype.intersects=function(ray,fastCheck){var pickingInfo=new BABYLON.PickingInfo();if(!this._boundingInfo||!ray.intersectsSphere(this._boundingInfo.boundingSphere)||!ray.intersectsBox(this._boundingInfo.boundingBox)){return pickingInfo;}this._generatePointsArray();var distance=Number.MAX_VALUE;for(var index=0;index1&&!subMesh.canIntersects(ray))continue;var currentDistance=subMesh.intersects(ray,this._positions,this._indices,fastCheck);if(currentDistance>0){if(fastCheck||currentDistance=0&&distance0){var verticesCount=positions.length/3;for(var firstIndex=verticesCount-2*(totalYRotationSteps+1);(firstIndex+totalYRotationSteps+2)0){if(fastCheck||currentDistance0&&distancemaxVertexIndex)maxVertexIndex=vertexIndex;}return new BABYLON.SubMesh(materialIndex,minVertexIndex,maxVertexIndex-minVertexIndex,startIndex,indexCount,mesh);};})();var BABYLON=BABYLON||{};(function(){BABYLON.BaseTexture=function(url,scene){this._scene=scene;this._scene.textures.push(this);};BABYLON.BaseTexture.prototype.delayLoadState=BABYLON.Engine.DELAYLOADSTATE_NONE;BABYLON.BaseTexture.prototype.hasAlpha=false;BABYLON.BaseTexture.prototype.hasAlpha=false;BABYLON.BaseTexture.prototype.level=1;BABYLON.BaseTexture.prototype._texture=null;BABYLON.BaseTexture.prototype.onDispose=null;BABYLON.BaseTexture.prototype.getInternalTexture=function(){return this._texture;};BABYLON.BaseTexture.prototype.isReady=function(){if(this.delayLoadState===BABYLON.Engine.DELAYLOADSTATE_NOTLOADED){return true;}if(this._texture){return this._texture.isReady;}return false;};BABYLON.BaseTexture.prototype.getSize=function(){if(this._texture._width){return{width:this._texture._width,height:this._texture._height};}if(this._texture._size){return{width:this._texture._size,height:this._texture._size};}return{width:0,height:0};};BABYLON.BaseTexture.prototype.getBaseSize=function(){if(!this.isReady())return{width:0,height:0};if(this._texture._size){return{width:this._texture._size,height:this._texture._size};}return{width:this._texture._baseWidth,height:this._texture._baseHeight};};BABYLON.BaseTexture.prototype._getFromCache=function(url,noMipmap){var texturesCache=this._scene.getEngine().getLoadedTexturesCache();for(var index=0;indexb._distanceToCamera){return-1;}return 0;});engine.setDepthWrite(false);engine.setAlphaMode(BABYLON.Engine.ALPHA_COMBINE);for(subIndex=0;subIndex0||mesh.visibility<1.0){this._transparentSubMeshes.push(subMesh);}}else if(material.needAlphaTesting()){this._alphaTestSubMeshes.push(subMesh);}else{this._opaqueSubMeshes.push(subMesh);}};})();var BABYLON=BABYLON||{};(function(){BABYLON.RenderingManager=function(scene){this._scene=scene;this._renderingGroups=[];};BABYLON.RenderingManager.prototype._renderParticles=function(index,activeMeshes){if(this._scene._activeParticleSystems.length===0){return;}var beforeParticlesDate=new Date();for(var particleIndex=0;particleIndexbox.maximum.x){return false;}}else{var inv=1.0/this.direction.x;var min=(box.minimum.x-this.origin.x)*inv;var max=(box.maximum.x-this.origin.x)*inv;if(min>max){var temp=min;min=max;max=temp;}d=Math.max(min,d);maxValue=Math.min(max,maxValue);if(d>maxValue){return false;}}if(Math.abs(this.direction.y)<0.0000001){if(this.origin.ybox.maximum.y){return false;}}else{var inv=1.0/this.direction.y;var min=(box.minimum.y-this.origin.y)*inv;var max=(box.maximum.y-this.origin.y)*inv;if(min>max){var temp=min;min=max;max=temp;}d=Math.max(min,d);maxValue=Math.min(max,maxValue);if(d>maxValue){return false;}}if(Math.abs(this.direction.z)<0.0000001){if(this.origin.zbox.maximum.z){return false;}}else{var inv=1.0/this.direction.z;var min=(box.minimum.z-this.origin.z)*inv;var max=(box.maximum.z-this.origin.z)*inv;if(min>max){var temp=min;min=max;max=temp;}d=Math.max(min,d);maxValue=Math.min(max,maxValue);if(d>maxValue){return false;}}return true;};BABYLON.Ray.prototype.intersectsSphere=function(sphere){var x=sphere.center.x-this.origin.x;var y=sphere.center.y-this.origin.y;var z=sphere.center.z-this.origin.z;var pyth=(x*x)+(y*y)+(z*z);var rr=sphere.radius*sphere.radius;if(pyth<=rr){return true;}var dot=(x*this.direction.x)+(y*this.direction.y)+(z*this.direction.z);if(dot<0.0){return false;}var temp=pyth-(dot*dot);return temp<=rr;};BABYLON.Ray.prototype.intersectsTriangle=function(vertex0,vertex1,vertex2){if(!this._edge1){this._edge1=BABYLON.Vector3.Zero();this._edge2=BABYLON.Vector3.Zero();this._pvec=BABYLON.Vector3.Zero();this._tvec=BABYLON.Vector3.Zero();this._qvec=BABYLON.Vector3.Zero();}vertex1.subtractToRef(vertex0,this._edge1);vertex2.subtractToRef(vertex0,this._edge2);BABYLON.Vector3.CrossToRef(this.direction,this._edge2,this._pvec);var det=BABYLON.Vector3.Dot(this._edge1,this._pvec);if(det===0){return 0;}var invdet=1/det;this.origin.subtractToRef(vertex0,this._tvec);var bu=BABYLON.Vector3.Dot(this._tvec,this._pvec)*invdet;if(bu<0||bu>1.0){return 0;}BABYLON.Vector3.CrossToRef(this._tvec,this._edge1,this._qvec);var bv=BABYLON.Vector3.Dot(this.direction,this._qvec)*invdet;if(bv<0||bu+bv>1.0){return 0;}return BABYLON.Vector3.Dot(this._edge2,this._qvec)*invdet;};BABYLON.Ray.CreateNew=function(x,y,viewportWidth,viewportHeight,world,view,projection){var start=BABYLON.Vector3.Unproject(new BABYLON.Vector3(x,y,0),viewportWidth,viewportHeight,world,view,projection);var end=BABYLON.Vector3.Unproject(new BABYLON.Vector3(x,y,1),viewportWidth,viewportHeight,world,view,projection);var direction=end.subtract(start);direction.normalize();return new BABYLON.Ray(start,direction);};BABYLON.Ray.Transform=function(ray,matrix){var newOrigin=BABYLON.Vector3.TransformCoordinates(ray.origin,matrix);var newDirection=BABYLON.Vector3.TransformNormal(ray.direction,matrix);return new BABYLON.Ray(newOrigin,newDirection);};BABYLON.Color3=function(initialR,initialG,initialB){this.r=initialR;this.g=initialG;this.b=initialB;};BABYLON.Color3.prototype.toString=function(){return"{R: "+this.r+" G:"+this.g+" B:"+this.b+"}";};BABYLON.Color3.prototype.multiply=function(otherColor){return new BABYLON.Color3(this.r*otherColor.r,this.g*otherColor.g,this.b*otherColor.b);};BABYLON.Color3.prototype.multiplyToRef=function(otherColor,result){result.r=this.r*otherColor.r;result.g=this.g*otherColor.g;result.b=this.b*otherColor.b;};BABYLON.Color3.prototype.equals=function(otherColor){return this.r===otherColor.r&&this.g===otherColor.g&&this.b===otherColor.b;};BABYLON.Color3.prototype.scale=function(scale){return new BABYLON.Color3(this.r*scale,this.g*scale,this.b*scale);};BABYLON.Color3.prototype.scaleToRef=function(scale,result){result.r=this.r*scale;result.g=this.g*scale;result.b=this.b*scale;};BABYLON.Color3.prototype.clone=function(){return new BABYLON.Color3(this.r,this.g,this.b);};BABYLON.Color3.prototype.copyFrom=function(source){this.r=source.r;this.g=source.g;this.b=source.b;};BABYLON.Color3.prototype.copyFromFloats=function(r,g,b){this.r=r;this.g=g;this.b=b;};BABYLON.Color3.FromArray=function(array){return new BABYLON.Color3(array[0],array[1],array[2]);};BABYLON.Color4=function(initialR,initialG,initialB,initialA){this.r=initialR;this.g=initialG;this.b=initialB;this.a=initialA;};BABYLON.Color4.prototype.addInPlace=function(right){this.r+=right.r;this.g+=right.g;this.b+=right.b;this.a+=right.a;};BABYLON.Color4.prototype.add=function(right){return new BABYLON.Color4(this.r+right.r,this.g+right.g,this.b+right.b,this.a+right.a);};BABYLON.Color4.prototype.subtract=function(right){return new BABYLON.Color4(this.r-right.r,this.g-right.g,this.b-right.b,this.a-right.a);};BABYLON.Color4.prototype.subtractToRef=function(right,result){result.r=this.r-right.r;result.g=this.g-right.g;result.b=this.b-right.b;result.a=this.a-right.a;};BABYLON.Color4.prototype.scale=function(scale){return new BABYLON.Color4(this.r*scale,this.g*scale,this.b*scale,this.a*scale);};BABYLON.Color4.prototype.scaleToRef=function(scale,result){result.r=this.r*scale;result.g=this.g*scale;result.b=this.b*scale;result.a=this.a*scale;};BABYLON.Color4.prototype.toString=function(){return"{R: "+this.r+" G:"+this.g+" B:"+this.b+" A:"+this.a+"}";};BABYLON.Color4.prototype.clone=function(){return new BABYLON.Color4(this.r,this.g,this.b,this.a);};BABYLON.Color4.Lerp=function(left,right,amount){var result=new BABYLON.Color4(0,0,0,0);BABYLON.Color4.LerpToRef(left,right,amount,result);return result;};BABYLON.Color4.LerpToRef=function(left,right,amount,result){result.r=left.r+(right.r-left.r)*amount;result.g=left.g+(right.g-left.g)*amount;result.b=left.b+(right.b-left.b)*amount;result.a=left.a+(right.a-left.a)*amount;};BABYLON.Color4.FromArray=function(array,offset){if(!offset){offset=0;}return new BABYLON.Color4(array[offset],array[offset+1],array[offset+2],array[offset+3]);};BABYLON.Vector2=function(initialX,initialY){this.x=initialX;this.y=initialY;};BABYLON.Vector2.prototype.toString=function(){return"{X: "+this.x+" Y:"+this.y+"}";};BABYLON.Vector2.prototype.add=function(otherVector){return new BABYLON.Vector2(this.x+otherVector.x,this.y+otherVector.y);};BABYLON.Vector2.prototype.subtract=function(otherVector){return new BABYLON.Vector2(this.x-otherVector.x,this.y-otherVector.y);};BABYLON.Vector2.prototype.negate=function(){return new BABYLON.Vector2(-this.x,-this.y);};BABYLON.Vector2.prototype.scaleInPlace=function(scale){this.x*=scale;this.y*=scale;};BABYLON.Vector2.prototype.scale=function(scale){return new BABYLON.Vector2(this.x*scale,this.y*scale);};BABYLON.Vector2.prototype.equals=function(otherVector){return this.x===otherVector.x&&this.y===otherVector.y;};BABYLON.Vector2.prototype.length=function(){return Math.sqrt(this.x*this.x+this.y*this.y);};BABYLON.Vector2.prototype.lengthSquared=function(){return(this.x*this.x+this.y*this.y);};BABYLON.Vector2.prototype.normalize=function(){var len=this.length();if(len===0)return;var num=1.0/len;this.x*=num;this.y*=num;};BABYLON.Vector2.prototype.clone=function(){return new BABYLON.Vector2(this.x,this.y);};BABYLON.Vector2.Zero=function(){return new BABYLON.Vector2(0,0);};BABYLON.Vector2.CatmullRom=function(value1,value2,value3,value4,amount){var squared=amount*amount;var cubed=amount*squared;var x=0.5*((((2.0*value2.x)+((-value1.x+value3.x)*amount))+(((((2.0*value1.x)-(5.0*value2.x))+(4.0*value3.x))-value4.x)*squared))+((((-value1.x+(3.0*value2.x))-(3.0*value3.x))+value4.x)*cubed));var y=0.5*((((2.0*value2.y)+((-value1.y+value3.y)*amount))+(((((2.0*value1.y)-(5.0*value2.y))+(4.0*value3.y))-value4.y)*squared))+((((-value1.y+(3.0*value2.y))-(3.0*value3.y))+value4.y)*cubed));return new BABYLON.Vector2(x,y);};BABYLON.Vector2.Clamp=function(value,min,max){var x=value.x;x=(x>max.x)?max.x:x;x=(xmax.y)?max.y:y;y=(yright.x)?left.x:right.x;var y=(left.y>right.y)?left.y:right.y;return new BABYLON.Vector2(x,y);};BABYLON.Vector2.Transform=function(vector,transformation){var x=(vector.x*transformation.m[0])+(vector.y*transformation.m[4]);var y=(vector.x*transformation.m[1])+(vector.y*transformation.m[5]);return new BABYLON.Vector2(x,y);};BABYLON.Vector2.Distance=function(value1,value2){return Math.sqrt(BABYLON.Vector2.DistanceSquared(value1,value2));};BABYLON.Vector2.DistanceSquared=function(value1,value2){var x=value1.x-value2.x;var y=value1.y-value2.y;return(x*x)+(y*y);};BABYLON.Vector3=function(initialX,initialY,initialZ){this.x=initialX;this.y=initialY;this.z=initialZ;};BABYLON.Vector3.prototype.toString=function(){return"{X: "+this.x+" Y:"+this.y+" Z:"+this.z+"}";};BABYLON.Vector3.prototype.toArray=function(array,index){array[index]=this.x;array[index+1]=this.y;array[index+2]=this.z;};BABYLON.Vector3.prototype.addInPlace=function(otherVector){this.x+=otherVector.x;this.y+=otherVector.y;this.z+=otherVector.z;};BABYLON.Vector3.prototype.add=function(otherVector){return new BABYLON.Vector3(this.x+otherVector.x,this.y+otherVector.y,this.z+otherVector.z);};BABYLON.Vector3.prototype.addToRef=function(otherVector,result){result.x=this.x+otherVector.x;result.y=this.y+otherVector.y;result.z=this.z+otherVector.z;};BABYLON.Vector3.prototype.subtractInPlace=function(otherVector){this.x-=otherVector.x;this.y-=otherVector.y;this.z-=otherVector.z;};BABYLON.Vector3.prototype.subtract=function(otherVector){return new BABYLON.Vector3(this.x-otherVector.x,this.y-otherVector.y,this.z-otherVector.z);};BABYLON.Vector3.prototype.subtractToRef=function(otherVector,result){result.x=this.x-otherVector.x;result.y=this.y-otherVector.y;result.z=this.z-otherVector.z;};BABYLON.Vector3.prototype.subtractFromFloats=function(x,y,z){return new BABYLON.Vector3(this.x-x,this.y-y,this.z-z);};BABYLON.Vector3.prototype.subtractFromFloatsToRef=function(x,y,z,result){result.x=this.x-x;result.y=this.y-y;result.z=this.z-z;};BABYLON.Vector3.prototype.negate=function(){return new BABYLON.Vector3(-this.x,-this.y,-this.z);};BABYLON.Vector3.prototype.scaleInPlace=function(scale){this.x*=scale;this.y*=scale;this.z*=scale;};BABYLON.Vector3.prototype.scale=function(scale){return new BABYLON.Vector3(this.x*scale,this.y*scale,this.z*scale);};BABYLON.Vector3.prototype.scaleToRef=function(scale,result){result.x=this.x*scale;result.y=this.y*scale;result.z=this.z*scale;};BABYLON.Vector3.prototype.equals=function(otherVector){return this.x===otherVector.x&&this.y===otherVector.y&&this.z===otherVector.z;};BABYLON.Vector3.prototype.equalsToFloats=function(x,y,z){return this.x===x&&this.y===y&&this.z===z;};BABYLON.Vector3.prototype.multiplyInPlace=function(otherVector){this.x*=otherVector.x;this.y*=otherVector.y;this.z*=otherVector.z;};BABYLON.Vector3.prototype.multiply=function(otherVector){return new BABYLON.Vector3(this.x*otherVector.x,this.y*otherVector.y,this.z*otherVector.z);};BABYLON.Vector3.prototype.multiplyToRef=function(otherVector,result){result.x=this.x*otherVector.x;result.y=this.y*otherVector.y;result.z=this.z*otherVector.z;};BABYLON.Vector3.prototype.multiplyByFloats=function(x,y,z){return new BABYLON.Vector3(this.x*x,this.y*y,this.z*z);};BABYLON.Vector3.prototype.divide=function(otherVector){return new BABYLON.Vector3(this.x/otherVector.x,this.y/otherVector.y,this.z/otherVector.z);};BABYLON.Vector3.prototype.divideToRef=function(otherVector,result){result.x=this.x/otherVector.x;result.y=this.y/otherVector.y;result.z=this.z/otherVector.z;};BABYLON.Vector3.prototype.length=function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z);};BABYLON.Vector3.prototype.lengthSquared=function(){return(this.x*this.x+this.y*this.y+this.z*this.z);};BABYLON.Vector3.prototype.normalize=function(){var len=this.length();if(len===0)return;var num=1.0/len;this.x*=num;this.y*=num;this.z*=num;};BABYLON.Vector3.prototype.clone=function(){return new BABYLON.Vector3(this.x,this.y,this.z);};BABYLON.Vector3.prototype.copyFrom=function(source){this.x=source.x;this.y=source.y;this.z=source.z;};BABYLON.Vector3.prototype.copyFromFloats=function(x,y,z){this.x=x;this.y=y;this.z=z;};BABYLON.Vector3.FromArray=function(array,offset){if(!offset){offset=0;}return new BABYLON.Vector3(array[offset],array[offset+1],array[offset+2]);};BABYLON.Vector3.FromArrayToRef=function(array,offset,result){if(!offset){offset=0;}result.x=array[offset];result.y=array[offset+1];result.z=array[offset+2];};BABYLON.Vector3.FromFloatsToRef=function(x,y,z,result){result.x=x;result.y=y;result.z=z;};BABYLON.Vector3.Zero=function(){return new BABYLON.Vector3(0,0,0);};BABYLON.Vector3.Up=function(){return new BABYLON.Vector3(0,1.0,0);};BABYLON.Vector3.TransformCoordinates=function(vector,transformation){var result=BABYLON.Vector3.Zero();BABYLON.Vector3.TransformCoordinatesToRef(vector,transformation,result);return result;};BABYLON.Vector3.TransformCoordinatesToRef=function(vector,transformation,result){var x=(vector.x*transformation.m[0])+(vector.y*transformation.m[4])+(vector.z*transformation.m[8])+transformation.m[12];var y=(vector.x*transformation.m[1])+(vector.y*transformation.m[5])+(vector.z*transformation.m[9])+transformation.m[13];var z=(vector.x*transformation.m[2])+(vector.y*transformation.m[6])+(vector.z*transformation.m[10])+transformation.m[14];var w=(vector.x*transformation.m[3])+(vector.y*transformation.m[7])+(vector.z*transformation.m[11])+transformation.m[15];result.x=x/w;result.y=y/w;result.z=z/w;};BABYLON.Vector3.TransformCoordinatesFromFloatsToRef=function(x,y,z,transformation,result){var rx=(x*transformation.m[0])+(y*transformation.m[4])+(z*transformation.m[8])+transformation.m[12];var ry=(x*transformation.m[1])+(y*transformation.m[5])+(z*transformation.m[9])+transformation.m[13];var rz=(x*transformation.m[2])+(y*transformation.m[6])+(z*transformation.m[10])+transformation.m[14];var rw=(x*transformation.m[3])+(y*transformation.m[7])+(z*transformation.m[11])+transformation.m[15];result.x=rx/rw;result.y=ry/rw;result.z=rz/rw;};BABYLON.Vector3.TransformNormal=function(vector,transformation){var result=BABYLON.Vector3.Zero();BABYLON.Vector3.TransformNormalToRef(vector,transformation,result);return result;};BABYLON.Vector3.TransformNormalToRef=function(vector,transformation,result){result.x=(vector.x*transformation.m[0])+(vector.y*transformation.m[4])+(vector.z*transformation.m[8]);result.y=(vector.x*transformation.m[1])+(vector.y*transformation.m[5])+(vector.z*transformation.m[9]);result.z=(vector.x*transformation.m[2])+(vector.y*transformation.m[6])+(vector.z*transformation.m[10]);};BABYLON.Vector3.TransformNormalFromFloatsToRef=function(x,y,z,transformation,result){result.x=(x*transformation.m[0])+(y*transformation.m[4])+(z*transformation.m[8]);result.y=(x*transformation.m[1])+(y*transformation.m[5])+(z*transformation.m[9]);result.z=(x*transformation.m[2])+(y*transformation.m[6])+(z*transformation.m[10]);};BABYLON.Vector3.CatmullRom=function(value1,value2,value3,value4,amount){var squared=amount*amount;var cubed=amount*squared;var x=0.5*((((2.0*value2.x)+((-value1.x+value3.x)*amount))+(((((2.0*value1.x)-(5.0*value2.x))+(4.0*value3.x))-value4.x)*squared))+((((-value1.x+(3.0*value2.x))-(3.0*value3.x))+value4.x)*cubed));var y=0.5*((((2.0*value2.y)+((-value1.y+value3.y)*amount))+(((((2.0*value1.y)-(5.0*value2.y))+(4.0*value3.y))-value4.y)*squared))+((((-value1.y+(3.0*value2.y))-(3.0*value3.y))+value4.y)*cubed));var z=0.5*((((2.0*value2.z)+((-value1.z+value3.z)*amount))+(((((2.0*value1.z)-(5.0*value2.z))+(4.0*value3.z))-value4.z)*squared))+((((-value1.z+(3.0*value2.z))-(3.0*value3.z))+value4.z)*cubed));return new BABYLON.Vector3(x,y,z);};BABYLON.Vector3.Clamp=function(value,min,max){var x=value.x;x=(x>max.x)?max.x:x;x=(xmax.y)?max.y:y;y=(ymax.z)?max.z:z;z=(zright.x)?left.x:right.x;var y=(left.y>right.y)?left.y:right.y;var z=(left.z>right.z)?left.z:right.z;return new BABYLON.Vector3(x,y,z);};BABYLON.Vector3.Distance=function(value1,value2){return Math.sqrt(BABYLON.Vector3.DistanceSquared(value1,value2));};BABYLON.Vector3.DistanceSquared=function(value1,value2){var x=value1.x-value2.x;var y=value1.y-value2.y;var z=value1.z-value2.z;return(x*x)+(y*y)+(z*z);};BABYLON.Quaternion=function(initialX,initialY,initialZ,initialW){this.x=initialX;this.y=initialY;this.z=initialZ;this.w=initialW;};BABYLON.Quaternion.prototype.toString=function(){return"{X: "+this.x+" Y:"+this.y+" Z:"+this.z+" W:"+this.w+"}";};BABYLON.Quaternion.prototype.equals=function(otherQuaternion){return this.x===otherQuaternion.x&&this.y===otherQuaternion.y&&this.z===otherQuaternion.z&&this.w===otherQuaternion.w;};BABYLON.Quaternion.prototype.clone=function(){return new BABYLON.Quaternion(this.x,this.y,this.z,this.w);};BABYLON.Quaternion.prototype.copyFrom=function(other){this.x=other.x;this.y=other.y;this.z=other.z;this.w=other.w;};BABYLON.Quaternion.prototype.add=function(other){return new BABYLON.Quaternion(this.x+other.x,this.y+other.y,this.z+other.z,this.w+other.w);};BABYLON.Quaternion.prototype.scale=function(value){return new BABYLON.Quaternion(this.x*value,this.y*value,this.z*value,this.w*value);};BABYLON.Quaternion.prototype.multiply=function(q1){var result=new BABYLON.Quaternion(0,0,0,1.0);this.multiplyToRef(q1,result);return result;};BABYLON.Quaternion.prototype.multiplyToRef=function(q1,result){result.x=this.x*q1.w+this.y*q1.z-this.z*q1.y+this.w*q1.x;result.y=-this.x*q1.z+this.y*q1.w+this.z*q1.x+this.w*q1.y;result.z=this.x*q1.y-this.y*q1.x+this.z*q1.w+this.w*q1.z;result.w=-this.x*q1.x-this.y*q1.y-this.z*q1.z+this.w*q1.w;};BABYLON.Quaternion.prototype.length=function(){return Math.sqrt((this.x*this.x)+(this.y*this.y)+(this.z*this.z)+(this.w*this.w));};BABYLON.Quaternion.prototype.normalize=function(){var length=1.0/this.length();this.x*=length;this.y*=length;this.z*=length;this.w*=length;};BABYLON.Quaternion.prototype.toEulerAngles=function(){var qx=this.x;var qy=this.y;var qz=this.z;var qw=this.w;var sqx=qx*qx;var sqy=qy*qy;var sqz=qz*qz;var yaw=Math.atan2(2.0*(qy*qw-qx*qz),1.0-2.0*(sqy+sqz));var pitch=Math.asin(2.0*(qx*qy+qz*qw));var roll=Math.atan2(2.0*(qx*qw-qy*qz),1.0-2.0*(sqx+sqz));var gimbaLockTest=qx*qy+qz*qw;if(gimbaLockTest>0.499){yaw=2.0*Math.atan2(qx,qw);roll=0;}else if(gimbaLockTest<-0.499){yaw=-2.0*Math.atan2(qx,qw);roll=0;}return new BABYLON.Vector3(pitch,yaw,roll);};BABYLON.Quaternion.prototype.toRotationMatrix=function(result){var xx=this.x*this.x;var yy=this.y*this.y;var zz=this.z*this.z;var xy=this.x*this.y;var zw=this.z*this.w;var zx=this.z*this.x;var yw=this.y*this.w;var yz=this.y*this.z;var xw=this.x*this.w;result.m[0]=1.0-(2.0*(yy+zz));result.m[1]=2.0*(xy+zw);result.m[2]=2.0*(zx-yw);result.m[3]=0;result.m[4]=2.0*(xy-zw);result.m[5]=1.0-(2.0*(zz+xx));result.m[6]=2.0*(yz+xw);result.m[7]=0;result.m[8]=2.0*(zx+yw);result.m[9]=2.0*(yz-xw);result.m[10]=1.0-(2.0*(yy+xx));result.m[11]=0;result.m[12]=0;result.m[13]=0;result.m[14]=0;result.m[15]=1.0;};BABYLON.Quaternion.FromArray=function(array,offset){if(!offset){offset=0;}return new BABYLON.Quaternion(array[offset],array[offset+1],array[offset+2],array[offset+3]);};BABYLON.Quaternion.RotationYawPitchRoll=function(yaw,pitch,roll){var result=new BABYLON.Quaternion();BABYLON.Quaternion.RotationYawPitchRollToRef(yaw,pitch,roll,result);return result;};BABYLON.Quaternion.RotationYawPitchRollToRef=function(yaw,pitch,roll,result){var halfRoll=roll*0.5;var halfPitch=pitch*0.5;var halfYaw=yaw*0.5;var sinRoll=Math.sin(halfRoll);var cosRoll=Math.cos(halfRoll);var sinPitch=Math.sin(halfPitch);var cosPitch=Math.cos(halfPitch);var sinYaw=Math.sin(halfYaw);var cosYaw=Math.cos(halfYaw);result.x=(cosYaw*sinPitch*cosRoll)+(sinYaw*cosPitch*sinRoll);result.y=(sinYaw*cosPitch*cosRoll)-(cosYaw*sinPitch*sinRoll);result.z=(cosYaw*cosPitch*sinRoll)-(sinYaw*sinPitch*cosRoll);result.w=(cosYaw*cosPitch*cosRoll)+(sinYaw*sinPitch*sinRoll);};BABYLON.Quaternion.Slerp=function(left,right,amount){var num2;var num3;var num=amount;var num4=(((left.x*right.x)+(left.y*right.y))+(left.z*right.z))+(left.w*right.w);var flag=false;if(num4<0){flag=true;num4=-num4;}if(num4>0.999999){num3=1-num;num2=flag?-num:num;}else{var num5=Math.acos(num4);var num6=(1.0/Math.sin(num5));num3=(Math.sin((1.0-num)*num5))*num6;num2=flag?((-Math.sin(num*num5))*num6):((Math.sin(num*num5))*num6);}return new BABYLON.Quaternion((num3*left.x)+(num2*right.x),(num3*left.y)+(num2*right.y),(num3*left.z)+(num2*right.z),(num3*left.w)+(num2*right.w));};if(!BABYLON.MatrixType){BABYLON.MatrixType=(typeof Float32Array!=='undefined')?Float32Array:Array;}BABYLON.Matrix=function(){this.m=new BABYLON.MatrixType(16);};BABYLON.Matrix.prototype.isIdentity=function(){if(this.m[0]!=1.0||this.m[5]!=1.0||this.m[10]!=1.0||this.m[15]!=1.0)return false;if(this.m[1]!=0.0||this.m[2]!=0.0||this.m[3]!=0.0||this.m[4]!=0.0||this.m[6]!=0.0||this.m[7]!=0.0||this.m[8]!=0.0||this.m[9]!=0.0||this.m[11]!=0.0||this.m[12]!=0.0||this.m[13]!=0.0||this.m[14]!=0.0)return false;return true;};BABYLON.Matrix.prototype.determinant=function(){var temp1=(this.m[10]*this.m[15])-(this.m[11]*this.m[14]);var temp2=(this.m[9]*this.m[15])-(this.m[11]*this.m[13]);var temp3=(this.m[9]*this.m[14])-(this.m[10]*this.m[13]);var temp4=(this.m[8]*this.m[15])-(this.m[11]*this.m[12]);var temp5=(this.m[8]*this.m[14])-(this.m[10]*this.m[12]);var temp6=(this.m[8]*this.m[13])-(this.m[9]*this.m[12]);return((((this.m[0]*(((this.m[5]*temp1)-(this.m[6]*temp2))+(this.m[7]*temp3)))-(this.m[1]*(((this.m[4]*temp1)-(this.m[6]*temp4))+(this.m[7]*temp5))))+(this.m[2]*(((this.m[4]*temp2)-(this.m[5]*temp4))+(this.m[7]*temp6))))-(this.m[3]*(((this.m[4]*temp3)-(this.m[5]*temp5))+(this.m[6]*temp6))));};BABYLON.Matrix.prototype.toArray=function(){return this.m;};BABYLON.Matrix.prototype.invert=function(){this.invertToRef(this);};BABYLON.Matrix.prototype.invertToRef=function(other){var l1=this.m[0];var l2=this.m[1];var l3=this.m[2];var l4=this.m[3];var l5=this.m[4];var l6=this.m[5];var l7=this.m[6];var l8=this.m[7];var l9=this.m[8];var l10=this.m[9];var l11=this.m[10];var l12=this.m[11];var l13=this.m[12];var l14=this.m[13];var l15=this.m[14];var l16=this.m[15];var l17=(l11*l16)-(l12*l15);var l18=(l10*l16)-(l12*l14);var l19=(l10*l15)-(l11*l14);var l20=(l9*l16)-(l12*l13);var l21=(l9*l15)-(l11*l13);var l22=(l9*l14)-(l10*l13);var l23=((l6*l17)-(l7*l18))+(l8*l19);var l24=-(((l5*l17)-(l7*l20))+(l8*l21));var l25=((l5*l18)-(l6*l20))+(l8*l22);var l26=-(((l5*l19)-(l6*l21))+(l7*l22));var l27=1.0/((((l1*l23)+(l2*l24))+(l3*l25))+(l4*l26));var l28=(l7*l16)-(l8*l15);var l29=(l6*l16)-(l8*l14);var l30=(l6*l15)-(l7*l14);var l31=(l5*l16)-(l8*l13);var l32=(l5*l15)-(l7*l13);var l33=(l5*l14)-(l6*l13);var l34=(l7*l12)-(l8*l11);var l35=(l6*l12)-(l8*l10);var l36=(l6*l11)-(l7*l10);var l37=(l5*l12)-(l8*l9);var l38=(l5*l11)-(l7*l9);var l39=(l5*l10)-(l6*l9);other.m[0]=l23*l27;other.m[4]=l24*l27;other.m[8]=l25*l27;other.m[12]=l26*l27;other.m[1]=-(((l2*l17)-(l3*l18))+(l4*l19))*l27;other.m[5]=(((l1*l17)-(l3*l20))+(l4*l21))*l27;other.m[9]=-(((l1*l18)-(l2*l20))+(l4*l22))*l27;other.m[13]=(((l1*l19)-(l2*l21))+(l3*l22))*l27;other.m[2]=(((l2*l28)-(l3*l29))+(l4*l30))*l27;other.m[6]=-(((l1*l28)-(l3*l31))+(l4*l32))*l27;other.m[10]=(((l1*l29)-(l2*l31))+(l4*l33))*l27;other.m[14]=-(((l1*l30)-(l2*l32))+(l3*l33))*l27;other.m[3]=-(((l2*l34)-(l3*l35))+(l4*l36))*l27;other.m[7]=(((l1*l34)-(l3*l37))+(l4*l38))*l27;other.m[11]=-(((l1*l35)-(l2*l37))+(l4*l39))*l27;other.m[15]=(((l1*l36)-(l2*l38))+(l3*l39))*l27;};BABYLON.Matrix.prototype.setTranslation=function(vector3){this.m[12]=vector3.x;this.m[13]=vector3.y;this.m[14]=vector3.z;};BABYLON.Matrix.prototype.multiply=function(other){var result=new BABYLON.Matrix();this.multiplyToRef(other,result);return result;};BABYLON.Matrix.prototype.copyFrom=function(other){for(var index=0;index<16;index++){this.m[index]=other.m[index];}};BABYLON.Matrix.prototype.multiplyToRef=function(other,result){this.multiplyToArray(other,result.m,0);};BABYLON.Matrix.prototype.multiplyToArray=function(other,result,offset){result[offset]=this.m[0]*other.m[0]+this.m[1]*other.m[4]+this.m[2]*other.m[8]+this.m[3]*other.m[12];result[offset+1]=this.m[0]*other.m[1]+this.m[1]*other.m[5]+this.m[2]*other.m[9]+this.m[3]*other.m[13];result[offset+2]=this.m[0]*other.m[2]+this.m[1]*other.m[6]+this.m[2]*other.m[10]+this.m[3]*other.m[14];result[offset+3]=this.m[0]*other.m[3]+this.m[1]*other.m[7]+this.m[2]*other.m[11]+this.m[3]*other.m[15];result[offset+4]=this.m[4]*other.m[0]+this.m[5]*other.m[4]+this.m[6]*other.m[8]+this.m[7]*other.m[12];result[offset+5]=this.m[4]*other.m[1]+this.m[5]*other.m[5]+this.m[6]*other.m[9]+this.m[7]*other.m[13];result[offset+6]=this.m[4]*other.m[2]+this.m[5]*other.m[6]+this.m[6]*other.m[10]+this.m[7]*other.m[14];result[offset+7]=this.m[4]*other.m[3]+this.m[5]*other.m[7]+this.m[6]*other.m[11]+this.m[7]*other.m[15];result[offset+8]=this.m[8]*other.m[0]+this.m[9]*other.m[4]+this.m[10]*other.m[8]+this.m[11]*other.m[12];result[offset+9]=this.m[8]*other.m[1]+this.m[9]*other.m[5]+this.m[10]*other.m[9]+this.m[11]*other.m[13];result[offset+10]=this.m[8]*other.m[2]+this.m[9]*other.m[6]+this.m[10]*other.m[10]+this.m[11]*other.m[14];result[offset+11]=this.m[8]*other.m[3]+this.m[9]*other.m[7]+this.m[10]*other.m[11]+this.m[11]*other.m[15];result[offset+12]=this.m[12]*other.m[0]+this.m[13]*other.m[4]+this.m[14]*other.m[8]+this.m[15]*other.m[12];result[offset+13]=this.m[12]*other.m[1]+this.m[13]*other.m[5]+this.m[14]*other.m[9]+this.m[15]*other.m[13];result[offset+14]=this.m[12]*other.m[2]+this.m[13]*other.m[6]+this.m[14]*other.m[10]+this.m[15]*other.m[14];result[offset+15]=this.m[12]*other.m[3]+this.m[13]*other.m[7]+this.m[14]*other.m[11]+this.m[15]*other.m[15];};BABYLON.Matrix.prototype.equals=function(value){return(this.m[0]===value.m[0]&&this.m[1]===value.m[1]&&this.m[2]===value.m[2]&&this.m[3]===value.m[3]&&this.m[4]===value.m[4]&&this.m[5]===value.m[5]&&this.m[6]===value.m[6]&&this.m[7]===value.m[7]&&this.m[8]===value.m[8]&&this.m[9]===value.m[9]&&this.m[10]===value.m[10]&&this.m[11]===value.m[11]&&this.m[12]===value.m[12]&&this.m[13]===value.m[13]&&this.m[14]===value.m[14]&&this.m[15]===value.m[15]);};BABYLON.Matrix.prototype.clone=function(){return BABYLON.Matrix.FromValues(this.m[0],this.m[1],this.m[2],this.m[3],this.m[4],this.m[5],this.m[6],this.m[7],this.m[8],this.m[9],this.m[10],this.m[11],this.m[12],this.m[13],this.m[14],this.m[15]);};BABYLON.Matrix.FromArray=function(array,offset){var result=new BABYLON.Matrix();BABYLON.Matrix.FromArrayToRef(array,offset,result);return result;};BABYLON.Matrix.FromArrayToRef=function(array,offset,result){if(!offset){offset=0;}for(var index=0;index<16;index++){result.m[index]=array[index+offset];}};BABYLON.Matrix.FromValuesToRef=function(initialM11,initialM12,initialM13,initialM14,initialM21,initialM22,initialM23,initialM24,initialM31,initialM32,initialM33,initialM34,initialM41,initialM42,initialM43,initialM44,result){result.m[0]=initialM11;result.m[1]=initialM12;result.m[2]=initialM13;result.m[3]=initialM14;result.m[4]=initialM21;result.m[5]=initialM22;result.m[6]=initialM23;result.m[7]=initialM24;result.m[8]=initialM31;result.m[9]=initialM32;result.m[10]=initialM33;result.m[11]=initialM34;result.m[12]=initialM41;result.m[13]=initialM42;result.m[14]=initialM43;result.m[15]=initialM44;};BABYLON.Matrix.FromValues=function(initialM11,initialM12,initialM13,initialM14,initialM21,initialM22,initialM23,initialM24,initialM31,initialM32,initialM33,initialM34,initialM41,initialM42,initialM43,initialM44){var result=new BABYLON.Matrix();result.m[0]=initialM11;result.m[1]=initialM12;result.m[2]=initialM13;result.m[3]=initialM14;result.m[4]=initialM21;result.m[5]=initialM22;result.m[6]=initialM23;result.m[7]=initialM24;result.m[8]=initialM31;result.m[9]=initialM32;result.m[10]=initialM33;result.m[11]=initialM34;result.m[12]=initialM41;result.m[13]=initialM42;result.m[14]=initialM43;result.m[15]=initialM44;return result;};BABYLON.Matrix.Identity=function(){return BABYLON.Matrix.FromValues(1.0,0,0,0,0,1.0,0,0,0,0,1.0,0,0,0,0,1.0);};BABYLON.Matrix.IdentityToRef=function(result){BABYLON.Matrix.FromValuesToRef(1.0,0,0,0,0,1.0,0,0,0,0,1.0,0,0,0,0,1.0,result);};BABYLON.Matrix.Zero=function(){return BABYLON.Matrix.FromValues(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);};BABYLON.Matrix.RotationX=function(angle){var result=new BABYLON.Matrix();BABYLON.Matrix.RotationXToRef(angle,result);return result;};BABYLON.Matrix.RotationXToRef=function(angle,result){var s=Math.sin(angle);var c=Math.cos(angle);result.m[0]=1.0;result.m[15]=1.0;result.m[5]=c;result.m[10]=c;result.m[9]=-s;result.m[6]=s;result.m[1]=0;result.m[2]=0;result.m[3]=0;result.m[4]=0;result.m[7]=0;result.m[8]=0;result.m[11]=0;result.m[12]=0;result.m[13]=0;result.m[14]=0;};BABYLON.Matrix.RotationY=function(angle){var result=new BABYLON.Matrix();BABYLON.Matrix.RotationYToRef(angle,result);return result;};BABYLON.Matrix.RotationYToRef=function(angle,result){var s=Math.sin(angle);var c=Math.cos(angle);result.m[5]=1.0;result.m[15]=1.0;result.m[0]=c;result.m[2]=-s;result.m[8]=s;result.m[10]=c;result.m[1]=0;result.m[3]=0;result.m[4]=0;result.m[6]=0;result.m[7]=0;result.m[9]=0;result.m[11]=0;result.m[12]=0;result.m[13]=0;result.m[14]=0;};BABYLON.Matrix.RotationZ=function(angle){var result=new BABYLON.Matrix();BABYLON.Matrix.RotationZToRef(angle,result);return result;};BABYLON.Matrix.RotationZToRef=function(angle,result){var s=Math.sin(angle);var c=Math.cos(angle);result.m[10]=1.0;result.m[15]=1.0;result.m[0]=c;result.m[1]=s;result.m[4]=-s;result.m[5]=c;result.m[2]=0;result.m[3]=0;result.m[6]=0;result.m[7]=0;result.m[8]=0;result.m[9]=0;result.m[11]=0;result.m[12]=0;result.m[13]=0;result.m[14]=0;};BABYLON.Matrix.RotationAxis=function(axis,angle){var s=Math.sin(-angle);var c=Math.cos(-angle);var c1=1-c;axis.normalize();var result=BABYLON.Matrix.Zero();result.m[0]=(axis.x*axis.x)*c1+c;result.m[1]=(axis.x*axis.y)*c1-(axis.z*s);result.m[2]=(axis.x*axis.z)*c1+(axis.y*s);result.m[3]=0.0;result.m[4]=(axis.y*axis.x)*c1+(axis.z*s);result.m[5]=(axis.y*axis.y)*c1+c;result.m[6]=(axis.y*axis.z)*c1-(axis.x*s);result.m[7]=0.0;result.m[8]=(axis.z*axis.x)*c1-(axis.y*s);result.m[9]=(axis.z*axis.y)*c1+(axis.x*s);result.m[10]=(axis.z*axis.z)*c1+c;result.m[11]=0.0;result.m[15]=1.0;return result;};BABYLON.Matrix.RotationYawPitchRoll=function(yaw,pitch,roll){var result=new BABYLON.Matrix();BABYLON.Matrix.RotationYawPitchRollToRef(yaw,pitch,roll,result);return result;};var tempQuaternion=new BABYLON.Quaternion();BABYLON.Matrix.RotationYawPitchRollToRef=function(yaw,pitch,roll,result){BABYLON.Quaternion.RotationYawPitchRollToRef(yaw,pitch,roll,tempQuaternion);tempQuaternion.toRotationMatrix(result);};BABYLON.Matrix.Scaling=function(x,y,z){var result=BABYLON.Matrix.Zero();BABYLON.Matrix.ScalingToRef(x,y,z,result);return result;};BABYLON.Matrix.ScalingToRef=function(x,y,z,result){result.m[0]=x;result.m[1]=0;result.m[2]=0;result.m[3]=0;result.m[4]=0;result.m[5]=y;result.m[6]=0;result.m[7]=0;result.m[8]=0;result.m[9]=0;result.m[10]=z;result.m[11]=0;result.m[12]=0;result.m[13]=0;result.m[14]=0;result.m[15]=1.0;};BABYLON.Matrix.Translation=function(x,y,z){var result=BABYLON.Matrix.Identity();BABYLON.Matrix.TranslationToRef(x,y,z,result);return result;};BABYLON.Matrix.TranslationToRef=function(x,y,z,result){BABYLON.Matrix.FromValuesToRef(1.0,0,0,0,0,1.0,0,0,0,0,1.0,0,x,y,z,1.0,result);};BABYLON.Matrix.LookAtLH=function(eye,target,up){var result=BABYLON.Matrix.Zero();BABYLON.Matrix.LookAtLHToRef(eye,target,up,result);return result;};var xAxis=BABYLON.Vector3.Zero();var yAxis=BABYLON.Vector3.Zero();var zAxis=BABYLON.Vector3.Zero();BABYLON.Matrix.LookAtLHToRef=function(eye,target,up,result){target.subtractToRef(eye,zAxis);zAxis.normalize();BABYLON.Vector3.CrossToRef(up,zAxis,xAxis);xAxis.normalize();BABYLON.Vector3.CrossToRef(zAxis,xAxis,yAxis);yAxis.normalize();var ex=-BABYLON.Vector3.Dot(xAxis,eye);var ey=-BABYLON.Vector3.Dot(yAxis,eye);var ez=-BABYLON.Vector3.Dot(zAxis,eye);return BABYLON.Matrix.FromValuesToRef(xAxis.x,yAxis.x,zAxis.x,0,xAxis.y,yAxis.y,zAxis.y,0,xAxis.z,yAxis.z,zAxis.z,0,ex,ey,ez,1,result);};BABYLON.Matrix.OrthoLH=function(width,height,znear,zfar){var hw=2.0/width;var hh=2.0/height;var id=1.0/(zfar-znear);var nid=znear/(znear-zfar);return BABYLON.Matrix.FromValues(hw,0,0,0,0,hh,0,0,0,0,id,0,0,0,nid,1);};BABYLON.Matrix.OrthoOffCenterLH=function(left,right,bottom,top,znear,zfar){var matrix=BABYLON.Matrix.Zero();BABYLON.Matrix.OrthoOffCenterLHToRef(left,right,bottom,top,znear,zfar,matrix);return matrix;};BABYLON.Matrix.OrthoOffCenterLHToRef=function(left,right,bottom,top,znear,zfar,result){result.m[0]=2.0/(right-left);result.m[1]=result.m[2]=result.m[3]=0;result.m[5]=2.0/(top-bottom);result.m[4]=result.m[6]=result.m[7]=0;result.m[10]=-1.0/(znear-zfar);result.m[8]=result.m[9]=result.m[11]=0;result.m[12]=(left+right)/(left-right);result.m[13]=(top+bottom)/(bottom-top);result.m[14]=znear/(znear-zfar);result.m[15]=1.0;};BABYLON.Matrix.PerspectiveLH=function(width,height,znear,zfar){var matrix=BABYLON.Matrix.Zero();matrix.m[0]=(2.0*znear)/width;matrix.m[1]=matrix.m[2]=matrix.m[3]=0.0;matrix.m[5]=(2.0*znear)/height;matrix.m[4]=matrix.m[6]=matrix.m[7]=0.0;matrix.m[10]=-zfar/(znear-zfar);matrix.m[8]=matrix.m[9]=0.0;matrix.m[11]=1.0;matrix.m[12]=matrix.m[13]=matrix.m[15]=0.0;matrix.m[14]=(znear*zfar)/(znear-zfar);return matrix;};BABYLON.Matrix.PerspectiveFovLH=function(fov,aspect,znear,zfar){var matrix=BABYLON.Matrix.Zero();BABYLON.Matrix.PerspectiveFovLHToRef(fov,aspect,znear,zfar,matrix);return matrix;};BABYLON.Matrix.PerspectiveFovLHToRef=function(fov,aspect,znear,zfar,result){var tan=1.0/(Math.tan(fov*0.5));result.m[0]=tan/aspect;result.m[1]=result.m[2]=result.m[3]=0.0;result.m[5]=tan;result.m[4]=result.m[6]=result.m[7]=0.0;result.m[8]=result.m[9]=0.0;result.m[10]=-zfar/(znear-zfar);result.m[11]=1.0;result.m[12]=result.m[13]=result.m[15]=0.0;result.m[14]=(znear*zfar)/(znear-zfar);};BABYLON.Matrix.AffineTransformation=function(scaling,rotationCenter,rotation,translation){return BABYLON.Matrix.Scaling(scaling,scaling,scaling)*BABYLON.Matrix.Translation(-rotationCenter)*BABYLON.Matrix.RotationQuaternion(rotation)*BABYLON.Matrix.Translation(rotationCenter)*BABYLON.Matrix.Translation(translation);};BABYLON.Matrix.GetFinalMatrix=function(viewport,world,view,projection,zmin,zmax){var cw=viewport.width;var ch=viewport.height;var cx=viewport.x;var cy=viewport.y;var viewportMatrix=new BABYLON.Matrix(cw/2.0,0,0,0,0,-ch/2.0,0,0,0,0,zmax-zmin,0,cx+cw/2.0,ch/2.0+cy,zmin,1);return world.multiply(view).multiply(projection).multiply(viewportMatrix);};BABYLON.Matrix.Transpose=function(matrix){var result=new BABYLON.Matrix();result.m[0]=matrix.m[0];result.m[1]=matrix.m[4];result.m[2]=matrix.m[8];result.m[3]=matrix.m[12];result.m[4]=matrix.m[1];result.m[5]=matrix.m[5];result.m[6]=matrix.m[9];result.m[7]=matrix.m[13];result.m[8]=matrix.m[2];result.m[9]=matrix.m[6];result.m[10]=matrix.m[10];result.m[11]=matrix.m[14];result.m[12]=matrix.m[3];result.m[13]=matrix.m[7];result.m[14]=matrix.m[11];result.m[15]=matrix.m[15];return result;};BABYLON.Matrix.Reflection=function(plane){var matrix=new BABYLON.Matrix();BABYLON.Matrix.ReflectionToRef(plane,matrix);return matrix;};BABYLON.Matrix.ReflectionToRef=function(plane,result){plane.normalize();var x=plane.normal.x;var y=plane.normal.y;var z=plane.normal.z;var temp=-2*x;var temp2=-2*y;var temp3=-2*z;result.m[0]=(temp*x)+1;result.m[1]=temp2*x;result.m[2]=temp3*x;result.m[3]=0.0;result.m[4]=temp*y;result.m[5]=(temp2*y)+1;result.m[6]=temp3*y;result.m[7]=0.0;result.m[8]=temp*z;result.m[9]=temp2*z;result.m[10]=(temp3*z)+1;result.m[11]=0.0;result.m[12]=temp*plane.d;result.m[13]=temp2*plane.d;result.m[14]=temp3*plane.d;result.m[15]=1.0;};BABYLON.Plane=function(a,b,c,d){this.normal=new BABYLON.Vector3(a,b,c);this.d=d;};BABYLON.Plane.prototype.normalize=function(){var norm=(Math.sqrt((this.normal.x*this.normal.x)+(this.normal.y*this.normal.y)+(this.normal.z*this.normal.z)));var magnitude=0;if(norm!=0){magnitude=1.0/norm;}this.normal.x*=magnitude;this.normal.y*=magnitude;this.normal.z*=magnitude;this.d*=magnitude;};BABYLON.Plane.prototype.transform=function(transformation){var transposedMatrix=BABYLON.Matrix.Transpose(transformation);var x=this.normal.x;var y=this.normal.y;var z=this.normal.z;var d=this.d;var normalX=(((x*transposedMatrix.m[0])+(y*transposedMatrix.m[1]))+(z*transposedMatrix.m[2]))+(d*transposedMatrix.m[3]);var normalY=(((x*transposedMatrix.m[4])+(y*transposedMatrix.m[5]))+(z*transposedMatrix.m[6]))+(d*transposedMatrix.m[7]);var normalZ=(((x*transposedMatrix.m[8])+(y*transposedMatrix.m[9]))+(z*transposedMatrix.m[10]))+(d*transposedMatrix.m[11]);var finalD=(((x*transposedMatrix.m[12])+(y*transposedMatrix.m[13]))+(z*transposedMatrix.m[14]))+(d*transposedMatrix.m[15]);return new BABYLON.Plane(normalX,normalY,normalZ,finalD);};BABYLON.Plane.prototype.dotCoordinate=function(point){return((((this.normal.x*point.x)+(this.normal.y*point.y))+(this.normal.z*point.z))+this.d);};BABYLON.Plane.prototype.copyFromPoints=function(point1,point2,point3){var x1=point2.x-point1.x;var y1=point2.y-point1.y;var z1=point2.z-point1.z;var x2=point3.x-point1.x;var y2=point3.y-point1.y;var z2=point3.z-point1.z;var yz=(y1*z2)-(z1*y2);var xz=(z1*x2)-(x1*z2);var xy=(x1*y2)-(y1*x2);var pyth=(Math.sqrt((yz*yz)+(xz*xz)+(xy*xy)));var invPyth;if(pyth!=0){invPyth=1.0/pyth;}else{invPyth=0;}this.normal.x=yz*invPyth;this.normal.y=xz*invPyth;this.normal.z=xy*invPyth;this.d=-((this.normal.x*point1.x)+(this.normal.y*point1.y)+(this.normal.z*point1.z));};BABYLON.Plane.prototype.isFrontFacingTo=function(direction,epsilon){var dot=BABYLON.Vector3.Dot(this.normal,direction);return(dot<=epsilon);};BABYLON.Plane.prototype.signedDistanceTo=function(point){return BABYLON.Vector3.Dot(point,this.normal)+this.d;};BABYLON.Plane.FromArray=function(array){return new BABYLON.Plane(array[0],array[1],array[2],array[3]);};BABYLON.Plane.FromPoints=function(point1,point2,point3){var result=new BABYLON.Plane(0,0,0,0);result.copyFromPoints(point1,point2,point3);return result;};BABYLON.Plane.FromPositionAndNormal=function(origin,normal){var result=new BABYLON.Plane(0,0,0,0);normal.normalize();result.normal=normal;result.d=-(normal.x*origin.x+normal.y*origin.y+normal.z*origin.z);return result;};BABYLON.Plane.SignedDistanceToPlaneFromPositionAndNormal=function(origin,normal,point){var d=-(normal.x*origin.x+normal.y*origin.y+normal.z*origin.z);return BABYLON.Vector3.Dot(point,normal)+d;};BABYLON.Frustum={};BABYLON.Frustum.GetPlanes=function(transform){var frustumPlanes=[];for(var index=0;index<6;index++){frustumPlanes.push(new BABYLON.Plane(0,0,0,0));}BABYLON.Frustum.GetPlanesToRef(transform,frustumPlanes);return frustumPlanes;};BABYLON.Frustum.GetPlanesToRef=function(transform,frustumPlanes){frustumPlanes[0].normal.x=transform.m[3]+transform.m[2];frustumPlanes[0].normal.y=transform.m[7]+transform.m[6];frustumPlanes[0].normal.z=transform.m[10]+transform.m[10];frustumPlanes[0].d=transform.m[15]+transform.m[14];frustumPlanes[0].normalize();frustumPlanes[1].normal.x=transform.m[3]-transform.m[2];frustumPlanes[1].normal.y=transform.m[7]-transform.m[6];frustumPlanes[1].normal.z=transform.m[11]-transform.m[10];frustumPlanes[1].d=transform.m[15]-transform.m[14];frustumPlanes[1].normalize();frustumPlanes[2].normal.x=transform.m[3]+transform.m[0];frustumPlanes[2].normal.y=transform.m[7]+transform.m[4];frustumPlanes[2].normal.z=transform.m[11]+transform.m[8];frustumPlanes[2].d=transform.m[15]+transform.m[12];frustumPlanes[2].normalize();frustumPlanes[3].normal.x=transform.m[3]-transform.m[0];frustumPlanes[3].normal.y=transform.m[7]-transform.m[4];frustumPlanes[3].normal.z=transform.m[11]-transform.m[8];frustumPlanes[3].d=transform.m[15]-transform.m[12];frustumPlanes[3].normalize();frustumPlanes[4].normal.x=transform.m[3]-transform.m[1];frustumPlanes[4].normal.y=transform.m[7]-transform.m[5];frustumPlanes[4].normal.z=transform.m[11]-transform.m[9];frustumPlanes[4].d=transform.m[15]-transform.m[13];frustumPlanes[4].normalize();frustumPlanes[5].normal.x=transform.m[3]+transform.m[1];frustumPlanes[5].normal.y=transform.m[7]+transform.m[5];frustumPlanes[5].normal.z=transform.m[11]+transform.m[9];frustumPlanes[5].d=transform.m[15]+transform.m[13];frustumPlanes[5].normalize();};BABYLON.Viewport={};BABYLON.Viewport=function(x,y,width,height){this.width=width;this.height=height;this.x=x;this.y=y;};BABYLON.Viewport.prototype.toGlobal=function(engine){var width=engine.getRenderWidth()*engine.getHardwareScalingLevel();var height=engine.getRenderHeight()*engine.getHardwareScalingLevel();return new BABYLON.Viewport(this.x*width,this.y*height,this.width*width,this.height*height);};})();var BABYLON=BABYLON||{};(function(){BABYLON.Tools={};BABYLON.Tools.ExtractMinAndMax=function(positions,start,count){var minimum=new BABYLON.Vector3(Number.MAX_VALUE,Number.MAX_VALUE,Number.MAX_VALUE);var maximum=new BABYLON.Vector3(-Number.MAX_VALUE,-Number.MAX_VALUE,-Number.MAX_VALUE);for(var index=start;indexthis.data.length){this.data.length*=2;}};BABYLON.Tools.SmartArray.prototype.pushNoDuplicate=function(value){if(this.indexOf(value)>-1){return;}this.push(value);};BABYLON.Tools.SmartArray.prototype.sort=function(compareFn){this.data.sort(compareFn);};BABYLON.Tools.SmartArray.prototype.reset=function(){this.length=0;};BABYLON.Tools.SmartArray.prototype.concat=function(array){if(array.length===0){return;}if(this.length+array.length>this.data.length){this.data.length=(this.length+array.length)*2;}for(var index=0;indexthis.data.length){this.data.length=(this.length+array.length)*2;}for(var index=0;index=this.length){this.data[this.length++]=item;}}};BABYLON.Tools.SmartArray.prototype.indexOf=function(value){var position=this.data.indexOf(value);if(position>=this.length){return-1;}return position;};BABYLON.Tools.GetPointerPrefix=function(){var eventPrefix="pointer";if(!navigator.pointerEnabled){eventPrefix="mouse";}return eventPrefix;};BABYLON.Tools.QueueNewFrame=function(func){if(window.requestAnimationFrame)window.requestAnimationFrame(func);else if(window.msRequestAnimationFrame)window.msRequestAnimationFrame(func);else if(window.webkitRequestAnimationFrame)window.webkitRequestAnimationFrame(func);else if(window.mozRequestAnimationFrame)window.mozRequestAnimationFrame(func);else if(window.oRequestAnimationFrame)window.oRequestAnimationFrame(func);else{window.setTimeout(func,16);}};BABYLON.Tools.RequestFullscreen=function(element){if(element.requestFullscreen)element.requestFullscreen();else if(element.msRequestFullscreen)element.msRequestFullscreen();else if(element.webkitRequestFullscreen)element.webkitRequestFullscreen();else if(element.mozRequestFullScreen)element.mozRequestFullScreen();};BABYLON.Tools.ExitFullscreen=function(){if(document.exitFullscreen){document.exitFullscreen();}else if(document.mozCancelFullScreen){document.mozCancelFullScreen();}else if(document.webkitCancelFullScreen){document.webkitCancelFullScreen();}else if(document.msCancelFullScreen){document.msCancelFullScreen();}};BABYLON.Tools.BaseUrl="";BABYLON.Tools.LoadImage=function(url,onload,onerror,database){var img=new Image();img.onload=function(){onload(img);};img.onerror=function(err){onerror(img,err);};var noIndexedDB=function(){img.src=url;};var loadFromIndexedDB=function(){database.loadImageFromDB(url,img);};if(database&&database.enableTexturesOffline&&BABYLON.Database.isUASupportingBlobStorage){database.openAsync(loadFromIndexedDB,noIndexedDB);}else{if(url.indexOf("file:")===-1){noIndexedDB();}else{try{var textureName=url.substring(5);var blobURL;try{blobURL=URL.createObjectURL(BABYLON.FilesTextures[textureName],{oneTimeOnly:true});}catch(ex){blobURL=URL.createObjectURL(BABYLON.FilesTextures[textureName]);}img.src=blobURL;}catch(e){console.log("Error while trying to load texture: "+textureName);img.src=null;}}}return img;};BABYLON.Tools.LoadFile=function(url,callback,progressCallBack,database){var noIndexedDB=function(){var request=new XMLHttpRequest();var loadUrl=BABYLON.Tools.BaseUrl+url;request.open('GET',loadUrl,true);request.onprogress=progressCallBack;request.onreadystatechange=function(){if(request.readyState==4){if(request.status==200){callback(request.responseText);}else{throw new Error(request.status,"Unable to load "+loadUrl);}}};request.send(null);};var loadFromIndexedDB=function(){database.loadSceneFromDB(url,callback,progressCallBack,noIndexedDB);};if(database&&url.indexOf(".babylon")!==-1&&(database.enableSceneOffline)){database.openAsync(loadFromIndexedDB,noIndexedDB);}else{noIndexedDB();}};BABYLON.Tools.ReadFile=function(fileToLoad,callback,progressCallBack){var reader=new FileReader();reader.onload=function(e){callback(e.target.result);};reader.onprogress=progressCallBack;reader.readAsText(fileToLoad);};BABYLON.Tools.isIE=function(){return window.ActiveXObject!==undefined;};BABYLON.Tools.WithinEpsilon=function(a,b){var num=a-b;return-1.401298E-45<=num&&num<=1.401298E-45;};var cloneValue=function(source,destinationObject){if(!source)return null;if(source instanceof BABYLON.Mesh){return null;}if(source instanceof BABYLON.SubMesh){return source.clone(destinationObject);}else if(source.clone){return source.clone();}return null;};BABYLON.Tools.DeepCopy=function(source,destination,doNotCopyList,mustCopyList){for(var prop in source){if(prop[0]==="_"&&(!mustCopyList||mustCopyList.indexOf(prop)===-1)){continue;}if(doNotCopyList&&doNotCopyList.indexOf(prop)!==-1){continue;}var sourceValue=source[prop];var typeOfSourceValue=typeof sourceValue;if(typeOfSourceValue=="function"){continue;}if(typeOfSourceValue=="object"){if(sourceValue instanceof Array){destination[prop]=[];if(sourceValue.length>0){if(typeof sourceValue[0]=="object"){for(var index=0;index=2){deltaTime=previousFramesDuration[length-1]-previousFramesDuration[length-2];}if(length>=fpsRange){if(length>fpsRange){previousFramesDuration.splice(0,1);length=previousFramesDuration.length;}var sum=0;for(var id=0;id=0){this._gl.vertexAttribPointer(order,vertexDeclaration[index],this._gl.FLOAT,false,vertexStrideSize,offset);}offset+=vertexDeclaration[index]*4;}}if(this._cachedIndexBuffer!==indexBuffer){this._cachedIndexBuffer=indexBuffer;this._gl.bindBuffer(this._gl.ELEMENT_ARRAY_BUFFER,indexBuffer);}};BABYLON.Engine.prototype.bindMultiBuffers=function(vertexBuffers,indexBuffer,effect){if(this._cachedVertexBuffers!==vertexBuffers||this._cachedEffectForVertexBuffers!==effect){this._cachedVertexBuffers=vertexBuffers;this._cachedEffectForVertexBuffers=effect;var attributes=effect.getAttributesNames();for(var index=0;index=0){var vertexBuffer=vertexBuffers[attributes[index]];var stride=vertexBuffer.getStrideSize();this._gl.bindBuffer(this._gl.ARRAY_BUFFER,vertexBuffer._buffer);this._gl.vertexAttribPointer(order,stride,this._gl.FLOAT,false,stride*4,0);}}}if(this._cachedIndexBuffer!==indexBuffer){this._cachedIndexBuffer=indexBuffer;this._gl.bindBuffer(this._gl.ELEMENT_ARRAY_BUFFER,indexBuffer);}};BABYLON.Engine.prototype._releaseBuffer=function(buffer){buffer.references--;if(buffer.references===0){this._gl.deleteBuffer(buffer);}};BABYLON.Engine.prototype.draw=function(useTriangles,indexStart,indexCount){this._gl.drawElements(useTriangles?this._gl.TRIANGLES:this._gl.LINES,indexCount,this._gl.UNSIGNED_SHORT,indexStart*2);};BABYLON.Engine.prototype.createEffect=function(baseName,attributesNames,uniformsNames,samplers,defines,optionalDefines){var vertex=baseName.vertex||baseName;var fragment=baseName.fragment||baseName;var name=vertex+"+"+fragment+"@"+defines;if(this._compiledEffects[name]){return this._compiledEffects[name];}var effect=new BABYLON.Effect(baseName,attributesNames,uniformsNames,samplers,this,defines,optionalDefines);this._compiledEffects[name]=effect;return effect;};var compileShader=function(gl,source,type,defines){var shader=gl.createShader(type==="vertex"?gl.VERTEX_SHADER:gl.FRAGMENT_SHADER);gl.shaderSource(shader,(defines?defines+"\n":"")+source);gl.compileShader(shader);if(!gl.getShaderParameter(shader,gl.COMPILE_STATUS)){throw new Error(gl.getShaderInfoLog(shader));}return shader;};BABYLON.Engine.prototype.createShaderProgram=function(vertexCode,fragmentCode,defines){var vertexShader=compileShader(this._gl,vertexCode,"vertex",defines);var fragmentShader=compileShader(this._gl,fragmentCode,"fragment",defines);var shaderProgram=this._gl.createProgram();this._gl.attachShader(shaderProgram,vertexShader);this._gl.attachShader(shaderProgram,fragmentShader);this._gl.linkProgram(shaderProgram);var error=this._gl.getProgramInfoLog(shaderProgram);if(error){throw new Error(error);}this._gl.deleteShader(vertexShader);this._gl.deleteShader(fragmentShader);return shaderProgram;};BABYLON.Engine.prototype.getUniforms=function(shaderProgram,uniformsNames){var results=[];for(var index=0;index=0){this._gl.enableVertexAttribArray(effect.getAttribute(index));}}this._currentEffect=effect;};BABYLON.Engine.prototype.setMatrices=function(uniform,matrices){if(!uniform)return;this._gl.uniformMatrix4fv(uniform,false,matrices);};BABYLON.Engine.prototype.setMatrix=function(uniform,matrix){if(!uniform)return;this._gl.uniformMatrix4fv(uniform,false,matrix.toArray());};BABYLON.Engine.prototype.setFloat=function(uniform,value){if(!uniform)return;this._gl.uniform1f(uniform,value);};BABYLON.Engine.prototype.setFloat2=function(uniform,x,y){if(!uniform)return;this._gl.uniform2f(uniform,x,y);};BABYLON.Engine.prototype.setFloat3=function(uniform,x,y,z){if(!uniform)return;this._gl.uniform3f(uniform,x,y,z);};BABYLON.Engine.prototype.setBool=function(uniform,bool){if(!uniform)return;this._gl.uniform1i(uniform,bool);};BABYLON.Engine.prototype.setFloat4=function(uniform,x,y,z,w){if(!uniform)return;this._gl.uniform4f(uniform,x,y,z,w);};BABYLON.Engine.prototype.setColor3=function(uniform,color3){if(!uniform)return;this._gl.uniform3f(uniform,color3.r,color3.g,color3.b);};BABYLON.Engine.prototype.setColor4=function(uniform,color3,alpha){if(!uniform)return;this._gl.uniform4f(uniform,color3.r,color3.g,color3.b,alpha);};BABYLON.Engine.prototype.setState=function(culling){if(this._currentState.culling!==culling){if(culling){this._gl.cullFace(this.cullBackFaces?this._gl.BACK:this._gl.FRONT);this._gl.enable(this._gl.CULL_FACE);}else{this._gl.disable(this._gl.CULL_FACE);}this._currentState.culling=culling;}};BABYLON.Engine.prototype.setDepthBuffer=function(enable){if(enable){this._gl.enable(this._gl.DEPTH_TEST);}else{this._gl.disable(this._gl.DEPTH_TEST);}};BABYLON.Engine.prototype.setDepthWrite=function(enable){this._gl.depthMask(enable);};BABYLON.Engine.prototype.setColorWrite=function(enable){this._gl.colorMask(enable,enable,enable,enable);};BABYLON.Engine.prototype.setAlphaMode=function(mode){switch(mode){case BABYLON.Engine.ALPHA_DISABLE:this.setDepthWrite(true);this._gl.disable(this._gl.BLEND);break;case BABYLON.Engine.ALPHA_COMBINE:this.setDepthWrite(false);this._gl.blendFuncSeparate(this._gl.SRC_ALPHA,this._gl.ONE_MINUS_SRC_ALPHA,this._gl.ZERO,this._gl.ONE);this._gl.enable(this._gl.BLEND);break;case BABYLON.Engine.ALPHA_ADD:this.setDepthWrite(false);this._gl.blendFuncSeparate(this._gl.ONE,this._gl.ONE,this._gl.ZERO,this._gl.ONE);this._gl.enable(this._gl.BLEND);break;}};BABYLON.Engine.prototype.setAlphaTesting=function(enable){this._alphaTest=enable;};BABYLON.Engine.prototype.getAlphaTesting=function(){return this._alphaTest;};BABYLON.Engine.prototype.wipeCaches=function(){this._activeTexturesCache=[];this._currentEffect=null;this._currentState={culling:null};this._cachedVertexBuffers=null;this._cachedVertexBuffers=null;this._cachedEffectForVertexBuffers=null;};var getExponantOfTwo=function(value,max){var count=1;do{count*=2;}while(countmax)count=max;return count;};BABYLON.Engine.prototype.createTexture=function(url,noMipmap,invertY,scene){var texture=this._gl.createTexture();var that=this;var onload=function(img){var potWidth=getExponantOfTwo(img.width,that._caps.maxTextureSize);var potHeight=getExponantOfTwo(img.height,that._caps.maxTextureSize);var isPot=(img.width==potWidth&&img.height==potHeight);if(!isPot){that._workingCanvas.width=potWidth;that._workingCanvas.height=potHeight;that._workingContext.drawImage(img,0,0,img.width,img.height,0,0,potWidth,potHeight);};that._gl.bindTexture(that._gl.TEXTURE_2D,texture);that._gl.pixelStorei(that._gl.UNPACK_FLIP_Y_WEBGL,invertY===undefined?true:invertY);that._gl.texImage2D(that._gl.TEXTURE_2D,0,that._gl.RGBA,that._gl.RGBA,that._gl.UNSIGNED_BYTE,isPot?img:that._workingCanvas);that._gl.texParameteri(that._gl.TEXTURE_2D,that._gl.TEXTURE_MAG_FILTER,that._gl.LINEAR);if(noMipmap){that._gl.texParameteri(that._gl.TEXTURE_2D,that._gl.TEXTURE_MIN_FILTER,that._gl.LINEAR);}else{that._gl.texParameteri(that._gl.TEXTURE_2D,that._gl.TEXTURE_MIN_FILTER,that._gl.LINEAR_MIPMAP_LINEAR);that._gl.generateMipmap(that._gl.TEXTURE_2D);}that._gl.bindTexture(that._gl.TEXTURE_2D,null);that._activeTexturesCache=[];texture._baseWidth=img.width;texture._baseHeight=img.height;texture._width=potWidth;texture._height=potHeight;texture.isReady=true;scene._removePendingData(texture);};var onerror=function(){scene._removePendingData(texture);};scene._addPendingData(texture);BABYLON.Tools.LoadImage(url,onload,onerror,scene.database);texture.url=url;texture.noMipmap=noMipmap;texture.references=1;this._loadedTexturesCache.push(texture);return texture;};BABYLON.Engine.prototype.createDynamicTexture=function(width,height,generateMipMaps){var texture=this._gl.createTexture();width=getExponantOfTwo(width,this._caps.maxTextureSize);height=getExponantOfTwo(height,this._caps.maxTextureSize);this._gl.bindTexture(this._gl.TEXTURE_2D,texture);this._gl.texParameteri(this._gl.TEXTURE_2D,this._gl.TEXTURE_MAG_FILTER,this._gl.LINEAR);if(!generateMipMaps){this._gl.texParameteri(this._gl.TEXTURE_2D,this._gl.TEXTURE_MIN_FILTER,this._gl.LINEAR);}else{this._gl.texParameteri(this._gl.TEXTURE_2D,this._gl.TEXTURE_MIN_FILTER,this._gl.LINEAR_MIPMAP_LINEAR);}this._gl.bindTexture(this._gl.TEXTURE_2D,null);this._activeTexturesCache=[];texture._baseWidth=width;texture._baseHeight=height;texture._width=width;texture._height=height;texture.isReady=false;texture.generateMipMaps=generateMipMaps;texture.references=1;this._loadedTexturesCache.push(texture);return texture;};BABYLON.Engine.prototype.updateDynamicTexture=function(texture,canvas,invertY){this._gl.bindTexture(this._gl.TEXTURE_2D,texture);this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL,invertY);this._gl.texImage2D(this._gl.TEXTURE_2D,0,this._gl.RGBA,this._gl.RGBA,this._gl.UNSIGNED_BYTE,canvas);if(texture.generateMipMaps){this._gl.generateMipmap(this._gl.TEXTURE_2D);}this._gl.bindTexture(this._gl.TEXTURE_2D,null);this._activeTexturesCache=[];texture.isReady=true;};BABYLON.Engine.prototype.updateVideoTexture=function(texture,video){this._gl.bindTexture(this._gl.TEXTURE_2D,texture);this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL,false);if(video.videoWidth!==texture._width||video.videoHeight!==texture._height){if(!texture._workingCanvas){texture._workingCanvas=document.createElement("canvas");texture._workingContext=texture._workingCanvas.getContext("2d");texture._workingCanvas.width=texture._width;texture._workingCanvas.height=texture._height;}texture._workingContext.drawImage(video,0,0,video.videoWidth,video.videoHeight,0,0,texture._width,texture._height);this._gl.texImage2D(this._gl.TEXTURE_2D,0,this._gl.RGBA,this._gl.RGBA,this._gl.UNSIGNED_BYTE,texture._workingCanvas);}else{this._gl.texImage2D(this._gl.TEXTURE_2D,0,this._gl.RGBA,this._gl.RGBA,this._gl.UNSIGNED_BYTE,video);}if(texture.generateMipMaps){this._gl.generateMipmap(this._gl.TEXTURE_2D);}this._gl.bindTexture(this._gl.TEXTURE_2D,null);this._activeTexturesCache=[];texture.isReady=true;};BABYLON.Engine.prototype.createRenderTargetTexture=function(size,options){var generateMipMaps=false;var generateDepthBuffer=true;var samplingMode=BABYLON.Texture.TRILINEAR_SAMPLINGMODE;if(options!==undefined){generateMipMaps=options.generateMipMaps===undefined?options:options.generateMipmaps;generateDepthBuffer=options.generateDepthBuffer===undefined?true:options.generateDepthBuffer;if(options.samplingMode!==undefined){samplingMode=options.samplingMode;}}var gl=this._gl;var texture=gl.createTexture();gl.bindTexture(gl.TEXTURE_2D,texture);var width=size.width||size;var height=size.height||size;var magFilter=gl.NEAREST;var minFilter=gl.NEAREST;if(samplingMode===BABYLON.Texture.BILINEAR_SAMPLINGMODE){magFilter=gl.LINEAR;if(generateMipMaps){minFilter=gl.LINEAR_MIPMAP_NEAREST;}else{minFilter=gl.LINEAR;}}else if(samplingMode===BABYLON.Texture.TRILINEAR_SAMPLINGMODE){magFilter=gl.LINEAR;if(generateMipMaps){minFilter=gl.LINEAR_MIPMAP_LINEAR;}else{minFilter=gl.LINEAR;}}gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,magFilter);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,minFilter);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.CLAMP_TO_EDGE);gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,width,height,0,gl.RGBA,gl.UNSIGNED_BYTE,null);var depthBuffer;if(generateDepthBuffer){depthBuffer=gl.createRenderbuffer();gl.bindRenderbuffer(gl.RENDERBUFFER,depthBuffer);gl.renderbufferStorage(gl.RENDERBUFFER,gl.DEPTH_COMPONENT16,width,height);}var framebuffer=gl.createFramebuffer();gl.bindFramebuffer(gl.FRAMEBUFFER,framebuffer);gl.framebufferTexture2D(gl.FRAMEBUFFER,gl.COLOR_ATTACHMENT0,gl.TEXTURE_2D,texture,0);if(generateDepthBuffer){gl.framebufferRenderbuffer(gl.FRAMEBUFFER,gl.DEPTH_ATTACHMENT,gl.RENDERBUFFER,depthBuffer);}gl.bindTexture(gl.TEXTURE_2D,null);gl.bindRenderbuffer(gl.RENDERBUFFER,null);gl.bindFramebuffer(gl.FRAMEBUFFER,null);texture._framebuffer=framebuffer;if(generateDepthBuffer){texture._depthBuffer=depthBuffer;}texture._width=width;texture._height=height;texture.isReady=true;texture.generateMipMaps=generateMipMaps;texture.references=1;this._activeTexturesCache=[];this._loadedTexturesCache.push(texture);return texture;};var extensions=["_px.jpg","_py.jpg","_pz.jpg","_nx.jpg","_ny.jpg","_nz.jpg"];var cascadeLoad=function(rootUrl,index,loadedImages,scene,onfinish){var img;var onload=function(){loadedImages.push(img);scene._removePendingData(img);if(index!=extensions.length-1){cascadeLoad(rootUrl,index+1,loadedImages,scene,onfinish);}else{onfinish(loadedImages);}};var onerror=function(){scene._removePendingData(img);};img=BABYLON.Tools.LoadImage(rootUrl+extensions[index],onload,onerror,scene.database);scene._addPendingData(img);};BABYLON.Engine.prototype.createCubeTexture=function(rootUrl,scene){var gl=this._gl;var texture=gl.createTexture();texture.isCube=true;texture.url=rootUrl;texture.references=1;this._loadedTexturesCache.push(texture);var that=this;cascadeLoad(rootUrl,0,[],scene,function(imgs){var width=getExponantOfTwo(imgs[0].width,that._caps.maxCubemapTextureSize);var height=width;that._workingCanvas.width=width;that._workingCanvas.height=height;var faces=[gl.TEXTURE_CUBE_MAP_POSITIVE_X,gl.TEXTURE_CUBE_MAP_POSITIVE_Y,gl.TEXTURE_CUBE_MAP_POSITIVE_Z,gl.TEXTURE_CUBE_MAP_NEGATIVE_X,gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,gl.TEXTURE_CUBE_MAP_NEGATIVE_Z];gl.bindTexture(gl.TEXTURE_CUBE_MAP,texture);gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,false);for(var index=0;indexthis.maximumWorld.x)this.maximumWorld.x=v.x;if(v.y>this.maximumWorld.y)this.maximumWorld.y=v.y;if(v.z>this.maximumWorld.z)this.maximumWorld.z=v.z;}this.maximumWorld.addToRef(this.minimumWorld,this.center);this.center.scaleInPlace(0.5);BABYLON.Vector3.FromArrayToRef(world.m,0,this.directions[0]);BABYLON.Vector3.FromArrayToRef(world.m,4,this.directions[1]);BABYLON.Vector3.FromArrayToRef(world.m,8,this.directions[2]);};BABYLON.BoundingBox.prototype.isInFrustrum=function(frustumPlanes){return BABYLON.BoundingBox.IsInFrustrum(this.vectorsWorld,frustumPlanes);};BABYLON.BoundingBox.prototype.intersectsPoint=function(point){if(this.maximumWorld.xpoint.x)return false;if(this.maximumWorld.ypoint.y)return false;if(this.maximumWorld.zpoint.z)return false;return true;};BABYLON.BoundingBox.prototype.intersectsSphere=function(sphere){var vector=BABYLON.Vector3.Clamp(sphere.centerWorld,this.minimumWorld,this.maximumWorld);var num=BABYLON.Vector3.DistanceSquared(sphere.centerWorld,vector);return(num<=(sphere.radiusWorld*sphere.radiusWorld));};BABYLON.BoundingBox.prototype.intersectsMinMax=function(min,max){if(this.maximumWorld.xmax.x)return false;if(this.maximumWorld.ymax.y)return false;if(this.maximumWorld.zmax.z)return false;return true;};BABYLON.BoundingBox.intersects=function(box0,box1){if(box0.maximumWorld.xbox1.maximumWorld.x)return false;if(box0.maximumWorld.ybox1.maximumWorld.y)return false;if(box0.maximumWorld.zbox1.maximumWorld.z)return false;return true;};BABYLON.BoundingBox.IsInFrustrum=function(boundingVectors,frustumPlanes){for(var p=0;p<6;p++){var inCount=8;for(var i=0;i<8;i++){if(frustumPlanes[p].dotCoordinate(boundingVectors[i])<0){--inCount;}else{break;}}if(inCount==0)return false;}return true;};})();var BABYLON=BABYLON||{};(function(){BABYLON.BoundingInfo=function(minimum,maximum){this.boundingBox=new BABYLON.BoundingBox(minimum,maximum);this.boundingSphere=new BABYLON.BoundingSphere(minimum,maximum);};BABYLON.BoundingInfo.prototype._update=function(world,scale){this.boundingBox._update(world);this.boundingSphere._update(world,scale);};var extentsOverlap=function(min0,max0,min1,max1){return!(min0>max1||min1>max0);};var computeBoxExtents=function(axis,box){var p=BABYLON.Vector3.Dot(box.center,axis);var r0=Math.abs(BABYLON.Vector3.Dot(box.directions[0],axis))*box.extends.x;var r1=Math.abs(BABYLON.Vector3.Dot(box.directions[1],axis))*box.extends.y;var r2=Math.abs(BABYLON.Vector3.Dot(box.directions[2],axis))*box.extends.z;var r=r0+r1+r2;return{min:p-r,max:p+r};};var axisOverlap=function(axis,box0,box1){var result0=computeBoxExtents(axis,box0);var result1=computeBoxExtents(axis,box1);return extentsOverlap(result0.min,result0.max,result1.min,result1.max);};BABYLON.BoundingInfo.prototype.isInFrustrum=function(frustumPlanes){if(!this.boundingSphere.isInFrustrum(frustumPlanes))return false;return this.boundingBox.isInFrustrum(frustumPlanes);};BABYLON.BoundingInfo.prototype._checkCollision=function(collider){return collider._canDoCollision(this.boundingSphere.centerWorld,this.boundingSphere.radiusWorld,this.boundingBox.minimumWorld,this.boundingBox.maximumWorld);};BABYLON.BoundingInfo.prototype.intersectsPoint=function(point){if(!this.boundingSphere.centerWorld){return false;}if(!this.boundingSphere.intersectsPoint(point)){return false;}if(!this.boundingBox.intersectsPoint(point)){return false;}return true;};BABYLON.BoundingInfo.prototype.intersects=function(boundingInfo,precise){if(!this.boundingSphere.centerWorld||!boundingInfo.boundingSphere.centerWorld){return false;}if(!BABYLON.BoundingSphere.intersects(this.boundingSphere,boundingInfo.boundingSphere)){return false;}if(!BABYLON.BoundingBox.intersects(this.boundingBox,boundingInfo.boundingBox)){return false;}if(!precise){return true;}var box0=this.boundingBox;var box1=boundingInfo.boundingBox;if(!axisOverlap(box0.directions[0],box0,box1))return false;if(!axisOverlap(box0.directions[1],box0,box1))return false;if(!axisOverlap(box0.directions[2],box0,box1))return false;if(!axisOverlap(box1.directions[0],box0,box1))return false;if(!axisOverlap(box1.directions[1],box0,box1))return false;if(!axisOverlap(box1.directions[2],box0,box1))return false;if(!axisOverlap(BABYLON.Vector3.Cross(box0.directions[0],box1.directions[0]),box0,box1))return false;if(!axisOverlap(BABYLON.Vector3.Cross(box0.directions[0],box1.directions[1]),box0,box1))return false;if(!axisOverlap(BABYLON.Vector3.Cross(box0.directions[0],box1.directions[2]),box0,box1))return false;if(!axisOverlap(BABYLON.Vector3.Cross(box0.directions[1],box1.directions[0]),box0,box1))return false;if(!axisOverlap(BABYLON.Vector3.Cross(box0.directions[1],box1.directions[1]),box0,box1))return false;if(!axisOverlap(BABYLON.Vector3.Cross(box0.directions[1],box1.directions[2]),box0,box1))return false;if(!axisOverlap(BABYLON.Vector3.Cross(box0.directions[2],box1.directions[0]),box0,box1))return false;if(!axisOverlap(BABYLON.Vector3.Cross(box0.directions[2],box1.directions[1]),box0,box1))return false;if(!axisOverlap(BABYLON.Vector3.Cross(box0.directions[2],box1.directions[2]),box0,box1))return false;return true;};})();var BABYLON=BABYLON||{};(function(){BABYLON.Light=function(name,scene){this.name=name;this.id=name;this._childrenFlag=true;this._scene=scene;scene.lights.push(this);this.animations=[];this.excludedMeshes=[];};BABYLON.Light.prototype=Object.create(BABYLON.Node.prototype);BABYLON.Light.prototype.intensity=1.0;BABYLON.Light.prototype.getScene=function(){return this._scene;};BABYLON.Light.prototype.getShadowGenerator=function(){return this._shadowGenerator;};BABYLON.Light.prototype.transferToEffect=function(){};BABYLON.Light.prototype.getWorldMatrix=function(){var worldMatrix=this._getWorldMatrix();if(this.parent&&this.parent.getWorldMatrix){if(!this._parentedWorldMatrix){this._parentedWorldMatrix=BABYLON.Matrix.Identity();}worldMatrix.multiplyToRef(this.parent.getWorldMatrix(),this._parentedWorldMatrix);return this._parentedWorldMatrix;}return worldMatrix;};BABYLON.Light.prototype.dispose=function(){if(this._shadowGenerator){this._shadowGenerator.dispose();this._shadowGenerator=null;}var index=this._scene.lights.indexOf(this);this._scene.lights.splice(index,1);};})();var BABYLON=BABYLON||{};(function(){BABYLON.PointLight=function(name,position,scene){BABYLON.Light.call(this,name,scene);this.position=position;this.diffuse=new BABYLON.Color3(1.0,1.0,1.0);this.specular=new BABYLON.Color3(1.0,1.0,1.0);};BABYLON.PointLight.prototype=Object.create(BABYLON.Light.prototype);BABYLON.PointLight.prototype.transferToEffect=function(effect,positionUniformName){if(this.parent&&this.parent.getWorldMatrix){if(!this._transformedPosition){this._transformedPosition=BABYLON.Vector3.Zero();}BABYLON.Vector3.TransformCoordinatesToRef(this.position,this.parent.getWorldMatrix(),this._transformedPosition);effect.setFloat4(positionUniformName,this._transformedPosition.x,this._transformedPosition.y,this._transformedPosition.z,0);return;}effect.setFloat4(positionUniformName,this.position.x,this.position.y,this.position.z,0);};BABYLON.PointLight.prototype.getShadowGenerator=function(){return null;};BABYLON.PointLight.prototype._getWorldMatrix=function(){if(!this._worldMatrix){this._worldMatrix=BABYLON.Matrix.Identity();}BABYLON.Matrix.TranslationToRef(this.position.x,this.position.y,this.position.z,this._worldMatrix);return this._worldMatrix;};})();var BABYLON=BABYLON||{};(function(){BABYLON.SpotLight=function(name,position,direction,angle,exponent,scene){BABYLON.Light.call(this,name,scene);this.position=position;this.direction=direction;this.angle=angle;this.exponent=exponent;this.diffuse=new BABYLON.Color3(1.0,1.0,1.0);this.specular=new BABYLON.Color3(1.0,1.0,1.0);};BABYLON.SpotLight.prototype=Object.create(BABYLON.Light.prototype);BABYLON.SpotLight.prototype.transferToEffect=function(effect,positionUniformName,directionUniformName){var normalizeDirection;if(this.parent&&this.parent.getWorldMatrix){if(!this._transformedDirection){this._transformedDirection=BABYLON.Vector3.Zero();}if(!this._transformedPosition){this._transformedPosition=BABYLON.Vector3.Zero();}var parentWorldMatrix=this.parent.getWorldMatrix();BABYLON.Vector3.TransformCoordinatesToRef(this.position,parentWorldMatrix,this._transformedPosition);BABYLON.Vector3.TransformNormalToRef(this.direction,parentWorldMatrix,this._transformedDirection);effect.setFloat4(positionUniformName,this._transformedPosition.x,this._transformedPosition.y,this._transformedPosition.z,this.exponent);normalizeDirection=BABYLON.Vector3.Normalize(this._transformedDirection);}else{effect.setFloat4(positionUniformName,this.position.x,this.position.y,this.position.z,this.exponent);normalizeDirection=BABYLON.Vector3.Normalize(this.direction);}effect.setFloat4(directionUniformName,normalizeDirection.x,normalizeDirection.y,normalizeDirection.z,Math.cos(this.angle*0.5));};BABYLON.SpotLight.prototype._getWorldMatrix=function(){if(!this._worldMatrix){this._worldMatrix=BABYLON.Matrix.Identity();}BABYLON.Matrix.TranslationToRef(this.position.x,this.position.y,this.position.z,this._worldMatrix);return this._worldMatrix;};})();var BABYLON=BABYLON||{};(function(){BABYLON.DirectionalLight=function(name,direction,scene){BABYLON.Light.call(this,name,scene);this.position=direction.scale(-1);this.direction=direction;this.diffuse=new BABYLON.Color3(1.0,1.0,1.0);this.specular=new BABYLON.Color3(1.0,1.0,1.0);};BABYLON.DirectionalLight.prototype=Object.create(BABYLON.Light.prototype);BABYLON.DirectionalLight.prototype._computeTransformedPosition=function(){if(this.parent&&this.parent.getWorldMatrix){if(!this._transformedPosition){this._transformedPosition=BABYLON.Vector3.Zero();}BABYLON.Vector3.TransformCoordinatesToRef(this.position,this.parent.getWorldMatrix(),this._transformedPosition);return true;}return false;};BABYLON.DirectionalLight.prototype.transferToEffect=function(effect,directionUniformName){if(this.parent&&this.parent.getWorldMatrix){if(!this._transformedDirection){this._transformedDirection=BABYLON.Vector3.Zero();}BABYLON.Vector3.TransformNormalToRef(this.direction,this.parent.getWorldMatrix(),this._transformedDirection);effect.setFloat4(directionUniformName,this._transformedDirection.x,this._transformedDirection.y,this._transformedDirection.z,1);return;}effect.setFloat4(directionUniformName,this.direction.x,this.direction.y,this.direction.z,1);};BABYLON.DirectionalLight.prototype._getWorldMatrix=function(){if(!this._worldMatrix){this._worldMatrix=BABYLON.Matrix.Identity();}BABYLON.Matrix.TranslationToRef(this.position.x,this.position.y,this.position.z,this._worldMatrix);return this._worldMatrix;};})();var BABYLON=BABYLON||{};(function(){BABYLON.ShadowGenerator=function(mapSize,light){this._light=light;this._scene=light.getScene();light._shadowGenerator=this;this._shadowMap=new BABYLON.RenderTargetTexture(light.name+"_shadowMap",mapSize,this._scene,false);this._shadowMap.wrapU=BABYLON.Texture.CLAMP_ADDRESSMODE;this._shadowMap.wrapV=BABYLON.Texture.CLAMP_ADDRESSMODE;this._shadowMap.renderParticles=false;var that=this;var renderSubMesh=function(subMesh){var mesh=subMesh.getMesh();var world=mesh.getWorldMatrix();var engine=that._scene.getEngine();if(that.isReady(mesh)){engine.enableEffect(that._effect);if(mesh.skeleton&&mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind)&&mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind)){that._effect.setMatrix("world",world);that._effect.setMatrix("viewProjection",that.getTransformMatrix());that._effect.setMatrices("mBones",mesh.skeleton.getTransformMatrices());}else{world.multiplyToRef(that.getTransformMatrix(),that._worldViewProjection);that._effect.setMatrix("worldViewProjection",that._worldViewProjection);}mesh.bindAndDraw(subMesh,that._effect,false);}};this._shadowMap.customRenderFunction=function(opaqueSubMeshes,alphaTestSubMeshes){var index;for(index=0;index=0;};var intersectBoxAASphere=function(boxMin,boxMax,sphereCenter,sphereRadius){if(boxMin.x>sphereCenter.x+sphereRadius)return false;if(sphereCenter.x-sphereRadius>boxMax.x)return false;if(boxMin.y>sphereCenter.y+sphereRadius)return false;if(sphereCenter.y-sphereRadius>boxMax.y)return false;if(boxMin.z>sphereCenter.z+sphereRadius)return false;if(sphereCenter.z-sphereRadius>boxMax.z)return false;return true;};var getLowestRoot=function(a,b,c,maxR){var determinant=b*b-4.0*a*c;var result={root:0,found:false};if(determinant<0)return result;var sqrtD=Math.sqrt(determinant);var r1=(-b-sqrtD)/(2.0*a);var r2=(-b+sqrtD)/(2.0*a);if(r1>r2){var temp=r2;r2=r1;r1=temp;}if(r1>0&&r10&&r2this.velocityWorldLength+max+sphereRadius){return false;}if(!intersectBoxAASphere(vecMin,vecMax,this.basePointWorld,this.velocityWorldLength+max))return false;return true;};BABYLON.Collider.prototype._testTriangle=function(faceIndex,subMesh,p1,p2,p3){var t0;var embeddedInPlane=false;if(!subMesh._trianglePlanes){subMesh._trianglePlanes=[];}if(!subMesh._trianglePlanes[faceIndex]){subMesh._trianglePlanes[faceIndex]=new BABYLON.Plane(0,0,0,0);subMesh._trianglePlanes[faceIndex].copyFromPoints(p1,p2,p3);}var trianglePlane=subMesh._trianglePlanes[faceIndex];if((!subMesh.getMaterial())&&!trianglePlane.isFrontFacingTo(this.normalizedVelocity,0))return;var signedDistToTrianglePlane=trianglePlane.signedDistanceTo(this.basePoint);var normalDotVelocity=BABYLON.Vector3.Dot(trianglePlane.normal,this.velocity);if(normalDotVelocity==0){if(Math.abs(signedDistToTrianglePlane)>=1.0)return;embeddedInPlane=true;t0=0;}else{t0=(-1.0-signedDistToTrianglePlane)/normalDotVelocity;var t1=(1.0-signedDistToTrianglePlane)/normalDotVelocity;if(t0>t1){var temp=t1;t1=t0;t0=temp;}if(t0>1.0||t1<0.0)return;if(t0<0)t0=0;if(t0>1.0)t0=1.0;}this._collisionPoint.copyFromFloats(0,0,0);var found=false;var t=1.0;if(!embeddedInPlane){this.basePoint.subtractToRef(trianglePlane.normal,this._planeIntersectionPoint);this.velocity.scaleToRef(t0,this._tempVector);this._planeIntersectionPoint.addInPlace(this._tempVector);if(this._checkPointInTriangle(this._planeIntersectionPoint,p1,p2,p3,trianglePlane.normal)){found=true;t=t0;this._collisionPoint.copyFrom(this._planeIntersectionPoint);}}if(!found){var velocitySquaredLength=this.velocity.lengthSquared();var a=velocitySquaredLength;this.basePoint.subtractToRef(p1,this._tempVector);var b=2.0*(BABYLON.Vector3.Dot(this.velocity,this._tempVector));var c=this._tempVector.lengthSquared-1.0;var lowestRoot=getLowestRoot(a,b,c,t);if(lowestRoot.found){t=lowestRoot.root;found=true;this._collisionPoint.copyFrom(p1);}this.basePoint.subtractToRef(p2,this._tempVector);b=2.0*(BABYLON.Vector3.Dot(this.velocity,this._tempVector));c=this._tempVector.lengthSquared-1.0;lowestRoot=getLowestRoot(a,b,c,t);if(lowestRoot.found){t=lowestRoot.root;found=true;this._collisionPoint.copyFrom(p2);}this.basePoint.subtractToRef(p3,this._tempVector);b=2.0*(BABYLON.Vector3.Dot(this.velocity,this._tempVector));c=this._tempVector.lengthSquared-1.0;lowestRoot=getLowestRoot(a,b,c,t);if(lowestRoot.found){t=lowestRoot.root;found=true;this._collisionPoint.copyFrom(p3);}p2.subtractToRef(p1,this._edge);p1.subtractToRef(this.basePoint,this._baseToVertex);var edgeSquaredLength=this._edge.lengthSquared();var edgeDotVelocity=BABYLON.Vector3.Dot(this._edge,this.velocity);var edgeDotBaseToVertex=BABYLON.Vector3.Dot(this._edge,this._baseToVertex);a=edgeSquaredLength*(-velocitySquaredLength)+edgeDotVelocity*edgeDotVelocity;b=edgeSquaredLength*(2.0*BABYLON.Vector3.Dot(this.velocity,this._baseToVertex))-2.0*edgeDotVelocity*edgeDotBaseToVertex;c=edgeSquaredLength*(1.0-this._baseToVertex.lengthSquared())+edgeDotBaseToVertex*edgeDotBaseToVertex;lowestRoot=getLowestRoot(a,b,c,t);if(lowestRoot.found){var f=(edgeDotVelocity*lowestRoot.root-edgeDotBaseToVertex)/edgeSquaredLength;if(f>=0.0&&f<=1.0){t=lowestRoot.root;found=true;this._edge.scaleInPlace(f);p1.addToRef(this._edge,this._collisionPoint);}}p3.subtractToRef(p2,this._edge);p2.subtractToRef(this.basePoint,this._baseToVertex);edgeSquaredLength=this._edge.lengthSquared();edgeDotVelocity=BABYLON.Vector3.Dot(this._edge,this.velocity);edgeDotBaseToVertex=BABYLON.Vector3.Dot(this._edge,this._baseToVertex);a=edgeSquaredLength*(-velocitySquaredLength)+edgeDotVelocity*edgeDotVelocity;b=edgeSquaredLength*(2.0*BABYLON.Vector3.Dot(this.velocity,this._baseToVertex))-2.0*edgeDotVelocity*edgeDotBaseToVertex;c=edgeSquaredLength*(1.0-this._baseToVertex.lengthSquared())+edgeDotBaseToVertex*edgeDotBaseToVertex;lowestRoot=getLowestRoot(a,b,c,t);if(lowestRoot.found){var f=(edgeDotVelocity*lowestRoot.root-edgeDotBaseToVertex)/edgeSquaredLength;if(f>=0.0&&f<=1.0){t=lowestRoot.root;found=true;this._edge.scaleInPlace(f);p2.addToRef(this._edge,this._collisionPoint);}}p1.subtractToRef(p3,this._edge);p3.subtractToRef(this.basePoint,this._baseToVertex);edgeSquaredLength=this._edge.lengthSquared();edgeDotVelocity=BABYLON.Vector3.Dot(this._edge,this.velocity);edgeDotBaseToVertex=BABYLON.Vector3.Dot(this._edge,this._baseToVertex);a=edgeSquaredLength*(-velocitySquaredLength)+edgeDotVelocity*edgeDotVelocity;b=edgeSquaredLength*(2.0*BABYLON.Vector3.Dot(this.velocity,this._baseToVertex))-2.0*edgeDotVelocity*edgeDotBaseToVertex;c=edgeSquaredLength*(1.0-this._baseToVertex.lengthSquared())+edgeDotBaseToVertex*edgeDotBaseToVertex;lowestRoot=getLowestRoot(a,b,c,t);if(lowestRoot.found){var f=(edgeDotVelocity*lowestRoot.root-edgeDotBaseToVertex)/edgeSquaredLength;if(f>=0.0&&f<=1.0){t=lowestRoot.root;found=true;this._edge.scaleInPlace(f);p3.addToRef(this._edge,this._collisionPoint);}}}if(found){var distToCollision=t*this.velocity.length();if(!this.collisionFound||distToCollision=0.0){this.rotation.y=(-Math.atan(vDir.z/vDir.x)+Math.PI/2.0);}else{this.rotation.y=(-Math.atan(vDir.z/vDir.x)-Math.PI/2.0);}this.rotation.z=-Math.acos(BABYLON.Vector3.Dot(new BABYLON.Vector3(0,1.0,0),this.upVector));if(isNaN(this.rotation.x))this.rotation.x=0;if(isNaN(this.rotation.y))this.rotation.y=0;if(isNaN(this.rotation.z))this.rotation.z=0;};BABYLON.FreeCamera.prototype.attachControl=function(canvas,noPreventDefault){var previousPosition;var that=this;var engine=this._scene.getEngine();if(this._attachedCanvas){return;}this._attachedCanvas=canvas;if(this._onMouseDown===undefined){this._onMouseDown=function(evt){previousPosition={x:evt.clientX,y:evt.clientY};if(!noPreventDefault){evt.preventDefault();}};this._onMouseUp=function(evt){previousPosition=null;if(!noPreventDefault){evt.preventDefault();}};this._onMouseOut=function(evt){previousPosition=null;that._keys=[];if(!noPreventDefault){evt.preventDefault();}};this._onMouseMove=function(evt){if(!previousPosition&&!engine.isPointerLock){return;}var offsetX;var offsetY;if(!engine.isPointerLock){offsetX=evt.clientX-previousPosition.x;offsetY=evt.clientY-previousPosition.y;}else{offsetX=evt.movementX||evt.mozMovementX||evt.webkitMovementX||evt.msMovementX||0;offsetY=evt.movementY||evt.mozMovementY||evt.webkitMovementY||evt.msMovementY||0;}that.cameraRotation.y+=offsetX/that.angularSensibility;that.cameraRotation.x+=offsetY/that.angularSensibility;previousPosition={x:evt.clientX,y:evt.clientY};if(!noPreventDefault){evt.preventDefault();}};this._onKeyDown=function(evt){if(that.keysUp.indexOf(evt.keyCode)!==-1||that.keysDown.indexOf(evt.keyCode)!==-1||that.keysLeft.indexOf(evt.keyCode)!==-1||that.keysRight.indexOf(evt.keyCode)!==-1){var index=that._keys.indexOf(evt.keyCode);if(index===-1){that._keys.push(evt.keyCode);}if(!noPreventDefault){evt.preventDefault();}}};this._onKeyUp=function(evt){if(that.keysUp.indexOf(evt.keyCode)!==-1||that.keysDown.indexOf(evt.keyCode)!==-1||that.keysLeft.indexOf(evt.keyCode)!==-1||that.keysRight.indexOf(evt.keyCode)!==-1){var index=that._keys.indexOf(evt.keyCode);if(index>=0){that._keys.splice(index,1);}if(!noPreventDefault){evt.preventDefault();}}};this._onLostFocus=function(){that._keys=[];};this._reset=function(){that._keys=[];previousPosition=null;that.cameraDirection=new BABYLON.Vector3(0,0,0);that.cameraRotation=new BABYLON.Vector2(0,0);};}canvas.addEventListener("mousedown",this._onMouseDown,false);canvas.addEventListener("mouseup",this._onMouseUp,false);canvas.addEventListener("mouseout",this._onMouseOut,false);canvas.addEventListener("mousemove",this._onMouseMove,false);window.addEventListener("keydown",this._onKeyDown,false);window.addEventListener("keyup",this._onKeyUp,false);window.addEventListener("blur",this._onLostFocus,false);};BABYLON.FreeCamera.prototype.detachControl=function(canvas){if(this._attachedCanvas!=canvas){return;}canvas.removeEventListener("mousedown",this._onMouseDown);canvas.removeEventListener("mouseup",this._onMouseUp);canvas.removeEventListener("mouseout",this._onMouseOut);canvas.removeEventListener("mousemove",this._onMouseMove);window.removeEventListener("keydown",this._onKeyDown);window.removeEventListener("keyup",this._onKeyUp);window.removeEventListener("blur",this._onLostFocus);this._attachedCanvas=null;if(this._reset){this._reset();}};BABYLON.FreeCamera.prototype._collideWithWorld=function(velocity){this.position.subtractFromFloatsToRef(0,this.ellipsoid.y,0,this._oldPosition);this._collider.radius=this.ellipsoid;this._scene._getNewPosition(this._oldPosition,velocity,this._collider,3,this._newPosition);this._newPosition.subtractToRef(this._oldPosition,this._diffPosition);if(this._diffPosition.length()>BABYLON.Engine.collisionsEpsilon){this.position.addInPlace(this._diffPosition);if(this.onCollide){this.onCollide(this._collider.collidedMesh);}}};BABYLON.FreeCamera.prototype._checkInputs=function(){if(!this._localDirection){this._localDirection=BABYLON.Vector3.Zero();this._transformedDirection=BABYLON.Vector3.Zero();}for(var index=0;index0||Math.abs(this.cameraDirection.y)>0||Math.abs(this.cameraDirection.z)>0;var needToRotate=Math.abs(this.cameraRotation.x)>0||Math.abs(this.cameraRotation.y)>0;if(needToMove){if(this.checkCollisions&&this._scene.collisionsEnabled){this._collideWithWorld(this.cameraDirection);if(this.applyGravity){var oldPosition=this.position;this._collideWithWorld(this._scene.gravity);this._needMoveForGravity=(BABYLON.Vector3.DistanceSquared(oldPosition,this.position)!=0);}}else{this.position.addInPlace(this.cameraDirection);}}if(needToRotate){this.rotation.x+=this.cameraRotation.x;this.rotation.y+=this.cameraRotation.y;if(!this.noRotationConstraint){var limit=(Math.PI/2)*0.95;if(this.rotation.x>limit)this.rotation.x=limit;if(this.rotation.x<-limit)this.rotation.x=-limit;}}if(needToMove){this.cameraDirection.scaleInPlace(this.inertia);}if(needToRotate){this.cameraRotation.scaleInPlace(this.inertia);}};BABYLON.FreeCamera.prototype._getViewMatrix=function(){BABYLON.Vector3.FromFloatsToRef(0,0,1,this._referencePoint);if(!this.lockedTarget){if(this.upVector.x!=0||this.upVector.y!=1.0||this.upVector.z!=0){BABYLON.Matrix.LookAtLHToRef(BABYLON.Vector3.Zero(),this._referencePoint,this.upVector,this._lookAtTemp);BABYLON.Matrix.RotationYawPitchRollToRef(this.rotation.y,this.rotation.x,this.rotation.z,this._cameraRotationMatrix);this._lookAtTemp.multiplyToRef(this._cameraRotationMatrix,this._tempMatrix);this._lookAtTemp.invert();this._tempMatrix.multiplyToRef(this._lookAtTemp,this._cameraRotationMatrix);}else{BABYLON.Matrix.RotationYawPitchRollToRef(this.rotation.y,this.rotation.x,this.rotation.z,this._cameraRotationMatrix);}BABYLON.Vector3.TransformCoordinatesToRef(this._referencePoint,this._cameraRotationMatrix,this._transformedReferencePoint);this.position.addToRef(this._transformedReferencePoint,this._currentTarget);}else{if(this.lockedTarget.position){this._currentTarget.copyFrom(this.lockedTarget.position);}else{this._currentTarget.copyFrom(this.lockedTarget);}}BABYLON.Matrix.LookAtLHToRef(this.position,this._currentTarget,this.upVector,this._viewMatrix);return this._viewMatrix;};})();var BABYLON=BABYLON||{};(function(){BABYLON.TouchCamera=function(name,position,scene){BABYLON.FreeCamera.call(this,name,position,scene);this._offsetX=null;this._offsetY=null;this._pointerCount=0;this._pointerPressed=[];};BABYLON.TouchCamera.prototype=Object.create(BABYLON.FreeCamera.prototype);BABYLON.TouchCamera.prototype.angularSensibility=200000.0;BABYLON.TouchCamera.prototype.moveSensibility=500.0;BABYLON.TouchCamera.prototype.attachControl=function(canvas,noPreventDefault){var previousPosition;var that=this;if(this._attachedCanvas){return;}this._attachedCanvas=canvas;if(this._onPointerDown===undefined){this._onPointerDown=function(evt){if(!noPreventDefault){evt.preventDefault();}that._pointerPressed.push(evt.pointerId);if(that._pointerPressed.length!==1){return;}previousPosition={x:evt.clientX,y:evt.clientY};};this._onPointerUp=function(evt){if(!noPreventDefault){evt.preventDefault();}var index=that._pointerPressed.indexOf(evt.pointerId);if(index===-1){return;}that._pointerPressed.splice(index,1);if(index!=0){return;}previousPosition=null;that._offsetX=null;that._offsetY=null;};this._onPointerMove=function(evt){if(!noPreventDefault){evt.preventDefault();}if(!previousPosition){return;}var index=that._pointerPressed.indexOf(evt.pointerId);if(index!=0){return;}that._offsetX=evt.clientX-previousPosition.x;that._offsetY=-(evt.clientY-previousPosition.y);};this._onLostFocus=function(){that._offsetX=null;that._offsetY=null;};}canvas.addEventListener("pointerdown",this._onPointerDown);canvas.addEventListener("pointerup",this._onPointerUp);canvas.addEventListener("pointerout",this._onPointerUp);canvas.addEventListener("pointermove",this._onPointerMove);window.addEventListener("blur",this._onLostFocus);};BABYLON.TouchCamera.prototype.detachControl=function(canvas){if(this._attachedCanvas!=canvas){return;}canvas.removeEventListener("pointerdown",this._onPointerDown);canvas.removeEventListener("pointerup",this._onPointerUp);canvas.removeEventListener("pointerout",this._onPointerUp);canvas.removeEventListener("pointermove",this._onPointerMove);window.removeEventListener("blur",this._onLostFocus);this._attachedCanvas=null;};BABYLON.TouchCamera.prototype._checkInputs=function(){if(!this._offsetX){return;}this.cameraRotation.y+=this._offsetX/this.angularSensibility;if(this._pointerPressed.length>1){this.cameraRotation.x+=-this._offsetY/this.angularSensibility;}else{var speed=this._computeLocalCameraSpeed();var direction=new BABYLON.Vector3(0,0,speed*this._offsetY/this.moveSensibility);BABYLON.Matrix.RotationYawPitchRollToRef(this.rotation.y,this.rotation.x,0,this._cameraRotationMatrix);this.cameraDirection.addInPlace(BABYLON.Vector3.TransformCoordinates(direction,this._cameraRotationMatrix));}};})();var BABYLON=BABYLON||{};(function(){BABYLON.DeviceOrientationCamera=function(name,position,scene){BABYLON.FreeCamera.call(this,name,position,scene);this._offsetX=null;this._offsetY=null;this._orientationGamma=0;this._orientationBeta=0;this._initialOrientationGamma=0;this._initialOrientationBeta=0;};BABYLON.DeviceOrientationCamera.prototype=Object.create(BABYLON.FreeCamera.prototype);BABYLON.DeviceOrientationCamera.prototype.angularSensibility=10000.0;BABYLON.DeviceOrientationCamera.prototype.moveSensibility=50.0;BABYLON.DeviceOrientationCamera.prototype.attachControl=function(canvas,noPreventDefault){if(this._attachedCanvas){return;}this._attachedCanvas=canvas;var that=this;if(!this._orientationChanged){this._orientationChanged=function(evt){if(!that._initialOrientationGamma){that._initialOrientationGamma=evt.gamma;that._initialOrientationBeta=evt.beta;}that._orientationGamma=evt.gamma;that._orientationBeta=evt.beta;that._offsetY=(that._initialOrientationBeta-that._orientationBeta);that._offsetX=(that._initialOrientationGamma-that._orientationGamma);};}window.addEventListener("deviceorientation",this._orientationChanged);};BABYLON.DeviceOrientationCamera.prototype.detachControl=function(canvas){if(this._attachedCanvas!=canvas){return;}window.removeEventListener("deviceorientation",this._orientationChanged);this._attachedCanvas=null;this._orientationGamma=0;this._orientationBeta=0;this._initialOrientationGamma=0;this._initialOrientationBeta=0;};BABYLON.DeviceOrientationCamera.prototype._checkInputs=function(){if(!this._offsetX){return;}this.cameraRotation.y-=this._offsetX/this.angularSensibility;var speed=this._computeLocalCameraSpeed();var direction=new BABYLON.Vector3(0,0,speed*this._offsetY/this.moveSensibility);BABYLON.Matrix.RotationYawPitchRollToRef(this.rotation.y,this.rotation.x,0,this._cameraRotationMatrix);this.cameraDirection.addInPlace(BABYLON.Vector3.TransformCoordinates(direction,this._cameraRotationMatrix));};})();var BABYLON=BABYLON||{};(function(){var eventPrefix=BABYLON.Tools.GetPointerPrefix();BABYLON.ArcRotateCamera=function(name,alpha,beta,radius,target,scene){BABYLON.Camera.call(this,name,BABYLON.Vector3.Zero(),scene);this.alpha=alpha;this.beta=beta;this.radius=radius;this.target=target;this._keys=[];this.keysUp=[38];this.keysDown=[40];this.keysLeft=[37];this.keysRight=[39];this._viewMatrix=new BABYLON.Matrix();this.getViewMatrix();};BABYLON.ArcRotateCamera.prototype=Object.create(BABYLON.Camera.prototype);BABYLON.ArcRotateCamera.prototype.inertialAlphaOffset=0;BABYLON.ArcRotateCamera.prototype.inertialBetaOffset=0;BABYLON.ArcRotateCamera.prototype.lowerAlphaLimit=null;BABYLON.ArcRotateCamera.prototype.upperAlphaLimit=null;BABYLON.ArcRotateCamera.prototype.lowerBetaLimit=null;BABYLON.ArcRotateCamera.prototype.upperBetaLimit=null;BABYLON.ArcRotateCamera.prototype.lowerRadiusLimit=null;BABYLON.ArcRotateCamera.prototype.upperRadiusLimit=null;BABYLON.ArcRotateCamera.prototype.angularSensibility=1000.0;BABYLON.ArcRotateCamera.prototype.attachControl=function(canvas,noPreventDefault){var previousPosition;var that=this;var pointerId;if(this._attachedCanvas){return;}this._attachedCanvas=canvas;var engine=this._scene.getEngine();if(this._onPointerDown===undefined){this._onPointerDown=function(evt){if(pointerId){return;}pointerId=evt.pointerId;previousPosition={x:evt.clientX,y:evt.clientY};if(!noPreventDefault){evt.preventDefault();}};this._onPointerUp=function(evt){previousPosition=null;pointerId=null;if(!noPreventDefault){evt.preventDefault();}};this._onPointerMove=function(evt){if(!previousPosition){return;}if(pointerId!==evt.pointerId){return;}var offsetX=evt.clientX-previousPosition.x;var offsetY=evt.clientY-previousPosition.y;that.inertialAlphaOffset-=offsetX/that.angularSensibility;that.inertialBetaOffset-=offsetY/that.angularSensibility;previousPosition={x:evt.clientX,y:evt.clientY};if(!noPreventDefault){evt.preventDefault();}};this._onMouseMove=function(evt){if(!engine.isPointerLock){return;}var offsetX=evt.movementX||evt.mozMovementX||evt.webkitMovementX||evt.msMovementX||0;var offsetY=evt.movementY||evt.mozMovementY||evt.webkitMovementY||evt.msMovementY||0;that.inertialAlphaOffset-=offsetX/that.angularSensibility;that.inertialBetaOffset-=offsetY/that.angularSensibility;if(!noPreventDefault){evt.preventDefault();}};this._wheel=function(event){var delta=0;if(event.wheelDelta){delta=event.wheelDelta/120;}else if(event.detail){delta=-event.detail/3;}if(delta)that.radius-=delta;if(event.preventDefault){if(!noPreventDefault){event.preventDefault();}}};this._onKeyDown=function(evt){if(that.keysUp.indexOf(evt.keyCode)!==-1||that.keysDown.indexOf(evt.keyCode)!==-1||that.keysLeft.indexOf(evt.keyCode)!==-1||that.keysRight.indexOf(evt.keyCode)!==-1){var index=that._keys.indexOf(evt.keyCode);if(index===-1){that._keys.push(evt.keyCode);}if(evt.preventDefault){if(!noPreventDefault){evt.preventDefault();}}}};this._onKeyUp=function(evt){if(that.keysUp.indexOf(evt.keyCode)!==-1||that.keysDown.indexOf(evt.keyCode)!==-1||that.keysLeft.indexOf(evt.keyCode)!==-1||that.keysRight.indexOf(evt.keyCode)!==-1){var index=that._keys.indexOf(evt.keyCode);if(index>=0){that._keys.splice(index,1);}if(evt.preventDefault){if(!noPreventDefault){evt.preventDefault();}}}};this._onLostFocus=function(){that._keys=[];pointerId=null;};this._onGestureStart=function(e){if(window.MSGesture===undefined){return;}if(!that._MSGestureHandler){that._MSGestureHandler=new MSGesture();that._MSGestureHandler.target=canvas;}that._MSGestureHandler.addPointer(e.pointerId);};this._onGesture=function(e){that.radius*=e.scale;if(e.preventDefault){if(!noPreventDefault){e.stopPropagation();e.preventDefault();}}};this._reset=function(){that._keys=[];that.inertialAlphaOffset=0;that.inertialBetaOffset=0;previousPosition=null;pointerId=null;};}canvas.addEventListener(eventPrefix+"down",this._onPointerDown,false);canvas.addEventListener(eventPrefix+"up",this._onPointerUp,false);canvas.addEventListener(eventPrefix+"out",this._onPointerUp,false);canvas.addEventListener(eventPrefix+"move",this._onPointerMove,false);canvas.addEventListener("mousemove",this._onMouseMove,false);canvas.addEventListener("MSPointerDown",this._onGestureStart,false);canvas.addEventListener("MSGestureChange",this._onGesture,false);window.addEventListener("keydown",this._onKeyDown,false);window.addEventListener("keyup",this._onKeyUp,false);window.addEventListener('mousewheel',this._wheel,false);window.addEventListener("blur",this._onLostFocus,false);};BABYLON.ArcRotateCamera.prototype.detachControl=function(canvas){if(this._attachedCanvas!=canvas){return;}canvas.removeEventListener(eventPrefix+"down",this._onPointerDown);canvas.removeEventListener(eventPrefix+"up",this._onPointerUp);canvas.removeEventListener(eventPrefix+"out",this._onPointerUp);canvas.removeEventListener(eventPrefix+"move",this._onPointerMove);canvas.removeEventListener("mousemove",this._onMouseMove);canvas.removeEventListener("MSPointerDown",this._onGestureStart);canvas.removeEventListener("MSGestureChange",this._onGesture);window.removeEventListener("keydown",this._onKeyDown);window.removeEventListener("keyup",this._onKeyUp);window.removeEventListener('mousewheel',this._wheel);window.removeEventListener("blur",this._onLostFocus);this._MSGestureHandler=null;this._attachedCanvas=null;if(this._reset){this._reset();}};BABYLON.ArcRotateCamera.prototype._update=function(){for(var index=0;indexthis.upperAlphaLimit){this.alpha=this.upperAlphaLimit;}if(this.lowerBetaLimit&&this.betathis.upperBetaLimit){this.beta=this.upperBetaLimit;}if(this.lowerRadiusLimit&&this.radiusthis.upperRadiusLimit){this.radius=this.upperRadiusLimit;}};BABYLON.ArcRotateCamera.prototype.setPosition=function(position){var radiusv3=position.subtract(this.target.position?this.target.position:this.target);this.radius=radiusv3.length();this.alpha=Math.atan(radiusv3.z/radiusv3.x);this.beta=Math.acos(radiusv3.y/this.radius);};BABYLON.ArcRotateCamera.prototype._getViewMatrix=function(){if(this.beta>Math.PI)this.beta=Math.PI;if(this.beta<=0)this.beta=0.01;var cosa=Math.cos(this.alpha);var sina=Math.sin(this.alpha);var cosb=Math.cos(this.beta);var sinb=Math.sin(this.beta);this.target.addToRef(new BABYLON.Vector3(this.radius*cosa*sinb,this.radius*cosb,this.radius*sina*sinb),this.position);BABYLON.Matrix.LookAtLHToRef(this.position,this.target,this.upVector,this._viewMatrix);return this._viewMatrix;};})();var BABYLON=BABYLON||{};(function(){BABYLON.Scene=function(engine){this._engine=engine;this.autoClear=true;this.clearColor=new BABYLON.Color3(0.2,0.2,0.3);this.ambientColor=new BABYLON.Color3(0,0,0);engine.scenes.push(this);this._totalVertices=0;this._activeVertices=0;this._activeParticles=0;this._lastFrameDuration=0;this._evaluateActiveMeshesDuration=0;this._renderTargetsDuration=0;this._renderDuration=0;this._renderId=0;this._executeWhenReadyTimeoutId=-1;this._toBeDisposed=new BABYLON.Tools.SmartArray(256);this._onReadyCallbacks=[];this._pendingData=[];this._onBeforeRenderCallbacks=[];this.fogMode=BABYLON.Scene.FOGMODE_NONE;this.fogColor=new BABYLON.Color3(0.2,0.2,0.3);this.fogDensity=0.1;this.fogStart=0;this.fogEnd=1000.0;this.lightsEnabled=true;this.lights=[];this.cameras=[];this.activeCamera=null;this.meshes=[];this._activeMeshes=new BABYLON.Tools.SmartArray(256);this._processedMaterials=new BABYLON.Tools.SmartArray(256);this._renderTargets=new BABYLON.Tools.SmartArray(256);this._activeParticleSystems=new BABYLON.Tools.SmartArray(256);this._activeSkeletons=new BABYLON.Tools.SmartArray(32);this._renderingManager=new BABYLON.RenderingManager(this);this.materials=[];this.multiMaterials=[];this.defaultMaterial=new BABYLON.StandardMaterial("default material",this);this.texturesEnabled=true;this.textures=[];this.particlesEnabled=true;this.particleSystems=[];this.spriteManagers=[];this.layers=[];this.skeletons=[];this.lensFlareSystems=[];this.collisionsEnabled=true;this.gravity=new BABYLON.Vector3(0,-9.0,0);this._activeAnimatables=[];this._transformMatrix=BABYLON.Matrix.Zero();this._scaledPosition=BABYLON.Vector3.Zero();this._scaledVelocity=BABYLON.Vector3.Zero();this.postProcessesEnabled=true;this.postProcessManager=new BABYLON.PostProcessManager(this);this.renderTargetsEnabled=true;this.customRenderTargets=[];this.activeCameras=[];};BABYLON.Scene.prototype.getEngine=function(){return this._engine;};BABYLON.Scene.prototype.getTotalVertices=function(){return this._totalVertices;};BABYLON.Scene.prototype.getActiveVertices=function(){return this._activeVertices;};BABYLON.Scene.prototype.getActiveParticles=function(){return this._activeParticles;};BABYLON.Scene.prototype.getLastFrameDuration=function(){return this._lastFrameDuration;};BABYLON.Scene.prototype.getEvaluateActiveMeshesDuration=function(){return this._evaluateActiveMeshesDuration;};BABYLON.Scene.prototype.getRenderTargetsDuration=function(){return this._renderTargetsDuration;};BABYLON.Scene.prototype.getRenderDuration=function(){return this._renderDuration;};BABYLON.Scene.prototype.getParticlesDuration=function(){return this._particlesDuration;};BABYLON.Scene.prototype.getSpritesDuration=function(){return this._spritesDuration;};BABYLON.Scene.prototype.getAnimationRatio=function(){return this._animationRatio;};BABYLON.Scene.prototype.getRenderId=function(){return this._renderId;};BABYLON.Scene.prototype.isReady=function(){if(this._pendingData.length>0){return false;}for(var index=0;index-1){this._onBeforeRenderCallbacks.splice(index,1);}};BABYLON.Scene.prototype._addPendingData=function(data){this._pendingData.push(data);};BABYLON.Scene.prototype._removePendingData=function(data){var index=this._pendingData.indexOf(data);if(index!==-1){this._pendingData.splice(index,1);}};BABYLON.Scene.prototype.getWaitingItemsCount=function(){return this._pendingData.length;};BABYLON.Scene.prototype.executeWhenReady=function(func){this._onReadyCallbacks.push(func);if(this._executeWhenReadyTimeoutId!==-1){return;}var that=this;this._executeWhenReadyTimeoutId=setTimeout(function(){that._checkIsReady();},150);};BABYLON.Scene.prototype._checkIsReady=function(){if(this.isReady()){this._onReadyCallbacks.forEach(function(func){func();});this._onReadyCallbacks=[];this._executeWhenReadyTimeoutId=-1;return;}var that=this;this._executeWhenReadyTimeoutId=setTimeout(function(){that._checkIsReady();},150);};BABYLON.Scene.prototype.beginAnimation=function(target,from,to,loop,speedRatio,onAnimationEnd){if(speedRatio===undefined){speedRatio=1.0;}if(target.animations){this.stopAnimation(target);var animatable=new BABYLON._Animatable(target,from,to,loop,speedRatio,onAnimationEnd);this._activeAnimatables.push(animatable);}if(target.getAnimatables){var animatables=target.getAnimatables();for(var index=0;index=0;index--){if(this.meshes[index].id===id){return this.meshes[index];}}return null;};BABYLON.Scene.prototype.getLastEntryByID=function(id){for(var index=this.meshes.length-1;index>=0;index--){if(this.meshes[index].id===id){return this.meshes[index];}}for(var index=this.cameras.length-1;index>=0;index--){if(this.cameras[index].id===id){return this.cameras[index];}}for(var index=this.lights.length-1;index>=0;index--){if(this.lights[index].id===id){return this.lights[index];}}return null;};BABYLON.Scene.prototype.getMeshByName=function(name){for(var index=0;index=0;index--){if(this.skeletons[index].id===id){return this.skeletons[index];}}return null;};BABYLON.Scene.prototype.getSkeletonById=function(id){for(var index=0;index0&&mesh.isInFrustrum(this._frustumPlanes))){if(mesh._renderId===0){this._activeMeshes.push(mesh);}mesh._renderId=this._renderId;if(mesh.skeleton){this._activeSkeletons.pushNoDuplicate(mesh.skeleton);}var subMeshes=block.subMeshes[meshIndex];for(var subIndex=0;subIndex0&&mesh.isInFrustrum(this._frustumPlanes)){this._activeMeshes.push(mesh);if(mesh.skeleton){this._activeSkeletons.pushNoDuplicate(mesh.skeleton);}for(var subIndex=0;subIndex0){engine.restoreDefaultFramebuffer();}this._renderTargetsDuration=new Date()-beforeRenderTargetDate;this.postProcessManager._prepareFrame();var beforeRenderDate=new Date();if(this.layers.length){engine.setDepthBuffer(false);var layerIndex;var layer;for(layerIndex=0;layerIndex0){var currentRenderId=this._renderId;for(var cameraIndex=0;cameraIndex=maximumRetry){finalPosition.copyFrom(position);return;}collider._initialize(position,velocity,closeDistance);for(var index=0;indexmax.x)max.x=v.x;if(v.y>max.y)max.y=v.y;if(v.z>max.z)max.z=v.z;};var min=new BABYLON.Vector3(Number.MAX_VALUE,Number.MAX_VALUE,Number.MAX_VALUE);var max=new BABYLON.Vector3(-Number.MAX_VALUE,-Number.MAX_VALUE,-Number.MAX_VALUE);for(var index=0;index=pickingInfo.distance)continue;pickingInfo=result;if(fastCheck){break;}}return pickingInfo||new BABYLON.PickingInfo();};BABYLON.Scene.prototype.pick=function(x,y,predicate,fastCheck){var that=this;return this._internalPick(function(world){return that.createPickingRay(x,y,world);},predicate,fastCheck);};BABYLON.Scene.prototype.pickWithRay=function(ray,predicate,fastCheck){var that=this;return this._internalPick(function(world){if(!that._pickWithRayInverseMatrix){that._pickWithRayInverseMatrix=BABYLON.Matrix.Identity();}world.invertToRef(that._pickWithRayInverseMatrix);return BABYLON.Ray.Transform(ray,that._pickWithRayInverseMatrix);},predicate,fastCheck);};BABYLON.Scene.prototype.enablePhysics=function(gravity){if(this._physicsEngine){return true;}if(!BABYLON.PhysicsEngine.IsSupported()){return false;}this._physicsEngine=new BABYLON.PhysicsEngine(gravity);return true;};BABYLON.Scene.prototype.disablePhysicsEngine=function(){if(!this._physicsEngine){return;}this._physicsEngine.dispose();this._physicsEngine=undefined;};BABYLON.Scene.prototype.isPhysicsEnabled=function(){return this._physicsEngine!==undefined;};BABYLON.Scene.prototype.setGravity=function(gravity){if(!this._physicsEngine){return;}this._physicsEngine._setGravity(gravity);};BABYLON.Scene.FOGMODE_NONE=0;BABYLON.Scene.FOGMODE_EXP=1;BABYLON.Scene.FOGMODE_EXP2=2;BABYLON.Scene.FOGMODE_LINEAR=3;})();var BABYLON=BABYLON||{};(function(){BABYLON.VertexBuffer=function(mesh,data,kind,updatable){this._mesh=mesh;this._engine=mesh.getScene().getEngine();this._updatable=updatable;if(updatable){this._buffer=this._engine.createDynamicVertexBuffer(data.length*4);this._engine.updateDynamicVertexBuffer(this._buffer,data);}else{this._buffer=this._engine.createVertexBuffer(data);}this._data=data;this._kind=kind;switch(kind){case BABYLON.VertexBuffer.PositionKind:this._strideSize=3;this._mesh._resetPointsArrayCache();break;case BABYLON.VertexBuffer.NormalKind:this._strideSize=3;break;case BABYLON.VertexBuffer.UVKind:this._strideSize=2;break;case BABYLON.VertexBuffer.UV2Kind:this._strideSize=2;break;case BABYLON.VertexBuffer.ColorKind:this._strideSize=3;break;case BABYLON.VertexBuffer.MatricesIndicesKind:this._strideSize=4;break;case BABYLON.VertexBuffer.MatricesWeightsKind:this._strideSize=4;break;}};BABYLON.VertexBuffer.prototype.isUpdatable=function(){return this._updatable;};BABYLON.VertexBuffer.prototype.getData=function(){return this._data;};BABYLON.VertexBuffer.prototype.getStrideSize=function(){return this._strideSize;};BABYLON.VertexBuffer.prototype.update=function(data){this._engine.updateDynamicVertexBuffer(this._buffer,data);this._data=data;if(this._kind===BABYLON.VertexBuffer.PositionKind){this._mesh._resetPointsArrayCache();}};BABYLON.VertexBuffer.prototype.dispose=function(){this._engine._releaseBuffer(this._buffer);};BABYLON.VertexBuffer.PositionKind="position";BABYLON.VertexBuffer.NormalKind="normal";BABYLON.VertexBuffer.UVKind="uv";BABYLON.VertexBuffer.UV2Kind="uv2";BABYLON.VertexBuffer.ColorKind="color";BABYLON.VertexBuffer.MatricesIndicesKind="matricesIndices";BABYLON.VertexBuffer.MatricesWeightsKind="matricesWeights";})();var BABYLON=BABYLON||{};(function(){BABYLON.Mesh=function(name,scene){this.name=name;this.id=name;this._scene=scene;this._totalVertices=0;this._worldMatrix=BABYLON.Matrix.Identity();scene.meshes.push(this);this.position=new BABYLON.Vector3(0,0,0);this.rotation=new BABYLON.Vector3(0,0,0);this.rotationQuaternion=null;this.scaling=new BABYLON.Vector3(1,1,1);this._pivotMatrix=BABYLON.Matrix.Identity();this._indices=[];this.subMeshes=[];this._renderId=0;this._onBeforeRenderCallbacks=[];this.animations=[];this._positions=null;this._cache={localMatrixUpdated:false,position:BABYLON.Vector3.Zero(),scaling:BABYLON.Vector3.Zero(),rotation:BABYLON.Vector3.Zero(),rotationQuaternion:new BABYLON.Quaternion(0,0,0,0)};this._childrenFlag=false;this._localScaling=BABYLON.Matrix.Zero();this._localRotation=BABYLON.Matrix.Zero();this._localTranslation=BABYLON.Matrix.Zero();this._localBillboard=BABYLON.Matrix.Zero();this._localPivotScaling=BABYLON.Matrix.Zero();this._localPivotScalingRotation=BABYLON.Matrix.Zero();this._localWorld=BABYLON.Matrix.Zero();this._worldMatrix=BABYLON.Matrix.Zero();this._rotateYByPI=BABYLON.Matrix.RotationY(Math.PI);this._collisionsTransformMatrix=BABYLON.Matrix.Zero();this._collisionsScalingMatrix=BABYLON.Matrix.Zero();this._absolutePosition=BABYLON.Vector3.Zero();};BABYLON.Mesh.prototype=Object.create(BABYLON.Node.prototype);BABYLON.Mesh.BILLBOARDMODE_NONE=0;BABYLON.Mesh.BILLBOARDMODE_X=1;BABYLON.Mesh.BILLBOARDMODE_Y=2;BABYLON.Mesh.BILLBOARDMODE_Z=4;BABYLON.Mesh.BILLBOARDMODE_ALL=7;BABYLON.Mesh.prototype.delayLoadState=BABYLON.Engine.DELAYLOADSTATE_NONE;BABYLON.Mesh.prototype.material=null;BABYLON.Mesh.prototype.isVisible=true;BABYLON.Mesh.prototype.isPickable=true;BABYLON.Mesh.prototype.visibility=1.0;BABYLON.Mesh.prototype.billboardMode=BABYLON.Mesh.BILLBOARDMODE_NONE;BABYLON.Mesh.prototype.checkCollisions=false;BABYLON.Mesh.prototype.receiveShadows=false;BABYLON.Mesh.prototype._isDisposed=false;BABYLON.Mesh.prototype.onDispose=null;BABYLON.Mesh.prototype.skeleton=null;BABYLON.Mesh.prototype.renderingGroupId=0;BABYLON.Mesh.prototype.infiniteDistance=false;BABYLON.Mesh.prototype.getBoundingInfo=function(){return this._boundingInfo;};BABYLON.Mesh.prototype.getScene=function(){return this._scene;};BABYLON.Mesh.prototype.getWorldMatrix=function(){if(this._currentRenderId!==this._scene.getRenderId()){this.computeWorldMatrix();}return this._worldMatrix;};BABYLON.Mesh.prototype.getAbsolutePosition=function(){return this._absolutePosition;};BABYLON.Mesh.prototype.getTotalVertices=function(){return this._totalVertices;};BABYLON.Mesh.prototype.getVerticesData=function(kind){return this._vertexBuffers[kind].getData();};BABYLON.Mesh.prototype.isVerticesDataPresent=function(kind){if(!this._vertexBuffers&&this._delayInfo){return this._delayInfo.indexOf(kind)!==-1;}return this._vertexBuffers[kind]!==undefined;};BABYLON.Mesh.prototype.getTotalIndices=function(){return this._indices.length;};BABYLON.Mesh.prototype.getIndices=function(){return this._indices;};BABYLON.Mesh.prototype.getVertexStrideSize=function(){return this._vertexStrideSize;};BABYLON.Mesh.prototype.setPivotMatrix=function(matrix){this._pivotMatrix=matrix;this._cache.pivotMatrixUpdated=true;};BABYLON.Mesh.prototype.getPivotMatrix=function(){return this._localMatrix;};BABYLON.Mesh.prototype.isSynchronized=function(){if(this.billboardMode!==BABYLON.Mesh.BILLBOARDMODE_NONE)return false;if(this._cache.pivotMatrixUpdated){return false;}if(this.infiniteDistance){return false;}if(!this._cache.position.equals(this.position))return false;if(this.rotationQuaternion){if(!this._cache.rotationQuaternion.equals(this.rotationQuaternion))return false;}else{if(!this._cache.rotation.equals(this.rotation))return false;}if(!this._cache.scaling.equals(this.scaling))return false;if(this.parent)return!this.parent._needToSynchonizeChildren();return true;};BABYLON.Mesh.prototype.isReady=function(){return this._isReady;};BABYLON.Mesh.prototype.isAnimated=function(){return this._animationStarted;};BABYLON.Mesh.prototype.isDisposed=function(){return this._isDisposed;};BABYLON.Mesh.prototype.markAsDirty=function(property){if(property==="rotation"){this.rotationQuaternion=null;}this._childrenFlag=true;};BABYLON.Mesh.prototype.refreshBoundingInfo=function(){var data=this.getVerticesData(BABYLON.VertexBuffer.PositionKind);if(!data){return;}var extend=BABYLON.Tools.ExtractMinAndMax(data,0,this._totalVertices);this._boundingInfo=new BABYLON.BoundingInfo(extend.minimum,extend.maximum);for(var index=0;index-1){this._onBeforeRenderCallbacks.splice(index,1);}};BABYLON.Mesh.prototype.render=function(subMesh){if(!this._vertexBuffers||!this._indexBuffer){return;}for(var callbackIndex=0;callbackIndex1&&!subMesh._checkCollision(collider))continue;this._collideForSubMesh(subMesh,transformMatrix,collider);}};BABYLON.Mesh.prototype._checkCollision=function(collider){if(!this._boundingInfo._checkCollision(collider))return;BABYLON.Matrix.ScalingToRef(1.0/collider.radius.x,1.0/collider.radius.y,1.0/collider.radius.z,this._collisionsScalingMatrix);this._worldMatrix.multiplyToRef(this._collisionsScalingMatrix,this._collisionsTransformMatrix);this._processCollisionsForSubModels(collider,this._collisionsTransformMatrix);};BABYLON.Mesh.prototype.intersectsMesh=function(mesh,precise){if(!this._boundingInfo||!mesh._boundingInfo){return false;}return this._boundingInfo.intersects(mesh._boundingInfo,precise);};BABYLON.Mesh.prototype.intersectsPoint=function(point){if(!this._boundingInfo){return false;}return this._boundingInfo.intersectsPoint(point);};BABYLON.Mesh.prototype.intersects=function(ray,fastCheck){var pickingInfo=new BABYLON.PickingInfo();if(!this._boundingInfo||!ray.intersectsSphere(this._boundingInfo.boundingSphere)||!ray.intersectsBox(this._boundingInfo.boundingBox)){return pickingInfo;}this._generatePointsArray();var distance=Number.MAX_VALUE;for(var index=0;index1&&!subMesh.canIntersects(ray))continue;var currentDistance=subMesh.intersects(ray,this._positions,this._indices,fastCheck);if(currentDistance>0){if(fastCheck||currentDistance=0&&distance0){var verticesCount=positions.length/3;for(var firstIndex=verticesCount-2*(totalYRotationSteps+1);(firstIndex+totalYRotationSteps+2)0){if(fastCheck||currentDistance0&&distancemaxVertexIndex)maxVertexIndex=vertexIndex;}return new BABYLON.SubMesh(materialIndex,minVertexIndex,maxVertexIndex-minVertexIndex,startIndex,indexCount,mesh);};})();var BABYLON=BABYLON||{};(function(){BABYLON.BaseTexture=function(url,scene){this._scene=scene;this._scene.textures.push(this);};BABYLON.BaseTexture.prototype.delayLoadState=BABYLON.Engine.DELAYLOADSTATE_NONE;BABYLON.BaseTexture.prototype.hasAlpha=false;BABYLON.BaseTexture.prototype.level=1;BABYLON.BaseTexture.prototype._texture=null;BABYLON.BaseTexture.prototype.onDispose=null;BABYLON.BaseTexture.prototype.getInternalTexture=function(){return this._texture;};BABYLON.BaseTexture.prototype.isReady=function(){if(this.delayLoadState===BABYLON.Engine.DELAYLOADSTATE_NOTLOADED){return true;}if(this._texture){return this._texture.isReady;}return false;};BABYLON.BaseTexture.prototype.getSize=function(){if(this._texture._width){return{width:this._texture._width,height:this._texture._height};}if(this._texture._size){return{width:this._texture._size,height:this._texture._size};}return{width:0,height:0};};BABYLON.BaseTexture.prototype.getBaseSize=function(){if(!this.isReady())return{width:0,height:0};if(this._texture._size){return{width:this._texture._size,height:this._texture._size};}return{width:this._texture._baseWidth,height:this._texture._baseHeight};};BABYLON.BaseTexture.prototype._getFromCache=function(url,noMipmap){var texturesCache=this._scene.getEngine().getLoadedTexturesCache();for(var index=0;index=0){this._scene.textures.splice(index,1);}if(this._texture===undefined){return;}this.releaseInternalTexture();if(this.onDispose){this.onDispose();}};})();var BABYLON=BABYLON||{};(function(){BABYLON.RenderingGroup=function(index,scene){this.index=index;this._scene=scene;this._opaqueSubMeshes=new BABYLON.Tools.SmartArray(256);this._transparentSubMeshes=new BABYLON.Tools.SmartArray(256);this._alphaTestSubMeshes=new BABYLON.Tools.SmartArray(256);};BABYLON.RenderingGroup.prototype.render=function(customRenderFunction,beforeTransparents){if(customRenderFunction){customRenderFunction(this._opaqueSubMeshes,this._alphaTestSubMeshes,this._transparentSubMeshes,beforeTransparents);return true;}if(this._opaqueSubMeshes.length===0&&this._alphaTestSubMeshes.length===0&&this._transparentSubMeshes===0){return false;}var engine=this._scene.getEngine();var subIndex;var submesh;for(subIndex=0;subIndexb._distanceToCamera){return-1;}return 0;});engine.setAlphaMode(BABYLON.Engine.ALPHA_COMBINE);for(subIndex=0;subIndex0||mesh.visibility<1.0){this._transparentSubMeshes.push(subMesh);}}else if(material.needAlphaTesting()){this._alphaTestSubMeshes.push(subMesh);}else{this._opaqueSubMeshes.push(subMesh);}};})();var BABYLON=BABYLON||{};(function(){BABYLON.RenderingManager=function(scene){this._scene=scene;this._renderingGroups=[];};BABYLON.RenderingManager.prototype._renderParticles=function(index,activeMeshes){if(this._scene._activeParticleSystems.length===0){return;}var beforeParticlesDate=new Date();for(var particleIndex=0;particleIndex 1.0 || uv.y < 0. || uv.y > 1.0)\n {\n return 1.0;\n }\n\n float shadow = unpack(texture2D(shadowSampler, uv));\n\n if (depth.z > shadow)\n {\n return 0.;\n }\n return 1.;\n}\n\n// Thanks to http://devmaster.net/\nfloat ChebychevInequality(vec2 moments, float t)\n{\n if (t <= moments.x)\n {\n return 1.0;\n }\n\n float variance = moments.y - (moments.x * moments.x);\n variance = max(variance, 0.);\n\n float d = t - moments.x;\n return variance / (variance + d * d);\n}\n\nfloat computeShadowWithVSM(vec4 vPositionFromLight, sampler2D shadowSampler)\n{\n vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;\n vec2 uv = 0.5 * depth.xy + vec2(0.5, 0.5);\n\n if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0)\n {\n return 1.0;\n }\n\n vec4 texel = texture2D(shadowSampler, uv);\n\n vec2 moments = vec2(unpackHalf(texel.xy), unpackHalf(texel.zw));\n return clamp(1.3 - ChebychevInequality(moments, depth.z), 0., 1.0);\n}\n#endif\n\n// Bump\n#ifdef BUMP\n#extension GL_OES_standard_derivatives : enable\nvarying vec2 vBumpUV;\nuniform vec2 vBumpInfos;\nuniform sampler2D bumpSampler;\n\n// Thanks to http://www.thetenthplanet.de/archives/1180\nmat3 cotangent_frame(vec3 normal, vec3 p, vec2 uv)\n{\n // get edge vectors of the pixel triangle\n vec3 dp1 = dFdx(p);\n vec3 dp2 = dFdy(p);\n vec2 duv1 = dFdx(uv);\n vec2 duv2 = dFdy(uv);\n\n // solve the linear system\n vec3 dp2perp = cross(dp2, normal);\n vec3 dp1perp = cross(normal, dp1);\n vec3 tangent = dp2perp * duv1.x + dp1perp * duv2.x;\n vec3 binormal = dp2perp * duv1.y + dp1perp * duv2.y;\n\n // construct a scale-invariant frame \n float invmax = inversesqrt(max(dot(tangent, tangent), dot(binormal, binormal)));\n return mat3(tangent * invmax, binormal * invmax, normal);\n}\n\nvec3 perturbNormal(vec3 viewDir)\n{\n vec3 map = texture2D(bumpSampler, vBumpUV).xyz * vBumpInfos.y;\n map = map * 255. / 127. - 128. / 127.;\n mat3 TBN = cotangent_frame(vNormalW, -viewDir, vBumpUV);\n return normalize(TBN * map);\n}\n#endif\n\n#ifdef CLIPPLANE\nvarying float fClipDistance;\n#endif\n\n// Fog\n#ifdef FOG\n\n#define FOGMODE_NONE 0.\n#define FOGMODE_EXP 1.\n#define FOGMODE_EXP2 2.\n#define FOGMODE_LINEAR 3.\n#define E 2.71828\n\nuniform vec4 vFogInfos;\nuniform vec3 vFogColor;\nvarying float fFogDistance;\n\nfloat CalcFogFactor()\n{\n float fogCoeff = 1.0;\n float fogStart = vFogInfos.y;\n float fogEnd = vFogInfos.z;\n float fogDensity = vFogInfos.w;\n\n if (FOGMODE_LINEAR == vFogInfos.x)\n {\n fogCoeff = (fogEnd - fFogDistance) / (fogEnd - fogStart);\n }\n else if (FOGMODE_EXP == vFogInfos.x)\n {\n fogCoeff = 1.0 / pow(E, fFogDistance * fogDensity);\n }\n else if (FOGMODE_EXP2 == vFogInfos.x)\n {\n fogCoeff = 1.0 / pow(E, fFogDistance * fFogDistance * fogDensity * fogDensity);\n }\n\n return clamp(fogCoeff, 0.0, 1.0);\n}\n#endif\n\n// Light Computing\nstruct lightingInfo\n{\n vec3 diffuse;\n vec3 specular;\n};\n\nlightingInfo computeLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, vec3 specularColor) {\n lightingInfo result;\n\n vec3 lightVectorW;\n if (lightData.w == 0.)\n {\n lightVectorW = normalize(lightData.xyz - vPositionW);\n }\n else\n {\n lightVectorW = normalize(-lightData.xyz);\n }\n\n // diffuse\n float ndl = max(0., dot(vNormal, lightVectorW));\n\n // Specular\n vec3 angleW = normalize(viewDirectionW + lightVectorW);\n float specComp = max(0., dot(vNormal, angleW));\n specComp = pow(specComp, vSpecularColor.a);\n\n result.diffuse = ndl * diffuseColor;\n result.specular = specComp * specularColor;\n\n return result;\n}\n\nlightingInfo computeSpotLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec4 lightDirection, vec3 diffuseColor, vec3 specularColor) {\n lightingInfo result;\n\n vec3 lightVectorW = normalize(lightData.xyz - vPositionW);\n\n // diffuse\n float cosAngle = max(0., dot(-lightDirection.xyz, lightVectorW));\n float spotAtten = 0.0;\n\n if (cosAngle >= lightDirection.w)\n {\n cosAngle = max(0., pow(cosAngle, lightData.w));\n spotAtten = max(0., (cosAngle - lightDirection.w) / (1. - cosAngle));\n\n // Diffuse\n float ndl = max(0., dot(vNormal, -lightDirection.xyz));\n\n // Specular\n vec3 angleW = normalize(viewDirectionW - lightDirection.xyz);\n float specComp = max(0., dot(vNormal, angleW));\n specComp = pow(specComp, vSpecularColor.a);\n\n result.diffuse = ndl * spotAtten * diffuseColor;\n result.specular = specComp * specularColor * spotAtten;\n\n return result;\n }\n\n result.diffuse = vec3(0.);\n result.specular = vec3(0.);\n\n return result;\n}\n\nlightingInfo computeHemisphericLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, vec3 specularColor, vec3 groundColor) {\n lightingInfo result;\n\n // Diffuse\n float ndl = dot(vNormal, lightData.xyz) * 0.5 + 0.5;\n\n // Specular\n vec3 angleW = normalize(viewDirectionW + lightData.xyz);\n float specComp = max(0., dot(vNormal, angleW));\n specComp = pow(specComp, vSpecularColor.a);\n\n result.diffuse = mix(groundColor, diffuseColor, ndl);\n result.specular = specComp * specularColor;\n\n return result;\n}\n\nvoid main(void) {\n // Clip plane\n#ifdef CLIPPLANE\n if (fClipDistance > 0.0)\n discard;\n#endif\n\n vec3 viewDirectionW = normalize(vEyePosition - vPositionW);\n\n // Base color\n vec4 baseColor = vec4(1., 1., 1., 1.);\n vec3 diffuseColor = vDiffuseColor.rgb;\n\n#ifdef VERTEXCOLOR\n diffuseColor *= vColor;\n#endif\n\n#ifdef DIFFUSE\n baseColor = texture2D(diffuseSampler, vDiffuseUV);\n\n#ifdef ALPHATEST\n if (baseColor.a < 0.4)\n discard;\n#endif\n\n baseColor.rgb *= vDiffuseInfos.y;\n#endif\n\n // Bump\n vec3 normalW = vNormalW;\n\n#ifdef BUMP\n normalW = perturbNormal(viewDirectionW);\n#endif\n\n // Ambient color\n vec3 baseAmbientColor = vec3(1., 1., 1.);\n\n#ifdef AMBIENT\n baseAmbientColor = texture2D(ambientSampler, vAmbientUV).rgb * vAmbientInfos.y;\n#endif\n\n // Lighting\n vec3 diffuseBase = vec3(0., 0., 0.);\n vec3 specularBase = vec3(0., 0., 0.);\n float shadow = 1.;\n\n#ifdef LIGHT0\n#ifdef SPOTLIGHT0\n lightingInfo info = computeSpotLighting(viewDirectionW, normalW, vLightData0, vLightDirection0, vLightDiffuse0, vLightSpecular0);\n#endif\n#ifdef HEMILIGHT0\n lightingInfo info = computeHemisphericLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0, vLightSpecular0, vLightGround0);\n#endif\n#ifdef POINTDIRLIGHT0\n lightingInfo info = computeLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0, vLightSpecular0);\n#endif\n#ifdef SHADOW0\n#ifdef SHADOWVSM0\n shadow = computeShadowWithVSM(vPositionFromLight0, shadowSampler0);\n#else\n shadow = computeShadow(vPositionFromLight0, shadowSampler0);\n#endif\n#else\n shadow = 1.;\n#endif\n diffuseBase += info.diffuse * shadow;\n specularBase += info.specular * shadow;\n#endif\n\n#ifdef LIGHT1\n#ifdef SPOTLIGHT1\n info = computeSpotLighting(viewDirectionW, normalW, vLightData1, vLightDirection1, vLightDiffuse1, vLightSpecular1);\n#endif\n#ifdef HEMILIGHT1\n info = computeHemisphericLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1, vLightSpecular1, vLightGround1);\n#endif\n#ifdef POINTDIRLIGHT1\n info = computeLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1, vLightSpecular1);\n#endif\n#ifdef SHADOW1\n#ifdef SHADOWVSM1\n shadow = computeShadowWithVSM(vPositionFromLight1, shadowSampler1);\n#else\n shadow = computeShadow(vPositionFromLight1, shadowSampler1);\n#endif\n#else\n shadow = 1.;\n#endif\n diffuseBase += info.diffuse * shadow;\n specularBase += info.specular * shadow;\n#endif\n\n#ifdef LIGHT2\n#ifdef SPOTLIGHT2\n info = computeSpotLighting(viewDirectionW, normalW, vLightData2, vLightDirection2, vLightDiffuse2, vLightSpecular2);\n#endif\n#ifdef HEMILIGHT2\n info = computeHemisphericLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2, vLightSpecular2, vLightGround2);\n#endif\n#ifdef POINTDIRLIGHT2\n info = computeLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2, vLightSpecular2);\n#endif\n#ifdef SHADOW2\n#ifdef SHADOWVSM2\n shadow = computeShadowWithVSM(vPositionFromLight2, shadowSampler2);\n#else\n shadow = computeShadow(vPositionFromLight2, shadowSampler2);\n#endif \n#else\n shadow = 1.;\n#endif\n diffuseBase += info.diffuse * shadow;\n specularBase += info.specular * shadow;\n#endif\n\n#ifdef LIGHT3\n#ifdef SPOTLIGHT3\n info = computeSpotLighting(viewDirectionW, normalW, vLightData3, vLightDirection3, vLightDiffuse3, vLightSpecular3);\n#endif\n#ifdef HEMILIGHT3\n info = computeHemisphericLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3, vLightSpecular3, vLightGround3);\n#endif\n#ifdef POINTDIRLIGHT3\n info = computeLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3, vLightSpecular3);\n#endif\n#ifdef SHADOW3\n#ifdef SHADOWVSM3\n shadow = computeShadowWithVSM(vPositionFromLight3, shadowSampler3);\n#else\n shadow = computeShadow(vPositionFromLight3, shadowSampler3);\n#endif \n#else\n shadow = 1.;\n#endif\n diffuseBase += info.diffuse * shadow;\n specularBase += info.specular * shadow;\n#endif\n\n // Reflection\n vec3 reflectionColor = vec3(0., 0., 0.);\n\n#ifdef REFLECTION\n vec3 vReflectionUVW = computeReflectionCoords(vReflectionInfos.x, vec4(vPositionW, 1.0), normalW);\n\n if (vReflectionInfos.z != 0.0)\n {\n reflectionColor = textureCube(reflectionCubeSampler, vReflectionUVW).rgb * vReflectionInfos.y;\n }\n else\n {\n vec2 coords = vReflectionUVW.xy;\n\n if (vReflectionInfos.x == MAP_PROJECTION)\n {\n coords /= vReflectionUVW.z;\n }\n\n coords.y = 1.0 - coords.y;\n\n reflectionColor = texture2D(reflection2DSampler, coords).rgb * vReflectionInfos.y;\n }\n#endif\n\n // Alpha\n float alpha = vDiffuseColor.a;\n\n#ifdef OPACITY\n vec3 opacityMap = texture2D(opacitySampler, vOpacityUV).rgb * vec3(0.3, 0.59, 0.11);\n alpha *= (opacityMap.x + opacityMap.y + opacityMap.z)* vOpacityInfos.y;\n#endif\n\n // Emissive\n vec3 emissiveColor = vEmissiveColor;\n#ifdef EMISSIVE\n emissiveColor += texture2D(emissiveSampler, vEmissiveUV).rgb * vEmissiveInfos.y;\n#endif\n\n // Specular map\n vec3 specularColor = vSpecularColor.rgb;\n#ifdef SPECULAR\n specularColor = texture2D(specularSampler, vSpecularUV).rgb * vSpecularInfos.y;\n#endif\n\n // Composition\n vec3 finalDiffuse = clamp(diffuseBase * diffuseColor + emissiveColor + vAmbientColor, 0.0, 1.0) * baseColor.rgb;\n vec3 finalSpecular = specularBase * specularColor;\n\n vec4 color = vec4(finalDiffuse * baseAmbientColor + finalSpecular + reflectionColor, alpha);\n\n#ifdef FOG\n float fog = CalcFogFactor();\n color.rgb = fog * color.rgb + (1.0 - fog) * vFogColor;\n#endif\n\n gl_FragColor = color;\n}", -defaultVertexShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n// Attributes\nattribute vec3 position;\nattribute vec3 normal;\n#ifdef UV1\nattribute vec2 uv;\n#endif\n#ifdef UV2\nattribute vec2 uv2;\n#endif\n#ifdef VERTEXCOLOR\nattribute vec3 color;\n#endif\n#ifdef BONES\nattribute vec4 matricesIndices;\nattribute vec4 matricesWeights;\n#endif\n\n// Uniforms\nuniform mat4 world;\nuniform mat4 view;\n\n#ifdef DIFFUSE\nvarying vec2 vDiffuseUV;\nuniform mat4 diffuseMatrix;\nuniform vec2 vDiffuseInfos;\n#endif\n\n#ifdef AMBIENT\nvarying vec2 vAmbientUV;\nuniform mat4 ambientMatrix;\nuniform vec2 vAmbientInfos;\n#endif\n\n#ifdef OPACITY\nvarying vec2 vOpacityUV;\nuniform mat4 opacityMatrix;\nuniform vec2 vOpacityInfos;\n#endif\n\n#ifdef EMISSIVE\nvarying vec2 vEmissiveUV;\nuniform vec2 vEmissiveInfos;\nuniform mat4 emissiveMatrix;\n#endif\n\n#ifdef SPECULAR\nvarying vec2 vSpecularUV;\nuniform vec2 vSpecularInfos;\nuniform mat4 specularMatrix;\n#endif\n\n#ifdef BUMP\nvarying vec2 vBumpUV;\nuniform vec2 vBumpInfos;\nuniform mat4 bumpMatrix;\n#endif\n\n#ifdef BONES\nuniform mat4 mBones[BonesPerMesh];\nuniform mat4 viewProjection;\n#else\nuniform mat4 worldViewProjection;\n#endif\n\n// Output\nvarying vec3 vPositionW;\nvarying vec3 vNormalW;\n\n#ifdef VERTEXCOLOR\nvarying vec3 vColor;\n#endif\n\n#ifdef CLIPPLANE\nuniform vec4 vClipPlane;\nvarying float fClipDistance;\n#endif\n\n#ifdef FOG\nvarying float fFogDistance;\n#endif\n\n#ifdef SHADOWS\n#ifdef LIGHT0\nuniform mat4 lightMatrix0;\nvarying vec4 vPositionFromLight0;\n#endif\n#ifdef LIGHT1\nuniform mat4 lightMatrix1;\nvarying vec4 vPositionFromLight1;\n#endif\n#ifdef LIGHT2\nuniform mat4 lightMatrix2;\nvarying vec4 vPositionFromLight2;\n#endif\n#ifdef LIGHT3\nuniform mat4 lightMatrix3;\nvarying vec4 vPositionFromLight3;\n#endif\n#endif\n\n#ifdef REFLECTION\nvarying vec3 vPositionUVW;\n#endif\n\nvoid main(void) {\n mat4 finalWorld;\n\n#ifdef REFLECTION\n vPositionUVW = position;\n#endif \n\n#ifdef BONES\n mat4 m0 = mBones[int(matricesIndices.x)] * matricesWeights.x;\n mat4 m1 = mBones[int(matricesIndices.y)] * matricesWeights.y;\n mat4 m2 = mBones[int(matricesIndices.z)] * matricesWeights.z;\n\n#ifdef BONES4\n mat4 m3 = mBones[int(matricesIndices.w)] * matricesWeights.w;\n finalWorld = world * (m0 + m1 + m2 + m3);\n#else\n finalWorld = world * (m0 + m1 + m2);\n#endif \n\n gl_Position = viewProjection * finalWorld * vec4(position, 1.0);\n#else\n finalWorld = world;\n gl_Position = worldViewProjection * vec4(position, 1.0);\n#endif\n\n vec4 worldPos = finalWorld * vec4(position, 1.0);\n vPositionW = vec3(worldPos);\n vNormalW = normalize(vec3(finalWorld * vec4(normal, 0.0)));\n\n // Texture coordinates\n#ifndef UV1\n vec2 uv = vec2(0., 0.);\n#endif\n#ifndef UV2\n vec2 uv2 = vec2(0., 0.);\n#endif\n\n#ifdef DIFFUSE\n if (vDiffuseInfos.x == 0.)\n {\n vDiffuseUV = vec2(diffuseMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vDiffuseUV = vec2(diffuseMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n#ifdef AMBIENT\n if (vAmbientInfos.x == 0.)\n {\n vAmbientUV = vec2(ambientMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vAmbientUV = vec2(ambientMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n#ifdef OPACITY\n if (vOpacityInfos.x == 0.)\n {\n vOpacityUV = vec2(opacityMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vOpacityUV = vec2(opacityMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n#ifdef EMISSIVE\n if (vEmissiveInfos.x == 0.)\n {\n vEmissiveUV = vec2(emissiveMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vEmissiveUV = vec2(emissiveMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n#ifdef SPECULAR\n if (vSpecularInfos.x == 0.)\n {\n vSpecularUV = vec2(specularMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vSpecularUV = vec2(specularMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n#ifdef BUMP\n if (vBumpInfos.x == 0.)\n {\n vBumpUV = vec2(bumpMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vBumpUV = vec2(bumpMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n // Clip plane\n#ifdef CLIPPLANE\n fClipDistance = dot(worldPos, vClipPlane);\n#endif\n\n // Fog\n#ifdef FOG\n fFogDistance = (view * worldPos).z;\n#endif\n\n // Shadows\n#ifdef SHADOWS\n#ifdef LIGHT0\n vPositionFromLight0 = lightMatrix0 * vec4(position, 1.0);\n#endif\n#ifdef LIGHT1\n vPositionFromLight1 = lightMatrix1 * vec4(position, 1.0);\n#endif\n#ifdef LIGHT2\n vPositionFromLight2 = lightMatrix2 * vec4(position, 1.0);\n#endif\n#ifdef LIGHT3\n vPositionFromLight3 = lightMatrix3 * vec4(position, 1.0);\n#endif\n#endif\n\n // Vertex color\n#ifdef VERTEXCOLOR\n vColor = color;\n#endif\n}", +defaultPixelShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n#define MAP_EXPLICIT 0.\n#define MAP_SPHERICAL 1.\n#define MAP_PLANAR 2.\n#define MAP_CUBIC 3.\n#define MAP_PROJECTION 4.\n#define MAP_SKYBOX 5.\n\n// Constants\nuniform vec3 vEyePosition;\nuniform vec3 vAmbientColor;\nuniform vec4 vDiffuseColor;\nuniform vec4 vSpecularColor;\nuniform vec3 vEmissiveColor;\n\n// Input\nvarying vec3 vPositionW;\nvarying vec3 vNormalW;\n\n#ifdef VERTEXCOLOR\nvarying vec3 vColor;\n#endif\n\n// Lights\n#ifdef LIGHT0\nuniform vec4 vLightData0;\nuniform vec3 vLightDiffuse0;\nuniform vec3 vLightSpecular0;\n#ifdef SHADOW0\nvarying vec4 vPositionFromLight0;\nuniform sampler2D shadowSampler0;\n#endif\n#ifdef SPOTLIGHT0\nuniform vec4 vLightDirection0;\n#endif\n#ifdef HEMILIGHT0\nuniform vec3 vLightGround0;\n#endif\n#endif\n\n#ifdef LIGHT1\nuniform vec4 vLightData1;\nuniform vec3 vLightDiffuse1;\nuniform vec3 vLightSpecular1;\n#ifdef SHADOW1\nvarying vec4 vPositionFromLight1;\nuniform sampler2D shadowSampler1;\n#endif\n#ifdef SPOTLIGHT1\nuniform vec4 vLightDirection1;\n#endif\n#ifdef HEMILIGHT1\nuniform vec3 vLightGround1;\n#endif\n#endif\n\n#ifdef LIGHT2\nuniform vec4 vLightData2;\nuniform vec3 vLightDiffuse2;\nuniform vec3 vLightSpecular2;\n#ifdef SHADOW2\nvarying vec4 vPositionFromLight2;\nuniform sampler2D shadowSampler2;\n#endif\n#ifdef SPOTLIGHT2\nuniform vec4 vLightDirection2;\n#endif\n#ifdef HEMILIGHT2\nuniform vec3 vLightGround2;\n#endif\n#endif\n\n#ifdef LIGHT3\nuniform vec4 vLightData3;\nuniform vec3 vLightDiffuse3;\nuniform vec3 vLightSpecular3;\n#ifdef SHADOW3\nvarying vec4 vPositionFromLight3;\nuniform sampler2D shadowSampler3;\n#endif\n#ifdef SPOTLIGHT3\nuniform vec4 vLightDirection3;\n#endif\n#ifdef HEMILIGHT3\nuniform vec3 vLightGround3;\n#endif\n#endif\n\n// Samplers\n#ifdef DIFFUSE\nvarying vec2 vDiffuseUV;\nuniform sampler2D diffuseSampler;\nuniform vec2 vDiffuseInfos;\n#endif\n\n#ifdef AMBIENT\nvarying vec2 vAmbientUV;\nuniform sampler2D ambientSampler;\nuniform vec2 vAmbientInfos;\n#endif\n\n#ifdef OPACITY \nvarying vec2 vOpacityUV;\nuniform sampler2D opacitySampler;\nuniform vec2 vOpacityInfos;\n#endif\n\n#ifdef EMISSIVE\nvarying vec2 vEmissiveUV;\nuniform vec2 vEmissiveInfos;\nuniform sampler2D emissiveSampler;\n#endif\n\n#ifdef SPECULAR\nvarying vec2 vSpecularUV;\nuniform vec2 vSpecularInfos;\nuniform sampler2D specularSampler;\n#endif\n\n// Reflection\n#ifdef REFLECTION\nvarying vec3 vPositionUVW;\nuniform samplerCube reflectionCubeSampler;\nuniform sampler2D reflection2DSampler;\nuniform vec3 vReflectionInfos;\nuniform mat4 reflectionMatrix;\nuniform mat4 view;\n\nvec3 computeReflectionCoords(float mode, vec4 worldPos, vec3 worldNormal)\n{\n if (mode == MAP_SPHERICAL)\n {\n vec3 coords = vec3(view * vec4(worldNormal, 0.0));\n\n return vec3(reflectionMatrix * vec4(coords, 1.0));\n }\n else if (mode == MAP_PLANAR)\n {\n vec3 viewDir = worldPos.xyz - vEyePosition;\n vec3 coords = normalize(reflect(viewDir, worldNormal));\n\n return vec3(reflectionMatrix * vec4(coords, 1));\n }\n else if (mode == MAP_CUBIC)\n {\n vec3 viewDir = worldPos.xyz - vEyePosition;\n vec3 coords = reflect(viewDir, worldNormal);\n\n return vec3(reflectionMatrix * vec4(coords, 0));\n }\n else if (mode == MAP_PROJECTION)\n {\n return vec3(reflectionMatrix * (view * worldPos));\n }\n else if (mode == MAP_SKYBOX)\n {\n return vPositionUVW;\n }\n\n return vec3(0, 0, 0);\n}\n#endif\n\n// Shadows\n#ifdef SHADOWS\n\nfloat unpack(vec4 color)\n{\n const vec4 bitShift = vec4(1. / (255. * 255. * 255.), 1. / (255. * 255.), 1. / 255., 1.);\n return dot(color, bitShift);\n}\n\nfloat unpackHalf(vec2 color)\n{\n return color.x + (color.y / 255.0);\n}\n\nfloat computeShadow(vec4 vPositionFromLight, sampler2D shadowSampler)\n{\n vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;\n vec2 uv = 0.5 * depth.xy + vec2(0.5, 0.5);\n\n if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0)\n {\n return 1.0;\n }\n\n float shadow = unpack(texture2D(shadowSampler, uv));\n\n if (depth.z > shadow)\n {\n return 0.;\n }\n return 1.;\n}\n\n// Thanks to http://devmaster.net/\nfloat ChebychevInequality(vec2 moments, float t)\n{\n if (t <= moments.x)\n {\n return 1.0;\n }\n\n float variance = moments.y - (moments.x * moments.x);\n variance = max(variance, 0.);\n\n float d = t - moments.x;\n return variance / (variance + d * d);\n}\n\nfloat computeShadowWithVSM(vec4 vPositionFromLight, sampler2D shadowSampler)\n{\n vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;\n vec2 uv = 0.5 * depth.xy + vec2(0.5, 0.5);\n\n if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0)\n {\n return 1.0;\n }\n\n vec4 texel = texture2D(shadowSampler, uv);\n\n vec2 moments = vec2(unpackHalf(texel.xy), unpackHalf(texel.zw));\n return clamp(1.3 - ChebychevInequality(moments, depth.z), 0., 1.0);\n}\n#endif\n\n// Bump\n#ifdef BUMP\n#extension GL_OES_standard_derivatives : enable\nvarying vec2 vBumpUV;\nuniform vec2 vBumpInfos;\nuniform sampler2D bumpSampler;\n\n// Thanks to http://www.thetenthplanet.de/archives/1180\nmat3 cotangent_frame(vec3 normal, vec3 p, vec2 uv)\n{\n // get edge vectors of the pixel triangle\n vec3 dp1 = dFdx(p);\n vec3 dp2 = dFdy(p);\n vec2 duv1 = dFdx(uv);\n vec2 duv2 = dFdy(uv);\n\n // solve the linear system\n vec3 dp2perp = cross(dp2, normal);\n vec3 dp1perp = cross(normal, dp1);\n vec3 tangent = dp2perp * duv1.x + dp1perp * duv2.x;\n vec3 binormal = dp2perp * duv1.y + dp1perp * duv2.y;\n\n // construct a scale-invariant frame \n float invmax = inversesqrt(max(dot(tangent, tangent), dot(binormal, binormal)));\n return mat3(tangent * invmax, binormal * invmax, normal);\n}\n\nvec3 perturbNormal(vec3 viewDir)\n{\n vec3 map = texture2D(bumpSampler, vBumpUV).xyz * vBumpInfos.y;\n map = map * 255. / 127. - 128. / 127.;\n mat3 TBN = cotangent_frame(vNormalW, -viewDir, vBumpUV);\n return normalize(TBN * map);\n}\n#endif\n\n#ifdef CLIPPLANE\nvarying float fClipDistance;\n#endif\n\n// Fog\n#ifdef FOG\n\n#define FOGMODE_NONE 0.\n#define FOGMODE_EXP 1.\n#define FOGMODE_EXP2 2.\n#define FOGMODE_LINEAR 3.\n#define E 2.71828\n\nuniform vec4 vFogInfos;\nuniform vec3 vFogColor;\nvarying float fFogDistance;\n\nfloat CalcFogFactor()\n{\n float fogCoeff = 1.0;\n float fogStart = vFogInfos.y;\n float fogEnd = vFogInfos.z;\n float fogDensity = vFogInfos.w;\n\n if (FOGMODE_LINEAR == vFogInfos.x)\n {\n fogCoeff = (fogEnd - fFogDistance) / (fogEnd - fogStart);\n }\n else if (FOGMODE_EXP == vFogInfos.x)\n {\n fogCoeff = 1.0 / pow(E, fFogDistance * fogDensity);\n }\n else if (FOGMODE_EXP2 == vFogInfos.x)\n {\n fogCoeff = 1.0 / pow(E, fFogDistance * fFogDistance * fogDensity * fogDensity);\n }\n\n return clamp(fogCoeff, 0.0, 1.0);\n}\n#endif\n\n// Light Computing\nstruct lightingInfo\n{\n vec3 diffuse;\n vec3 specular;\n};\n\nlightingInfo computeLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, vec3 specularColor) {\n lightingInfo result;\n\n vec3 lightVectorW;\n if (lightData.w == 0.)\n {\n lightVectorW = normalize(lightData.xyz - vPositionW);\n }\n else\n {\n lightVectorW = normalize(-lightData.xyz);\n }\n\n // diffuse\n float ndl = max(0., dot(vNormal, lightVectorW));\n\n // Specular\n vec3 angleW = normalize(viewDirectionW + lightVectorW);\n float specComp = max(0., dot(vNormal, angleW));\n specComp = pow(specComp, vSpecularColor.a);\n\n result.diffuse = ndl * diffuseColor;\n result.specular = specComp * specularColor;\n\n return result;\n}\n\nlightingInfo computeSpotLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec4 lightDirection, vec3 diffuseColor, vec3 specularColor) {\n lightingInfo result;\n\n vec3 lightVectorW = normalize(lightData.xyz - vPositionW);\n\n // diffuse\n float cosAngle = max(0., dot(-lightDirection.xyz, lightVectorW));\n float spotAtten = 0.0;\n\n if (cosAngle >= lightDirection.w)\n {\n cosAngle = max(0., pow(cosAngle, lightData.w));\n spotAtten = max(0., (cosAngle - lightDirection.w) / (1. - cosAngle));\n\n // Diffuse\n float ndl = max(0., dot(vNormal, -lightDirection.xyz));\n\n // Specular\n vec3 angleW = normalize(viewDirectionW - lightDirection.xyz);\n float specComp = max(0., dot(vNormal, angleW));\n specComp = pow(specComp, vSpecularColor.a);\n\n result.diffuse = ndl * spotAtten * diffuseColor;\n result.specular = specComp * specularColor * spotAtten;\n\n return result;\n }\n\n result.diffuse = vec3(0.);\n result.specular = vec3(0.);\n\n return result;\n}\n\nlightingInfo computeHemisphericLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, vec3 specularColor, vec3 groundColor) {\n lightingInfo result;\n\n // Diffuse\n float ndl = dot(vNormal, lightData.xyz) * 0.5 + 0.5;\n\n // Specular\n vec3 angleW = normalize(viewDirectionW + lightData.xyz);\n float specComp = max(0., dot(vNormal, angleW));\n specComp = pow(specComp, vSpecularColor.a);\n\n result.diffuse = mix(groundColor, diffuseColor, ndl);\n result.specular = specComp * specularColor;\n\n return result;\n}\n\nvoid main(void) {\n // Clip plane\n#ifdef CLIPPLANE\n if (fClipDistance > 0.0)\n discard;\n#endif\n\n vec3 viewDirectionW = normalize(vEyePosition - vPositionW);\n\n // Base color\n vec4 baseColor = vec4(1., 1., 1., 1.);\n vec3 diffuseColor = vDiffuseColor.rgb;\n\n#ifdef VERTEXCOLOR\n diffuseColor *= vColor;\n#endif\n\n#ifdef DIFFUSE\n baseColor = texture2D(diffuseSampler, vDiffuseUV);\n\n#ifdef ALPHATEST\n if (baseColor.a < 0.4)\n discard;\n#endif\n\n baseColor.rgb *= vDiffuseInfos.y;\n#endif\n\n // Bump\n vec3 normalW = vNormalW;\n\n#ifdef BUMP\n normalW = perturbNormal(viewDirectionW);\n#endif\n\n // Ambient color\n vec3 baseAmbientColor = vec3(1., 1., 1.);\n\n#ifdef AMBIENT\n baseAmbientColor = texture2D(ambientSampler, vAmbientUV).rgb * vAmbientInfos.y;\n#endif\n\n // Lighting\n vec3 diffuseBase = vec3(0., 0., 0.);\n vec3 specularBase = vec3(0., 0., 0.);\n float shadow = 1.;\n\n#ifdef LIGHT0\n#ifdef SPOTLIGHT0\n lightingInfo info = computeSpotLighting(viewDirectionW, normalW, vLightData0, vLightDirection0, vLightDiffuse0, vLightSpecular0);\n#endif\n#ifdef HEMILIGHT0\n lightingInfo info = computeHemisphericLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0, vLightSpecular0, vLightGround0);\n#endif\n#ifdef POINTDIRLIGHT0\n lightingInfo info = computeLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0, vLightSpecular0);\n#endif\n#ifdef SHADOW0\n#ifdef SHADOWVSM0\n shadow = computeShadowWithVSM(vPositionFromLight0, shadowSampler0);\n#else\n shadow = computeShadow(vPositionFromLight0, shadowSampler0);\n#endif\n#else\n shadow = 1.;\n#endif\n diffuseBase += info.diffuse * shadow;\n specularBase += info.specular * shadow;\n#endif\n\n#ifdef LIGHT1\n#ifdef SPOTLIGHT1\n info = computeSpotLighting(viewDirectionW, normalW, vLightData1, vLightDirection1, vLightDiffuse1, vLightSpecular1);\n#endif\n#ifdef HEMILIGHT1\n info = computeHemisphericLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1, vLightSpecular1, vLightGround1);\n#endif\n#ifdef POINTDIRLIGHT1\n info = computeLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1, vLightSpecular1);\n#endif\n#ifdef SHADOW1\n#ifdef SHADOWVSM1\n shadow = computeShadowWithVSM(vPositionFromLight1, shadowSampler1);\n#else\n shadow = computeShadow(vPositionFromLight1, shadowSampler1);\n#endif\n#else\n shadow = 1.;\n#endif\n diffuseBase += info.diffuse * shadow;\n specularBase += info.specular * shadow;\n#endif\n\n#ifdef LIGHT2\n#ifdef SPOTLIGHT2\n info = computeSpotLighting(viewDirectionW, normalW, vLightData2, vLightDirection2, vLightDiffuse2, vLightSpecular2);\n#endif\n#ifdef HEMILIGHT2\n info = computeHemisphericLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2, vLightSpecular2, vLightGround2);\n#endif\n#ifdef POINTDIRLIGHT2\n info = computeLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2, vLightSpecular2);\n#endif\n#ifdef SHADOW2\n#ifdef SHADOWVSM2\n shadow = computeShadowWithVSM(vPositionFromLight2, shadowSampler2);\n#else\n shadow = computeShadow(vPositionFromLight2, shadowSampler2);\n#endif \n#else\n shadow = 1.;\n#endif\n diffuseBase += info.diffuse * shadow;\n specularBase += info.specular * shadow;\n#endif\n\n#ifdef LIGHT3\n#ifdef SPOTLIGHT3\n info = computeSpotLighting(viewDirectionW, normalW, vLightData3, vLightDirection3, vLightDiffuse3, vLightSpecular3);\n#endif\n#ifdef HEMILIGHT3\n info = computeHemisphericLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3, vLightSpecular3, vLightGround3);\n#endif\n#ifdef POINTDIRLIGHT3\n info = computeLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3, vLightSpecular3);\n#endif\n#ifdef SHADOW3\n#ifdef SHADOWVSM3\n shadow = computeShadowWithVSM(vPositionFromLight3, shadowSampler3);\n#else\n shadow = computeShadow(vPositionFromLight3, shadowSampler3);\n#endif \n#else\n shadow = 1.;\n#endif\n diffuseBase += info.diffuse * shadow;\n specularBase += info.specular * shadow;\n#endif\n\n // Reflection\n vec3 reflectionColor = vec3(0., 0., 0.);\n\n#ifdef REFLECTION\n vec3 vReflectionUVW = computeReflectionCoords(vReflectionInfos.x, vec4(vPositionW, 1.0), normalW);\n\n if (vReflectionInfos.z != 0.0)\n {\n reflectionColor = textureCube(reflectionCubeSampler, vReflectionUVW).rgb * vReflectionInfos.y;\n }\n else\n {\n vec2 coords = vReflectionUVW.xy;\n\n if (vReflectionInfos.x == MAP_PROJECTION)\n {\n coords /= vReflectionUVW.z;\n }\n\n coords.y = 1.0 - coords.y;\n\n reflectionColor = texture2D(reflection2DSampler, coords).rgb * vReflectionInfos.y;\n }\n#endif\n\n // Alpha\n float alpha = vDiffuseColor.a;\n\n#ifdef OPACITY\n vec4 opacityMap = texture2D(opacitySampler, vOpacityUV);\n opacityMap.rgb = opacityMap.rgb * vec3(0.3, 0.59, 0.11) * opacityMap.a;\n alpha *= (opacityMap.x + opacityMap.y + opacityMap.z)* vOpacityInfos.y;\n#endif\n\n // Emissive\n vec3 emissiveColor = vEmissiveColor;\n#ifdef EMISSIVE\n emissiveColor += texture2D(emissiveSampler, vEmissiveUV).rgb * vEmissiveInfos.y;\n#endif\n\n // Specular map\n vec3 specularColor = vSpecularColor.rgb;\n#ifdef SPECULAR\n specularColor = texture2D(specularSampler, vSpecularUV).rgb * vSpecularInfos.y;\n#endif\n\n // Composition\n vec3 finalDiffuse = clamp(diffuseBase * diffuseColor + emissiveColor + vAmbientColor, 0.0, 1.0) * baseColor.rgb;\n vec3 finalSpecular = specularBase * specularColor;\n\n vec4 color = vec4(finalDiffuse * baseAmbientColor + finalSpecular + reflectionColor, alpha);\n\n#ifdef FOG\n float fog = CalcFogFactor();\n color.rgb = fog * color.rgb + (1.0 - fog) * vFogColor;\n#endif\n\n gl_FragColor = color;\n}", +defaultVertexShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n// Attributes\nattribute vec3 position;\nattribute vec3 normal;\n#ifdef UV1\nattribute vec2 uv;\n#endif\n#ifdef UV2\nattribute vec2 uv2;\n#endif\n#ifdef VERTEXCOLOR\nattribute vec3 color;\n#endif\n#ifdef BONES\nattribute vec4 matricesIndices;\nattribute vec4 matricesWeights;\n#endif\n\n// Uniforms\nuniform mat4 world;\nuniform mat4 view;\nuniform mat4 viewProjection;\n\n#ifdef DIFFUSE\nvarying vec2 vDiffuseUV;\nuniform mat4 diffuseMatrix;\nuniform vec2 vDiffuseInfos;\n#endif\n\n#ifdef AMBIENT\nvarying vec2 vAmbientUV;\nuniform mat4 ambientMatrix;\nuniform vec2 vAmbientInfos;\n#endif\n\n#ifdef OPACITY\nvarying vec2 vOpacityUV;\nuniform mat4 opacityMatrix;\nuniform vec2 vOpacityInfos;\n#endif\n\n#ifdef EMISSIVE\nvarying vec2 vEmissiveUV;\nuniform vec2 vEmissiveInfos;\nuniform mat4 emissiveMatrix;\n#endif\n\n#ifdef SPECULAR\nvarying vec2 vSpecularUV;\nuniform vec2 vSpecularInfos;\nuniform mat4 specularMatrix;\n#endif\n\n#ifdef BUMP\nvarying vec2 vBumpUV;\nuniform vec2 vBumpInfos;\nuniform mat4 bumpMatrix;\n#endif\n\n#ifdef BONES\nuniform mat4 mBones[BonesPerMesh];\n#endif\n\n// Output\nvarying vec3 vPositionW;\nvarying vec3 vNormalW;\n\n#ifdef VERTEXCOLOR\nvarying vec3 vColor;\n#endif\n\n#ifdef CLIPPLANE\nuniform vec4 vClipPlane;\nvarying float fClipDistance;\n#endif\n\n#ifdef FOG\nvarying float fFogDistance;\n#endif\n\n#ifdef SHADOWS\n#ifdef LIGHT0\nuniform mat4 lightMatrix0;\nvarying vec4 vPositionFromLight0;\n#endif\n#ifdef LIGHT1\nuniform mat4 lightMatrix1;\nvarying vec4 vPositionFromLight1;\n#endif\n#ifdef LIGHT2\nuniform mat4 lightMatrix2;\nvarying vec4 vPositionFromLight2;\n#endif\n#ifdef LIGHT3\nuniform mat4 lightMatrix3;\nvarying vec4 vPositionFromLight3;\n#endif\n#endif\n\n#ifdef REFLECTION\nvarying vec3 vPositionUVW;\n#endif\n\nvoid main(void) {\n mat4 finalWorld;\n\n#ifdef REFLECTION\n vPositionUVW = position;\n#endif \n\n#ifdef BONES\n mat4 m0 = mBones[int(matricesIndices.x)] * matricesWeights.x;\n mat4 m1 = mBones[int(matricesIndices.y)] * matricesWeights.y;\n mat4 m2 = mBones[int(matricesIndices.z)] * matricesWeights.z;\n\n#ifdef BONES4\n mat4 m3 = mBones[int(matricesIndices.w)] * matricesWeights.w;\n finalWorld = world * (m0 + m1 + m2 + m3);\n#else\n finalWorld = world * (m0 + m1 + m2);\n#endif \n\n#else\n finalWorld = world;\n#endif\n gl_Position = viewProjection * finalWorld * vec4(position, 1.0);\n\n vec4 worldPos = finalWorld * vec4(position, 1.0);\n vPositionW = vec3(worldPos);\n vNormalW = normalize(vec3(finalWorld * vec4(normal, 0.0)));\n\n // Texture coordinates\n#ifndef UV1\n vec2 uv = vec2(0., 0.);\n#endif\n#ifndef UV2\n vec2 uv2 = vec2(0., 0.);\n#endif\n\n#ifdef DIFFUSE\n if (vDiffuseInfos.x == 0.)\n {\n vDiffuseUV = vec2(diffuseMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vDiffuseUV = vec2(diffuseMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n#ifdef AMBIENT\n if (vAmbientInfos.x == 0.)\n {\n vAmbientUV = vec2(ambientMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vAmbientUV = vec2(ambientMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n#ifdef OPACITY\n if (vOpacityInfos.x == 0.)\n {\n vOpacityUV = vec2(opacityMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vOpacityUV = vec2(opacityMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n#ifdef EMISSIVE\n if (vEmissiveInfos.x == 0.)\n {\n vEmissiveUV = vec2(emissiveMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vEmissiveUV = vec2(emissiveMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n#ifdef SPECULAR\n if (vSpecularInfos.x == 0.)\n {\n vSpecularUV = vec2(specularMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vSpecularUV = vec2(specularMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n#ifdef BUMP\n if (vBumpInfos.x == 0.)\n {\n vBumpUV = vec2(bumpMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vBumpUV = vec2(bumpMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n // Clip plane\n#ifdef CLIPPLANE\n fClipDistance = dot(worldPos, vClipPlane);\n#endif\n\n // Fog\n#ifdef FOG\n fFogDistance = (view * worldPos).z;\n#endif\n\n // Shadows\n#ifdef SHADOWS\n#ifdef LIGHT0\n vPositionFromLight0 = lightMatrix0 * vec4(position, 1.0);\n#endif\n#ifdef LIGHT1\n vPositionFromLight1 = lightMatrix1 * vec4(position, 1.0);\n#endif\n#ifdef LIGHT2\n vPositionFromLight2 = lightMatrix2 * vec4(position, 1.0);\n#endif\n#ifdef LIGHT3\n vPositionFromLight3 = lightMatrix3 * vec4(position, 1.0);\n#endif\n#endif\n\n // Vertex color\n#ifdef VERTEXCOLOR\n vColor = color;\n#endif\n}", fxaaPixelShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n#define FXAA_REDUCE_MIN (1.0/128.0)\n#define FXAA_REDUCE_MUL (1.0/8.0)\n#define FXAA_SPAN_MAX 8.0\n\nvarying vec2 vUV;\nuniform sampler2D textureSampler;\nuniform vec2 texelSize;\n\nvoid main(){\n vec2 localTexelSize = texelSize;\n vec3 rgbNW = texture2D(textureSampler, (vUV + vec2(-1.0, -1.0) * localTexelSize)).xyz;\n vec3 rgbNE = texture2D(textureSampler, (vUV + vec2(1.0, -1.0) * localTexelSize)).xyz;\n vec3 rgbSW = texture2D(textureSampler, (vUV + vec2(-1.0, 1.0) * localTexelSize)).xyz;\n vec3 rgbSE = texture2D(textureSampler, (vUV + vec2(1.0, 1.0) * localTexelSize)).xyz;\n vec3 rgbM = texture2D(textureSampler, vUV ).xyz;\n vec3 luma = vec3(0.299, 0.587, 0.114);\n float lumaNW = dot(rgbNW, luma);\n float lumaNE = dot(rgbNE, luma);\n float lumaSW = dot(rgbSW, luma);\n float lumaSE = dot(rgbSE, luma);\n float lumaM = dot(rgbM, luma);\n float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));\n float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));\n\n vec2 dir = vec2(-((lumaNW + lumaNE) - (lumaSW + lumaSE)), ((lumaNW + lumaSW) - (lumaNE + lumaSE)));\n\n float dirReduce = max(\n (lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL),\n FXAA_REDUCE_MIN);\n\n float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce);\n dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX),\n max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),\n dir * rcpDirMin)) * localTexelSize;\n\n vec3 rgbA = 0.5 * (\n texture2D(textureSampler, vUV + dir * (1.0 / 3.0 - 0.5)).xyz +\n texture2D(textureSampler, vUV + dir * (2.0 / 3.0 - 0.5)).xyz);\n\n vec3 rgbB = rgbA * 0.5 + 0.25 * (\n texture2D(textureSampler, vUV + dir * -0.5).xyz +\n texture2D(textureSampler, vUV + dir * 0.5).xyz);\n float lumaB = dot(rgbB, luma);\n if ((lumaB < lumaMin) || (lumaB > lumaMax)) {\n gl_FragColor = vec4(rgbA, 1.0);\n }\n else {\n gl_FragColor = vec4(rgbB, 1.0);\n }\n}", -iedefaultPixelShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n#define MAP_PROJECTION 4.\n\n// Constants\nuniform vec3 vEyePosition;\nuniform vec3 vAmbientColor;\nuniform vec4 vDiffuseColor;\nuniform vec4 vSpecularColor;\nuniform vec3 vEmissiveColor;\n\n// Input\nvarying vec3 vPositionW;\nvarying vec3 vNormalW;\n\n#ifdef VERTEXCOLOR\nvarying vec3 vColor;\n#endif\n\n// Lights\n#ifdef LIGHT0\nuniform vec4 vLightData0;\nuniform vec3 vLightDiffuse0;\nuniform vec3 vLightSpecular0;\n#ifdef SHADOW0\nvarying vec4 vPositionFromLight0;\nuniform sampler2D shadowSampler0;\n#endif\n#ifdef SPOTLIGHT0\nuniform vec4 vLightDirection0;\n#endif\n#ifdef HEMILIGHT0\nuniform vec3 vLightGround0;\n#endif\n#endif\n\n#ifdef LIGHT1\nuniform vec4 vLightData1;\nuniform vec3 vLightDiffuse1;\nuniform vec3 vLightSpecular1;\n#ifdef SHADOW1\nvarying vec4 vPositionFromLight1;\nuniform sampler2D shadowSampler1;\n#endif\n#ifdef SPOTLIGHT1\nuniform vec4 vLightDirection1;\n#endif\n#ifdef HEMILIGHT1\nuniform vec3 vLightGround1;\n#endif\n#endif\n\n#ifdef LIGHT2\nuniform vec4 vLightData2;\nuniform vec3 vLightDiffuse2;\nuniform vec3 vLightSpecular2;\n#ifdef SHADOW2\nvarying vec4 vPositionFromLight2;\nuniform sampler2D shadowSampler2;\n#endif\n#ifdef SPOTLIGHT2\nuniform vec4 vLightDirection2;\n#endif\n#ifdef HEMILIGHT2\nuniform vec3 vLightGround2;\n#endif\n#endif\n\n#ifdef LIGHT3\nuniform vec4 vLightData3;\nuniform vec3 vLightDiffuse3;\nuniform vec3 vLightSpecular3;\n#ifdef SHADOW3\nvarying vec4 vPositionFromLight3;\nuniform sampler2D shadowSampler3;\n#endif\n#ifdef SPOTLIGHT3\nuniform vec4 vLightDirection3;\n#endif\n#ifdef HEMILIGHT3\nuniform vec3 vLightGround3;\n#endif\n#endif\n\n// Samplers\n#ifdef DIFFUSE\nvarying vec2 vDiffuseUV;\nuniform sampler2D diffuseSampler;\nuniform vec2 vDiffuseInfos;\n#endif\n\n#ifdef AMBIENT\nvarying vec2 vAmbientUV;\nuniform sampler2D ambientSampler;\nuniform vec2 vAmbientInfos;\n#endif\n\n#ifdef OPACITY \nvarying vec2 vOpacityUV;\nuniform sampler2D opacitySampler;\nuniform vec2 vOpacityInfos;\n#endif\n\n#ifdef REFLECTION\nvarying vec3 vReflectionUVW;\nuniform samplerCube reflectionCubeSampler;\nuniform sampler2D reflection2DSampler;\nuniform vec3 vReflectionInfos;\n#endif\n\n#ifdef EMISSIVE\nvarying vec2 vEmissiveUV;\nuniform vec2 vEmissiveInfos;\nuniform sampler2D emissiveSampler;\n#endif\n\n#ifdef SPECULAR\nvarying vec2 vSpecularUV;\nuniform vec2 vSpecularInfos;\nuniform sampler2D specularSampler;\n#endif\n\n// Shadows\n#ifdef SHADOWS\n\nfloat unpack(vec4 color)\n{\n const vec4 bitShift = vec4(1. / (255. * 255. * 255.), 1. / (255. * 255.), 1. / 255., 1.);\n return dot(color, bitShift);\n}\n\nfloat unpackHalf(vec2 color)\n{\n return color.x + (color.y / 255.0);\n}\n\nfloat computeShadow(vec4 vPositionFromLight, sampler2D shadowSampler)\n{\n vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;\n vec2 uv = 0.5 * depth.xy + vec2(0.5, 0.5);\n\n if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0)\n {\n return 1.0;\n }\n\n float shadow = unpack(texture2D(shadowSampler, uv));\n\n if (depth.z > shadow)\n {\n return 0.;\n }\n return 1.;\n}\n\n// Thanks to http://devmaster.net/\nfloat ChebychevInequality(vec2 moments, float t)\n{\n if (t <= moments.x)\n {\n return 1.0;\n }\n\n float variance = moments.y - (moments.x * moments.x);\n variance = max(variance, 0.);\n\n float d = t - moments.x;\n return variance / (variance + d * d);\n}\n\nfloat computeShadowWithVSM(vec4 vPositionFromLight, sampler2D shadowSampler)\n{\n vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;\n vec2 uv = 0.5 * depth.xy + vec2(0.5, 0.5);\n\n if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0)\n {\n return 1.0;\n }\n\n vec4 texel = texture2D(shadowSampler, uv);\n\n vec2 moments = vec2(unpackHalf(texel.xy), unpackHalf(texel.zw));\n return clamp(1.3 - ChebychevInequality(moments, depth.z), 0., 1.0);\n}\n#endif\n\n#ifdef CLIPPLANE\nvarying float fClipDistance;\n#endif\n\n// Fog\n#ifdef FOG\n\n#define FOGMODE_NONE 0.\n#define FOGMODE_EXP 1.\n#define FOGMODE_EXP2 2.\n#define FOGMODE_LINEAR 3.\n#define E 2.71828\n\nuniform vec4 vFogInfos;\nuniform vec3 vFogColor;\nvarying float fFogDistance;\n\nfloat CalcFogFactor()\n{\n float fogCoeff = 1.0;\n float fogStart = vFogInfos.y;\n float fogEnd = vFogInfos.z;\n float fogDensity = vFogInfos.w;\n\n if (FOGMODE_LINEAR == vFogInfos.x)\n {\n fogCoeff = (fogEnd - fFogDistance) / (fogEnd - fogStart);\n }\n else if (FOGMODE_EXP == vFogInfos.x)\n {\n fogCoeff = 1.0 / pow(E, fFogDistance * fogDensity);\n }\n else if (FOGMODE_EXP2 == vFogInfos.x)\n {\n fogCoeff = 1.0 / pow(E, fFogDistance * fFogDistance * fogDensity * fogDensity);\n }\n\n return clamp(fogCoeff, 0.0, 1.0);\n}\n#endif\n\n// Light Computing\nmat3 computeLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, vec3 specularColor) {\n mat3 result;\n\n vec3 lightVectorW;\n if (lightData.w == 0.)\n {\n lightVectorW = normalize(lightData.xyz - vPositionW);\n }\n else\n {\n lightVectorW = normalize(-lightData.xyz);\n }\n\n // diffuse\n float ndl = max(0., dot(vNormal, lightVectorW));\n\n // Specular\n vec3 angleW = normalize(viewDirectionW + lightVectorW);\n float specComp = max(0., dot(vNormal, angleW));\n specComp = max(0., pow(specComp, max(1.0, vSpecularColor.a)));\n\n result[0] = ndl * diffuseColor;\n result[1] = specComp * specularColor;\n result[2] = vec3(0.);\n\n return result;\n}\n\nmat3 computeSpotLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec4 lightDirection, vec3 diffuseColor, vec3 specularColor) {\n mat3 result;\n\n vec3 lightVectorW = normalize(lightData.xyz - vPositionW);\n\n // diffuse\n float cosAngle = max(0., dot(-lightDirection.xyz, lightVectorW));\n float spotAtten = 0.0;\n\n if (cosAngle >= lightDirection.w)\n {\n cosAngle = max(0., pow(cosAngle, lightData.w));\n spotAtten = max(0., (cosAngle - lightDirection.w) / (1. - cosAngle));\n\n // Diffuse\n float ndl = max(0., dot(vNormal, -lightDirection.xyz));\n\n // Specular\n vec3 angleW = normalize(viewDirectionW - lightDirection.xyz);\n float specComp = max(0., dot(vNormal, angleW));\n specComp = pow(specComp, vSpecularColor.a);\n\n result[0] = ndl * spotAtten * diffuseColor;\n result[1] = specComp * specularColor * spotAtten;\n result[2] = vec3(0.);\n\n return result;\n }\n\n result[0] = vec3(0.);\n result[1] = vec3(0.);\n result[2] = vec3(0.);\n\n return result;\n}\n\nmat3 computeHemisphericLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, vec3 specularColor, vec3 groundColor) {\n mat3 result;\n\n // Diffuse\n float ndl = dot(vNormal, lightData.xyz) * 0.5 + 0.5;\n\n // Specular\n vec3 angleW = normalize(viewDirectionW + lightData.xyz);\n float specComp = max(0., dot(vNormal, angleW));\n specComp = pow(specComp, vSpecularColor.a);\n\n result[0] = mix(groundColor, diffuseColor, ndl);\n result[1] = specComp * specularColor;\n result[2] = vec3(0.);\n\n return result;\n}\n\nvoid main(void) {\n // Clip plane\n#ifdef CLIPPLANE\n if (fClipDistance > 0.0)\n discard;\n#endif\n\n vec3 viewDirectionW = normalize(vEyePosition - vPositionW);\n\n // Base color\n vec4 baseColor = vec4(1., 1., 1., 1.);\n vec3 diffuseColor = vDiffuseColor.rgb;\n\n#ifdef VERTEXCOLOR\n diffuseColor *= vColor;\n#endif\n\n#ifdef DIFFUSE\n baseColor = texture2D(diffuseSampler, vDiffuseUV);\n\n#ifdef ALPHATEST\n if (baseColor.a < 0.4)\n discard;\n#endif\n\n baseColor.rgb *= vDiffuseInfos.y;\n#endif\n\n // Bump\n vec3 normalW = vNormalW;\n\n // Ambient color\n vec3 baseAmbientColor = vec3(1., 1., 1.);\n\n#ifdef AMBIENT\n baseAmbientColor = texture2D(ambientSampler, vAmbientUV).rgb * vAmbientInfos.y;\n#endif\n\n // Lighting\n vec3 diffuseBase = vec3(0., 0., 0.);\n vec3 specularBase = vec3(0., 0., 0.);\n float shadow = 1.;\n\n#ifdef LIGHT0\n#ifdef SPOTLIGHT0\n mat3 info = computeSpotLighting(viewDirectionW, normalW, vLightData0, vLightDirection0, vLightDiffuse0, vLightSpecular0);\n#endif\n#ifdef HEMILIGHT0\n mat3 info = computeHemisphericLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0, vLightSpecular0, vLightGround0);\n#endif\n#ifdef POINTDIRLIGHT0\n mat3 info = computeLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0, vLightSpecular0);\n#endif\n#ifdef SHADOW0\n#ifdef SHADOWVSM0\n shadow = computeShadowWithVSM(vPositionFromLight0, shadowSampler0);\n#else\n shadow = computeShadow(vPositionFromLight0, shadowSampler0);\n#endif\n#else\n shadow = 1.;\n#endif\n diffuseBase += info[0] * shadow;\n specularBase += info[1] * shadow;\n#endif\n\n#ifdef LIGHT1\n#ifdef SPOTLIGHT1\n info = computeSpotLighting(viewDirectionW, normalW, vLightData1, vLightDirection1, vLightDiffuse1, vLightSpecular1);\n#endif\n#ifdef HEMILIGHT1\n info = computeHemisphericLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1, vLightSpecular1, vLightGround1);\n#endif\n#ifdef POINTDIRLIGHT1\n info = computeLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1, vLightSpecular1);\n#endif\n#ifdef SHADOW1\n#ifdef SHADOWVSM1\n shadow = computeShadowWithVSM(vPositionFromLight1, shadowSampler1);\n#else\n shadow = computeShadow(vPositionFromLight1, shadowSampler1);\n#endif\n#else\n shadow = 1.;\n#endif\n diffuseBase += info[0] * shadow;\n specularBase += info[1] * shadow;\n#endif\n\n#ifdef LIGHT2\n#ifdef SPOTLIGHT2\n info = computeSpotLighting(viewDirectionW, normalW, vLightData2, vLightDirection2, vLightDiffuse2, vLightSpecular2);\n#endif\n#ifdef HEMILIGHT2\n info = computeHemisphericLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2, vLightSpecular2, vLightGround2);\n#endif\n#ifdef POINTDIRLIGHT2\n info = computeLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2, vLightSpecular2);\n#endif\n#ifdef SHADOW2\n#ifdef SHADOWVSM2\n shadow = computeShadowWithVSM(vPositionFromLight2, shadowSampler2);\n#else\n shadow = computeShadow(vPositionFromLight2, shadowSampler2);\n#endif \n#else\n shadow = 1.;\n#endif\n diffuseBase += info[0] * shadow;\n specularBase += info[1] * shadow;\n#endif\n\n#ifdef LIGHT3\n#ifdef SPOTLIGHT3\n info = computeSpotLighting(viewDirectionW, normalW, vLightData3, vLightDirection3, vLightDiffuse3, vLightSpecular3);\n#endif\n#ifdef HEMILIGHT3\n info = computeHemisphericLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3, vLightSpecular3, vLightGround3);\n#endif\n#ifdef POINTDIRLIGHT3\n info = computeLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3, vLightSpecular3);\n#endif\n#ifdef SHADOW3\n#ifdef SHADOWVSM3\n shadow = computeShadowWithVSM(vPositionFromLight3, shadowSampler3);\n#else\n shadow = computeShadow(vPositionFromLight3, shadowSampler3);\n#endif \n#else\n shadow = 1.;\n#endif\n diffuseBase += info[0] * shadow;\n specularBase += info[1] * shadow;\n#endif\n\n // Reflection\n vec3 reflectionColor = vec3(0., 0., 0.);\n\n#ifdef REFLECTION\n if (vReflectionInfos.z != 0.0)\n {\n reflectionColor = textureCube(reflectionCubeSampler, vReflectionUVW).rgb * vReflectionInfos.y;\n }\n else\n {\n vec2 coords = vReflectionUVW.xy;\n\n if (vReflectionInfos.x == MAP_PROJECTION)\n {\n coords /= vReflectionUVW.z;\n }\n\n coords.y = 1.0 - coords.y;\n\n reflectionColor = texture2D(reflection2DSampler, coords).rgb * vReflectionInfos.y;\n }\n#endif\n\n // Alpha\n float alpha = vDiffuseColor.a;\n\n#ifdef OPACITY\n vec3 opacityMap = texture2D(opacitySampler, vOpacityUV).rgb * vec3(0.3, 0.59, 0.11);\n alpha *= (opacityMap.x + opacityMap.y + opacityMap.z)* vOpacityInfos.y;\n#endif\n\n // Emissive\n vec3 emissiveColor = vEmissiveColor;\n#ifdef EMISSIVE\n emissiveColor += texture2D(emissiveSampler, vEmissiveUV).rgb * vEmissiveInfos.y;\n#endif\n\n // Specular map\n vec3 specularColor = vSpecularColor.rgb;\n#ifdef SPECULAR\n specularColor = texture2D(specularSampler, vSpecularUV).rgb * vSpecularInfos.y;\n#endif\n\n // Composition\n vec3 finalDiffuse = clamp(diffuseBase * diffuseColor + emissiveColor + vAmbientColor, 0.0, 1.0) * baseColor.rgb;\n vec3 finalSpecular = specularBase * specularColor;\n\n vec4 color = vec4(finalDiffuse * baseAmbientColor + finalSpecular + reflectionColor, alpha);\n\n#ifdef FOG\n float fog = CalcFogFactor();\n color.rgb = fog * color.rgb + (1.0 - fog) * vFogColor;\n#endif\n\n gl_FragColor = color;\n}", -iedefaultVertexShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n#define MAP_EXPLICIT 0.\n#define MAP_SPHERICAL 1.\n#define MAP_PLANAR 2.\n#define MAP_CUBIC 3.\n#define MAP_PROJECTION 4.\n#define MAP_SKYBOX 5.\n\n// Attributes\nattribute vec3 position;\nattribute vec3 normal;\n#ifdef UV1\nattribute vec2 uv;\n#endif\n#ifdef UV2\nattribute vec2 uv2;\n#endif\n#ifdef VERTEXCOLOR\nattribute vec3 color;\n#endif\n#ifdef BONES\nattribute vec4 matricesIndices;\nattribute vec4 matricesWeights;\n#endif\n\n// Uniforms\nuniform mat4 world;\nuniform mat4 view;\n\n#ifdef DIFFUSE\nvarying vec2 vDiffuseUV;\nuniform mat4 diffuseMatrix;\nuniform vec2 vDiffuseInfos;\n#endif\n\n#ifdef AMBIENT\nvarying vec2 vAmbientUV;\nuniform mat4 ambientMatrix;\nuniform vec2 vAmbientInfos;\n#endif\n\n#ifdef OPACITY\nvarying vec2 vOpacityUV;\nuniform mat4 opacityMatrix;\nuniform vec2 vOpacityInfos;\n#endif\n\n#ifdef REFLECTION\nuniform vec3 vEyePosition;\nvarying vec3 vReflectionUVW;\nuniform vec3 vReflectionInfos;\nuniform mat4 reflectionMatrix;\n#endif\n\n#ifdef EMISSIVE\nvarying vec2 vEmissiveUV;\nuniform vec2 vEmissiveInfos;\nuniform mat4 emissiveMatrix;\n#endif\n\n#ifdef SPECULAR\nvarying vec2 vSpecularUV;\nuniform vec2 vSpecularInfos;\nuniform mat4 specularMatrix;\n#endif\n\n#ifdef BUMP\nvarying vec2 vBumpUV;\nuniform vec2 vBumpInfos;\nuniform mat4 bumpMatrix;\n#endif\n\n#ifdef BONES\nuniform mat4 mBones[BonesPerMesh];\nuniform mat4 viewProjection;\n#else\nuniform mat4 worldViewProjection;\n#endif\n\n// Output\nvarying vec3 vPositionW;\nvarying vec3 vNormalW;\n\n#ifdef VERTEXCOLOR\nvarying vec3 vColor;\n#endif\n\n#ifdef CLIPPLANE\nuniform vec4 vClipPlane;\nvarying float fClipDistance;\n#endif\n\n#ifdef FOG\nvarying float fFogDistance;\n#endif\n\n#ifdef SHADOWS\n#ifdef LIGHT0\nuniform mat4 lightMatrix0;\nvarying vec4 vPositionFromLight0;\n#endif\n#ifdef LIGHT1\nuniform mat4 lightMatrix1;\nvarying vec4 vPositionFromLight1;\n#endif\n#ifdef LIGHT2\nuniform mat4 lightMatrix2;\nvarying vec4 vPositionFromLight2;\n#endif\n#ifdef LIGHT3\nuniform mat4 lightMatrix3;\nvarying vec4 vPositionFromLight3;\n#endif\n#endif\n\n#ifdef REFLECTION\nvec3 computeReflectionCoords(float mode, vec4 worldPos, vec3 worldNormal)\n{\n if (mode == MAP_SPHERICAL)\n {\n vec3 coords = vec3(view * vec4(worldNormal, 0.0));\n\n return vec3(reflectionMatrix * vec4(coords, 1.0));\n }\n else if (mode == MAP_PLANAR)\n {\n vec3 viewDir = worldPos.xyz - vEyePosition;\n vec3 coords = normalize(reflect(viewDir, worldNormal));\n\n return vec3(reflectionMatrix * vec4(coords, 1));\n }\n else if (mode == MAP_CUBIC)\n {\n vec3 viewDir = worldPos.xyz - vEyePosition;\n vec3 coords = reflect(viewDir, worldNormal);\n\n return vec3(reflectionMatrix * vec4(coords, 0));\n }\n else if (mode == MAP_PROJECTION)\n {\n return vec3(reflectionMatrix * (view * worldPos));\n }\n else if (mode == MAP_SKYBOX)\n {\n return position;\n }\n\n return vec3(0, 0, 0);\n}\n#endif\n\nvoid main(void) {\n mat4 finalWorld;\n\n#ifdef BONES\n mat4 m0 = mBones[int(matricesIndices.x)] * matricesWeights.x;\n mat4 m1 = mBones[int(matricesIndices.y)] * matricesWeights.y;\n mat4 m2 = mBones[int(matricesIndices.z)] * matricesWeights.z;\n\n#ifdef BONES4\n mat4 m3 = mBones[int(matricesIndices.w)] * matricesWeights.w;\n finalWorld = world * (m0 + m1 + m2 + m3);\n#else\n finalWorld = world * (m0 + m1 + m2);\n#endif \n gl_Position = viewProjection * finalWorld * vec4(position, 1.0);\n#else\n\n finalWorld = world;\n gl_Position = worldViewProjection * vec4(position, 1.0);\n#endif\n\n vec4 worldPos = finalWorld * vec4(position, 1.0);\n vPositionW = vec3(worldPos);\n vNormalW = normalize(vec3(finalWorld * vec4(normal, 0.0)));\n\n // Texture coordinates\n#ifndef UV1\n vec2 uv = vec2(0., 0.);\n#endif\n#ifndef UV2\n vec2 uv2 = vec2(0., 0.);\n#endif\n\n#ifdef DIFFUSE\n if (vDiffuseInfos.x == 0.)\n {\n vDiffuseUV = vec2(diffuseMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vDiffuseUV = vec2(diffuseMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n#ifdef AMBIENT\n if (vAmbientInfos.x == 0.)\n {\n vAmbientUV = vec2(ambientMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vAmbientUV = vec2(ambientMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n#ifdef OPACITY\n if (vOpacityInfos.x == 0.)\n {\n vOpacityUV = vec2(opacityMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vOpacityUV = vec2(opacityMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n#ifdef REFLECTION\n vReflectionUVW = computeReflectionCoords(vReflectionInfos.x, vec4(vPositionW, 1.0), vNormalW);\n#endif\n\n#ifdef EMISSIVE\n if (vEmissiveInfos.x == 0.)\n {\n vEmissiveUV = vec2(emissiveMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vEmissiveUV = vec2(emissiveMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n#ifdef SPECULAR\n if (vSpecularInfos.x == 0.)\n {\n vSpecularUV = vec2(specularMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vSpecularUV = vec2(specularMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n#ifdef BUMP\n if (vBumpInfos.x == 0.)\n {\n vBumpUV = vec2(bumpMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vBumpUV = vec2(bumpMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n // Clip plane\n#ifdef CLIPPLANE\n fClipDistance = dot(worldPos, vClipPlane);\n#endif\n\n // Fog\n#ifdef FOG\n fFogDistance = (view * worldPos).z;\n#endif\n\n // Shadows\n#ifdef SHADOWS\n#ifdef LIGHT0\n vPositionFromLight0 = lightMatrix0 * vec4(position, 1.0);\n#endif\n#ifdef LIGHT1\n vPositionFromLight1 = lightMatrix1 * vec4(position, 1.0);\n#endif\n#ifdef LIGHT2\n vPositionFromLight2 = lightMatrix2 * vec4(position, 1.0);\n#endif\n#ifdef LIGHT3\n vPositionFromLight3 = lightMatrix3 * vec4(position, 1.0);\n#endif\n#endif\n\n // Vertex color\n#ifdef VERTEXCOLOR\n vColor = color;\n#endif\n}", +iedefaultPixelShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n#define MAP_PROJECTION 4.\n\n// Constants\nuniform vec3 vEyePosition;\nuniform vec3 vAmbientColor;\nuniform vec4 vDiffuseColor;\nuniform vec4 vSpecularColor;\nuniform vec3 vEmissiveColor;\n\n// Input\nvarying vec3 vPositionW;\nvarying vec3 vNormalW;\n\n#ifdef VERTEXCOLOR\nvarying vec3 vColor;\n#endif\n\n// Lights\n#ifdef LIGHT0\nuniform vec4 vLightData0;\nuniform vec3 vLightDiffuse0;\nuniform vec3 vLightSpecular0;\n#ifdef SHADOW0\nvarying vec4 vPositionFromLight0;\nuniform sampler2D shadowSampler0;\n#endif\n#ifdef SPOTLIGHT0\nuniform vec4 vLightDirection0;\n#endif\n#ifdef HEMILIGHT0\nuniform vec3 vLightGround0;\n#endif\n#endif\n\n#ifdef LIGHT1\nuniform vec4 vLightData1;\nuniform vec3 vLightDiffuse1;\nuniform vec3 vLightSpecular1;\n#ifdef SHADOW1\nvarying vec4 vPositionFromLight1;\nuniform sampler2D shadowSampler1;\n#endif\n#ifdef SPOTLIGHT1\nuniform vec4 vLightDirection1;\n#endif\n#ifdef HEMILIGHT1\nuniform vec3 vLightGround1;\n#endif\n#endif\n\n#ifdef LIGHT2\nuniform vec4 vLightData2;\nuniform vec3 vLightDiffuse2;\nuniform vec3 vLightSpecular2;\n#ifdef SHADOW2\nvarying vec4 vPositionFromLight2;\nuniform sampler2D shadowSampler2;\n#endif\n#ifdef SPOTLIGHT2\nuniform vec4 vLightDirection2;\n#endif\n#ifdef HEMILIGHT2\nuniform vec3 vLightGround2;\n#endif\n#endif\n\n#ifdef LIGHT3\nuniform vec4 vLightData3;\nuniform vec3 vLightDiffuse3;\nuniform vec3 vLightSpecular3;\n#ifdef SHADOW3\nvarying vec4 vPositionFromLight3;\nuniform sampler2D shadowSampler3;\n#endif\n#ifdef SPOTLIGHT3\nuniform vec4 vLightDirection3;\n#endif\n#ifdef HEMILIGHT3\nuniform vec3 vLightGround3;\n#endif\n#endif\n\n// Samplers\n#ifdef DIFFUSE\nvarying vec2 vDiffuseUV;\nuniform sampler2D diffuseSampler;\nuniform vec2 vDiffuseInfos;\n#endif\n\n#ifdef AMBIENT\nvarying vec2 vAmbientUV;\nuniform sampler2D ambientSampler;\nuniform vec2 vAmbientInfos;\n#endif\n\n#ifdef OPACITY \nvarying vec2 vOpacityUV;\nuniform sampler2D opacitySampler;\nuniform vec2 vOpacityInfos;\n#endif\n\n#ifdef REFLECTION\nvarying vec3 vReflectionUVW;\nuniform samplerCube reflectionCubeSampler;\nuniform sampler2D reflection2DSampler;\nuniform vec3 vReflectionInfos;\n#endif\n\n#ifdef EMISSIVE\nvarying vec2 vEmissiveUV;\nuniform vec2 vEmissiveInfos;\nuniform sampler2D emissiveSampler;\n#endif\n\n#ifdef SPECULAR\nvarying vec2 vSpecularUV;\nuniform vec2 vSpecularInfos;\nuniform sampler2D specularSampler;\n#endif\n\n// Shadows\n#ifdef SHADOWS\n\nfloat unpack(vec4 color)\n{\n const vec4 bitShift = vec4(1. / (255. * 255. * 255.), 1. / (255. * 255.), 1. / 255., 1.);\n return dot(color, bitShift);\n}\n\nfloat unpackHalf(vec2 color)\n{\n return color.x + (color.y / 255.0);\n}\n\nfloat computeShadow(vec4 vPositionFromLight, sampler2D shadowSampler)\n{\n vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;\n vec2 uv = 0.5 * depth.xy + vec2(0.5, 0.5);\n\n if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0)\n {\n return 1.0;\n }\n\n float shadow = unpack(texture2D(shadowSampler, uv));\n\n if (depth.z > shadow)\n {\n return 0.;\n }\n return 1.;\n}\n\n// Thanks to http://devmaster.net/\nfloat ChebychevInequality(vec2 moments, float t)\n{\n if (t <= moments.x)\n {\n return 1.0;\n }\n\n float variance = moments.y - (moments.x * moments.x);\n variance = max(variance, 0.);\n\n float d = t - moments.x;\n return variance / (variance + d * d);\n}\n\nfloat computeShadowWithVSM(vec4 vPositionFromLight, sampler2D shadowSampler)\n{\n vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;\n vec2 uv = 0.5 * depth.xy + vec2(0.5, 0.5);\n\n if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0)\n {\n return 1.0;\n }\n\n vec4 texel = texture2D(shadowSampler, uv);\n\n vec2 moments = vec2(unpackHalf(texel.xy), unpackHalf(texel.zw));\n return clamp(1.3 - ChebychevInequality(moments, depth.z), 0., 1.0);\n}\n#endif\n\n#ifdef CLIPPLANE\nvarying float fClipDistance;\n#endif\n\n// Fog\n#ifdef FOG\n\n#define FOGMODE_NONE 0.\n#define FOGMODE_EXP 1.\n#define FOGMODE_EXP2 2.\n#define FOGMODE_LINEAR 3.\n#define E 2.71828\n\nuniform vec4 vFogInfos;\nuniform vec3 vFogColor;\nvarying float fFogDistance;\n\nfloat CalcFogFactor()\n{\n float fogCoeff = 1.0;\n float fogStart = vFogInfos.y;\n float fogEnd = vFogInfos.z;\n float fogDensity = vFogInfos.w;\n\n if (FOGMODE_LINEAR == vFogInfos.x)\n {\n fogCoeff = (fogEnd - fFogDistance) / (fogEnd - fogStart);\n }\n else if (FOGMODE_EXP == vFogInfos.x)\n {\n fogCoeff = 1.0 / pow(E, fFogDistance * fogDensity);\n }\n else if (FOGMODE_EXP2 == vFogInfos.x)\n {\n fogCoeff = 1.0 / pow(E, fFogDistance * fFogDistance * fogDensity * fogDensity);\n }\n\n return clamp(fogCoeff, 0.0, 1.0);\n}\n#endif\n\n// Light Computing\nmat3 computeLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, vec3 specularColor) {\n mat3 result;\n\n vec3 lightVectorW;\n if (lightData.w == 0.)\n {\n lightVectorW = normalize(lightData.xyz - vPositionW);\n }\n else\n {\n lightVectorW = normalize(-lightData.xyz);\n }\n\n // diffuse\n float ndl = max(0., dot(vNormal, lightVectorW));\n\n // Specular\n vec3 angleW = normalize(viewDirectionW + lightVectorW);\n float specComp = max(0., dot(vNormal, angleW));\n specComp = max(0., pow(specComp, max(1.0, vSpecularColor.a)));\n\n result[0] = ndl * diffuseColor;\n result[1] = specComp * specularColor;\n result[2] = vec3(0.);\n\n return result;\n}\n\nmat3 computeSpotLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec4 lightDirection, vec3 diffuseColor, vec3 specularColor) {\n mat3 result;\n\n vec3 lightVectorW = normalize(lightData.xyz - vPositionW);\n\n // diffuse\n float cosAngle = max(0., dot(-lightDirection.xyz, lightVectorW));\n float spotAtten = 0.0;\n\n if (cosAngle >= lightDirection.w)\n {\n cosAngle = max(0., pow(cosAngle, lightData.w));\n spotAtten = max(0., (cosAngle - lightDirection.w) / (1. - cosAngle));\n\n // Diffuse\n float ndl = max(0., dot(vNormal, -lightDirection.xyz));\n\n // Specular\n vec3 angleW = normalize(viewDirectionW - lightDirection.xyz);\n float specComp = max(0., dot(vNormal, angleW));\n specComp = pow(specComp, vSpecularColor.a);\n\n result[0] = ndl * spotAtten * diffuseColor;\n result[1] = specComp * specularColor * spotAtten;\n result[2] = vec3(0.);\n\n return result;\n }\n\n result[0] = vec3(0.);\n result[1] = vec3(0.);\n result[2] = vec3(0.);\n\n return result;\n}\n\nmat3 computeHemisphericLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, vec3 specularColor, vec3 groundColor) {\n mat3 result;\n\n // Diffuse\n float ndl = dot(vNormal, lightData.xyz) * 0.5 + 0.5;\n\n // Specular\n vec3 angleW = normalize(viewDirectionW + lightData.xyz);\n float specComp = max(0., dot(vNormal, angleW));\n specComp = pow(specComp, vSpecularColor.a);\n\n result[0] = mix(groundColor, diffuseColor, ndl);\n result[1] = specComp * specularColor;\n result[2] = vec3(0.);\n\n return result;\n}\n\nvoid main(void) {\n // Clip plane\n#ifdef CLIPPLANE\n if (fClipDistance > 0.0)\n discard;\n#endif\n\n vec3 viewDirectionW = normalize(vEyePosition - vPositionW);\n\n // Base color\n vec4 baseColor = vec4(1., 1., 1., 1.);\n vec3 diffuseColor = vDiffuseColor.rgb;\n\n#ifdef VERTEXCOLOR\n diffuseColor *= vColor;\n#endif\n\n#ifdef DIFFUSE\n baseColor = texture2D(diffuseSampler, vDiffuseUV);\n\n#ifdef ALPHATEST\n if (baseColor.a < 0.4)\n discard;\n#endif\n\n baseColor.rgb *= vDiffuseInfos.y;\n#endif\n\n // Bump\n vec3 normalW = vNormalW;\n\n // Ambient color\n vec3 baseAmbientColor = vec3(1., 1., 1.);\n\n#ifdef AMBIENT\n baseAmbientColor = texture2D(ambientSampler, vAmbientUV).rgb * vAmbientInfos.y;\n#endif\n\n // Lighting\n vec3 diffuseBase = vec3(0., 0., 0.);\n vec3 specularBase = vec3(0., 0., 0.);\n float shadow = 1.;\n\n#ifdef LIGHT0\n#ifdef SPOTLIGHT0\n mat3 info = computeSpotLighting(viewDirectionW, normalW, vLightData0, vLightDirection0, vLightDiffuse0, vLightSpecular0);\n#endif\n#ifdef HEMILIGHT0\n mat3 info = computeHemisphericLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0, vLightSpecular0, vLightGround0);\n#endif\n#ifdef POINTDIRLIGHT0\n mat3 info = computeLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0, vLightSpecular0);\n#endif\n#ifdef SHADOW0\n#ifdef SHADOWVSM0\n shadow = computeShadowWithVSM(vPositionFromLight0, shadowSampler0);\n#else\n shadow = computeShadow(vPositionFromLight0, shadowSampler0);\n#endif\n#else\n shadow = 1.;\n#endif\n diffuseBase += info[0] * shadow;\n specularBase += info[1] * shadow;\n#endif\n\n#ifdef LIGHT1\n#ifdef SPOTLIGHT1\n info = computeSpotLighting(viewDirectionW, normalW, vLightData1, vLightDirection1, vLightDiffuse1, vLightSpecular1);\n#endif\n#ifdef HEMILIGHT1\n info = computeHemisphericLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1, vLightSpecular1, vLightGround1);\n#endif\n#ifdef POINTDIRLIGHT1\n info = computeLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1, vLightSpecular1);\n#endif\n#ifdef SHADOW1\n#ifdef SHADOWVSM1\n shadow = computeShadowWithVSM(vPositionFromLight1, shadowSampler1);\n#else\n shadow = computeShadow(vPositionFromLight1, shadowSampler1);\n#endif\n#else\n shadow = 1.;\n#endif\n diffuseBase += info[0] * shadow;\n specularBase += info[1] * shadow;\n#endif\n\n#ifdef LIGHT2\n#ifdef SPOTLIGHT2\n info = computeSpotLighting(viewDirectionW, normalW, vLightData2, vLightDirection2, vLightDiffuse2, vLightSpecular2);\n#endif\n#ifdef HEMILIGHT2\n info = computeHemisphericLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2, vLightSpecular2, vLightGround2);\n#endif\n#ifdef POINTDIRLIGHT2\n info = computeLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2, vLightSpecular2);\n#endif\n#ifdef SHADOW2\n#ifdef SHADOWVSM2\n shadow = computeShadowWithVSM(vPositionFromLight2, shadowSampler2);\n#else\n shadow = computeShadow(vPositionFromLight2, shadowSampler2);\n#endif \n#else\n shadow = 1.;\n#endif\n diffuseBase += info[0] * shadow;\n specularBase += info[1] * shadow;\n#endif\n\n#ifdef LIGHT3\n#ifdef SPOTLIGHT3\n info = computeSpotLighting(viewDirectionW, normalW, vLightData3, vLightDirection3, vLightDiffuse3, vLightSpecular3);\n#endif\n#ifdef HEMILIGHT3\n info = computeHemisphericLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3, vLightSpecular3, vLightGround3);\n#endif\n#ifdef POINTDIRLIGHT3\n info = computeLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3, vLightSpecular3);\n#endif\n#ifdef SHADOW3\n#ifdef SHADOWVSM3\n shadow = computeShadowWithVSM(vPositionFromLight3, shadowSampler3);\n#else\n shadow = computeShadow(vPositionFromLight3, shadowSampler3);\n#endif \n#else\n shadow = 1.;\n#endif\n diffuseBase += info[0] * shadow;\n specularBase += info[1] * shadow;\n#endif\n\n // Reflection\n vec3 reflectionColor = vec3(0., 0., 0.);\n\n#ifdef REFLECTION\n if (vReflectionInfos.z != 0.0)\n {\n reflectionColor = textureCube(reflectionCubeSampler, vReflectionUVW).rgb * vReflectionInfos.y;\n }\n else\n {\n vec2 coords = vReflectionUVW.xy;\n\n if (vReflectionInfos.x == MAP_PROJECTION)\n {\n coords /= vReflectionUVW.z;\n }\n\n coords.y = 1.0 - coords.y;\n\n reflectionColor = texture2D(reflection2DSampler, coords).rgb * vReflectionInfos.y;\n }\n#endif\n\n // Alpha\n float alpha = vDiffuseColor.a;\n\n#ifdef OPACITY\n vec4 opacityMap = texture2D(opacitySampler, vOpacityUV);\n opacityMap.rgb = opacityMap.rgb * vec3(0.3, 0.59, 0.11) * opacityMap.a;\n alpha *= (opacityMap.x + opacityMap.y + opacityMap.z)* vOpacityInfos.y;\n#endif\n\n // Emissive\n vec3 emissiveColor = vEmissiveColor;\n#ifdef EMISSIVE\n emissiveColor += texture2D(emissiveSampler, vEmissiveUV).rgb * vEmissiveInfos.y;\n#endif\n\n // Specular map\n vec3 specularColor = vSpecularColor.rgb;\n#ifdef SPECULAR\n specularColor = texture2D(specularSampler, vSpecularUV).rgb * vSpecularInfos.y;\n#endif\n\n // Composition\n vec3 finalDiffuse = clamp(diffuseBase * diffuseColor + emissiveColor + vAmbientColor, 0.0, 1.0) * baseColor.rgb;\n vec3 finalSpecular = specularBase * specularColor;\n\n vec4 color = vec4(finalDiffuse * baseAmbientColor + finalSpecular + reflectionColor, alpha);\n\n#ifdef FOG\n float fog = CalcFogFactor();\n color.rgb = fog * color.rgb + (1.0 - fog) * vFogColor;\n#endif\n\n gl_FragColor = color;\n}", +iedefaultVertexShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n#define MAP_EXPLICIT 0.\n#define MAP_SPHERICAL 1.\n#define MAP_PLANAR 2.\n#define MAP_CUBIC 3.\n#define MAP_PROJECTION 4.\n#define MAP_SKYBOX 5.\n\n// Attributes\nattribute vec3 position;\nattribute vec3 normal;\n#ifdef UV1\nattribute vec2 uv;\n#endif\n#ifdef UV2\nattribute vec2 uv2;\n#endif\n#ifdef VERTEXCOLOR\nattribute vec3 color;\n#endif\n#ifdef BONES\nattribute vec4 matricesIndices;\nattribute vec4 matricesWeights;\n#endif\n\n// Uniforms\nuniform mat4 world;\nuniform mat4 view;\nuniform mat4 viewProjection;\n\n#ifdef DIFFUSE\nvarying vec2 vDiffuseUV;\nuniform mat4 diffuseMatrix;\nuniform vec2 vDiffuseInfos;\n#endif\n\n#ifdef AMBIENT\nvarying vec2 vAmbientUV;\nuniform mat4 ambientMatrix;\nuniform vec2 vAmbientInfos;\n#endif\n\n#ifdef OPACITY\nvarying vec2 vOpacityUV;\nuniform mat4 opacityMatrix;\nuniform vec2 vOpacityInfos;\n#endif\n\n#ifdef REFLECTION\nuniform vec3 vEyePosition;\nvarying vec3 vReflectionUVW;\nuniform vec3 vReflectionInfos;\nuniform mat4 reflectionMatrix;\n#endif\n\n#ifdef EMISSIVE\nvarying vec2 vEmissiveUV;\nuniform vec2 vEmissiveInfos;\nuniform mat4 emissiveMatrix;\n#endif\n\n#ifdef SPECULAR\nvarying vec2 vSpecularUV;\nuniform vec2 vSpecularInfos;\nuniform mat4 specularMatrix;\n#endif\n\n#ifdef BUMP\nvarying vec2 vBumpUV;\nuniform vec2 vBumpInfos;\nuniform mat4 bumpMatrix;\n#endif\n\n#ifdef BONES\nuniform mat4 mBones[BonesPerMesh];\n#endif\n\n// Output\nvarying vec3 vPositionW;\nvarying vec3 vNormalW;\n\n#ifdef VERTEXCOLOR\nvarying vec3 vColor;\n#endif\n\n#ifdef CLIPPLANE\nuniform vec4 vClipPlane;\nvarying float fClipDistance;\n#endif\n\n#ifdef FOG\nvarying float fFogDistance;\n#endif\n\n#ifdef SHADOWS\n#ifdef LIGHT0\nuniform mat4 lightMatrix0;\nvarying vec4 vPositionFromLight0;\n#endif\n#ifdef LIGHT1\nuniform mat4 lightMatrix1;\nvarying vec4 vPositionFromLight1;\n#endif\n#ifdef LIGHT2\nuniform mat4 lightMatrix2;\nvarying vec4 vPositionFromLight2;\n#endif\n#ifdef LIGHT3\nuniform mat4 lightMatrix3;\nvarying vec4 vPositionFromLight3;\n#endif\n#endif\n\n#ifdef REFLECTION\nvec3 computeReflectionCoords(float mode, vec4 worldPos, vec3 worldNormal)\n{\n if (mode == MAP_SPHERICAL)\n {\n vec3 coords = vec3(view * vec4(worldNormal, 0.0));\n\n return vec3(reflectionMatrix * vec4(coords, 1.0));\n }\n else if (mode == MAP_PLANAR)\n {\n vec3 viewDir = worldPos.xyz - vEyePosition;\n vec3 coords = normalize(reflect(viewDir, worldNormal));\n\n return vec3(reflectionMatrix * vec4(coords, 1));\n }\n else if (mode == MAP_CUBIC)\n {\n vec3 viewDir = worldPos.xyz - vEyePosition;\n vec3 coords = reflect(viewDir, worldNormal);\n\n return vec3(reflectionMatrix * vec4(coords, 0));\n }\n else if (mode == MAP_PROJECTION)\n {\n return vec3(reflectionMatrix * (view * worldPos));\n }\n else if (mode == MAP_SKYBOX)\n {\n return position;\n }\n\n return vec3(0, 0, 0);\n}\n#endif\n\nvoid main(void) {\n mat4 finalWorld;\n\n#ifdef BONES\n mat4 m0 = mBones[int(matricesIndices.x)] * matricesWeights.x;\n mat4 m1 = mBones[int(matricesIndices.y)] * matricesWeights.y;\n mat4 m2 = mBones[int(matricesIndices.z)] * matricesWeights.z;\n\n#ifdef BONES4\n mat4 m3 = mBones[int(matricesIndices.w)] * matricesWeights.w;\n finalWorld = world * (m0 + m1 + m2 + m3);\n#else\n finalWorld = world * (m0 + m1 + m2);\n#endif \n\n#else\n finalWorld = world;\n#endif\n\n gl_Position = viewProjection * finalWorld * vec4(position, 1.0);\n\n vec4 worldPos = finalWorld * vec4(position, 1.0);\n vPositionW = vec3(worldPos);\n vNormalW = normalize(vec3(finalWorld * vec4(normal, 0.0)));\n\n // Texture coordinates\n#ifndef UV1\n vec2 uv = vec2(0., 0.);\n#endif\n#ifndef UV2\n vec2 uv2 = vec2(0., 0.);\n#endif\n\n#ifdef DIFFUSE\n if (vDiffuseInfos.x == 0.)\n {\n vDiffuseUV = vec2(diffuseMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vDiffuseUV = vec2(diffuseMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n#ifdef AMBIENT\n if (vAmbientInfos.x == 0.)\n {\n vAmbientUV = vec2(ambientMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vAmbientUV = vec2(ambientMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n#ifdef OPACITY\n if (vOpacityInfos.x == 0.)\n {\n vOpacityUV = vec2(opacityMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vOpacityUV = vec2(opacityMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n#ifdef REFLECTION\n vReflectionUVW = computeReflectionCoords(vReflectionInfos.x, vec4(vPositionW, 1.0), vNormalW);\n#endif\n\n#ifdef EMISSIVE\n if (vEmissiveInfos.x == 0.)\n {\n vEmissiveUV = vec2(emissiveMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vEmissiveUV = vec2(emissiveMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n#ifdef SPECULAR\n if (vSpecularInfos.x == 0.)\n {\n vSpecularUV = vec2(specularMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vSpecularUV = vec2(specularMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n#ifdef BUMP\n if (vBumpInfos.x == 0.)\n {\n vBumpUV = vec2(bumpMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vBumpUV = vec2(bumpMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n // Clip plane\n#ifdef CLIPPLANE\n fClipDistance = dot(worldPos, vClipPlane);\n#endif\n\n // Fog\n#ifdef FOG\n fFogDistance = (view * worldPos).z;\n#endif\n\n // Shadows\n#ifdef SHADOWS\n#ifdef LIGHT0\n vPositionFromLight0 = lightMatrix0 * vec4(position, 1.0);\n#endif\n#ifdef LIGHT1\n vPositionFromLight1 = lightMatrix1 * vec4(position, 1.0);\n#endif\n#ifdef LIGHT2\n vPositionFromLight2 = lightMatrix2 * vec4(position, 1.0);\n#endif\n#ifdef LIGHT3\n vPositionFromLight3 = lightMatrix3 * vec4(position, 1.0);\n#endif\n#endif\n\n // Vertex color\n#ifdef VERTEXCOLOR\n vColor = color;\n#endif\n}", layerPixelShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n// Samplers\nvarying vec2 vUV;\nuniform sampler2D textureSampler;\n\n// Color\nuniform vec4 color;\n\nvoid main(void) {\n vec4 baseColor = texture2D(textureSampler, vUV);\n\n gl_FragColor = baseColor * color;\n}", layerVertexShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n// Attributes\nattribute vec2 position;\n\n// Uniforms\nuniform mat4 textureMatrix;\n\n// Output\nvarying vec2 vUV;\n\nconst vec2 madd = vec2(0.5, 0.5);\n\nvoid main(void) { \n\n vUV = vec2(textureMatrix * vec4(position * madd + madd, 1.0, 0.0));\n gl_Position = vec4(position, 0.0, 1.0);\n}", lensFlarePixelShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n// Samplers\nvarying vec2 vUV;\nuniform sampler2D textureSampler;\n\n// Color\nuniform vec4 color;\n\nvoid main(void) {\n vec4 baseColor = texture2D(textureSampler, vUV);\n\n gl_FragColor = baseColor * color;\n}", @@ -15,8 +15,8 @@ particlesVertexShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n// Attr passPixelShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n// Samplers\nvarying vec2 vUV;\nuniform sampler2D textureSampler;\n\nvoid main(void) \n{\n gl_FragColor = texture2D(textureSampler, vUV);\n}", postprocessVertexShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n// Attributes\nattribute vec2 position;\n\n// Output\nvarying vec2 vUV;\n\nconst vec2 madd = vec2(0.5, 0.5);\n\nvoid main(void) { \n\n vUV = position * madd + madd;\n gl_Position = vec4(position, 0.0, 1.0);\n}", refractionPixelShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n// Samplers\nvarying vec2 vUV;\nuniform sampler2D textureSampler;\nuniform sampler2D refractionSampler;\n\n// Parameters\nuniform vec3 baseColor;\nuniform float depth;\nuniform float colorLevel;\n\nvoid main() {\n float ref = 1.0 - texture2D(refractionSampler, vUV).r;\n\n vec2 uv = vUV - vec2(0.5);\n vec2 offset = uv * depth * ref;\n vec3 sourceColor = texture2D(textureSampler, vUV - offset).rgb;\n\n gl_FragColor = vec4(sourceColor + sourceColor * ref * colorLevel, 1.0);\n}", -shadowMapPixelShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\nvec4 pack(float depth)\n{\n const vec4 bitOffset = vec4(255. * 255. * 255., 255. * 255., 255., 1.);\n const vec4 bitMask = vec4(0., 1. / 255., 1. / 255., 1. / 255.);\n \n vec4 comp = fract(depth * bitOffset);\n comp -= comp.xxyz * bitMask;\n \n return comp;\n}\n\n// Thanks to http://devmaster.net/\nvec2 packHalf(float depth) \n{ \n const vec2 bitOffset = vec2(1.0 / 255., 0.);\n vec2 color = vec2(depth, fract(depth * 255.));\n\n return color - (color.yy * bitOffset);\n}\n\n\nvoid main(void)\n{\n#ifdef VSM\n float moment1 = gl_FragCoord.z / gl_FragCoord.w; \n float moment2 = moment1 * moment1;\n gl_FragColor = vec4(packHalf(moment1), packHalf(moment2));\n#else\n gl_FragColor = pack(gl_FragCoord.z / gl_FragCoord.w);\n#endif\n}", -shadowMapVertexShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n// Attribute\nattribute vec3 position;\n#ifdef BONES\nattribute vec4 matricesIndices;\nattribute vec4 matricesWeights;\n#endif\n\n// Uniform\n#ifdef BONES\nuniform mat4 world;\nuniform mat4 mBones[BonesPerMesh];\nuniform mat4 viewProjection;\n#else\nuniform mat4 worldViewProjection;\n#endif\n\nvoid main(void)\n{\n#ifdef BONES\n mat4 m0 = mBones[int(matricesIndices.x)] * matricesWeights.x;\n mat4 m1 = mBones[int(matricesIndices.y)] * matricesWeights.y;\n mat4 m2 = mBones[int(matricesIndices.z)] * matricesWeights.z;\n mat4 m3 = mBones[int(matricesIndices.w)] * matricesWeights.w;\n mat4 finalWorld = world * (m0 + m1 + m2 + m3);\n gl_Position = viewProjection * finalWorld * vec4(position, 1.0);\n#else\n gl_Position = worldViewProjection * vec4(position, 1.0);\n#endif\n}", +shadowMapPixelShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\nvec4 pack(float depth)\n{\n const vec4 bitOffset = vec4(255. * 255. * 255., 255. * 255., 255., 1.);\n const vec4 bitMask = vec4(0., 1. / 255., 1. / 255., 1. / 255.);\n \n vec4 comp = fract(depth * bitOffset);\n comp -= comp.xxyz * bitMask;\n \n return comp;\n}\n\n// Thanks to http://devmaster.net/\nvec2 packHalf(float depth) \n{ \n const vec2 bitOffset = vec2(1.0 / 255., 0.);\n vec2 color = vec2(depth, fract(depth * 255.));\n\n return color - (color.yy * bitOffset);\n}\n\n#ifndef VSM\nvarying vec4 vPosition;\n#endif\n\nvoid main(void)\n{\n#ifdef VSM\n float moment1 = gl_FragCoord.z / gl_FragCoord.w;\n float moment2 = moment1 * moment1;\n gl_FragColor = vec4(packHalf(moment1), packHalf(moment2));\n#else\n gl_FragColor = pack(vPosition.z / vPosition.w);\n#endif\n}", +shadowMapVertexShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n// Attribute\nattribute vec3 position;\n#ifdef BONES\nattribute vec4 matricesIndices;\nattribute vec4 matricesWeights;\n#endif\n\n// Uniform\n#ifdef BONES\nuniform mat4 world;\nuniform mat4 mBones[BonesPerMesh];\nuniform mat4 viewProjection;\n#else\nuniform mat4 worldViewProjection;\n#endif\n\n#ifndef VSM\nvarying vec4 vPosition;\n#endif\n\nvoid main(void)\n{\n#ifdef BONES\n mat4 m0 = mBones[int(matricesIndices.x)] * matricesWeights.x;\n mat4 m1 = mBones[int(matricesIndices.y)] * matricesWeights.y;\n mat4 m2 = mBones[int(matricesIndices.z)] * matricesWeights.z;\n mat4 m3 = mBones[int(matricesIndices.w)] * matricesWeights.w;\n mat4 finalWorld = world * (m0 + m1 + m2 + m3);\n gl_Position = viewProjection * finalWorld * vec4(position, 1.0);\n#else\n#ifndef VSM\n vPosition = worldViewProjection * vec4(position, 1.0);\n#endif\n gl_Position = worldViewProjection * vec4(position, 1.0);\n#endif\n}", spritesPixelShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\nuniform bool alphaTest;\n\nvarying vec4 vColor;\n\n// Samplers\nvarying vec2 vUV;\nuniform sampler2D diffuseSampler;\n\n// Fog\n#ifdef FOG\n\n#define FOGMODE_NONE 0.\n#define FOGMODE_EXP 1.\n#define FOGMODE_EXP2 2.\n#define FOGMODE_LINEAR 3.\n#define E 2.71828\n\nuniform vec4 vFogInfos;\nuniform vec3 vFogColor;\nvarying float fFogDistance;\n\nfloat CalcFogFactor()\n{\n float fogCoeff = 1.0;\n float fogStart = vFogInfos.y;\n float fogEnd = vFogInfos.z;\n float fogDensity = vFogInfos.w;\n\n if (FOGMODE_LINEAR == vFogInfos.x)\n {\n fogCoeff = (fogEnd - fFogDistance) / (fogEnd - fogStart);\n }\n else if (FOGMODE_EXP == vFogInfos.x)\n {\n fogCoeff = 1.0 / pow(E, fFogDistance * fogDensity);\n }\n else if (FOGMODE_EXP2 == vFogInfos.x)\n {\n fogCoeff = 1.0 / pow(E, fFogDistance * fFogDistance * fogDensity * fogDensity);\n }\n\n return min(1., max(0., fogCoeff));\n}\n#endif\n\n\nvoid main(void) {\n vec4 baseColor = texture2D(diffuseSampler, vUV);\n\n if (alphaTest) \n {\n if (baseColor.a < 0.95)\n discard;\n }\n\n baseColor *= vColor;\n\n#ifdef FOG\n float fog = CalcFogFactor();\n baseColor.rgb = fog * baseColor.rgb + (1.0 - fog) * vFogColor;\n#endif\n\n gl_FragColor = baseColor;\n}", spritesVertexShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n// Attributes\nattribute vec3 position;\nattribute vec4 options;\nattribute vec4 cellInfo;\nattribute vec4 color;\n\n// Uniforms\nuniform vec2 textureInfos;\nuniform mat4 view;\nuniform mat4 projection;\n\n// Output\nvarying vec2 vUV;\nvarying vec4 vColor;\n\n#ifdef FOG\nvarying float fFogDistance;\n#endif\n\nvoid main(void) { \n vec3 viewPos = (view * vec4(position, 1.0)).xyz; \n vec3 cornerPos;\n \n float angle = options.x;\n float size = options.y;\n vec2 offset = options.zw;\n vec2 uvScale = textureInfos.xy;\n\n cornerPos = vec3(offset.x - 0.5, offset.y - 0.5, 0.) * size;\n\n // Rotate\n vec3 rotatedCorner;\n rotatedCorner.x = cornerPos.x * cos(angle) - cornerPos.y * sin(angle);\n rotatedCorner.y = cornerPos.x * sin(angle) + cornerPos.y * cos(angle);\n rotatedCorner.z = 0.;\n\n // Position\n viewPos += rotatedCorner;\n gl_Position = projection * vec4(viewPos, 1.0); \n\n // Color\n vColor = color;\n \n // Texture\n vec2 uvOffset = vec2(abs(offset.x - cellInfo.x), 1.0 - abs(offset.y - cellInfo.y));\n\n vUV = (uvOffset + cellInfo.zw) * uvScale;\n\n // Fog\n#ifdef FOG\n fFogDistance = viewPos.z;\n#endif\n}", -};})();var BABYLON=BABYLON||{};(function(){BABYLON.Material=function(name,scene){this.name=name;this.id=name;this._scene=scene;scene.materials.push(this);};BABYLON.Material.prototype.checkReadyOnEveryCall=true;BABYLON.Material.prototype.alpha=1.0;BABYLON.Material.prototype.wireframe=false;BABYLON.Material.prototype.backFaceCulling=true;BABYLON.Material.prototype._effect=null;BABYLON.Material.prototype.onDispose=null;BABYLON.Material.prototype.isReady=function(mesh){return true;};BABYLON.Material.prototype.getEffect=function(){return this._effect;};BABYLON.Material.prototype.needAlphaBlending=function(){return(this.alpha<1.0);};BABYLON.Material.prototype.needAlphaTesting=function(){return false;};BABYLON.Material.prototype._preBind=function(){var engine=this._scene.getEngine();engine.enableEffect(this._effect);engine.setState(this.backFaceCulling);};BABYLON.Material.prototype.bind=function(world,mesh){};BABYLON.Material.prototype.unbind=function(){};BABYLON.Material.prototype.baseDispose=function(){var index=this._scene.materials.indexOf(this);this._scene.materials.splice(index,1);if(this.onDispose){this.onDispose();}};BABYLON.Material.prototype.dispose=function(){this.baseDispose();};})();var BABYLON=BABYLON||{};(function(){BABYLON.StandardMaterial=function(name,scene){BABYLON.Material.call(this,name,scene);this.diffuseTexture=null;this.ambientTexture=null;this.opacityTexture=null;this.reflectionTexture=null;this.emissiveTexture=null;this.specularTexture=null;this.bumpTexture=null;this.ambientColor=new BABYLON.Color3(0,0,0);this.diffuseColor=new BABYLON.Color3(1,1,1);this.specularColor=new BABYLON.Color3(1,1,1);this.specularPower=64;this.emissiveColor=new BABYLON.Color3(0,0,0);this._cachedDefines=null;this._renderTargets=new BABYLON.Tools.SmartArray(16);this._worldViewProjectionMatrix=BABYLON.Matrix.Zero();this._lightMatrix=BABYLON.Matrix.Zero();this._globalAmbientColor=new BABYLON.Color3(0,0,0);this._baseColor=new BABYLON.Color3();this._scaledDiffuse=new BABYLON.Color3();this._scaledSpecular=new BABYLON.Color3();};BABYLON.StandardMaterial.prototype=Object.create(BABYLON.Material.prototype);BABYLON.StandardMaterial.prototype.needAlphaBlending=function(){return(this.alpha<1.0)||(this.opacityTexture!=null);};BABYLON.StandardMaterial.prototype.needAlphaTesting=function(){return this.diffuseTexture!=null&&this.diffuseTexture.hasAlpha;};BABYLON.StandardMaterial.prototype.isReady=function(mesh){if(!this.checkReadyOnEveryCall){if(this._renderId===this._scene.getRenderId()){return true;}}var engine=this._scene.getEngine();var defines=[];var optionalDefines=[];if(this.diffuseTexture){if(!this.diffuseTexture.isReady()){return false;}else{defines.push("#define DIFFUSE");}}if(this.ambientTexture){if(!this.ambientTexture.isReady()){return false;}else{defines.push("#define AMBIENT");}}if(this.opacityTexture){if(!this.opacityTexture.isReady()){return false;}else{defines.push("#define OPACITY");}}if(this.reflectionTexture){if(!this.reflectionTexture.isReady()){return false;}else{defines.push("#define REFLECTION");}}if(this.emissiveTexture){if(!this.emissiveTexture.isReady()){return false;}else{defines.push("#define EMISSIVE");}}if(this.specularTexture){if(!this.specularTexture.isReady()){return false;}else{defines.push("#define SPECULAR");optionalDefines.push(defines[defines.length-1]);}}if(this._scene.getEngine().getCaps().standardDerivatives&&this.bumpTexture){if(!this.bumpTexture.isReady()){return false;}else{defines.push("#define BUMP");optionalDefines.push(defines[defines.length-1]);}}if(BABYLON.clipPlane){defines.push("#define CLIPPLANE");}if(engine.getAlphaTesting()){defines.push("#define ALPHATEST");}if(this._scene.fogMode!==BABYLON.Scene.FOGMODE_NONE){defines.push("#define FOG");optionalDefines.push(defines[defines.length-1]);}var shadowsActivated=false;var lightIndex=0;for(var index=0;index0){optionalDefines.push(defines[defines.length-1]);}var type;if(light instanceof BABYLON.SpotLight){type="#define SPOTLIGHT"+lightIndex;}else if(light instanceof BABYLON.HemisphericLight){type="#define HEMILIGHT"+lightIndex;}else{type="#define POINTDIRLIGHT"+lightIndex;}defines.push(type);if(lightIndex>0){optionalDefines.push(defines[defines.length-1]);}var shadowGenerator=light.getShadowGenerator();if(mesh&&mesh.receiveShadows&&shadowGenerator){defines.push("#define SHADOW"+lightIndex);if(lightIndex>0){optionalDefines.push(defines[defines.length-1]);}if(!shadowsActivated){defines.push("#define SHADOWS");shadowsActivated=true;}if(shadowGenerator.useVarianceShadowMap){defines.push("#define SHADOWVSM"+lightIndex);if(lightIndex>0){optionalDefines.push(defines[defines.length-1]);}}}lightIndex++;if(lightIndex==4)break;}var attribs=[BABYLON.VertexBuffer.PositionKind,BABYLON.VertexBuffer.NormalKind];if(mesh){if(mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UVKind)){attribs.push(BABYLON.VertexBuffer.UVKind);defines.push("#define UV1");}if(mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UV2Kind)){attribs.push(BABYLON.VertexBuffer.UV2Kind);defines.push("#define UV2");}if(mesh.isVerticesDataPresent(BABYLON.VertexBuffer.ColorKind)){attribs.push(BABYLON.VertexBuffer.ColorKind);defines.push("#define VERTEXCOLOR");}if(mesh.skeleton&&mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind)&&mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind)){attribs.push(BABYLON.VertexBuffer.MatricesIndicesKind);attribs.push(BABYLON.VertexBuffer.MatricesWeightsKind);defines.push("#define BONES");defines.push("#define BonesPerMesh "+mesh.skeleton.bones.length);defines.push("#define BONES4");optionalDefines.push(defines[defines.length-1]);}}var join=defines.join("\n");if(this._cachedDefines!=join){this._cachedDefines=join;var shaderName="default";if(BABYLON.Tools.isIE()){shaderName="iedefault";}this._effect=this._scene.getEngine().createEffect(shaderName,attribs,["world","view","worldViewProjection","viewProjection","vEyePosition","vLightsType","vAmbientColor","vDiffuseColor","vSpecularColor","vEmissiveColor","vLightData0","vLightDiffuse0","vLightSpecular0","vLightDirection0","vLightGround0","lightMatrix0","vLightData1","vLightDiffuse1","vLightSpecular1","vLightDirection1","vLightGround1","lightMatrix1","vLightData2","vLightDiffuse2","vLightSpecular2","vLightDirection2","vLightGround2","lightMatrix2","vLightData3","vLightDiffuse3","vLightSpecular3","vLightDirection3","vLightGround3","lightMatrix3","vFogInfos","vFogColor","vDiffuseInfos","vAmbientInfos","vOpacityInfos","vReflectionInfos","vEmissiveInfos","vSpecularInfos","vBumpInfos","mBones","vClipPlane","diffuseMatrix","ambientMatrix","opacityMatrix","reflectionMatrix","emissiveMatrix","specularMatrix","bumpMatrix"],["diffuseSampler","ambientSampler","opacitySampler","reflectionCubeSampler","reflection2DSampler","emissiveSampler","specularSampler","bumpSampler","shadowSampler0","shadowSampler1","shadowSampler2","shadowSampler3"],join,optionalDefines);}if(!this._effect.isReady()){return false;}this._renderId=this._scene.getRenderId();return true;};BABYLON.StandardMaterial.prototype.getRenderTargetTextures=function(){this._renderTargets.reset();if(this.reflectionTexture&&this.reflectionTexture.isRenderTarget){this._renderTargets.push(this.reflectionTexture);}return this._renderTargets;};BABYLON.StandardMaterial.prototype.unbind=function(){if(this.reflectionTexture&&this.reflectionTexture.isRenderTarget){this._effect.setTexture("reflection2DSampler",null);}};BABYLON.StandardMaterial.prototype.bind=function(world,mesh){this._baseColor.copyFrom(this.diffuseColor);this._effect.setMatrix("world",world);if(mesh.skeleton&&mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind)&&mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind)){this._effect.setMatrix("viewProjection",this._scene.getTransformMatrix());this._effect.setMatrices("mBones",mesh.skeleton.getTransformMatrices());}else{world.multiplyToRef(this._scene.getTransformMatrix(),this._worldViewProjectionMatrix);this._effect.setMatrix("worldViewProjection",this._worldViewProjectionMatrix);}if(this.diffuseTexture){this._effect.setTexture("diffuseSampler",this.diffuseTexture);this._effect.setFloat2("vDiffuseInfos",this.diffuseTexture.coordinatesIndex,this.diffuseTexture.level);this._effect.setMatrix("diffuseMatrix",this.diffuseTexture._computeTextureMatrix());this._baseColor.copyFromFloats(1,1,1);}if(this.ambientTexture){this._effect.setTexture("ambientSampler",this.ambientTexture);this._effect.setFloat2("vAmbientInfos",this.ambientTexture.coordinatesIndex,this.ambientTexture.level);this._effect.setMatrix("ambientMatrix",this.ambientTexture._computeTextureMatrix());}if(this.opacityTexture){this._effect.setTexture("opacitySampler",this.opacityTexture);this._effect.setFloat2("vOpacityInfos",this.opacityTexture.coordinatesIndex,this.opacityTexture.level);this._effect.setMatrix("opacityMatrix",this.opacityTexture._computeTextureMatrix());}if(this.reflectionTexture){if(this.reflectionTexture.isCube){this._effect.setTexture("reflectionCubeSampler",this.reflectionTexture);}else{this._effect.setTexture("reflection2DSampler",this.reflectionTexture);}this._effect.setMatrix("reflectionMatrix",this.reflectionTexture._computeReflectionTextureMatrix());this._effect.setFloat3("vReflectionInfos",this.reflectionTexture.coordinatesMode,this.reflectionTexture.level,this.reflectionTexture.isCube?1:0);}if(this.emissiveTexture){this._effect.setTexture("emissiveSampler",this.emissiveTexture);this._effect.setFloat2("vEmissiveInfos",this.emissiveTexture.coordinatesIndex,this.emissiveTexture.level);this._effect.setMatrix("emissiveMatrix",this.emissiveTexture._computeTextureMatrix());}if(this.specularTexture){this._effect.setTexture("specularSampler",this.specularTexture);this._effect.setFloat2("vSpecularInfos",this.specularTexture.coordinatesIndex,this.specularTexture.level);this._effect.setMatrix("specularMatrix",this.specularTexture._computeTextureMatrix());}if(this.bumpTexture&&this._scene.getEngine().getCaps().standardDerivatives){this._effect.setTexture("bumpSampler",this.bumpTexture);this._effect.setFloat2("vBumpInfos",this.bumpTexture.coordinatesIndex,this.bumpTexture.level);this._effect.setMatrix("bumpMatrix",this.bumpTexture._computeTextureMatrix());}this._scene.ambientColor.multiplyToRef(this.ambientColor,this._globalAmbientColor);this._effect.setVector3("vEyePosition",this._scene.activeCamera.position);this._effect.setColor3("vAmbientColor",this._globalAmbientColor);this._effect.setColor4("vDiffuseColor",this._baseColor,this.alpha*mesh.visibility);this._effect.setColor4("vSpecularColor",this.specularColor,this.specularPower);this._effect.setColor3("vEmissiveColor",this.emissiveColor);var lightIndex=0;for(var index=0;index0){results.push(this.diffuseTexture);}if(this.ambientTexture&&this.ambientTexture.animations&&this.ambientTexture.animations.length>0){results.push(this.ambientTexture);}if(this.opacityTexture&&this.opacityTexture.animations&&this.opacityTexture.animations.length>0){results.push(this.opacityTexture);}if(this.reflectionTexture&&this.reflectionTexture.animations&&this.reflectionTexture.animations.length>0){results.push(this.reflectionTexture);}if(this.emissiveTexture&&this.emissiveTexture.animations&&this.emissiveTexture.animations.length>0){results.push(this.emissiveTexture);}if(this.specularTexture&&this.specularTexture.animations&&this.specularTexture.animations.length>0){results.push(this.specularTexture);}if(this.bumpTexture&&this.bumpTexture.animations&&this.bumpTexture.animations.length>0){results.push(this.bumpTexture);}return results;};BABYLON.StandardMaterial.prototype.dispose=function(){if(this.diffuseTexture){this.diffuseTexture.dispose();}if(this.ambientTexture){this.ambientTexture.dispose();}if(this.opacityTexture){this.opacityTexture.dispose();}if(this.reflectionTexture){this.reflectionTexture.dispose();}if(this.emissiveTexture){this.emissiveTexture.dispose();}if(this.specularTexture){this.specularTexture.dispose();}if(this.bumpTexture){this.bumpTexture.dispose();}this.baseDispose();};BABYLON.StandardMaterial.prototype.clone=function(name){var newStandardMaterial=new BABYLON.StandardMaterial(name,this._scene);newStandardMaterial.checkReadyOnEveryCall=this.checkReadyOnEveryCall;newStandardMaterial.alpha=this.alpha;newStandardMaterial.wireframe=this.wireframe;newStandardMaterial.backFaceCulling=this.backFaceCulling;if(this.diffuseTexture&&this.diffuseTexture.clone){newStandardMaterial.diffuseTexture=this.diffuseTexture.clone();}if(this.ambientTexture&&this.ambientTexture.clone){newStandardMaterial.ambientTexture=this.ambientTexture.clone();}if(this.opacityTexture&&this.opacityTexture.clone){newStandardMaterial.opacityTexture=this.opacityTexture.clone();}if(this.reflectionTexture&&this.reflectionTexture.clone){newStandardMaterial.reflectionTexture=this.reflectionTexture.clone();}if(this.emissiveTexture&&this.emissiveTexture.clone){newStandardMaterial.emissiveTexture=this.emissiveTexture.clone();}if(this.specularTexture&&this.specularTexture.clone){newStandardMaterial.specularTexture=this.specularTexture.clone();}if(this.bumpTexture&&this.bumpTexture.clone){newStandardMaterial.bumpTexture=this.bumpTexture.clone();}newStandardMaterial.ambientColor=this.ambientColor.clone();newStandardMaterial.diffuseColor=this.diffuseColor.clone();newStandardMaterial.specularColor=this.specularColor.clone();newStandardMaterial.specularPower=this.specularPower;newStandardMaterial.emissiveColor=this.emissiveColor.clone();return newStandardMaterial;};})();var BABYLON=BABYLON||{};(function(){BABYLON.MultiMaterial=function(name,scene){this.name=name;this.id=name;this._scene=scene;scene.multiMaterials.push(this);this.subMaterials=[];};BABYLON.MultiMaterial.prototype.getSubMaterial=function(index){if(index<0||index>=this.subMaterials.length){return this._scene.defaultMaterial;}return this.subMaterials[index];};BABYLON.MultiMaterial.prototype.isReady=function(mesh){var result=true;for(var index=0;indexversion.data){that.mustUpdateRessources=true;updateInDBCallback();}else{callback(version.data);}}else{that.mustUpdateRessources=true;updateInDBCallback();}};transaction.onabort=function(event){callback(-1);};var getRequest=transaction.objectStore("versions").get(url);getRequest.onsuccess=function(event){version=event.target.result;};getRequest.onerror=function(event){console.log("Error loading version for scene "+url+" from DB.");callback(-1);};}catch(ex){console.log("Error while accessing 'versions' object store (READ OP). Exception: "+ex.message);callback(-1);}}else{console.log("Error: IndexedDB not supported by your browser or BabylonJS Database is not open.");callback(-1);}};BABYLON.Database.prototype._saveVersionIntoDBAsync=function(url,callback){if(this.isSupported&&!this.hasReachedQuota){var that=this;try{var transaction=this.db.transaction(["versions"],"readwrite");transaction.onabort=function(event){try{if(event.srcElement.error.name==="QuotaExceededError"){that.hasReachedQuota=true;}}catch(ex){}callback(-1);};transaction.oncomplete=function(event){callback(that.manifestVersionFound);};var newVersion={};newVersion.sceneUrl=url;newVersion.data=this.manifestVersionFound;var addRequest=transaction.objectStore("versions").put(newVersion);addRequest.onsuccess=function(event){console.log("");};addRequest.onerror=function(event){console.log("Error in DB add version request in BABYLON.Database.");};}catch(ex){console.log("Error while accessing 'versions' object store (WRITE OP). Exception: "+ex.message);callback(-1);}}else{callback(-1);}};BABYLON.Database.prototype.loadSceneFromDB=function(url,sceneLoaded,progressCallBack,errorCallback){var that=this;var completeUrl=BABYLON.Database.ReturnFullUrlLocation(url);var saveAndLoadScene=function(event){that._saveSceneIntoDBAsync(completeUrl,sceneLoaded,progressCallBack);};this._checkVersionFromDB(completeUrl,function(version){if(version!==-1){if(!that.mustUpdateRessources){that._loadSceneFromDBAsync(completeUrl,sceneLoaded,saveAndLoadScene);}else{that._saveSceneIntoDBAsync(completeUrl,sceneLoaded,progressCallBack);}}else{errorCallback();}});};BABYLON.Database.prototype._loadSceneFromDBAsync=function(url,callback,notInDBCallback){if(this.isSupported){var scene;var transaction=this.db.transaction(["scenes"]);transaction.oncomplete=function(event){if(scene){callback(scene.data);}else{notInDBCallback();}};transaction.onabort=function(event){notInDBCallback();};var getRequest=transaction.objectStore("scenes").get(url);getRequest.onsuccess=function(event){scene=event.target.result;};getRequest.onerror=function(event){console.log("Error loading scene "+url+" from DB.");notInDBCallback();};}else{console.log("Error: IndexedDB not supported by your browser or BabylonJS Database is not open.");callback();}};BABYLON.Database.prototype._saveSceneIntoDBAsync=function(url,callback,progressCallback){if(this.isSupported){var xhr=new XMLHttpRequest(),sceneText;var that=this;xhr.open("GET",url,true);xhr.onprogress=progressCallback;xhr.addEventListener("load",function(){if(xhr.status===200){sceneText=xhr.responseText;if(!that.hasReachedQuota){var transaction=that.db.transaction(["scenes"],"readwrite");transaction.onabort=function(event){try{if(event.srcElement.error.name==="QuotaExceededError"){that.hasReachedQuota=true;}}catch(ex){}callback(sceneText);};transaction.oncomplete=function(event){callback(sceneText);};var newScene={};newScene.sceneUrl=url;newScene.data=sceneText;newScene.version=that.manifestVersionFound;try{var addRequest=transaction.objectStore("scenes").put(newScene);addRequest.onsuccess=function(event){console.log("");};addRequest.onerror=function(event){console.log("Error in DB add scene request in BABYLON.Database.");};}catch(ex){callback(sceneText);}}else{callback(sceneText);}}else{callback();}},false);xhr.addEventListener("error",function(event){console.log("error on XHR request.");callback();},false);xhr.send();}else{console.log("Error: IndexedDB not supported by your browser or BabylonJS Database is not open.");callback();}};})();var BABYLON=BABYLON||{};(function(){var loadCubeTexture=function(rootUrl,parsedTexture,scene){var texture=new BABYLON.CubeTexture(rootUrl+parsedTexture.name,scene);texture.name=parsedTexture.name;texture.hasAlpha=parsedTexture.hasAlpha;texture.level=parsedTexture.level;texture.coordinatesMode=parsedTexture.coordinatesMode;return texture;};var loadTexture=function(rootUrl,parsedTexture,scene){if(!parsedTexture.name&&!parsedTexture.isRenderTarget){return null;}if(parsedTexture.isCube){return loadCubeTexture(rootUrl,parsedTexture,scene);}var texture;if(parsedTexture.mirrorPlane){texture=new BABYLON.MirrorTexture(parsedTexture.name,parsedTexture.renderTargetSize,scene);texture._waitingRenderList=parsedTexture.renderList;texture.mirrorPlane=BABYLON.Plane.FromArray(parsedTexture.mirrorPlane);}else if(parsedTexture.isRenderTarget){texture=new BABYLON.RenderTargetTexture(parsedTexture.name,parsedTexture.renderTargetSize,scene);texture._waitingRenderList=parsedTexture.renderList;}else{texture=new BABYLON.Texture(rootUrl+parsedTexture.name,scene);}texture.name=parsedTexture.name;texture.hasAlpha=parsedTexture.hasAlpha;texture.level=parsedTexture.level;texture.coordinatesIndex=parsedTexture.coordinatesIndex;texture.coordinatesMode=parsedTexture.coordinatesMode;texture.uOffset=parsedTexture.uOffset;texture.vOffset=parsedTexture.vOffset;texture.uScale=parsedTexture.uScale;texture.vScale=parsedTexture.vScale;texture.uAng=parsedTexture.uAng;texture.vAng=parsedTexture.vAng;texture.wAng=parsedTexture.wAng;texture.wrapU=parsedTexture.wrapU;texture.wrapV=parsedTexture.wrapV;if(parsedTexture.animations){for(var animationIndex=0;animationIndex-1){parentBone=skeleton.bones[parsedBone.parentBoneIndex];}var bone=new BABYLON.Bone(parsedBone.name,skeleton,parentBone,BABYLON.Matrix.FromArray(parsedBone.matrix));if(parsedBone.animation){bone.animations.push(parseAnimation(parsedBone.animation));}}return skeleton;};var parseMaterial=function(parsedMaterial,scene,rootUrl){var material;material=new BABYLON.StandardMaterial(parsedMaterial.name,scene);material.ambientColor=BABYLON.Color3.FromArray(parsedMaterial.ambient);material.diffuseColor=BABYLON.Color3.FromArray(parsedMaterial.diffuse);material.specularColor=BABYLON.Color3.FromArray(parsedMaterial.specular);material.specularPower=parsedMaterial.specularPower;material.emissiveColor=BABYLON.Color3.FromArray(parsedMaterial.emissive);material.alpha=parsedMaterial.alpha;material.id=parsedMaterial.id;material.backFaceCulling=parsedMaterial.backFaceCulling;if(parsedMaterial.diffuseTexture){material.diffuseTexture=loadTexture(rootUrl,parsedMaterial.diffuseTexture,scene);}if(parsedMaterial.ambientTexture){material.ambientTexture=loadTexture(rootUrl,parsedMaterial.ambientTexture,scene);}if(parsedMaterial.opacityTexture){material.opacityTexture=loadTexture(rootUrl,parsedMaterial.opacityTexture,scene);}if(parsedMaterial.reflectionTexture){material.reflectionTexture=loadTexture(rootUrl,parsedMaterial.reflectionTexture,scene);}if(parsedMaterial.emissiveTexture){material.emissiveTexture=loadTexture(rootUrl,parsedMaterial.emissiveTexture,scene);}if(parsedMaterial.specularTexture){material.specularTexture=loadTexture(rootUrl,parsedMaterial.specularTexture,scene);}if(parsedMaterial.bumpTexture){material.bumpTexture=loadTexture(rootUrl,parsedMaterial.bumpTexture,scene);}return material;};var parseMaterialById=function(id,parsedData,scene,rootUrl){for(var index=0;index-1){mesh.skeleton=scene.getLastSkeletonByID(parsedMesh.skeletonId);}if(parsedMesh.animations){for(var animationIndex=0;animationIndex>8);floatIndices.push((matricesIndex&0x00FF0000)>>16);floatIndices.push(matricesIndex>>24);}mesh.setVerticesData(floatIndices,BABYLON.VertexBuffer.MatricesIndicesKind,false);}if(parsedGeometry.matricesWeights){mesh.setVerticesData(parsedGeometry.matricesWeights,BABYLON.VertexBuffer.MatricesWeightsKind,false);}mesh.setIndices(parsedGeometry.indices);}if(parsedGeometry.subMeshes){mesh.subMeshes=[];for(var subIndex=0;subIndex-1&&scene.skeletons){var skeletonAlreadyLoaded=(loadedSkeletonsIds.indexOf(parsedMesh.skeletonId)>-1);if(!skeletonAlreadyLoaded){for(var skeletonIndex=0;skeletonIndex>0;this._vertices[arrayOffset+9]=sprite.cellIndex-offset*rowSize;this._vertices[arrayOffset+10]=offset;this._vertices[arrayOffset+11]=sprite.color.r;this._vertices[arrayOffset+12]=sprite.color.g;this._vertices[arrayOffset+13]=sprite.color.b;this._vertices[arrayOffset+14]=sprite.color.a;};BABYLON.SpriteManager.prototype.render=function(){if(!this._effectBase.isReady()||!this._effectFog.isReady()||!this._spriteTexture||!this._spriteTexture.isReady())return 0;var engine=this._scene.getEngine();var baseSize=this._spriteTexture.getBaseSize();var deltaTime=BABYLON.Tools.GetDeltaTime();var max=Math.min(this._capacity,this.sprites.length);var rowSize=baseSize.width/this.cellSize;var offset=0;for(var index=0;indexthis._delay){this._time=this._time%this._delay;this.cellIndex+=this._direction;if(this.cellIndex==this._toIndex){if(this._loopAnimation){this.cellIndex=this._fromIndex;}else{this._animationStarted=false;if(this.disposeWhenFinishedAnimating){this.dispose();}}}}};BABYLON.Sprite.prototype.dispose=function(){for(var i=0;i0;for(var index=0;index=particle.lifeTime){this._stockParticles.push(this.particles.splice(index,1)[0]);index--;continue;}else{particle.colorStep.scaleToRef(this._scaledUpdateSpeed,this._scaledColorStep);particle.color.addInPlace(this._scaledColorStep);if(particle.color.a<0)particle.color.a=0;particle.direction.scaleToRef(this._scaledUpdateSpeed,this._scaledDirection);particle.position.addInPlace(this._scaledDirection);particle.angle+=particle.angularSpeed*this._scaledUpdateSpeed;this.gravity.scaleToRef(this._scaledUpdateSpeed,this._scaledGravity);particle.direction.addInPlace(this._scaledGravity);}}var worldMatrix;if(this.emitter.position){worldMatrix=this.emitter.getWorldMatrix();}else{worldMatrix=BABYLON.Matrix.Translation(this.emitter.x,this.emitter.y,this.emitter.z);}for(var index=0;index-1){emitCout=this.manualEmitCount;this.manualEmitCount=0;}else{emitCout=this.emitRate;}var newParticles=((emitCout*this._scaledUpdateSpeed)>>0);this._newPartsExcess+=emitCout*this._scaledUpdateSpeed-newParticles;if(this._newPartsExcess>1.0){newParticles+=this._newPartsExcess>>0;this._newPartsExcess-=this._newPartsExcess>>0;}this._alive=false;if(!this._stopped){this._actualFrame+=this._scaledUpdateSpeed;if(this.targetStopDuration&&this._actualFrame>=this.targetStopDuration)this.stop();}else{newParticles=0;}this._update(newParticles);if(this._stopped){if(!this._alive){this._started=false;if(this.disposeOnStop){this._scene._toBeDisposed.push(this);}}}var offset=0;for(var index=0;index0){return highLimitValue.clone?highLimitValue.clone():highLimitValue;}for(var key=0;key=currentFrame){var startValue=this._keys[key].value;var endValue=this._keys[key+1].value;var gradient=(currentFrame-this._keys[key].frame)/(this._keys[key+1].frame-this._keys[key].frame);switch(this.dataType){case BABYLON.Animation.ANIMATIONTYPE_FLOAT:switch(loopMode){case BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE:case BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT:return startValue+(endValue-startValue)*gradient;case BABYLON.Animation.ANIMATIONLOOPMODE_RELATIVE:return offsetValue*repeatCount+(startValue+(endValue-startValue)*gradient);}break;case BABYLON.Animation.ANIMATIONTYPE_QUATERNION:var quaternion=null;switch(loopMode){case BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE:case BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT:quaternion=BABYLON.Quaternion.Slerp(startValue,endValue,gradient);break;case BABYLON.Animation.ANIMATIONLOOPMODE_RELATIVE:quaternion=BABYLON.Quaternion.Slerp(startValue,endValue,gradient).add(offsetValue.scale(repeatCount));break;}return quaternion;case BABYLON.Animation.ANIMATIONTYPE_VECTOR3:switch(loopMode){case BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE:case BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT:return BABYLON.Vector3.Lerp(startValue,endValue,gradient);case BABYLON.Animation.ANIMATIONLOOPMODE_RELATIVE:return BABYLON.Vector3.Lerp(startValue,endValue,gradient).add(offsetValue.scale(repeatCount));}case BABYLON.Animation.ANIMATIONTYPE_MATRIX:switch(loopMode){case BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE:case BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT:case BABYLON.Animation.ANIMATIONLOOPMODE_RELATIVE:return startValue;}default:break;}break;}}return this._keys[this._keys.length-1].value;};BABYLON.Animation.prototype.animate=function(target,delay,from,to,loop,speedRatio){if(!this.targetPropertyPath||this.targetPropertyPath.length<1){return false;}var returnValue=true;if(this._keys[0].frame!=0){var newKey={frame:0,value:this._keys[0].value};this._keys.splice(0,0,newKey);}if(fromthis._keys[this._keys.length-1].frame){from=this._keys[0].frame;}if(tothis._keys[this._keys.length-1].frame){to=this._keys[this._keys.length-1].frame;}var range=to-from;var ratio=delay*(this.framePerSecond*speedRatio)/1000.0;if(ratio>range&&!loop){offsetValue=0;returnValue=false;}else{var offsetValue=0;var highLimitValue=0;if(this.loopMode!=BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE){var keyOffset=to.toString()+from.toString();if(!this._offsetsCache[keyOffset]){var fromValue=this._interpolate(from,0,BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE);var toValue=this._interpolate(to,0,BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE);switch(this.dataType){case BABYLON.Animation.ANIMATIONTYPE_FLOAT:this._offsetsCache[keyOffset]=toValue-fromValue;break;case BABYLON.Animation.ANIMATIONTYPE_QUATERNION:this._offsetsCache[keyOffset]=toValue.subtract(fromValue);break;case BABYLON.Animation.ANIMATIONTYPE_VECTOR3:this._offsetsCache[keyOffset]=toValue.subtract(fromValue);default:break;}this._highLimitsCache[keyOffset]=toValue;}highLimitValue=this._highLimitsCache[keyOffset];offsetValue=this._offsetsCache[keyOffset];}}var repeatCount=(ratio/range)>>0;var currentFrame=returnValue?from+ratio%range:to;var currentValue=this._interpolate(currentFrame,repeatCount,this.loopMode,offsetValue,highLimitValue);if(this.targetPropertyPath.length>1){var property=target[this.targetPropertyPath[0]];for(var index=1;indexthis._capacity){BABYLON.Octree._CreateBlocks(this._minPoint,this._maxPoint,this.meshes,this._capacity,this);}};BABYLON.OctreeBlock.prototype.addEntries=function(meshes){for(var index=0;index0){this._camera.postProcesses[0].width=-1;}};})();var BABYLON=BABYLON||{};(function(){BABYLON.PostProcessManager=function(scene){this._scene=scene;var vertices=[];vertices.push(1,1);vertices.push(-1,1);vertices.push(-1,-1);vertices.push(1,-1);this._vertexDeclaration=[2];this._vertexStrideSize=2*4;this._vertexBuffer=scene.getEngine().createVertexBuffer(vertices);var indices=[];indices.push(0);indices.push(1);indices.push(2);indices.push(0);indices.push(2);indices.push(3);this._indexBuffer=scene.getEngine().createIndexBuffer(indices);};BABYLON.PostProcessManager.prototype._prepareFrame=function(){var postProcesses=this._scene.activeCamera.postProcesses;if(postProcesses.length===0||!this._scene.postProcessesEnabled){return;}postProcesses[0].activate();};BABYLON.PostProcessManager.prototype._finalizeFrame=function(){var postProcesses=this._scene.activeCamera.postProcesses;if(postProcesses.length===0||!this._scene.postProcessesEnabled){return;}var engine=this._scene.getEngine();for(var index=0;index0){if((this._positionX>globalViewport.x)&&(this._positionXglobalViewport.y)&&(this._positionYdistance;};BABYLON.LensFlareSystem.prototype.render=function(){if(!this._effect.isReady())return false;var engine=this._scene.getEngine();var viewport=this._scene.activeCamera.viewport;var globalViewport=viewport.toGlobal(engine);if(!this.computeEffectivePosition(globalViewport)){return false;}if(!this._isVisible()){return false;}var awayX;var awayY;if(this._positionXglobalViewport.x+globalViewport.width-this.borderLimit){awayX=this._positionX-globalViewport.x-globalViewport.width+this.borderLimit;}else{awayX=0;}if(this._positionYglobalViewport.y+globalViewport.height-this.borderLimit){awayY=this._positionY-globalViewport.y-globalViewport.height+this.borderLimit;}else{awayY=0;}var away=(awayX>awayY)?awayX:awayY;if(away>this.borderLimit){away=this.borderLimit;}var intensity=1.0-(away/this.borderLimit);if(intensity<0){return false;}if(intensity>1.0){intensity=1.0;}var centerX=globalViewport.x+globalViewport.width/2;var centerY=globalViewport.y+globalViewport.height/2;var distX=centerX-this._positionX;var distY=centerY-this._positionY;engine.enableEffect(this._effect);engine.setState(false);engine.setDepthBuffer(false);engine.setAlphaMode(BABYLON.Engine.ALPHA_ADD);engine.bindBuffers(this._vertexBuffer,this._indexBuffer,this._vertexDeclaration,this._vertexStrideSize,this._effect);for(var index=0;index0){optionalDefines.push(defines[defines.length-1]);}var type;if(light instanceof BABYLON.SpotLight){type="#define SPOTLIGHT"+lightIndex;}else if(light instanceof BABYLON.HemisphericLight){type="#define HEMILIGHT"+lightIndex;}else{type="#define POINTDIRLIGHT"+lightIndex;}defines.push(type);if(lightIndex>0){optionalDefines.push(defines[defines.length-1]);}var shadowGenerator=light.getShadowGenerator();if(mesh&&mesh.receiveShadows&&shadowGenerator){defines.push("#define SHADOW"+lightIndex);if(lightIndex>0){optionalDefines.push(defines[defines.length-1]);}if(!shadowsActivated){defines.push("#define SHADOWS");shadowsActivated=true;}if(shadowGenerator.useVarianceShadowMap){defines.push("#define SHADOWVSM"+lightIndex);if(lightIndex>0){optionalDefines.push(defines[defines.length-1]);}}}lightIndex++;if(lightIndex==4)break;}}var attribs=[BABYLON.VertexBuffer.PositionKind,BABYLON.VertexBuffer.NormalKind];if(mesh){if(mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UVKind)){attribs.push(BABYLON.VertexBuffer.UVKind);defines.push("#define UV1");}if(mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UV2Kind)){attribs.push(BABYLON.VertexBuffer.UV2Kind);defines.push("#define UV2");}if(mesh.isVerticesDataPresent(BABYLON.VertexBuffer.ColorKind)){attribs.push(BABYLON.VertexBuffer.ColorKind);defines.push("#define VERTEXCOLOR");}if(mesh.skeleton&&mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind)&&mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind)){attribs.push(BABYLON.VertexBuffer.MatricesIndicesKind);attribs.push(BABYLON.VertexBuffer.MatricesWeightsKind);defines.push("#define BONES");defines.push("#define BonesPerMesh "+mesh.skeleton.bones.length);defines.push("#define BONES4");optionalDefines.push(defines[defines.length-1]);}}var join=defines.join("\n");if(this._cachedDefines!=join){this._cachedDefines=join;var shaderName="default";if(BABYLON.Tools.isIE()){shaderName="iedefault";}this._effect=this._scene.getEngine().createEffect(shaderName,attribs,["world","view","viewProjection","vEyePosition","vLightsType","vAmbientColor","vDiffuseColor","vSpecularColor","vEmissiveColor","vLightData0","vLightDiffuse0","vLightSpecular0","vLightDirection0","vLightGround0","lightMatrix0","vLightData1","vLightDiffuse1","vLightSpecular1","vLightDirection1","vLightGround1","lightMatrix1","vLightData2","vLightDiffuse2","vLightSpecular2","vLightDirection2","vLightGround2","lightMatrix2","vLightData3","vLightDiffuse3","vLightSpecular3","vLightDirection3","vLightGround3","lightMatrix3","vFogInfos","vFogColor","vDiffuseInfos","vAmbientInfos","vOpacityInfos","vReflectionInfos","vEmissiveInfos","vSpecularInfos","vBumpInfos","mBones","vClipPlane","diffuseMatrix","ambientMatrix","opacityMatrix","reflectionMatrix","emissiveMatrix","specularMatrix","bumpMatrix"],["diffuseSampler","ambientSampler","opacitySampler","reflectionCubeSampler","reflection2DSampler","emissiveSampler","specularSampler","bumpSampler","shadowSampler0","shadowSampler1","shadowSampler2","shadowSampler3"],join,optionalDefines);}if(!this._effect.isReady()){return false;}this._renderId=this._scene.getRenderId();this._wasPreviouslyReady=true;return true;};BABYLON.StandardMaterial.prototype.getRenderTargetTextures=function(){this._renderTargets.reset();if(this.reflectionTexture&&this.reflectionTexture.isRenderTarget){this._renderTargets.push(this.reflectionTexture);}return this._renderTargets;};BABYLON.StandardMaterial.prototype.unbind=function(){if(this.reflectionTexture&&this.reflectionTexture.isRenderTarget){this._effect.setTexture("reflection2DSampler",null);}};BABYLON.StandardMaterial.prototype.bind=function(world,mesh){this._baseColor.copyFrom(this.diffuseColor);this._effect.setMatrix("world",world);this._effect.setMatrix("viewProjection",this._scene.getTransformMatrix());if(mesh.skeleton&&mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind)&&mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind)){this._effect.setMatrices("mBones",mesh.skeleton.getTransformMatrices());}if(this.diffuseTexture){this._effect.setTexture("diffuseSampler",this.diffuseTexture);this._effect.setFloat2("vDiffuseInfos",this.diffuseTexture.coordinatesIndex,this.diffuseTexture.level);this._effect.setMatrix("diffuseMatrix",this.diffuseTexture._computeTextureMatrix());this._baseColor.copyFromFloats(1,1,1);}if(this.ambientTexture){this._effect.setTexture("ambientSampler",this.ambientTexture);this._effect.setFloat2("vAmbientInfos",this.ambientTexture.coordinatesIndex,this.ambientTexture.level);this._effect.setMatrix("ambientMatrix",this.ambientTexture._computeTextureMatrix());}if(this.opacityTexture){this._effect.setTexture("opacitySampler",this.opacityTexture);this._effect.setFloat2("vOpacityInfos",this.opacityTexture.coordinatesIndex,this.opacityTexture.level);this._effect.setMatrix("opacityMatrix",this.opacityTexture._computeTextureMatrix());}if(this.reflectionTexture){if(this.reflectionTexture.isCube){this._effect.setTexture("reflectionCubeSampler",this.reflectionTexture);}else{this._effect.setTexture("reflection2DSampler",this.reflectionTexture);}this._effect.setMatrix("reflectionMatrix",this.reflectionTexture._computeReflectionTextureMatrix());this._effect.setFloat3("vReflectionInfos",this.reflectionTexture.coordinatesMode,this.reflectionTexture.level,this.reflectionTexture.isCube?1:0);}if(this.emissiveTexture){this._effect.setTexture("emissiveSampler",this.emissiveTexture);this._effect.setFloat2("vEmissiveInfos",this.emissiveTexture.coordinatesIndex,this.emissiveTexture.level);this._effect.setMatrix("emissiveMatrix",this.emissiveTexture._computeTextureMatrix());}if(this.specularTexture){this._effect.setTexture("specularSampler",this.specularTexture);this._effect.setFloat2("vSpecularInfos",this.specularTexture.coordinatesIndex,this.specularTexture.level);this._effect.setMatrix("specularMatrix",this.specularTexture._computeTextureMatrix());}if(this.bumpTexture&&this._scene.getEngine().getCaps().standardDerivatives){this._effect.setTexture("bumpSampler",this.bumpTexture);this._effect.setFloat2("vBumpInfos",this.bumpTexture.coordinatesIndex,this.bumpTexture.level);this._effect.setMatrix("bumpMatrix",this.bumpTexture._computeTextureMatrix());}this._scene.ambientColor.multiplyToRef(this.ambientColor,this._globalAmbientColor);this._effect.setVector3("vEyePosition",this._scene.activeCamera.position);this._effect.setColor3("vAmbientColor",this._globalAmbientColor);this._effect.setColor4("vDiffuseColor",this._baseColor,this.alpha*mesh.visibility);this._effect.setColor4("vSpecularColor",this.specularColor,this.specularPower);this._effect.setColor3("vEmissiveColor",this.emissiveColor);if(this._scene.lightsEnabled){var lightIndex=0;for(var index=0;index0){results.push(this.diffuseTexture);}if(this.ambientTexture&&this.ambientTexture.animations&&this.ambientTexture.animations.length>0){results.push(this.ambientTexture);}if(this.opacityTexture&&this.opacityTexture.animations&&this.opacityTexture.animations.length>0){results.push(this.opacityTexture);}if(this.reflectionTexture&&this.reflectionTexture.animations&&this.reflectionTexture.animations.length>0){results.push(this.reflectionTexture);}if(this.emissiveTexture&&this.emissiveTexture.animations&&this.emissiveTexture.animations.length>0){results.push(this.emissiveTexture);}if(this.specularTexture&&this.specularTexture.animations&&this.specularTexture.animations.length>0){results.push(this.specularTexture);}if(this.bumpTexture&&this.bumpTexture.animations&&this.bumpTexture.animations.length>0){results.push(this.bumpTexture);}return results;};BABYLON.StandardMaterial.prototype.dispose=function(){if(this.diffuseTexture){this.diffuseTexture.dispose();}if(this.ambientTexture){this.ambientTexture.dispose();}if(this.opacityTexture){this.opacityTexture.dispose();}if(this.reflectionTexture){this.reflectionTexture.dispose();}if(this.emissiveTexture){this.emissiveTexture.dispose();}if(this.specularTexture){this.specularTexture.dispose();}if(this.bumpTexture){this.bumpTexture.dispose();}this.baseDispose();};BABYLON.StandardMaterial.prototype.clone=function(name){var newStandardMaterial=new BABYLON.StandardMaterial(name,this._scene);newStandardMaterial.checkReadyOnEveryCall=this.checkReadyOnEveryCall;newStandardMaterial.alpha=this.alpha;newStandardMaterial.wireframe=this.wireframe;newStandardMaterial.backFaceCulling=this.backFaceCulling;if(this.diffuseTexture&&this.diffuseTexture.clone){newStandardMaterial.diffuseTexture=this.diffuseTexture.clone();}if(this.ambientTexture&&this.ambientTexture.clone){newStandardMaterial.ambientTexture=this.ambientTexture.clone();}if(this.opacityTexture&&this.opacityTexture.clone){newStandardMaterial.opacityTexture=this.opacityTexture.clone();}if(this.reflectionTexture&&this.reflectionTexture.clone){newStandardMaterial.reflectionTexture=this.reflectionTexture.clone();}if(this.emissiveTexture&&this.emissiveTexture.clone){newStandardMaterial.emissiveTexture=this.emissiveTexture.clone();}if(this.specularTexture&&this.specularTexture.clone){newStandardMaterial.specularTexture=this.specularTexture.clone();}if(this.bumpTexture&&this.bumpTexture.clone){newStandardMaterial.bumpTexture=this.bumpTexture.clone();}newStandardMaterial.ambientColor=this.ambientColor.clone();newStandardMaterial.diffuseColor=this.diffuseColor.clone();newStandardMaterial.specularColor=this.specularColor.clone();newStandardMaterial.specularPower=this.specularPower;newStandardMaterial.emissiveColor=this.emissiveColor.clone();return newStandardMaterial;};})();var BABYLON=BABYLON||{};(function(){BABYLON.MultiMaterial=function(name,scene){this.name=name;this.id=name;this._scene=scene;scene.multiMaterials.push(this);this.subMaterials=[];};BABYLON.MultiMaterial.prototype.getSubMaterial=function(index){if(index<0||index>=this.subMaterials.length){return this._scene.defaultMaterial;}return this.subMaterials[index];};BABYLON.MultiMaterial.prototype.isReady=function(mesh){var result=true;for(var index=0;indexversion.data){that.mustUpdateRessources=true;updateInDBCallback();}else{callback(version.data);}}else{that.mustUpdateRessources=true;updateInDBCallback();}};transaction.onabort=function(event){callback(-1);};var getRequest=transaction.objectStore("versions").get(url);getRequest.onsuccess=function(event){version=event.target.result;};getRequest.onerror=function(event){console.log("Error loading version for scene "+url+" from DB.");callback(-1);};}catch(ex){console.log("Error while accessing 'versions' object store (READ OP). Exception: "+ex.message);callback(-1);}}else{console.log("Error: IndexedDB not supported by your browser or BabylonJS Database is not open.");callback(-1);}};BABYLON.Database.prototype._saveVersionIntoDBAsync=function(url,callback){if(this.isSupported&&!this.hasReachedQuota){var that=this;try{var transaction=this.db.transaction(["versions"],"readwrite");transaction.onabort=function(event){try{if(event.srcElement.error.name==="QuotaExceededError"){that.hasReachedQuota=true;}}catch(ex){}callback(-1);};transaction.oncomplete=function(event){callback(that.manifestVersionFound);};var newVersion={};newVersion.sceneUrl=url;newVersion.data=this.manifestVersionFound;var addRequest=transaction.objectStore("versions").put(newVersion);addRequest.onsuccess=function(event){console.log("");};addRequest.onerror=function(event){console.log("Error in DB add version request in BABYLON.Database.");};}catch(ex){console.log("Error while accessing 'versions' object store (WRITE OP). Exception: "+ex.message);callback(-1);}}else{callback(-1);}};BABYLON.Database.prototype.loadSceneFromDB=function(url,sceneLoaded,progressCallBack,errorCallback){var that=this;var completeUrl=BABYLON.Database.ReturnFullUrlLocation(url);var saveAndLoadScene=function(event){that._saveSceneIntoDBAsync(completeUrl,sceneLoaded,progressCallBack);};this._checkVersionFromDB(completeUrl,function(version){if(version!==-1){if(!that.mustUpdateRessources){that._loadSceneFromDBAsync(completeUrl,sceneLoaded,saveAndLoadScene);}else{that._saveSceneIntoDBAsync(completeUrl,sceneLoaded,progressCallBack);}}else{errorCallback();}});};BABYLON.Database.prototype._loadSceneFromDBAsync=function(url,callback,notInDBCallback){if(this.isSupported){var scene;var transaction=this.db.transaction(["scenes"]);transaction.oncomplete=function(event){if(scene){callback(scene.data);}else{notInDBCallback();}};transaction.onabort=function(event){notInDBCallback();};var getRequest=transaction.objectStore("scenes").get(url);getRequest.onsuccess=function(event){scene=event.target.result;};getRequest.onerror=function(event){console.log("Error loading scene "+url+" from DB.");notInDBCallback();};}else{console.log("Error: IndexedDB not supported by your browser or BabylonJS Database is not open.");callback();}};BABYLON.Database.prototype._saveSceneIntoDBAsync=function(url,callback,progressCallback){if(this.isSupported){var xhr=new XMLHttpRequest(),sceneText;var that=this;xhr.open("GET",url,true);xhr.onprogress=progressCallback;xhr.addEventListener("load",function(){if(xhr.status===200){sceneText=xhr.responseText;if(!that.hasReachedQuota){var transaction=that.db.transaction(["scenes"],"readwrite");transaction.onabort=function(event){try{if(event.srcElement.error.name==="QuotaExceededError"){that.hasReachedQuota=true;}}catch(ex){}callback(sceneText);};transaction.oncomplete=function(event){callback(sceneText);};var newScene={};newScene.sceneUrl=url;newScene.data=sceneText;newScene.version=that.manifestVersionFound;try{var addRequest=transaction.objectStore("scenes").put(newScene);addRequest.onsuccess=function(event){console.log("");};addRequest.onerror=function(event){console.log("Error in DB add scene request in BABYLON.Database.");};}catch(ex){callback(sceneText);}}else{callback(sceneText);}}else{callback();}},false);xhr.addEventListener("error",function(event){console.log("error on XHR request.");callback();},false);xhr.send();}else{console.log("Error: IndexedDB not supported by your browser or BabylonJS Database is not open.");callback();}};})();var BABYLON=BABYLON||{};(function(){var loadCubeTexture=function(rootUrl,parsedTexture,scene){var texture=new BABYLON.CubeTexture(rootUrl+parsedTexture.name,scene);texture.name=parsedTexture.name;texture.hasAlpha=parsedTexture.hasAlpha;texture.level=parsedTexture.level;texture.coordinatesMode=parsedTexture.coordinatesMode;return texture;};var loadTexture=function(rootUrl,parsedTexture,scene){if(!parsedTexture.name&&!parsedTexture.isRenderTarget){return null;}if(parsedTexture.isCube){return loadCubeTexture(rootUrl,parsedTexture,scene);}var texture;if(parsedTexture.mirrorPlane){texture=new BABYLON.MirrorTexture(parsedTexture.name,parsedTexture.renderTargetSize,scene);texture._waitingRenderList=parsedTexture.renderList;texture.mirrorPlane=BABYLON.Plane.FromArray(parsedTexture.mirrorPlane);}else if(parsedTexture.isRenderTarget){texture=new BABYLON.RenderTargetTexture(parsedTexture.name,parsedTexture.renderTargetSize,scene);texture._waitingRenderList=parsedTexture.renderList;}else{texture=new BABYLON.Texture(rootUrl+parsedTexture.name,scene);}texture.name=parsedTexture.name;texture.hasAlpha=parsedTexture.hasAlpha;texture.level=parsedTexture.level;texture.coordinatesIndex=parsedTexture.coordinatesIndex;texture.coordinatesMode=parsedTexture.coordinatesMode;texture.uOffset=parsedTexture.uOffset;texture.vOffset=parsedTexture.vOffset;texture.uScale=parsedTexture.uScale;texture.vScale=parsedTexture.vScale;texture.uAng=parsedTexture.uAng;texture.vAng=parsedTexture.vAng;texture.wAng=parsedTexture.wAng;texture.wrapU=parsedTexture.wrapU;texture.wrapV=parsedTexture.wrapV;if(parsedTexture.animations){for(var animationIndex=0;animationIndex-1){parentBone=skeleton.bones[parsedBone.parentBoneIndex];}var bone=new BABYLON.Bone(parsedBone.name,skeleton,parentBone,BABYLON.Matrix.FromArray(parsedBone.matrix));if(parsedBone.animation){bone.animations.push(parseAnimation(parsedBone.animation));}}return skeleton;};var parseMaterial=function(parsedMaterial,scene,rootUrl){var material;material=new BABYLON.StandardMaterial(parsedMaterial.name,scene);material.ambientColor=BABYLON.Color3.FromArray(parsedMaterial.ambient);material.diffuseColor=BABYLON.Color3.FromArray(parsedMaterial.diffuse);material.specularColor=BABYLON.Color3.FromArray(parsedMaterial.specular);material.specularPower=parsedMaterial.specularPower;material.emissiveColor=BABYLON.Color3.FromArray(parsedMaterial.emissive);material.alpha=parsedMaterial.alpha;material.id=parsedMaterial.id;material.backFaceCulling=parsedMaterial.backFaceCulling;if(parsedMaterial.diffuseTexture){material.diffuseTexture=loadTexture(rootUrl,parsedMaterial.diffuseTexture,scene);}if(parsedMaterial.ambientTexture){material.ambientTexture=loadTexture(rootUrl,parsedMaterial.ambientTexture,scene);}if(parsedMaterial.opacityTexture){material.opacityTexture=loadTexture(rootUrl,parsedMaterial.opacityTexture,scene);}if(parsedMaterial.reflectionTexture){material.reflectionTexture=loadTexture(rootUrl,parsedMaterial.reflectionTexture,scene);}if(parsedMaterial.emissiveTexture){material.emissiveTexture=loadTexture(rootUrl,parsedMaterial.emissiveTexture,scene);}if(parsedMaterial.specularTexture){material.specularTexture=loadTexture(rootUrl,parsedMaterial.specularTexture,scene);}if(parsedMaterial.bumpTexture){material.bumpTexture=loadTexture(rootUrl,parsedMaterial.bumpTexture,scene);}return material;};var parseMaterialById=function(id,parsedData,scene,rootUrl){for(var index=0;index-1){mesh.skeleton=scene.getLastSkeletonByID(parsedMesh.skeletonId);}if(parsedMesh.physicsImpostor){if(!scene.isPhysicsEnabled()){scene.enablePhysics();}switch(parsedMesh.physicsImpostor){case 1:mesh.setPhysicsState({impostor:BABYLON.PhysicsEngine.BoxImpostor,mass:parsedMesh.physicsMass,friction:parsedMesh.physicsFriction,restitution:parsedMesh.physicsRestitution});break;case 2:mesh.setPhysicsState({impostor:BABYLON.PhysicsEngine.SphereImpostor,mass:parsedMesh.physicsMass,friction:parsedMesh.physicsFriction,restitution:parsedMesh.physicsRestitution});break;}}if(parsedMesh.animations){for(var animationIndex=0;animationIndex>8);floatIndices.push((matricesIndex&0x00FF0000)>>16);floatIndices.push(matricesIndex>>24);}mesh.setVerticesData(floatIndices,BABYLON.VertexBuffer.MatricesIndicesKind,false);}if(parsedGeometry.matricesWeights){mesh.setVerticesData(parsedGeometry.matricesWeights,BABYLON.VertexBuffer.MatricesWeightsKind,false);}mesh.setIndices(parsedGeometry.indices);}if(parsedGeometry.subMeshes){mesh.subMeshes=[];for(var subIndex=0;subIndex-1&&scene.skeletons){var skeletonAlreadyLoaded=(loadedSkeletonsIds.indexOf(parsedMesh.skeletonId)>-1);if(!skeletonAlreadyLoaded){for(var skeletonIndex=0;skeletonIndex>0;this._vertices[arrayOffset+9]=sprite.cellIndex-offset*rowSize;this._vertices[arrayOffset+10]=offset;this._vertices[arrayOffset+11]=sprite.color.r;this._vertices[arrayOffset+12]=sprite.color.g;this._vertices[arrayOffset+13]=sprite.color.b;this._vertices[arrayOffset+14]=sprite.color.a;};BABYLON.SpriteManager.prototype.render=function(){if(!this._effectBase.isReady()||!this._effectFog.isReady()||!this._spriteTexture||!this._spriteTexture.isReady())return 0;var engine=this._scene.getEngine();var baseSize=this._spriteTexture.getBaseSize();var deltaTime=BABYLON.Tools.GetDeltaTime();var max=Math.min(this._capacity,this.sprites.length);var rowSize=baseSize.width/this.cellSize;var offset=0;for(var index=0;indexthis._delay){this._time=this._time%this._delay;this.cellIndex+=this._direction;if(this.cellIndex==this._toIndex){if(this._loopAnimation){this.cellIndex=this._fromIndex;}else{this._animationStarted=false;if(this.disposeWhenFinishedAnimating){this.dispose();}}}}};BABYLON.Sprite.prototype.dispose=function(){for(var i=0;i0;for(var index=0;index=particle.lifeTime){this._stockParticles.push(this.particles.splice(index,1)[0]);index--;continue;}else{particle.colorStep.scaleToRef(this._scaledUpdateSpeed,this._scaledColorStep);particle.color.addInPlace(this._scaledColorStep);if(particle.color.a<0)particle.color.a=0;particle.direction.scaleToRef(this._scaledUpdateSpeed,this._scaledDirection);particle.position.addInPlace(this._scaledDirection);particle.angle+=particle.angularSpeed*this._scaledUpdateSpeed;this.gravity.scaleToRef(this._scaledUpdateSpeed,this._scaledGravity);particle.direction.addInPlace(this._scaledGravity);}}var worldMatrix;if(this.emitter.position){worldMatrix=this.emitter.getWorldMatrix();}else{worldMatrix=BABYLON.Matrix.Translation(this.emitter.x,this.emitter.y,this.emitter.z);}for(var index=0;index-1){emitCout=this.manualEmitCount;this.manualEmitCount=0;}else{emitCout=this.emitRate;}var newParticles=((emitCout*this._scaledUpdateSpeed)>>0);this._newPartsExcess+=emitCout*this._scaledUpdateSpeed-newParticles;if(this._newPartsExcess>1.0){newParticles+=this._newPartsExcess>>0;this._newPartsExcess-=this._newPartsExcess>>0;}this._alive=false;if(!this._stopped){this._actualFrame+=this._scaledUpdateSpeed;if(this.targetStopDuration&&this._actualFrame>=this.targetStopDuration)this.stop();}else{newParticles=0;}this._update(newParticles);if(this._stopped){if(!this._alive){this._started=false;if(this.disposeOnStop){this._scene._toBeDisposed.push(this);}}}var offset=0;for(var index=0;index0){return highLimitValue.clone?highLimitValue.clone():highLimitValue;}this.currentFrame=currentFrame;for(var key=0;key=currentFrame){var startValue=this._keys[key].value;var endValue=this._keys[key+1].value;var gradient=(currentFrame-this._keys[key].frame)/(this._keys[key+1].frame-this._keys[key].frame);switch(this.dataType){case BABYLON.Animation.ANIMATIONTYPE_FLOAT:switch(loopMode){case BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE:case BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT:return this.floatInterpolateFunction(startValue,endValue,gradient);case BABYLON.Animation.ANIMATIONLOOPMODE_RELATIVE:return offsetValue*repeatCount+this.floatInterpolateFunction(startValue,endValue,gradient);}break;case BABYLON.Animation.ANIMATIONTYPE_QUATERNION:var quaternion=null;switch(loopMode){case BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE:case BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT:quaternion=this.quaternionInterpolateFunction(startValue,endValue,gradient);break;case BABYLON.Animation.ANIMATIONLOOPMODE_RELATIVE:quaternion=this.quaternionInterpolateFunction(startValue,endValue,gradient).add(offsetValue.scale(repeatCount));break;}return quaternion;case BABYLON.Animation.ANIMATIONTYPE_VECTOR3:switch(loopMode){case BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE:case BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT:return this.vector3InterpolateFunction(startValue,endValue,gradient);case BABYLON.Animation.ANIMATIONLOOPMODE_RELATIVE:return this.vector3InterpolateFunction(startValue,endValue,gradient).add(offsetValue.scale(repeatCount));}case BABYLON.Animation.ANIMATIONTYPE_MATRIX:switch(loopMode){case BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE:case BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT:case BABYLON.Animation.ANIMATIONLOOPMODE_RELATIVE:return startValue;}default:break;}break;}}return this._keys[this._keys.length-1].value;};BABYLON.Animation.prototype.animate=function(target,delay,from,to,loop,speedRatio){if(!this.targetPropertyPath||this.targetPropertyPath.length<1){return false;}var returnValue=true;if(this._keys[0].frame!=0){var newKey={frame:0,value:this._keys[0].value};this._keys.splice(0,0,newKey);}if(fromthis._keys[this._keys.length-1].frame){from=this._keys[0].frame;}if(tothis._keys[this._keys.length-1].frame){to=this._keys[this._keys.length-1].frame;}var range=to-from;var ratio=delay*(this.framePerSecond*speedRatio)/1000.0;if(ratio>range&&!loop){offsetValue=0;returnValue=false;}else{var offsetValue=0;var highLimitValue=0;if(this.loopMode!=BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE){var keyOffset=to.toString()+from.toString();if(!this._offsetsCache[keyOffset]){var fromValue=this._interpolate(from,0,BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE);var toValue=this._interpolate(to,0,BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE);switch(this.dataType){case BABYLON.Animation.ANIMATIONTYPE_FLOAT:this._offsetsCache[keyOffset]=toValue-fromValue;break;case BABYLON.Animation.ANIMATIONTYPE_QUATERNION:this._offsetsCache[keyOffset]=toValue.subtract(fromValue);break;case BABYLON.Animation.ANIMATIONTYPE_VECTOR3:this._offsetsCache[keyOffset]=toValue.subtract(fromValue);default:break;}this._highLimitsCache[keyOffset]=toValue;}highLimitValue=this._highLimitsCache[keyOffset];offsetValue=this._offsetsCache[keyOffset];}}var repeatCount=(ratio/range)>>0;var currentFrame=returnValue?from+ratio%range:to;var currentValue=this._interpolate(currentFrame,repeatCount,this.loopMode,offsetValue,highLimitValue);if(this.targetPropertyPath.length>1){var property=target[this.targetPropertyPath[0]];for(var index=1;indexthis._capacity){BABYLON.Octree._CreateBlocks(this._minPoint,this._maxPoint,this.meshes,this._capacity,this);}};BABYLON.OctreeBlock.prototype.addEntries=function(meshes){for(var index=0;index0){this._camera.postProcesses[0].width=-1;}};})();var BABYLON=BABYLON||{};(function(){BABYLON.PostProcessManager=function(scene){this._scene=scene;var vertices=[];vertices.push(1,1);vertices.push(-1,1);vertices.push(-1,-1);vertices.push(1,-1);this._vertexDeclaration=[2];this._vertexStrideSize=2*4;this._vertexBuffer=scene.getEngine().createVertexBuffer(vertices);var indices=[];indices.push(0);indices.push(1);indices.push(2);indices.push(0);indices.push(2);indices.push(3);this._indexBuffer=scene.getEngine().createIndexBuffer(indices);};BABYLON.PostProcessManager.prototype._prepareFrame=function(){var postProcesses=this._scene.activeCamera.postProcesses;if(postProcesses.length===0||!this._scene.postProcessesEnabled){return;}postProcesses[0].activate();};BABYLON.PostProcessManager.prototype._finalizeFrame=function(){var postProcesses=this._scene.activeCamera.postProcesses;if(postProcesses.length===0||!this._scene.postProcessesEnabled){return;}var engine=this._scene.getEngine();for(var index=0;index0){if((this._positionX>globalViewport.x)&&(this._positionXglobalViewport.y)&&(this._positionYdistance;};BABYLON.LensFlareSystem.prototype.render=function(){if(!this._effect.isReady())return false;var engine=this._scene.getEngine();var viewport=this._scene.activeCamera.viewport;var globalViewport=viewport.toGlobal(engine);if(!this.computeEffectivePosition(globalViewport)){return false;}if(!this._isVisible()){return false;}var awayX;var awayY;if(this._positionXglobalViewport.x+globalViewport.width-this.borderLimit){awayX=this._positionX-globalViewport.x-globalViewport.width+this.borderLimit;}else{awayX=0;}if(this._positionYglobalViewport.y+globalViewport.height-this.borderLimit){awayY=this._positionY-globalViewport.y-globalViewport.height+this.borderLimit;}else{awayY=0;}var away=(awayX>awayY)?awayX:awayY;if(away>this.borderLimit){away=this.borderLimit;}var intensity=1.0-(away/this.borderLimit);if(intensity<0){return false;}if(intensity>1.0){intensity=1.0;}var centerX=globalViewport.x+globalViewport.width/2;var centerY=globalViewport.y+globalViewport.height/2;var distX=centerX-this._positionX;var distY=centerY-this._positionY;engine.enableEffect(this._effect);engine.setState(false);engine.setDepthBuffer(false);engine.setAlphaMode(BABYLON.Engine.ALPHA_ADD);engine.bindBuffers(this._vertexBuffer,this._indexBuffer,this._vertexDeclaration,this._vertexStrideSize,this._effect);for(var index=0;index0){that.textureLoadingCallback(remaining);}}that.currentScene.render();}};function drag(e){e.stopPropagation();e.preventDefault();};function drop(eventDrop){eventDrop.stopPropagation();eventDrop.preventDefault();that.loadFiles(eventDrop);};BABYLON.FilesInput.prototype.loadFiles=function(event){if(that.startingProcessingFilesCallback)that.startingProcessingFilesCallback();var sceneFileToLoad;var filesToLoad;BABYLON.FilesTextures={};if(event&&event.dataTransfer&&event.dataTransfer.files){filesToLoad=event.dataTransfer.files;}if(event&&event.target&&event.target.files){filesToLoad=event.target.files;}if(filesToLoad&&filesToLoad.length>0){for(var i=0;i1.0){delta=1.0;}this._world.step(delta);for(var index=0;index 180) + console.log(numVecs+" created"); + */ +}; + +/** + * @method cross + * @memberof CANNON.Vec3 + * @brief Vector cross product + * @param CANNON.Vec3 v + * @param CANNON.Vec3 target Optional. Target to save in. + * @return CANNON.Vec3 + */ +CANNON.Vec3.prototype.cross = function(v,target){ + var vx=v.x, vy=v.y, vz=v.z, x=this.x, y=this.y, z=this.z; + target = target || new CANNON.Vec3(); + + target.x = (y * vz) - (z * vy); + target.y = (z * vx) - (x * vz); + target.z = (x * vy) - (y * vx); + + return target; +}; + +/** + * @method set + * @memberof CANNON.Vec3 + * @brief Set the vectors' 3 elements + * @param float x + * @param float y + * @param float z + * @return CANNON.Vec3 + */ +CANNON.Vec3.prototype.set = function(x,y,z){ + this.x = x; + this.y = y; + this.z = z; + return this; +}; + +/** + * @method vadd + * @memberof CANNON.Vec3 + * @brief Vector addition + * @param CANNON.Vec3 v + * @param CANNON.Vec3 target Optional. + * @return CANNON.Vec3 + */ +CANNON.Vec3.prototype.vadd = function(v,target){ + if(target){ + target.x = v.x + this.x; + target.y = v.y + this.y; + target.z = v.z + this.z; + } else { + return new CANNON.Vec3(this.x + v.x, + this.y + v.y, + this.z + v.z); + } +}; + +/** + * @method vsub + * @memberof CANNON.Vec3 + * @brief Vector subtraction + * @param CANNON.Vec3 v + * @param CANNON.Vec3 target Optional. Target to save in. + * @return CANNON.Vec3 + */ +CANNON.Vec3.prototype.vsub = function(v,target){ + if(target){ + target.x = this.x - v.x; + target.y = this.y - v.y; + target.z = this.z - v.z; + } else { + return new CANNON.Vec3(this.x-v.x, + this.y-v.y, + this.z-v.z); + } +}; + +/** + * @method crossmat + * @memberof CANNON.Vec3 + * @brief Get the cross product matrix a_cross from a vector, such that a x b = a_cross * b = c + * @see http://www8.cs.umu.se/kurser/TDBD24/VT06/lectures/Lecture6.pdf + * @return CANNON.Mat3 + */ +CANNON.Vec3.prototype.crossmat = function(){ + return new CANNON.Mat3([ 0, -this.z, this.y, + this.z, 0, -this.x, + -this.y, this.x, 0]); +}; + +/** + * @method normalize + * @memberof CANNON.Vec3 + * @brief Normalize the vector. Note that this changes the values in the vector. + * @return float Returns the norm of the vector + */ +CANNON.Vec3.prototype.normalize = function(){ + var x=this.x, y=this.y, z=this.z; + var n = Math.sqrt(x*x + y*y + z*z); + if(n>0.0){ + var invN = 1/n; + this.x *= invN; + this.y *= invN; + this.z *= invN; + } else { + // Make something up + this.x = 0; + this.y = 0; + this.z = 0; + } + return n; +}; + +/** + * @method unit + * @memberof CANNON.Vec3 + * @brief Get the version of this vector that is of length 1. + * @param CANNON.Vec3 target Optional target to save in + * @return CANNON.Vec3 Returns the unit vector + */ +CANNON.Vec3.prototype.unit = function(target){ + target = target || new CANNON.Vec3(); + var x=this.x, y=this.y, z=this.z; + var ninv = Math.sqrt(x*x + y*y + z*z); + if(ninv>0.0){ + ninv = 1.0/ninv; + target.x = x * ninv; + target.y = y * ninv; + target.z = z * ninv; + } else { + target.x = 1; + target.y = 0; + target.z = 0; + } + return target; +}; + +/** + * @method norm + * @memberof CANNON.Vec3 + * @brief Get the 2-norm (length) of the vector + * @return float + */ +CANNON.Vec3.prototype.norm = function(){ + var x=this.x, y=this.y, z=this.z; + return Math.sqrt(x*x + y*y + z*z); +}; + +/** + * @method norm2 + * @memberof CANNON.Vec3 + * @brief Get the squared length of the vector + * @return float + */ +CANNON.Vec3.prototype.norm2 = function(){ + return this.dot(this); +}; + +CANNON.Vec3.prototype.distanceTo = function(p){ + var x=this.x, y=this.y, z=this.z; + var px=p.x, py=p.y, pz=p.z; + return Math.sqrt((px-x)*(px-x)+ + (py-y)*(py-y)+ + (pz-z)*(pz-z)); +}; + +/** + * @method mult + * @memberof CANNON.Vec3 + * @brief Multiply the vector with a scalar + * @param float scalar + * @param CANNON.Vec3 target + * @return CANNON.Vec3 + */ +CANNON.Vec3.prototype.mult = function(scalar,target){ + target = target || new CANNON.Vec3(); + var x = this.x, + y = this.y, + z = this.z; + target.x = scalar * x; + target.y = scalar * y; + target.z = scalar * z; + return target; +}; + +/** + * @method dot + * @memberof CANNON.Vec3 + * @brief Calculate dot product + * @param CANNON.Vec3 v + * @return float + */ +CANNON.Vec3.prototype.dot = function(v){ + return this.x * v.x + this.y * v.y + this.z * v.z; +}; + +/** + * @method isZero + * @memberof CANNON.Vec3 + * @return bool + */ +CANNON.Vec3.prototype.isZero = function(){ + return this.x===0 && this.y===0 && this.z===0; +}; + +/** + * @method negate + * @memberof CANNON.Vec3 + * @brief Make the vector point in the opposite direction. + * @param CANNON.Vec3 target Optional target to save in + * @return CANNON.Vec3 + */ +CANNON.Vec3.prototype.negate = function(target){ + target = target || new CANNON.Vec3(); + target.x = -this.x; + target.y = -this.y; + target.z = -this.z; + return target; +}; + +/** + * @method tangents + * @memberof CANNON.Vec3 + * @brief Compute two artificial tangents to the vector + * @param CANNON.Vec3 t1 Vector object to save the first tangent in + * @param CANNON.Vec3 t2 Vector object to save the second tangent in + */ +var Vec3_tangents_n = new CANNON.Vec3(); +var Vec3_tangents_randVec = new CANNON.Vec3(); +CANNON.Vec3.prototype.tangents = function(t1,t2){ + var norm = this.norm(); + if(norm>0.0){ + var n = Vec3_tangents_n; + var inorm = 1/norm; + n.set(this.x*inorm,this.y*inorm,this.z*inorm); + var randVec = Vec3_tangents_randVec; + if(Math.abs(n.x) < 0.9){ + randVec.set(1,0,0); + n.cross(randVec,t1); + } else { + randVec.set(0,1,0); + n.cross(randVec,t1); + } + n.cross(t1,t2); + } else { + // The normal length is zero, make something up + t1.set(1,0,0).normalize(); + t2.set(0,1,0).normalize(); + } +}; + +/** + * @method toString + * @memberof CANNON.Vec3 + * @brief Converts to a more readable format + * @return string + */ +CANNON.Vec3.prototype.toString = function(){ + return this.x+","+this.y+","+this.z; +}; + +/** + * @method copy + * @memberof CANNON.Vec3 + * @brief Copy the vector. + * @param CANNON.Vec3 target + * @return CANNON.Vec3 + */ +CANNON.Vec3.prototype.copy = function(target){ + target = target || new CANNON.Vec3(); + target.x = this.x; + target.y = this.y; + target.z = this.z; + return target; +}; + + +/** + * @method lerp + * @memberof CANNON.Vec3 + * @brief Do a linear interpolation between two vectors + * @param CANNON.Vec3 v + * @param float t A number between 0 and 1. 0 will make this function return u, and 1 will make it return v. Numbers in between will generate a vector in between them. + * @param CANNON.Vec3 target + */ +CANNON.Vec3.prototype.lerp = function(v,t,target){ + var x=this.x, y=this.y, z=this.z; + target.x = x + (v.x-x)*t; + target.y = y + (v.y-y)*t; + target.z = z + (v.z-z)*t; +}; + +/** + * @method almostEquals + * @memberof CANNON.Vec3 + * @brief Check if a vector equals is almost equal to another one. + * @param CANNON.Vec3 v + * @param float precision + * @return bool + */ +CANNON.Vec3.prototype.almostEquals = function(v,precision){ + if(precision===undefined){ + precision = 1e-6; + } + if( Math.abs(this.x-v.x)>precision || + Math.abs(this.y-v.y)>precision || + Math.abs(this.z-v.z)>precision){ + return false; + } + return true; +}; + +/** + * @method almostZero + * @brief Check if a vector is almost zero + * @param float precision + * @memberof CANNON.Vec3 + */ +CANNON.Vec3.prototype.almostZero = function(precision){ + if(precision===undefined){ + precision = 1e-6; + } + if( Math.abs(this.x)>precision || + Math.abs(this.y)>precision || + Math.abs(this.z)>precision){ + return false; + } + return true; +}; + + +/** + * @class CANNON.Quaternion + * @brief A Quaternion describes a rotation in 3D space. + * @description The Quaternion is mathematically defined as Q = x*i + y*j + z*k + w, where (i,j,k) are imaginary basis vectors. (x,y,z) can be seen as a vector related to the axis of rotation, while the real multiplier, w, is related to the amount of rotation. + * @param float x Multiplier of the imaginary basis vector i. + * @param float y Multiplier of the imaginary basis vector j. + * @param float z Multiplier of the imaginary basis vector k. + * @param float w Multiplier of the real part. + * @see http://en.wikipedia.org/wiki/Quaternion + */ +CANNON.Quaternion = function(x,y,z,w){ + /** + * @property float x + * @memberof CANNON.Quaternion + */ + this.x = x!==undefined ? x : 0; + /** + * @property float y + * @memberof CANNON.Quaternion + */ + this.y = y!==undefined ? y : 0; + /** + * @property float z + * @memberof CANNON.Quaternion + */ + this.z = z!==undefined ? z : 0; + /** + * @property float w + * @memberof CANNON.Quaternion + * @brief The multiplier of the real quaternion basis vector. + */ + this.w = w!==undefined ? w : 1; +}; + +/** + * @method set + * @memberof CANNON.Quaternion + * @brief Set the value of the quaternion. + * @param float x + * @param float y + * @param float z + * @param float w + */ +CANNON.Quaternion.prototype.set = function(x,y,z,w){ + this.x = x; + this.y = y; + this.z = z; + this.w = w; +}; + +/** + * @method toString + * @memberof CANNON.Quaternion + * @brief Convert to a readable format + * @return string + */ +CANNON.Quaternion.prototype.toString = function(){ + return this.x+","+this.y+","+this.z+","+this.w; +}; + +/** + * @method setFromAxisAngle + * @memberof CANNON.Quaternion + * @brief Set the quaternion components given an axis and an angle. + * @param CANNON.Vec3 axis + * @param float angle in radians + */ +CANNON.Quaternion.prototype.setFromAxisAngle = function(axis,angle){ + var s = Math.sin(angle*0.5); + this.x = axis.x * s; + this.y = axis.y * s; + this.z = axis.z * s; + this.w = Math.cos(angle*0.5); +}; + +// saves axis to targetAxis and returns +CANNON.Quaternion.prototype.toAxisAngle = function(targetAxis){ + targetAxis = targetAxis || new CANNON.Vec3(); + this.normalize(); // if w>1 acos and sqrt will produce errors, this cant happen if quaternion is normalised + var angle = 2 * Math.acos(this.w); + var s = Math.sqrt(1-this.w*this.w); // assuming quaternion normalised then w is less than 1, so term always positive. + if (s < 0.001) { // test to avoid divide by zero, s is always positive due to sqrt + // if s close to zero then direction of axis not important + targetAxis.x = this.x; // if it is important that axis is normalised then replace with x=1; y=z=0; + targetAxis.y = this.y; + targetAxis.z = this.z; + } else { + targetAxis.x = this.x / s; // normalise axis + targetAxis.y = this.y / s; + targetAxis.z = this.z / s; + } + return [targetAxis,angle]; +}; + +/** + * @method setFromVectors + * @memberof CANNON.Quaternion + * @brief Set the quaternion value given two vectors. The resulting rotation will be the needed rotation to rotate u to v. + * @param CANNON.Vec3 u + * @param CANNON.Vec3 v + */ +CANNON.Quaternion.prototype.setFromVectors = function(u,v){ + var a = u.cross(v); + this.x = a.x; + this.y = a.y; + this.z = a.z; + this.w = Math.sqrt(Math.pow(u.norm(),2) * Math.pow(v.norm(),2)) + u.dot(v); + this.normalize(); +}; + +/** + * @method mult + * @memberof CANNON.Quaternion + * @brief Quaternion multiplication + * @param CANNON.Quaternion q + * @param CANNON.Quaternion target Optional. + * @return CANNON.Quaternion + */ +var Quaternion_mult_va = new CANNON.Vec3(); +var Quaternion_mult_vb = new CANNON.Vec3(); +var Quaternion_mult_vaxvb = new CANNON.Vec3(); +CANNON.Quaternion.prototype.mult = function(q,target){ + target = target || new CANNON.Quaternion(); + var w = this.w, + va = Quaternion_mult_va, + vb = Quaternion_mult_vb, + vaxvb = Quaternion_mult_vaxvb; + + va.set(this.x,this.y,this.z); + vb.set(q.x,q.y,q.z); + target.w = w*q.w - va.dot(vb); + va.cross(vb,vaxvb); + + target.x = w * vb.x + q.w*va.x + vaxvb.x; + target.y = w * vb.y + q.w*va.y + vaxvb.y; + target.z = w * vb.z + q.w*va.z + vaxvb.z; + + return target; +}; + +/** + * @method inverse + * @memberof CANNON.Quaternion + * @brief Get the inverse quaternion rotation. + * @param CANNON.Quaternion target + * @return CANNON.Quaternion + */ +CANNON.Quaternion.prototype.inverse = function(target){ + var x = this.x, y = this.y, z = this.z, w = this.w; + target = target || new CANNON.Quaternion(); + + this.conjugate(target); + var inorm2 = 1/(x*x + y*y + z*z + w*w); + target.x *= inorm2; + target.y *= inorm2; + target.z *= inorm2; + target.w *= inorm2; + + return target; +}; + +/** + * @method conjugate + * @memberof CANNON.Quaternion + * @brief Get the quaternion conjugate + * @param CANNON.Quaternion target + * @return CANNON.Quaternion + */ +CANNON.Quaternion.prototype.conjugate = function(target){ + target = target || new CANNON.Quaternion(); + + target.x = -this.x; + target.y = -this.y; + target.z = -this.z; + target.w = this.w; + + return target; +}; + +/** + * @method normalize + * @memberof CANNON.Quaternion + * @brief Normalize the quaternion. Note that this changes the values of the quaternion. + */ +CANNON.Quaternion.prototype.normalize = function(){ + var l = Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w); + if ( l === 0 ) { + this.x = 0; + this.y = 0; + this.z = 0; + this.w = 0; + } else { + l = 1 / l; + this.x *= l; + this.y *= l; + this.z *= l; + this.w *= l; + } +}; + +/** + * @method normalizeFast + * @memberof CANNON.Quaternion + * @brief Approximation of quaternion normalization. Works best when quat is already almost-normalized. + * @see http://jsperf.com/fast-quaternion-normalization + * @author unphased, https://github.com/unphased + */ +CANNON.Quaternion.prototype.normalizeFast = function () { + var f = (3.0-(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w))/2.0; + if ( f === 0 ) { + this.x = 0; + this.y = 0; + this.z = 0; + this.w = 0; + } else { + this.x *= f; + this.y *= f; + this.z *= f; + this.w *= f; + } +}; + +/** + * @method vmult + * @memberof CANNON.Quaternion + * @brief Multiply the quaternion by a vector + * @param CANNON.Vec3 v + * @param CANNON.Vec3 target Optional + * @return CANNON.Vec3 + */ +CANNON.Quaternion.prototype.vmult = function(v,target){ + target = target || new CANNON.Vec3(); + if(this.w===0.0){ + target.x = v.x; + target.y = v.y; + target.z = v.z; + } else { + + var x = v.x, + y = v.y, + z = v.z; + + var qx = this.x, + qy = this.y, + qz = this.z, + qw = this.w; + + // q*v + var ix = qw * x + qy * z - qz * y, + iy = qw * y + qz * x - qx * z, + iz = qw * z + qx * y - qy * x, + iw = -qx * x - qy * y - qz * z; + + target.x = ix * qw + iw * -qx + iy * -qz - iz * -qy; + target.y = iy * qw + iw * -qy + iz * -qx - ix * -qz; + target.z = iz * qw + iw * -qz + ix * -qy - iy * -qx; + } + + return target; +}; + +/** + * @method copy + * @memberof CANNON.Quaternion + * @param CANNON.Quaternion target + */ +CANNON.Quaternion.prototype.copy = function(target){ + target.x = this.x; + target.y = this.y; + target.z = this.z; + target.w = this.w; +}; + +/** + * @method toEuler + * @memberof CANNON.Quaternion + * @brief Convert the quaternion to euler angle representation. Order: YZX, as this page describes: http://www.euclideanspace.com/maths/standards/index.htm + * @param CANNON.Vec3 target + * @param string order Three-character string e.g. "YZX", which also is default. + */ +CANNON.Quaternion.prototype.toEuler = function(target,order){ + order = order || "YZX"; + + var heading, attitude, bank; + var x = this.x, y = this.y, z = this.z, w = this.w; + + switch(order){ + case "YZX": + var test = x*y + z*w; + if (test > 0.499) { // singularity at north pole + heading = 2 * Math.atan2(x,w); + attitude = Math.PI/2; + bank = 0; + } + if (test < -0.499) { // singularity at south pole + heading = -2 * Math.atan2(x,w); + attitude = - Math.PI/2; + bank = 0; + } + if(isNaN(heading)){ + var sqx = x*x; + var sqy = y*y; + var sqz = z*z; + heading = Math.atan2(2*y*w - 2*x*z , 1 - 2*sqy - 2*sqz); // Heading + attitude = Math.asin(2*test); // attitude + bank = Math.atan2(2*x*w - 2*y*z , 1 - 2*sqx - 2*sqz); // bank + } + break; + default: + throw new Error("Euler order "+order+" not supported yet."); + } + + target.y = heading; + target.z = attitude; + target.x = bank; +}; + +/** + * @class CANNON.EventTarget + * @see https://github.com/mrdoob/eventtarget.js/ + */ +CANNON.EventTarget = function () { + var listeners = {}; + this.addEventListener = function ( type, listener ) { + if ( listeners[ type ] === undefined ) { + listeners[ type ] = []; + } + if ( listeners[ type ].indexOf( listener ) === - 1 ) { + listeners[ type ].push( listener ); + } + }; + this.dispatchEvent = function ( event ) { + for ( var listener in listeners[ event.type ] ) { + listeners[ event.type ][ listener ]( event ); + } + }; + this.removeEventListener = function ( type, listener ) { + var index = listeners[ type ].indexOf( listener ); + if ( index !== - 1 ) { + listeners[ type ].splice( index, 1 ); + } + }; +}; + +/** + * @class CANNON.ObjectPool + * @brief For pooling objects that can be reused. + */ +CANNON.ObjectPool = function(){ + this.objects = []; + this.type = Object; +}; + +CANNON.ObjectPool.prototype.release = function(){ + var Nargs = arguments.length; + for(var i=0; i!==Nargs; i++){ + this.objects.push(arguments[i]); + } +}; + +CANNON.ObjectPool.prototype.get = function(){ + if(this.objects.length===0){ + return this.constructObject(); + } else { + return this.objects.pop(); + } +}; + +CANNON.ObjectPool.prototype.constructObject = function(){ + throw new Error("constructObject() not implemented in this ObjectPool subclass yet!"); +}; + +/** + * @class CANNON.Vec3Pool + */ +CANNON.Vec3Pool = function(){ + CANNON.ObjectPool.call(this); + this.type = CANNON.Vec3; +}; +CANNON.Vec3Pool.prototype = new CANNON.ObjectPool(); + +CANNON.Vec3Pool.prototype.constructObject = function(){ + return new CANNON.Vec3(); +}; + +/** + * @class CANNON.Shape + * @author schteppe + * @brief Base class for shapes + * @todo Should have a mechanism for caching bounding sphere radius instead of calculating it each time + */ +CANNON.Shape = function(){ + + /** + * @property int type + * @memberof CANNON.Shape + * @brief The type of this shape. Must be set to an int > 0 by subclasses. + * @see CANNON.Shape.types + */ + this.type = 0; + + this.aabbmin = new CANNON.Vec3(); + this.aabbmax = new CANNON.Vec3(); + + this.boundingSphereRadius = 0; + this.boundingSphereRadiusNeedsUpdate = true; +}; +CANNON.Shape.prototype.constructor = CANNON.Shape; + +/** + * @method computeBoundingSphereRadius + * @memberof CANNON.Shape + * @brief Computes the bounding sphere radius. The result is stored in the property .boundingSphereRadius + * @return float + */ +CANNON.Shape.prototype.computeBoundingSphereRadius = function(){ + throw "computeBoundingSphereRadius() not implemented for shape type "+this.type; +}; + +/** + * @method getBoundingSphereRadius + * @memberof CANNON.Shape + * @brief Returns the bounding sphere radius. The result is stored in the property .boundingSphereRadius + * @return float + */ +CANNON.Shape.prototype.getBoundingSphereRadius = function(){ + if (this.boundingSphereRadiusNeedsUpdate) { + this.computeBoundingSphereRadius(); + } + return this.boundingSphereRadius; +}; + +/** + * @method volume + * @memberof CANNON.Shape + * @brief Get the volume of this shape + * @return float + */ +CANNON.Shape.prototype.volume = function(){ + throw "volume() not implemented for shape type "+this.type; +}; + +/** + * @method calculateLocalInertia + * @memberof CANNON.Shape + * @brief Calculates the inertia in the local frame for this shape. + * @return CANNON.Vec3 + * @see http://en.wikipedia.org/wiki/List_of_moments_of_inertia + */ +CANNON.Shape.prototype.calculateLocalInertia = function(mass,target){ + throw "calculateLocalInertia() not implemented for shape type "+this.type; +}; + +/** + * @method calculateTransformedInertia + * @memberof CANNON.Shape + * @brief Calculates inertia in a specified frame for this shape. + * @return CANNON.Vec3 + */ +var Shape_calculateTransformedInertia_localInertia = new CANNON.Vec3(); +var Shape_calculateTransformedInertia_worldInertia = new CANNON.Vec3(); +CANNON.Shape.prototype.calculateTransformedInertia = function(mass,quat,target){ + target = target || new CANNON.Vec3(); + + // Compute inertia in the world frame + //quat.normalize(); + var localInertia = Shape_calculateTransformedInertia_localInertia; + var worldInertia = Shape_calculateTransformedInertia_worldInertia; + this.calculateLocalInertia(mass,localInertia); + + // @todo Is this rotation OK? Check! + quat.vmult(localInertia,worldInertia); + target.x = Math.abs(worldInertia.x); + target.y = Math.abs(worldInertia.y); + target.z = Math.abs(worldInertia.z); + return target; +}; + +// Calculates the local aabb and sets the result to .aabbmax and .aabbmin +CANNON.Shape.calculateLocalAABB = function(){ + throw new Error(".calculateLocalAABB is not implemented for this Shape yet!"); +}; + +/** + * @property Object types + * @memberof CANNON.Shape + * @brief The available shape types. + */ +CANNON.Shape.types = { + SPHERE:1, + PLANE:2, + BOX:4, + COMPOUND:8, + CONVEXPOLYHEDRON:16 +}; + + + +/** + * @class CANNON.Body + * @brief Base class for all body types. + * @param string type + * @extends CANNON.EventTarget + * @event collide The body object dispatches a "collide" event whenever it collides with another body. Event parameters are "with" (the body it collides with) and "contact" (the contact equation that is generated). + */ +CANNON.Body = function(type){ + + CANNON.EventTarget.apply(this); + + this.type = type; + + /** + * @property CANNON.World world + * @memberof CANNON.Body + * @brief Reference to the world the body is living in + */ + this.world = null; + + /** + * @property function preStep + * @memberof CANNON.Body + * @brief Callback function that is used BEFORE stepping the system. Use it to apply forces, for example. Inside the function, "this" will refer to this CANNON.Body object. + * @todo dispatch an event from the World instead + */ + this.preStep = null; + + /** + * @property function postStep + * @memberof CANNON.Body + * @brief Callback function that is used AFTER stepping the system. Inside the function, "this" will refer to this CANNON.Body object. + * @todo dispatch an event from the World instead + */ + this.postStep = null; + + this.vlambda = new CANNON.Vec3(); + + this.collisionFilterGroup = 1; + this.collisionFilterMask = 1; +}; + +/* + * @brief A dynamic body is fully simulated. Can be moved manually by the user, but normally they move according to forces. A dynamic body can collide with all body types. A dynamic body always has finite, non-zero mass. + */ +CANNON.Body.DYNAMIC = 1; + +/* + * @brief A static body does not move during simulation and behaves as if it has infinite mass. Static bodies can be moved manually by setting the position of the body. The velocity of a static body is always zero. Static bodies do not collide with other static or kinematic bodies. + */ +CANNON.Body.STATIC = 2; + +/* + * A kinematic body moves under simulation according to its velocity. They do not respond to forces. They can be moved manually, but normally a kinematic body is moved by setting its velocity. A kinematic body behaves as if it has infinite mass. Kinematic bodies do not collide with other static or kinematic bodies. + */ +CANNON.Body.KINEMATIC = 4; + +/** + * @class CANNON.Particle + * @brief A body consisting of one point mass. Does not have orientation. + * @param float mass + * @param CANNON.Material material + */ +CANNON.Particle = function(mass,material){ + + // Check input + if(typeof(mass)!=="number"){ + throw new Error("Argument 1 (mass) must be a number."); + } + if(typeof(material)!=="undefined" && !(material instanceof(CANNON.Material))){ + throw new Error("Argument 3 (material) must be an instance of CANNON.Material."); + } + + CANNON.Body.call(this,"particle"); + + /** + * @property CANNON.Vec3 position + * @memberof CANNON.Particle + */ + this.position = new CANNON.Vec3(); + + /** + * @property CANNON.Vec3 initPosition + * @memberof CANNON.Particle + * @brief Initial position of the body + */ + this.initPosition = new CANNON.Vec3(); + + /** + * @property CANNON.Vec3 velocity + * @memberof CANNON.Particle + */ + this.velocity = new CANNON.Vec3(); + + /** + * @property CANNON.Vec3 initVelocity + * @memberof CANNON.Particle + */ + this.initVelocity = new CANNON.Vec3(); + + /** + * @property CANNON.Vec3 force + * @memberof CANNON.Particle + * @brief Linear force on the body + */ + this.force = new CANNON.Vec3(); + + /** + * @property float mass + * @memberof CANNON.Particle + */ + this.mass = mass; + + /** + * @property float invMass + * @memberof CANNON.Particle + */ + this.invMass = mass>0 ? 1.0/mass : 0; + + /** + * @property CANNON.Material material + * @memberof CANNON.Particle + */ + this.material = material; + + /** + * @property float linearDamping + * @memberof CANNON.Particle + */ + this.linearDamping = 0.01; // Perhaps default should be zero here? + + /** + * @property int motionstate + * @memberof CANNON.Particle + * @brief One of the states CANNON.Body.DYNAMIC, CANNON.Body.STATIC and CANNON.Body.KINEMATIC + */ + this.motionstate = (mass <= 0.0 ? CANNON.Body.STATIC : CANNON.Body.DYNAMIC); + + /** + * @property bool allowSleep + * @memberof CANNON.Particle + * @brief If true, the body will automatically fall to sleep. + */ + this.allowSleep = true; + + // 0:awake, 1:sleepy, 2:sleeping + this.sleepState = 0; + + /** + * @property float sleepSpeedLimit + * @memberof CANNON.Particle + * @brief If the speed (the norm of the velocity) is smaller than this value, the body is considered sleepy. + */ + this.sleepSpeedLimit = 0.1; + + /** + * @property float sleepTimeLimit + * @memberof CANNON.Particle + * @brief If the body has been sleepy for this sleepTimeLimit seconds, it is considered sleeping. + */ + this.sleepTimeLimit = 1; + + this.timeLastSleepy = 0; + +}; + +CANNON.Particle.prototype = new CANNON.Body(); +CANNON.Particle.prototype.constructor = CANNON.Particle; + +/** +* @method isAwake +* @memberof CANNON.Particle +* @return bool +*/ +CANNON.Particle.prototype.isAwake = function(){ + return this.sleepState === 0; +}; + +/** +* @method isSleepy +* @memberof CANNON.Particle +* @return bool +*/ +CANNON.Particle.prototype.isSleepy = function(){ + return this.sleepState === 1; +}; + +/** +* @method isSleeping +* @memberof CANNON.Particle +* @return bool +*/ +CANNON.Particle.prototype.isSleeping = function(){ + return this.sleepState === 2; +}; + +/** +* @method wakeUp +* @memberof CANNON.Particle +* @brief Wake the body up. +*/ +CANNON.Particle.prototype.wakeUp = function(){ + var s = this.sleepState; + this.sleepState = 0; + if(s === 2){ + this.dispatchEvent({type:"wakeup"}); + } +}; + +/** +* @method sleep +* @memberof CANNON.Particle +* @brief Force body sleep +*/ +CANNON.Particle.prototype.sleep = function(){ + this.sleepState = 2; +}; + +/** +* @method sleepTick +* @memberof CANNON.Particle +* @param float time The world time in seconds +* @brief Called every timestep to update internal sleep timer and change sleep state if needed. +*/ +CANNON.Particle.prototype.sleepTick = function(time){ + if(this.allowSleep){ + var sleepState = this.sleepState; + var speedSquared = this.velocity.norm2(); + var speedLimitSquared = Math.pow(this.sleepSpeedLimit,2); + if(sleepState===0 && speedSquared < speedLimitSquared){ + this.sleepState = 1; // Sleepy + this.timeLastSleepy = time; + this.dispatchEvent({type:"sleepy"}); + } else if(sleepState===1 && speedSquared > speedLimitSquared){ + this.wakeUp(); // Wake up + } else if(sleepState===1 && (time - this.timeLastSleepy ) > this.sleepTimeLimit){ + this.sleepState = 2; // Sleeping + this.dispatchEvent({type:"sleep"}); + } + } +}; + + +/** + * @class CANNON.RigidBody + * @brief Rigid body base class + * @param float mass + * @param CANNON.Shape shape + * @param CANNON.Material material + */ +CANNON.RigidBody = function(mass,shape,material){ + + // Check input + if(typeof(mass)!=="number"){ + throw new Error("Argument 1 (mass) must be a number."); + } + if(typeof(material)!=="undefined" && !(material instanceof(CANNON.Material))){ + throw new Error("Argument 3 (material) must be an instance of CANNON.Material."); + } + + CANNON.Particle.call(this,mass,material); + + var that = this; + + /** + * @property CANNON.Vec3 tau + * @memberof CANNON.RigidBody + * @brief Rotational force on the body, around center of mass + */ + this.tau = new CANNON.Vec3(); + + /** + * @property CANNON.Quaternion quaternion + * @memberof CANNON.RigidBody + * @brief Orientation of the body + */ + this.quaternion = new CANNON.Quaternion(); + + /** + * @property CANNON.Quaternion initQuaternion + * @memberof CANNON.RigidBody + */ + this.initQuaternion = new CANNON.Quaternion(); + + /** + * @property CANNON.Vec3 angularVelocity + * @memberof CANNON.RigidBody + */ + this.angularVelocity = new CANNON.Vec3(); + + /** + * @property CANNON.Vec3 initAngularVelocity + * @memberof CANNON.RigidBody + */ + this.initAngularVelocity = new CANNON.Vec3(); + + /** + * @property CANNON.Shape shape + * @memberof CANNON.RigidBody + */ + this.shape = shape; + + /** + * @property CANNON.Vec3 inertia + * @memberof CANNON.RigidBody + */ + this.inertia = new CANNON.Vec3(); + shape.calculateLocalInertia(mass,this.inertia); + + this.inertiaWorld = new CANNON.Vec3(); + this.inertia.copy(this.inertiaWorld); + this.inertiaWorldAutoUpdate = false; + + /** + * @property CANNON.Vec3 intInertia + * @memberof CANNON.RigidBody + */ + this.invInertia = new CANNON.Vec3(this.inertia.x>0 ? 1.0/this.inertia.x : 0, + this.inertia.y>0 ? 1.0/this.inertia.y : 0, + this.inertia.z>0 ? 1.0/this.inertia.z : 0); + this.invInertiaWorld = new CANNON.Vec3(); + this.invInertia.copy(this.invInertiaWorld); + this.invInertiaWorldAutoUpdate = false; + + /** + * @property float angularDamping + * @memberof CANNON.RigidBody + */ + this.angularDamping = 0.01; // Perhaps default should be zero here? + + /** + * @property CANNON.Vec3 aabbmin + * @memberof CANNON.RigidBody + */ + this.aabbmin = new CANNON.Vec3(); + + /** + * @property CANNON.Vec3 aabbmax + * @memberof CANNON.RigidBody + */ + this.aabbmax = new CANNON.Vec3(); + + /** + * @property bool aabbNeedsUpdate + * @memberof CANNON.RigidBody + * @brief Indicates if the AABB needs to be updated before use. + */ + this.aabbNeedsUpdate = true; + + this.wlambda = new CANNON.Vec3(); +}; + +CANNON.RigidBody.prototype = new CANNON.Particle(0); +CANNON.RigidBody.prototype.constructor = CANNON.RigidBody; + +CANNON.RigidBody.prototype.computeAABB = function(){ + this.shape.calculateWorldAABB(this.position, + this.quaternion, + this.aabbmin, + this.aabbmax); + this.aabbNeedsUpdate = false; +}; + +/** + * Apply force to a world point. This could for example be a point on the RigidBody surface. Applying force this way will add to Body.force and Body.tau. + * @param CANNON.Vec3 force The amount of force to add. + * @param CANNON.Vec3 worldPoint A world point to apply the force on. + */ +var RigidBody_applyForce_r = new CANNON.Vec3(); +var RigidBody_applyForce_rotForce = new CANNON.Vec3(); +CANNON.RigidBody.prototype.applyForce = function(force,worldPoint){ + // Compute point position relative to the body center + var r = RigidBody_applyForce_r; + worldPoint.vsub(this.position,r); + + // Compute produced rotational force + var rotForce = RigidBody_applyForce_rotForce; + r.cross(force,rotForce); + + // Add linear force + this.force.vadd(force,this.force); + + // Add rotational force + this.tau.vadd(rotForce,this.tau); +}; + +/** + * Apply impulse to a world point. This could for example be a point on the RigidBody surface. An impulse is a force added to a body during a short period of time (impulse = force * time). Impulses will be added to Body.velocity and Body.angularVelocity. + * @param CANNON.Vec3 impulse The amount of impulse to add. + * @param CANNON.Vec3 worldPoint A world point to apply the force on. + */ +var RigidBody_applyImpulse_r = new CANNON.Vec3(); +var RigidBody_applyImpulse_velo = new CANNON.Vec3(); +var RigidBody_applyImpulse_rotVelo = new CANNON.Vec3(); +CANNON.RigidBody.prototype.applyImpulse = function(impulse,worldPoint){ + // Compute point position relative to the body center + var r = RigidBody_applyImpulse_r; + worldPoint.vsub(this.position,r); + + // Compute produced central impulse velocity + var velo = RigidBody_applyImpulse_velo; + impulse.copy(velo); + velo.mult(this.invMass,velo); + + // Add linear impulse + this.velocity.vadd(velo, this.velocity); + + // Compute produced rotational impulse velocity + var rotVelo = RigidBody_applyImpulse_rotVelo; + r.cross(impulse,rotVelo); + rotVelo.x *= this.invInertia.x; + rotVelo.y *= this.invInertia.y; + rotVelo.z *= this.invInertia.z; + + // Add rotational Impulse + this.angularVelocity.vadd(rotVelo, this.angularVelocity); +}; + + +/** + * @brief Spherical rigid body + * @class CANNON.Sphere + * @extends CANNON.Shape + * @param float radius + * @author schteppe / http://github.com/schteppe + */ +CANNON.Sphere = function(radius){ + CANNON.Shape.call(this); + + /** + * @property float radius + * @memberof CANNON.Sphere + */ + this.radius = radius!==undefined ? Number(radius) : 1.0; + this.type = CANNON.Shape.types.SPHERE; +}; +CANNON.Sphere.prototype = new CANNON.Shape(); +CANNON.Sphere.prototype.constructor = CANNON.Sphere; + +CANNON.Sphere.prototype.calculateLocalInertia = function(mass,target){ + target = target || new CANNON.Vec3(); + var I = 2.0*mass*this.radius*this.radius/5.0; + target.x = I; + target.y = I; + target.z = I; + return target; +}; + +CANNON.Sphere.prototype.volume = function(){ + return 4.0 * Math.PI * this.radius / 3.0; +}; + +CANNON.Sphere.prototype.computeBoundingSphereRadius = function(){ + this.boundingSphereRadiusNeedsUpdate = false; + this.boundingSphereRadius = this.radius; +}; + +CANNON.Sphere.prototype.calculateWorldAABB = function(pos,quat,min,max){ + var r = this.radius; + var axes = ['x','y','z']; + for(var i=0; i this.particles.length) + this.neighbors.pop(); + } +}; + +/** + * Get neighbors within smoothing volume, save in the array neighbors + * @param CANNON.Body particle + * @param Array neighbors + */ +var SPHSystem_getNeighbors_dist = new CANNON.Vec3(); +CANNON.SPHSystem.prototype.getNeighbors = function(particle,neighbors){ + var N = this.particles.length, + id = particle.id, + R2 = this.smoothingRadius * this.smoothingRadius, + dist = SPHSystem_getNeighbors_dist; + for(var i=0; i!==N; i++){ + var p = this.particles[i]; + p.position.vsub(particle.position,dist); + if(id!==p.id && dist.norm2() < R2){ + neighbors.push(p); + } + } +}; + +// Temp vectors for calculation +var SPHSystem_update_dist = new CANNON.Vec3(), + SPHSystem_update_a_pressure = new CANNON.Vec3(), + SPHSystem_update_a_visc = new CANNON.Vec3(), + SPHSystem_update_gradW = new CANNON.Vec3(), + SPHSystem_update_r_vec = new CANNON.Vec3(), + SPHSystem_update_u = new CANNON.Vec3(); // Relative velocity +CANNON.SPHSystem.prototype.update = function(){ + var N = this.particles.length, + dist = SPHSystem_update_dist, + cs = this.speedOfSound, + eps = this.eps; + + for(var i=0; i!==N; i++){ + var p = this.particles[i]; // Current particle + var neighbors = this.neighbors[i]; + + // Get neighbors + neighbors.length = 0; + this.getNeighbors(p,neighbors); + neighbors.push(this.particles[i]); // Add current too + var numNeighbors = neighbors.length; + + // Accumulate density for the particle + var sum = 0.0; + for(var j=0; j!==numNeighbors; j++){ + + //printf("Current particle has position %f %f %f\n",objects[id].pos.x(),objects[id].pos.y(),objects[id].pos.z()); + p.position.vsub(neighbors[j].position, dist); + var len = dist.norm(); + + var weight = this.w(len); + sum += neighbors[j].mass * weight; + } + + // Save + this.densities[i] = sum; + this.pressures[i] = cs * cs * (this.densities[i] - this.density); + } + + // Add forces + + // Sum to these accelerations + var a_pressure= SPHSystem_update_a_pressure; + var a_visc = SPHSystem_update_a_visc; + var gradW = SPHSystem_update_gradW; + var r_vec = SPHSystem_update_r_vec; + var u = SPHSystem_update_u; + + for(var i=0; i!==N; i++){ + + var particle = this.particles[i]; + + a_pressure.set(0,0,0); + a_visc.set(0,0,0); + + // Init vars + var Pij; + var nabla; + var Vij; + + // Sum up for all other neighbors + var neighbors = this.neighbors[i]; + var numNeighbors = neighbors.length; + + //printf("Neighbors: "); + for(var j=0; j!==numNeighbors; j++){ + + var neighbor = neighbors[j]; + //printf("%d ",nj); + + // Get r once for all.. + particle.position.vsub(neighbor.position,r_vec); + var r = r_vec.norm(); + + // Pressure contribution + Pij = -neighbor.mass * (this.pressures[i] / (this.densities[i]*this.densities[i] + eps) + this.pressures[j] / (this.densities[j]*this.densities[j] + eps)); + this.gradw(r_vec, gradW); + // Add to pressure acceleration + gradW.mult(Pij , gradW) + a_pressure.vadd(gradW, a_pressure); + + // Viscosity contribution + neighbor.velocity.vsub(particle.velocity, u); + u.mult( 1.0 / (0.0001+this.densities[i] * this.densities[j]) * this.viscosity * neighbor.mass , u ); + nabla = this.nablaw(r); + u.mult(nabla,u); + // Add to viscosity acceleration + a_visc.vadd( u, a_visc ); + } + + // Calculate force + a_visc.mult(particle.mass, a_visc); + a_pressure.mult(particle.mass, a_pressure); + + // Add force to particles + particle.force.vadd(a_visc, particle.force); + particle.force.vadd(a_pressure, particle.force); + } +}; + +// Calculate the weight using the W(r) weightfunction +CANNON.SPHSystem.prototype.w = function(r){ + // 315 + var h = this.smoothingRadius; + return 315.0/(64.0*Math.PI*Math.pow(h,9)) * Math.pow(h*h-r*r,3); +}; + +// calculate gradient of the weight function +CANNON.SPHSystem.prototype.gradw = function(rVec,resultVec){ + var r = rVec.norm(), + h = this.smoothingRadius; + rVec.mult(945.0/(32.0*Math.PI*Math.pow(h,9)) * Math.pow((h*h-r*r),2) , resultVec); +}; + +// Calculate nabla(W) +CANNON.SPHSystem.prototype.nablaw = function(r){ + var h = this.smoothingRadius; + var nabla = 945.0/(32.0*Math.PI*Math.pow(h,9)) * (h*h-r*r)*(7*r*r - 3*h*h); + return nabla; +}; + + +/** + * @class CANNON.Box + * @brief A 3d box shape. + * @param CANNON.Vec3 halfExtents + * @author schteppe + * @extends CANNON.Shape + */ +CANNON.Box = function(halfExtents){ + CANNON.Shape.call(this); + + /** + * @property CANNON.Vec3 halfExtents + * @memberof CANNON.Box + */ + this.halfExtents = halfExtents; + this.type = CANNON.Shape.types.BOX; + + /** + * @property CANNON.ConvexPolyhedron convexPolyhedronRepresentation + * @brief Used by the contact generator to make contacts with other convex polyhedra for example + * @memberof CANNON.Box + */ + this.convexPolyhedronRepresentation = null; + + this.updateConvexPolyhedronRepresentation(); +}; +CANNON.Box.prototype = new CANNON.Shape(); +CANNON.Box.prototype.constructor = CANNON.Box; + +/** + * @method updateConvexPolyhedronRepresentation + * @memberof CANNON.Box + * @brief Updates the local convex polyhedron representation used for some collisions. + */ +CANNON.Box.prototype.updateConvexPolyhedronRepresentation = function(){ + var sx = this.halfExtents.x; + var sy = this.halfExtents.y; + var sz = this.halfExtents.z; + var V = CANNON.Vec3; + + function createBoxPolyhedron(size){ + size = size || 1; + var vertices = [new CANNON.Vec3(-size,-size,-size), + new CANNON.Vec3( size,-size,-size), + new CANNON.Vec3( size, size,-size), + new CANNON.Vec3(-size, size,-size), + new CANNON.Vec3(-size,-size, size), + new CANNON.Vec3( size,-size, size), + new CANNON.Vec3( size, size, size), + new CANNON.Vec3(-size, size, size)]; + var faces =[[3,2,1,0], // -z + [4,5,6,7], // +z + [5,4,1,0], // -y + [2,3,6,7], // +y + [0,4,7,3 /*0,3,4,7*/ ], // -x + [1,2,5,6], // +x + ]; + var faceNormals = [new CANNON.Vec3( 0, 0,-1), + new CANNON.Vec3( 0, 0, 1), + new CANNON.Vec3( 0,-1, 0), + new CANNON.Vec3( 0, 1, 0), + new CANNON.Vec3(-1, 0, 0), + new CANNON.Vec3( 1, 0, 0)]; + var boxShape = new CANNON.ConvexPolyhedron(vertices, + faces, + faceNormals); + return boxShape; + } + + var h = new CANNON.ConvexPolyhedron([new V(-sx,-sy,-sz), + new V( sx,-sy,-sz), + new V( sx, sy,-sz), + new V(-sx, sy,-sz), + new V(-sx,-sy, sz), + new V( sx,-sy, sz), + new V( sx, sy, sz), + new V(-sx, sy, sz)], + [[3,2,1,0], // -z + [4,5,6,7], // +z + [5,4,1,0], // -y + [2,3,6,7], // +y + [0,4,7,3], // -x + [1,2,5,6], // +x + ], + [new V( 0, 0,-1), + new V( 0, 0, 1), + new V( 0,-1, 0), + new V( 0, 1, 0), + new V(-1, 0, 0), + new V( 1, 0, 0)]); + this.convexPolyhedronRepresentation = h; +}; + +CANNON.Box.prototype.calculateLocalInertia = function(mass,target){ + target = target || new CANNON.Vec3(); + var e = this.halfExtents; + target.x = 1.0 / 12.0 * mass * ( 2*e.y*2*e.y + 2*e.z*2*e.z ); + target.y = 1.0 / 12.0 * mass * ( 2*e.x*2*e.x + 2*e.z*2*e.z ); + target.z = 1.0 / 12.0 * mass * ( 2*e.y*2*e.y + 2*e.x*2*e.x ); + return target; +}; + +/** + * @method getSideNormals + * @memberof CANNON.Box + * @brief Get the box 6 side normals + * @param bool includeNegative If true, this function returns 6 vectors. If false, it only returns 3 (but you get 6 by reversing those 3) + * @param CANNON.Quaternion quat Orientation to apply to the normal vectors. If not provided, the vectors will be in respect to the local frame. + * @return array + */ +CANNON.Box.prototype.getSideNormals = function(sixTargetVectors,quat){ + var sides = sixTargetVectors; + var ex = this.halfExtents; + sides[0].set( ex.x, 0, 0); + sides[1].set( 0, ex.y, 0); + sides[2].set( 0, 0, ex.z); + sides[3].set( -ex.x, 0, 0); + sides[4].set( 0, -ex.y, 0); + sides[5].set( 0, 0, -ex.z); + + if(quat!==undefined){ + for(var i=0; i!==sides.length; i++){ + quat.vmult(sides[i],sides[i]); + } + } + + return sides; +}; + +CANNON.Box.prototype.volume = function(){ + return 8.0 * this.halfExtents.x * this.halfExtents.y * this.halfExtents.z; +}; + +CANNON.Box.prototype.computeBoundingSphereRadius = function(){ + this.boundingSphereRadius = this.halfExtents.norm(); + this.boundingSphereRadiusNeedsUpdate = false; +}; + +var worldCornerTempPos = new CANNON.Vec3(); +var worldCornerTempNeg = new CANNON.Vec3(); +CANNON.Box.prototype.forEachWorldCorner = function(pos,quat,callback){ + + var e = this.halfExtents; + var corners = [[ e.x, e.y, e.z], + [ -e.x, e.y, e.z], + [ -e.x, -e.y, e.z], + [ -e.x, -e.y, -e.z], + [ e.x, -e.y, -e.z], + [ e.x, e.y, -e.z], + [ -e.x, e.y, -e.z], + [ e.x, -e.y, e.z]]; + for(var i=0; i max.x){ + max.x = x; + } + if(y > max.y){ + max.y = y; + } + if(z > max.z){ + max.z = z; + } + + if(x < min.x){ + min.x = x; + } + if(y < min.y){ + min.y = y; + } + if(z < min.z){ + min.z = z; + } + }); +}; + +/** + * @class CANNON.Plane + * @extends CANNON.Shape + * @param CANNON.Vec3 normal + * @brief A plane, facing in the Z direction. + * @description A plane, facing in the Z direction. The plane has its surface at z=0 and everything below z=0 is assumed to be solid plane. To make the plane face in some other direction than z, you must put it inside a RigidBody and rotate that body. See the demos. + * @author schteppe + */ +CANNON.Plane = function(){ + CANNON.Shape.call(this); + this.type = CANNON.Shape.types.PLANE; + + // World oriented normal + this.worldNormal = new CANNON.Vec3(); + this.worldNormalNeedsUpdate = true; +}; +CANNON.Plane.prototype = new CANNON.Shape(); +CANNON.Plane.prototype.constructor = CANNON.Plane; + +CANNON.Plane.prototype.computeWorldNormal = function(quat){ + var n = this.worldNormal; + n.set(0,0,1); + quat.vmult(n,n); + this.worldNormalNeedsUpdate = false; +}; + +CANNON.Plane.prototype.calculateLocalInertia = function(mass,target){ + target = target || new CANNON.Vec3(); + return target; +}; + +CANNON.Plane.prototype.volume = function(){ + return Infinity; // The plane is infinite... +}; + +var tempNormal = new CANNON.Vec3(); +CANNON.Plane.prototype.calculateWorldAABB = function(pos,quat,min,max){ + // The plane AABB is infinite, except if the normal is pointing along any axis + tempNormal.set(0,0,1); // Default plane normal is z + quat.vmult(tempNormal,tempNormal); + min.set(-Infinity,-Infinity,-Infinity); + max.set(Infinity,Infinity,Infinity); + + if(tempNormal.x === 1){ max.x = pos.x; } + if(tempNormal.y === 1){ max.y = pos.y; } + if(tempNormal.z === 1){ max.z = pos.z; } + + if(tempNormal.x === -1){ min.x = pos.x; } + if(tempNormal.y === -1){ min.y = pos.y; } + if(tempNormal.z === -1){ min.z = pos.z; } + +}; + + +/** + * @class CANNON.Compound + * @extends CANNON.Shape + * @brief A shape made of several other shapes. + * @author schteppe + */ +CANNON.Compound = function(){ + CANNON.Shape.call(this); + this.type = CANNON.Shape.types.COMPOUND; + this.childShapes = []; + this.childOffsets = []; + this.childOrientations = []; +}; +CANNON.Compound.prototype = new CANNON.Shape(); +CANNON.Compound.prototype.constructor = CANNON.Compound; + +/** + * @method addChild + * @memberof CANNON.Compound + * @brief Add a child shape. + * @param CANNON.Shape shape + * @param CANNON.Vec3 offset + * @param CANNON.Quaternion orientation + */ +CANNON.Compound.prototype.addChild = function(shape,offset,orientation){ + offset = offset || new CANNON.Vec3(); + orientation = orientation || new CANNON.Quaternion(); + this.childShapes.push(shape); + this.childOffsets.push(offset); + this.childOrientations.push(orientation); +}; + +CANNON.Compound.prototype.volume = function(){ + var r = 0.0; + var Nchildren = this.childShapes.length; + for(var i=0; i!==Nchildren; i++){ + r += this.childShapes[i].volume(); + } + return r; +}; + +var Compound_calculateLocalInertia_mr2 = new CANNON.Vec3(); +var Compound_calculateLocalInertia_childInertia = new CANNON.Vec3(); +CANNON.Compound.prototype.calculateLocalInertia = function(mass,target){ + target = target || new CANNON.Vec3(); + + // Calculate the total volume, we will spread out this objects' mass on the sub shapes + var V = this.volume(); + var childInertia = Compound_calculateLocalInertia_childInertia; + for(var i=0, Nchildren=this.childShapes.length; i!==Nchildren; i++){ + // Get child information + var b = this.childShapes[i]; + var o = this.childOffsets[i]; + var q = this.childOrientations[i]; + var m = b.volume() / V * mass; + + // Get the child inertia, transformed relative to local frame + //var inertia = b.calculateTransformedInertia(m,q); + b.calculateLocalInertia(m,childInertia); // Todo transform! + //console.log(childInertia,m,b.volume(),V); + + // Add its inertia using the parallel axis theorem, i.e. + // I += I_child; + // I += m_child * r^2 + + target.vadd(childInertia,target); + var mr2 = Compound_calculateLocalInertia_mr2; + mr2.set(m*o.x*o.x, + m*o.y*o.y, + m*o.z*o.z); + target.vadd(mr2,target); + } + + return target; +}; + +CANNON.Compound.prototype.computeBoundingSphereRadius = function(){ + var r = 0.0; + for(var i = 0; i max.x){ + max.x = aabbmaxTemp.x; + } + if(aabbmaxTemp.y > max.y){ + max.y = aabbmaxTemp.y; + } + if(aabbmaxTemp.z > max.z){ + max.z = aabbmaxTemp.z; + } + } +}; + +/** + * @class CANNON.ConvexPolyhedron + * @extends CANNON.Shape + * @brief A set of points in space describing a convex shape. + * @author qiao / https://github.com/qiao (original author, see https://github.com/qiao/three.js/commit/85026f0c769e4000148a67d45a9e9b9c5108836f) + * @author schteppe / https://github.com/schteppe + * @see http://www.altdevblogaday.com/2011/05/13/contact-generation-between-3d-convex-meshes/ + * @see http://bullet.googlecode.com/svn/trunk/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp + * @todo move the clipping functions to ContactGenerator? + * @param array points An array of CANNON.Vec3's + * @param array faces + * @param array normals + */ +CANNON.ConvexPolyhedron = function( points , faces , normals ) { + var that = this; + CANNON.Shape.call( this ); + this.type = CANNON.Shape.types.CONVEXPOLYHEDRON; + + /* + * @brief Get face normal given 3 vertices + * @param CANNON.Vec3 va + * @param CANNON.Vec3 vb + * @param CANNON.Vec3 vc + * @param CANNON.Vec3 target + * @todo unit test? + */ + var cb = new CANNON.Vec3(); + var ab = new CANNON.Vec3(); + function normal( va, vb, vc, target ) { + vb.vsub(va,ab); + vc.vsub(vb,cb); + cb.cross(ab,target); + if ( !target.isZero() ) { + target.normalize(); + } + } + + /** + * @property array vertices + * @memberof CANNON.ConvexPolyhedron + * @brief Array of CANNON.Vec3 + */ + this.vertices = points||[]; + + this.worldVertices = []; // World transformed version of .vertices + this.worldVerticesNeedsUpdate = true; + + /** + * @property array faces + * @memberof CANNON.ConvexPolyhedron + * @brief Array of integer arrays, indicating which vertices each face consists of + * @todo Needed? + */ + this.faces = faces||[]; + + /** + * @property array faceNormals + * @memberof CANNON.ConvexPolyhedron + * @brief Array of CANNON.Vec3 + * @todo Needed? + */ + this.faceNormals = [];//normals||[]; + /* + for(var i=0; imax){ + max = val; + } + if(min===null || valmax){ + // Inconsistent - swap + var temp = min; + min = max; + max = temp; + } + // Output + maxmin[0] = max; + maxmin[1] = min; + } + + /** + * @method testSepAxis + * @memberof CANNON.ConvexPolyhedron + * @brief Test separating axis against two hulls. Both hulls are projected onto the axis and the overlap size is returned if there is one. + * @param CANNON.Vec3 axis + * @param CANNON.ConvexPolyhedron hullB + * @param CANNON.Vec3 posA + * @param CANNON.Quaternion quatA + * @param CANNON.Vec3 posB + * @param CANNON.Quaternion quatB + * @return float The overlap depth, or FALSE if no penetration. + */ + this.testSepAxis = function(axis, hullB, posA, quatA, posB, quatB){ + var maxminA=[], maxminB=[], hullA=this; + project(hullA, axis, posA, quatA, maxminA); + project(hullB, axis, posB, quatB, maxminB); + var maxA = maxminA[0]; + var minA = maxminA[1]; + var maxB = maxminB[0]; + var minB = maxminB[1]; + if(maxA0.0){ + target.negate(target); + } + return true; + }; + + /** + * @method clipAgainstHull + * @memberof CANNON.ConvexPolyhedron + * @brief Clip this hull against another hull + * @param CANNON.Vec3 posA + * @param CANNON.Quaternion quatA + * @param CANNON.ConvexPolyhedron hullB + * @param CANNON.Vec3 posB + * @param CANNON.Quaternion quatB + * @param CANNON.Vec3 separatingNormal + * @param float minDist Clamp distance + * @param float maxDist + * @param array result The an array of contact point objects, see clipFaceAgainstHull + * @see http://bullet.googlecode.com/svn/trunk/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp + */ + var WorldNormal = new CANNON.Vec3(); + this.clipAgainstHull = function(posA,quatA,hullB,posB,quatB,separatingNormal,minDist,maxDist,result){ + if(!(posA instanceof CANNON.Vec3)){ + throw new Error("posA must be Vec3"); + } + if(!(quatA instanceof CANNON.Quaternion)){ + throw new Error("quatA must be Quaternion"); + } + var hullA = this; + var curMaxDist = maxDist; + var closestFaceB = -1; + var dmax = -Infinity; + for(var face=0; face < hullB.faces.length; face++){ + hullB.faceNormals[face].copy(WorldNormal); + quatB.vmult(WorldNormal,WorldNormal); + //posB.vadd(WorldNormal,WorldNormal); + var d = WorldNormal.dot(separatingNormal); + if (d > dmax){ + dmax = d; + closestFaceB = face; + } + } + var worldVertsB1 = []; + var polyB = hullB.faces[closestFaceB]; + var numVertices = polyB.length; + for(var e0=0; e0=0){ + this.clipFaceAgainstHull(separatingNormal, + posA, + quatA, + worldVertsB1, + minDist, + maxDist, + result); + } + }; + + /** + * @method clipFaceAgainstHull + * @memberof CANNON.ConvexPolyhedron + * @brief Clip a face against a hull. + * @param CANNON.Vec3 separatingNormal + * @param CANNON.Vec3 posA + * @param CANNON.Quaternion quatA + * @param Array worldVertsB1 An array of CANNON.Vec3 with vertices in the world frame. + * @param float minDist Distance clamping + * @param float maxDist + * @param Array result Array to store resulting contact points in. Will be objects with properties: point, depth, normal. These are represented in world coordinates. + */ + var faceANormalWS = new CANNON.Vec3(); + var edge0 = new CANNON.Vec3(); + var WorldEdge0 = new CANNON.Vec3(); + var worldPlaneAnormal1 = new CANNON.Vec3(); + var planeNormalWS1 = new CANNON.Vec3(); + var worldA1 = new CANNON.Vec3(); + var localPlaneNormal = new CANNON.Vec3(); + var planeNormalWS = new CANNON.Vec3(); + this.clipFaceAgainstHull = function(separatingNormal, posA, quatA, worldVertsB1, minDist, maxDist,result){ + if(!(separatingNormal instanceof CANNON.Vec3)){ + throw new Error("sep normal must be vector"); + } + if(!(worldVertsB1 instanceof Array)){ + throw new Error("world verts must be array"); + } + minDist = Number(minDist); + maxDist = Number(maxDist); + var hullA = this; + var worldVertsB2 = []; + var pVtxIn = worldVertsB1; + var pVtxOut = worldVertsB2; + // Find the face with normal closest to the separating axis + var closestFaceA = -1; + var dmin = Infinity; + for(var face=0; face= 0, so output intersection + var newv = new CANNON.Vec3(); + firstVertex.lerp(lastVertex, + n_dot_first / (n_dot_first - n_dot_last), + newv); + outVertices.push(newv); + } + } else { + if(n_dot_last<0){ + // Start >= 0, end < 0 so output intersection and end + var newv = new CANNON.Vec3(); + firstVertex.lerp(lastVertex, + n_dot_first / (n_dot_first - n_dot_last), + newv); + outVertices.push(newv); + outVertices.push(lastVertex); + } + } + firstVertex = lastVertex; + n_dot_first = n_dot_last; + } + return outVertices; + }; + + var that = this; + function normalOfFace(i,target){ + var f = that.faces[i]; + var va = that.vertices[f[0]]; + var vb = that.vertices[f[1]]; + var vc = that.vertices[f[2]]; + return normal(va,vb,vc,target); + } + + function planeConstant(face_i,target){ + var f = that.faces[face_i]; + var n = that.faceNormals[face_i]; + var v = that.vertices[f[0]]; + var c = -n.dot(v); + return c; + } + + + function printFace(i){ + var f = that.faces[i], s = ""; + for(var j=0; j aabbmax.x){ + aabbmax.x = v.x; + } + if (v.y < aabbmin.y){ + aabbmin.y = v.y; + } else if(v.y > aabbmax.y){ + aabbmax.y = v.y; + } + if (v.z < aabbmin.z){ + aabbmin.z = v.z; + } else if(v.z > aabbmax.z){ + aabbmax.z = v.z; + } + } + }; + + //this.computeAABB(); +}; + +CANNON.ConvexPolyhedron.prototype = new CANNON.Shape(); +CANNON.ConvexPolyhedron.prototype.constructor = CANNON.ConvexPolyhedron; + +// Updates .worldVertices and sets .worldVerticesNeedsUpdate to false. +CANNON.ConvexPolyhedron.prototype.computeWorldVertices = function(position,quat){ + var N = this.vertices.length; + while(this.worldVertices.length < N){ + this.worldVertices.push( new CANNON.Vec3() ); + } + + var verts = this.vertices, + worldVerts = this.worldVertices; + for(var i=0; i!==N; i++){ + quat.vmult( verts[i] , worldVerts[i] ); + position.vadd( worldVerts[i] , worldVerts[i] ); + } + + this.worldVerticesNeedsUpdate = false; +}; + +// Updates .worldVertices and sets .worldVerticesNeedsUpdate to false. +CANNON.ConvexPolyhedron.prototype.computeWorldFaceNormals = function(quat){ + var N = this.faceNormals.length; + while(this.worldFaceNormals.length < N){ + this.worldFaceNormals.push( new CANNON.Vec3() ); + } + + var normals = this.faceNormals, + worldNormals = this.worldFaceNormals; + for(var i=0; i!==N; i++){ + quat.vmult( normals[i] , worldNormals[i] ); + } + + this.worldFaceNormalsNeedsUpdate = false; +}; + +CANNON.ConvexPolyhedron.prototype.computeBoundingSphereRadius = function(){ + // Assume points are distributed with local (0,0,0) as center + var max2 = 0; + var verts = this.vertices; + for(var i=0, N=verts.length; i!==N; i++) { + var norm2 = verts[i].norm2(); + if(norm2 > max2){ + max2 = norm2; + } + } + this.boundingSphereRadius = Math.sqrt(max2); + this.boundingSphereRadiusNeedsUpdate = false; +}; + +var tempWorldVertex = new CANNON.Vec3(); +CANNON.ConvexPolyhedron.prototype.calculateWorldAABB = function(pos,quat,min,max){ + var n = this.vertices.length, verts = this.vertices; + var minx,miny,minz,maxx,maxy,maxz; + for(var i=0; i maxx || maxx===undefined){ + maxx = v.x; + } + + if (v.y < miny || miny===undefined){ + miny = v.y; + } else if(v.y > maxy || maxy===undefined){ + maxy = v.y; + } + + if (v.z < minz || minz===undefined){ + minz = v.z; + } else if(v.z > maxz || maxz===undefined){ + maxz = v.z; + } + } + min.set(minx,miny,minz); + max.set(maxx,maxy,maxz); +}; + +// Just approximate volume! +CANNON.ConvexPolyhedron.prototype.volume = function(){ + if(this.boundingSphereRadiusNeedsUpdate){ + this.computeBoundingSphereRadius(); + } + return 4.0 * Math.PI * this.boundingSphereRadius / 3.0; +}; + +// Get an average of all the vertices +CANNON.ConvexPolyhedron.prototype.getAveragePointLocal = function(target){ + target = target || new CANNON.Vec3(); + var n = this.vertices.length, + verts = this.vertices; + for(var i=0; i0) || (r1>0 && r2<0)){ + return false; // Encountered some other sign. Exit. + } else { + } + } + + // If we got here, all dot products were of the same sign. + return positiveResult ? 1 : -1; +}; + + +function pointInConvex(p){ +} + +/** + * @class CANNON.Cylinder + * @extends CANNON.ConvexPolyhedron + * @author schteppe / https://github.com/schteppe + * @param float radiusTop + * @param float radiusBottom + * @param float height + * @param int numSegments The number of segments to build the cylinder out of + */ +CANNON.Cylinder = function( radiusTop, radiusBottom, height , numSegments ) { + var N = numSegments, + verts = [], + normals = [], + faces = [], + bottomface = [], + topface = [], + cos = Math.cos, + sin = Math.sin; + + // First bottom point + verts.push(new CANNON.Vec3(radiusBottom*cos(0), + radiusBottom*sin(0), + -height*0.5)); + bottomface.push(0); + + // First top point + verts.push(new CANNON.Vec3(radiusTop*cos(0), + radiusTop*sin(0), + height*0.5)); + topface.push(1); + + for(var i=0; i shape.getBoundingSphereRadius() ) { + return intersects; + } + + // Checking faces + var dot, scalar, faces = shape.faces, vertices = shape.vertices, normals = shape.faceNormals; + + + for (var fi = 0; fi < faces.length; fi++ ) { + + var face = faces[ fi ]; + var faceNormal = normals[ fi ]; + var q = quat; + var x = position; + + // determine if ray intersects the plane of the face + // note: this works regardless of the direction of the face normal + + // Get plane point in world coordinates... + vertices[face[0]].copy(vector); + q.vmult(vector,vector); + vector.vadd(x,vector); + + // ...but make it relative to the ray origin. We'll fix this later. + vector.vsub(this.origin,vector); + + // Get plane normal + q.vmult(faceNormal,normal); + + // If this dot product is negative, we have something interesting + dot = this.direction.dot(normal); + + // bail if ray and plane are parallel + if ( Math.abs( dot ) < precision ){ + continue; + } + + // calc distance to plane + scalar = normal.dot( vector ) / dot; + + // if negative distance, then plane is behind ray + if ( scalar < 0 ){ + continue; + } + + if ( dot < 0 ) { + + // Intersection point is origin + direction * scalar + this.direction.mult(scalar,intersectPoint); + intersectPoint.vadd(this.origin,intersectPoint); + + // a is the point we compare points b and c with. + vertices[ face[0] ].copy(a); + q.vmult(a,a); + x.vadd(a,a); + + for(var i=1; i= 0 ) && ( v >= 0 ) && ( u + v < 1 ); + } +}; +CANNON.Ray.prototype.constructor = CANNON.Ray; + + +/** + * @class CANNON.Broadphase + * @author schteppe + * @brief Base class for broadphase implementations + */ +CANNON.Broadphase = function(){ + /** + * @property CANNON.World world + * @brief The world to search for collisions in. + * @memberof CANNON.Broadphase + */ + this.world = null; + + /** + * If set to true, the broadphase uses bounding boxes for intersection test, else it uses bounding spheres. + * @property bool useBoundingBoxes + * @memberof CANNON.Broadphase + */ + this.useBoundingBoxes = false; +}; +CANNON.Broadphase.prototype.constructor = CANNON.BroadPhase; + +/** + * @method collisionPairs + * @memberof CANNON.Broadphase + * @brief Get the collision pairs from the world + * @param CANNON.World world The world to search in + * @param Array p1 Empty array to be filled with body objects + * @param Array p2 Empty array to be filled with body objects + * @return array An array with two subarrays of body indices + */ +CANNON.Broadphase.prototype.collisionPairs = function(world,p1,p2){ + throw new Error("collisionPairs not implemented for this BroadPhase class!"); +}; + +/** + * @method needBroadphaseCollision + * @memberof CANNON.Broadphase + * @brief Check if a body pair needs to be intersection tested at all. + * @param CANNON.Body bodyA + * @param CANNON.Body bodyB + * @return bool + */ +var Broadphase_needBroadphaseCollision_STATIC_OR_KINEMATIC = CANNON.Body.STATIC | CANNON.Body.KINEMATIC; +CANNON.Broadphase.prototype.needBroadphaseCollision = function(bodyA,bodyB){ + + // Check collision filter masks + if( (bodyA.collisionFilterGroup & bodyB.collisionFilterMask)===0 || (bodyB.collisionFilterGroup & bodyA.collisionFilterMask)===0){ + return false; + } + + // Check motionstate + if(((bodyA.motionstate & Broadphase_needBroadphaseCollision_STATIC_OR_KINEMATIC)!==0 || bodyA.isSleeping()) && + ((bodyB.motionstate & Broadphase_needBroadphaseCollision_STATIC_OR_KINEMATIC)!==0 || bodyB.isSleeping())) { + // Both bodies are static, kinematic or sleeping. Skip. + return false; + } + + // Two particles don't collide + if(!bodyA.shape && !bodyB.shape){ + return false; + } + + // Two planes don't collide + if(bodyA.shape instanceof CANNON.Plane && bodyB.shape instanceof CANNON.Plane){ + return false; + } + + return true; +}; + +/** + * @method intersectionTest + * @memberof CANNON.Broadphase + * @brief Check if a body pair needs to be intersection tested at all. + * @param CANNON.Body bodyA + * @param CANNON.Body bodyB + * @return bool + */ +CANNON.Broadphase.prototype.intersectionTest = function(bi,bj,pairs1,pairs2){ + if(this.useBoundingBoxes){ + this.doBoundingBoxBroadphase(bi,bj,pairs1,pairs2); + } else { + this.doBoundingSphereBroadphase(bi,bj,pairs1,pairs2); + } +}; + +/** + * @method doBoundingSphereBroadphase + * @memberof CANNON.Broadphase + * @brief Check if the bounding spheres of two bodies are intersecting. + * @param CANNON.Body bi + * @param CANNON.Body bj + * @param Array pairs1 bi is appended to this array if intersection + * @param Array pairs2 bj is appended to this array if intersection + */ +var Broadphase_collisionPairs_r = new CANNON.Vec3(), // Temp objects + Broadphase_collisionPairs_normal = new CANNON.Vec3(), + Broadphase_collisionPairs_quat = new CANNON.Quaternion(), + Broadphase_collisionPairs_relpos = new CANNON.Vec3(); +CANNON.Broadphase.prototype.doBoundingSphereBroadphase = function(bi,bj,pairs1,pairs2){ + + // Local fast access + var types = CANNON.Shape.types, + BOX_SPHERE_COMPOUND_CONVEX = types.SPHERE | types.BOX | types.COMPOUND | types.CONVEXPOLYHEDRON, + PLANE = types.PLANE, + STATIC_OR_KINEMATIC = CANNON.Body.STATIC | CANNON.Body.KINEMATIC; + + // Temp vecs + var r = Broadphase_collisionPairs_r, + normal = Broadphase_collisionPairs_normal, + quat = Broadphase_collisionPairs_quat, + relpos = Broadphase_collisionPairs_relpos; + + var bishape = bi.shape, bjshape = bj.shape; + if(bishape && bjshape){ + var ti = bishape.type, tj = bjshape.type; + + // --- Box / sphere / compound / convexpolyhedron collision --- + if((ti & BOX_SPHERE_COMPOUND_CONVEX) && (tj & BOX_SPHERE_COMPOUND_CONVEX)){ + // Rel. position + bj.position.vsub(bi.position,r); + + // Update bounding spheres if needed + if(bishape.boundingSphereRadiusNeedsUpdate){ + bishape.computeBoundingSphereRadius(); + } + if(bjshape.boundingSphereRadiusNeedsUpdate){ + bjshape.computeBoundingSphereRadius(); + } + + var boundingRadiusSum = bishape.boundingSphereRadius + bjshape.boundingSphereRadius; + if(r.norm2() < boundingRadiusSum*boundingRadiusSum){ + pairs1.push(bi); + pairs2.push(bj); + } + + // --- Sphere/box/compound/convexpoly versus plane --- + } else if((ti & BOX_SPHERE_COMPOUND_CONVEX) && (tj & types.PLANE) || (tj & BOX_SPHERE_COMPOUND_CONVEX) && (ti & types.PLANE)){ + var planeBody = (ti===PLANE) ? bi : bj, // Plane + otherBody = (ti!==PLANE) ? bi : bj; // Other + + var otherShape = otherBody.shape; + var planeShape = planeBody.shape; + + // Rel. position + otherBody.position.vsub(planeBody.position,r); + + if(planeShape.worldNormalNeedsUpdate){ + planeShape.computeWorldNormal(planeBody.quaternion); + } + + normal = planeShape.worldNormal; + + if(otherShape.boundingSphereRadiusNeedsUpdate){ + otherShape.computeBoundingSphereRadius(); + } + + var q = r.dot(normal) - otherShape.boundingSphereRadius; + if(q < 0.0){ + pairs1.push(bi); + pairs2.push(bj); + } + } + } else { + // Particle without shape + if(!bishape && !bjshape){ + // No collisions between 2 particles + } else { + var particle = bishape ? bj : bi; + var other = bishape ? bi : bj; + var otherShape = other.shape; + var type = otherShape.type; + + if(type & BOX_SPHERE_COMPOUND_CONVEX){ + if(type === types.SPHERE){ // particle-sphere + particle.position.vsub(other.position,relpos); + if(otherShape.radius*otherShape.radius >= relpos.norm2()){ + pairs1.push(particle); + pairs2.push(other); + } + } else if(type===types.CONVEXPOLYHEDRON || type===types.BOX || type===types.COMPOUND){ + + if(otherShape.boundingSphereRadiusNeedsUpdate){ + otherShape.computeBoundingSphereRadius(); + } + var R = otherShape.boundingSphereRadius; + particle.position.vsub(other.position,relpos); + if(R*R >= relpos.norm2()){ + pairs1.push(particle); + pairs2.push(other); + } + } + } else if(type === types.PLANE){ + // particle/plane + var plane = other; + normal.set(0,0,1); + plane.quaternion.vmult(normal,normal); + particle.position.vsub(plane.position,relpos); + if(normal.dot(relpos)<=0.0){ + pairs1.push(particle); + pairs2.push(other); + } + } + } + } +}; + +/** + * @method doBoundingBoxBroadphase + * @memberof CANNON.Broadphase + * @brief Check if the bounding boxes of two bodies are intersecting. + * @param CANNON.Body bi + * @param CANNON.Body bj + * @param Array pairs1 + * @param Array pairs2 + */ +CANNON.Broadphase.prototype.doBoundingBoxBroadphase = function(bi,bj,pairs1,pairs2){ + var bishape = bi.shape, + bjshape = bj.shape; + + if(bi.aabbNeedsUpdate){ + bi.computeAABB(); + } + if(bj.aabbNeedsUpdate){ + bj.computeAABB(); + } + + if(bishape && bjshape){ + // Check AABB / AABB + if( !( bi.aabbmax.x < bj.aabbmin.x || + bi.aabbmax.y < bj.aabbmin.y || + bi.aabbmax.z < bj.aabbmin.z || + bi.aabbmin.x > bj.aabbmax.x || + bi.aabbmin.y > bj.aabbmax.y || + bi.aabbmin.z > bj.aabbmax.z ) ){ + pairs1.push(bi); + pairs2.push(bj); + } + } else { + // Particle without shape + if(!bishape && !bjshape){ + // No collisions between 2 particles + } else { + // particle vs AABB + var p = !bishape ? bi : bj; + var other = !bishape ? bj : bi; + + if(other.shape instanceof CANNON.Plane){ + //console.log(p.position.z+"<"+other.aabbmin.z+" = ",p.position.z < other.aabbmin.z); + } + + if( !( p.position.x < other.aabbmin.x || + p.position.y < other.aabbmin.y || + p.position.z < other.aabbmin.z || + p.position.x > other.aabbmax.x || + p.position.y > other.aabbmax.y || + p.position.z > other.aabbmax.z ) ){ + pairs1.push(bi); + pairs2.push(bj); + } + } + } +}; + +/** + * @method makePairsUnique + * @memberof CANNON.Broadphase + * @brief Removes duplicate pairs from the pair arrays. + * @param Array pairs1 + * @param Array pairs2 + */ +var Broadphase_makePairsUnique_temp = {}, + Broadphase_makePairsUnique_p1 = [], + Broadphase_makePairsUnique_p2 = []; +CANNON.Broadphase.prototype.makePairsUnique = function(pairs1,pairs2){ + var t = Broadphase_makePairsUnique_temp, + p1 = Broadphase_makePairsUnique_p1, + p2 = Broadphase_makePairsUnique_p2, + N = pairs1.length; + + for(var i=0; i!==N; i++){ + p1[i] = pairs1[i]; + p2[i] = pairs2[i]; + } + + pairs1.length = 0; + pairs2.length = 0; + + for(var i=0; i!==N; i++){ + var id1 = p1[i].id, + id2 = p2[i].id; + var idx = id1 < id2 ? id1+","+id2 : id2+","+id1; + t[idx] = i; + } + + for(var idx in t){ + var i = t[idx]; + pairs1.push(p1[i]); + pairs2.push(p2[i]); + delete t[idx]; + } +}; + + +/** + * @class CANNON.NaiveBroadphase + * @brief Naive broadphase implementation, used in lack of better ones. + * @description The naive broadphase looks at all possible pairs without restriction, therefore it has complexity N^2 (which is bad) + * @extends CANNON.Broadphase + */ +CANNON.NaiveBroadphase = function(){ + CANNON.Broadphase.apply(this); +}; +CANNON.NaiveBroadphase.prototype = new CANNON.Broadphase(); +CANNON.NaiveBroadphase.prototype.constructor = CANNON.NaiveBroadphase; + +/** + * @method collisionPairs + * @memberof CANNON.NaiveBroadphase + * @brief Get all the collision pairs in the physics world + * @param CANNON.World world + * @param Array pairs1 + * @param Array pairs2 + */ +CANNON.NaiveBroadphase.prototype.collisionPairs = function(world,pairs1,pairs2){ + var bodies = world.bodies, + n = bodies.length, + i,j,bi,bj; + + // Naive N^2 ftw! + for(i=0; i!==n; i++){ + for(j=0; j!==i; j++){ + + bi = bodies[i]; + bj = bodies[j]; + + if(!this.needBroadphaseCollision(bi,bj)){ + continue; + } + + this.intersectionTest(bi,bj,pairs1,pairs2); + } + } +}; + + +/** + * @class CANNON.GridBroadphase + * @brief Axis aligned uniform grid broadphase. + * @extends CANNON.Broadphase + * @todo Needs support for more than just planes and spheres. + * @param CANNON.Vec3 aabbMin + * @param CANNON.Vec3 aabbMax + * @param int nx Number of boxes along x + * @param int ny Number of boxes along y + * @param int nz Number of boxes along z + */ +CANNON.GridBroadphase = function(aabbMin,aabbMax,nx,ny,nz){ + CANNON.Broadphase.apply(this); + this.nx = nx || 10; + this.ny = ny || 10; + this.nz = nz || 10; + this.aabbMin = aabbMin || new CANNON.Vec3(100,100,100); + this.aabbMax = aabbMax || new CANNON.Vec3(-100,-100,-100); + this.bins = []; +}; +CANNON.GridBroadphase.prototype = new CANNON.Broadphase(); +CANNON.GridBroadphase.prototype.constructor = CANNON.GridBroadphase; + +/** + * @method collisionPairs + * @memberof CANNON.GridBroadphase + * @brief Get all the collision pairs in the physics world + * @param CANNON.World world + * @param Array pairs1 + * @param Array pairs2 + */ +var GridBroadphase_collisionPairs_d = new CANNON.Vec3(); +var GridBroadphase_collisionPairs_binPos = new CANNON.Vec3(); +CANNON.GridBroadphase.prototype.collisionPairs = function(world,pairs1,pairs2){ + var N = world.numObjects(), + bodies = world.bodies; + + var max = this.aabbMax, + min = this.aabbMin, + nx = this.nx, + ny = this.ny, + nz = this.nz; + + var xmax = max.x, + ymax = max.y, + zmax = max.z, + xmin = min.x, + ymin = min.y, + zmin = min.z; + + var xmult = nx / (xmax-xmin), + ymult = ny / (ymax-ymin), + zmult = nz / (zmax-zmin); + + var binsizeX = (xmax - xmin) / nx, + binsizeY = (ymax - ymin) / ny, + binsizeZ = (zmax - zmin) / nz; + + var types = CANNON.Shape.types; + var SPHERE = types.SPHERE, + PLANE = types.PLANE, + BOX = types.BOX, + COMPOUND = types.COMPOUND, + CONVEXPOLYHEDRON = types.CONVEXPOLYHEDRON; + + var bins=this.bins, + Nbins=nx*ny*nz; + + // Reset bins + for(var i=bins.length-1; i!==Nbins; i++){ + bins.push([]); + } + for(var i=0; i!==Nbins; i++){ + bins[i].length = 0; + } + + var floor = Math.floor; + + // Put all bodies into the bins + for(var i=0; i!==N; i++){ + var bi = bodies[i]; + var si = bi.shape; + + switch(si.type){ + case SPHERE: + // Put in bin + // check if overlap with other bins + var x = bi.position.x, + y = bi.position.y, + z = bi.position.z; + var r = si.radius; + + var xi1 = floor(xmult * (x-r - xmin)), + yi1 = floor(ymult * (y-r - ymin)), + zi1 = floor(zmult * (z-r - zmin)), + xi2 = floor(xmult * (x+r - xmin)), + yi2 = floor(ymult * (y+r - ymin)), + zi2 = floor(zmult * (z+r - zmin)); + + for(var j=xi1; j!==xi2+1; j++){ + for(var k=yi1; k!==yi2+1; k++){ + for(var l=zi1; l!==zi2+1; l++){ + var xi = j, + yi = k, + zi = l; + var idx = xi * ( ny - 1 ) * ( nz - 1 ) + yi * ( nz - 1 ) + zi; + if(idx >= 0 && idx < Nbins){ + bins[ idx ].push( bi ); + } + } + } + } + break; + + case PLANE: + // Put in all bins for now + // @todo put only in bins that are actually intersecting the plane + var d = GridBroadphase_collisionPairs_d; + var binPos = GridBroadphase_collisionPairs_binPos; + var binRadiusSquared = (binsizeX*binsizeX + binsizeY*binsizeY + binsizeZ*binsizeZ) * 0.25; + + var planeNormal = si.worldNormal; + if(si.worldNormalNeedsUpdate){ + si.computeWorldNormal(bi.quaternion); + } + + for(var j=0; j!==nx; j++){ + for(var k=0; k!==ny; k++){ + for(var l=0; l!==nz; l++){ + var xi = j, + yi = k, + zi = l; + + binPos.set(xi*binsizeX+xmin, yi*binsizeY+ymin, zi*binsizeZ+zmin); + binPos.vsub(bi.position, d); + + if(d.dot(planeNormal) < binRadiusSquared){ + var idx = xi * ( ny - 1 ) * ( nz - 1 ) + yi * ( nz - 1 ) + zi; + bins[ idx ].push( bi ); + } + } + } + } + break; + + default: + console.warn("Shape "+si.type+" not supported in GridBroadphase!"); + break; + } + } + + // Check each bin + for(var i=0; i!==Nbins; i++){ + var bin = bins[i]; + + // Do N^2 broadphase inside + for(var j=0, NbodiesInBin=bin.length; j!==NbodiesInBin; j++){ + var bi = bin[j]; + + for(var k=0; k!==j; k++){ + var bj = bin[k]; + if(this.needBroadphaseCollision(bi,bj)){ + this.intersectionTest(bi,bj,pairs1,pairs2); + } + } + } + } + + this.makePairsUnique(pairs1,pairs2); +}; + + +/** + * @class CANNON.Solver + * @brief Constraint equation solver base class. + * @author schteppe / https://github.com/schteppe + */ +CANNON.Solver = function(){ + // All equations to be solved + this.equations = []; +}; + +// Should be implemented in subclasses! +CANNON.Solver.prototype.solve = function(dt,world){ + // Should return the number of iterations done! + return 0; +}; + +CANNON.Solver.prototype.addEquation = function(eq){ + this.equations.push(eq); +}; + +CANNON.Solver.prototype.removeEquation = function(eq){ + var eqs = this.equations; + var i = eqs.indexOf(eq); + if(i !== -1){ + eqs.splice(i,1); + } +}; + +CANNON.Solver.prototype.removeAllEquations = function(){ + this.equations.length = 0; +}; + + + +/** + * @class CANNON.Solver + * @brief Constraint equation Gauss-Seidel solver. + * @todo The spook parameters should be specified for each constraint, not globally. + * @author schteppe / https://github.com/schteppe + * @see https://www8.cs.umu.se/kurser/5DV058/VT09/lectures/spooknotes.pdf + * @extends CANNON.Solver + */ +CANNON.GSSolver = function(){ + CANNON.Solver.call(this); + + /** + * @property int iterations + * @brief The number of solver iterations determines quality of the constraints in the world. The more iterations, the more correct simulation. More iterations need more computations though. If you have a large gravity force in your world, you will need more iterations. + * @todo write more about solver and iterations in the wiki + * @memberof CANNON.GSSolver + */ + this.iterations = 10; + + /** + * When tolerance is reached, the system is assumed to be converged. + * @property float tolerance + */ + this.tolerance = 0; +}; +CANNON.GSSolver.prototype = new CANNON.Solver(); + +var GSSolver_solve_lambda = []; // Just temporary number holders that we want to reuse each solve. +var GSSolver_solve_invCs = []; +var GSSolver_solve_Bs = []; +CANNON.GSSolver.prototype.solve = function(dt,world){ + var d = this.d, + ks = this.k, + iter = 0, + maxIter = this.iterations, + tolSquared = this.tolerance*this.tolerance, + a = this.a, + b = this.b, + equations = this.equations, + Neq = equations.length, + bodies = world.bodies, + Nbodies = bodies.length, + h = dt, + q, B, invC, deltalambda, deltalambdaTot, GWlambda, lambdaj; + + // Things that does not change during iteration can be computed once + var invCs = GSSolver_solve_invCs, + Bs = GSSolver_solve_Bs, + lambda = GSSolver_solve_lambda; + invCs.length = 0; + Bs.length = 0; + lambda.length = 0; + for(var i=0; i!==Neq; i++){ + var c = equations[i]; + if(c.spookParamsNeedsUpdate){ + c.updateSpookParams(h); + c.spookParamsNeedsUpdate = false; + } + lambda[i] = 0.0; + Bs[i] = c.computeB(h); + invCs[i] = 1.0 / c.computeC(); + } + + + if(Neq !== 0){ + + // Reset vlambda + for(var i=0; i!==Nbodies; i++){ + var b=bodies[i], + vlambda=b.vlambda, + wlambda=b.wlambda; + vlambda.set(0,0,0); + if(wlambda){ + wlambda.set(0,0,0); + } + } + + // Iterate over equations + for(iter=0; iter!==maxIter; iter++){ + + // Accumulate the total error for each iteration. + deltalambdaTot = 0.0; + + for(var j=0; j!==Neq; j++){ + + var c = equations[j]; + + // Compute iteration + B = Bs[j]; + invC = invCs[j]; + lambdaj = lambda[j]; + GWlambda = c.computeGWlambda(); + deltalambda = invC * ( B - GWlambda - c.eps * lambdaj ); + + // Clamp if we are not within the min/max interval + if(lambdaj + deltalambda < c.minForce){ + deltalambda = c.minForce - lambdaj; + } else if(lambdaj + deltalambda > c.maxForce){ + deltalambda = c.maxForce - lambdaj; + } + lambda[j] += deltalambda; + + deltalambdaTot += deltalambda > 0.0 ? deltalambda : -deltalambda; // abs(deltalambda) + + c.addToWlambda(deltalambda); + } + + // If the total error is small enough - stop iterate + if(deltalambdaTot*deltalambdaTot < tolSquared){ + break; + } + } + + // Add result to velocity + for(var i=0; i!==Nbodies; i++){ + var b=bodies[i], + v=b.velocity, + w=b.angularVelocity; + v.vadd(b.vlambda, v); + if(w){ + w.vadd(b.wlambda, w); + } + } + } + + return iter; +}; + + +CANNON.SplitSolver = function(subsolver){ + CANNON.Solver.call(this); + this.subsolver = subsolver; +}; +CANNON.SplitSolver.prototype = new CANNON.Solver(); + +// Returns the number of subsystems +var SplitSolver_solve_nodes = []; // All allocated node objects +var SplitSolver_solve_eqs = []; // Temp array +var SplitSolver_solve_bds = []; // Temp array +var SplitSolver_solve_dummyWorld = {bodies:null}; // Temp object +CANNON.SplitSolver.prototype.solve = function(dt,world){ + var nodes=SplitSolver_solve_nodes, + bodies=world.bodies, + equations=this.equations, + Neq=equations.length, + Nbodies=bodies.length, + subsolver=this.subsolver; + // Create needed nodes, reuse if possible + for(var i=nodes.length; i!==Nbodies; i++){ + nodes.push({ body:bodies[i], children:[], eqs:[], visited:false }); + } + + // Reset node values + for(var i=0; i!==Nbodies; i++){ + var node = nodes[i]; + node.body = bodies[i]; + node.children.length = 0; + node.eqs.length = 0; + node.visited = false; + } + for(var k=0; k!==Neq; k++){ + var eq=equations[k], + i=bodies.indexOf(eq.bi), + j=bodies.indexOf(eq.bj), + ni=nodes[i], + nj=nodes[j]; + ni.children.push(nj); + ni.eqs.push(eq); + nj.children.push(ni); + nj.eqs.push(eq); + } + + var STATIC = CANNON.Body.STATIC; + function getUnvisitedNode(nodes){ + var Nnodes = nodes.length; + for(var i=0; i!==Nnodes; i++){ + var node = nodes[i]; + if(!node.visited && !(node.body.motionstate & STATIC)){ + return node; + } + } + return false; + } + + function bfs(root,visitFunc){ + var queue = []; + queue.push(root); + root.visited = true; + visitFunc(root); + while(queue.length) { + var node = queue.pop(); + // Loop over unvisited child nodes + var child; + while((child = getUnvisitedNode(node.children))) { + child.visited = true; + visitFunc(child); + queue.push(child); + } + } + } + + var child, n=0, eqs=SplitSolver_solve_eqs, bds=SplitSolver_solve_bds; + function visitFunc(node){ + bds.push(node.body); + var Neqs = node.eqs.length; + for(var i=0; i!==Neqs; i++){ + var eq = node.eqs[i]; + if(eqs.indexOf(eq) === -1){ + eqs.push(eq); + } + } + } + var dummyWorld = SplitSolver_solve_dummyWorld; + while((child = getUnvisitedNode(nodes))){ + eqs.length = 0; + bds.length = 0; + bfs(child,visitFunc); + + var Neqs = eqs.length; + for(var i=0; i!==Neqs; i++){ + subsolver.addEquation(eqs[i]); + } + + dummyWorld.bodies = bds; + var iter = subsolver.solve(dt,dummyWorld); + subsolver.removeAllEquations(); + n++; + } + + return n; +}; + + +/** + * @class CANNON.Material + * @brief Defines a physics material. + * @param string name + * @author schteppe + */ +CANNON.Material = function(name){ + /** + * @property string name + * @memberof CANNON.Material + */ + this.name = name; + this.id = -1; +}; + + + +/** + * @class CANNON.ContactMaterial + * @brief Defines what happens when two materials meet. + * @param CANNON.Material m1 + * @param CANNON.Material m2 + * @param float friction + * @param float restitution + * @todo Contact solving parameters here too? + */ +CANNON.ContactMaterial = function(m1, m2, friction, restitution){ + + /// Contact material index in the world, -1 until added to the world + this.id = -1; + + /// The two materials participating in the contact + this.materials = [m1,m2]; + + /// Kinetic friction + this.friction = friction!==undefined ? Number(friction) : 0.3; + + /// Restitution + this.restitution = restitution !== undefined ? Number(restitution) : 0.3; + + // Parameters to pass to the constraint when it is created + this.contactEquationStiffness = 1e7; + this.contactEquationRegularizationTime = 3; + this.frictionEquationStiffness = 1e7; + this.frictionEquationRegularizationTime = 3; +}; + + + +/** + * @class CANNON.World + * @brief The physics world + */ +CANNON.World = function(){ + + CANNON.EventTarget.apply(this); + + /** + * @property bool allowSleep + * @brief Makes bodies go to sleep when they've been inactive + * @memberof CANNON.World + */ + this.allowSleep = false; + + /** + * @property Array contacts + * @brief All the current contacts (instances of CANNON.ContactEquation) in the world. + * @memberof CANNON.World + */ + this.contacts = []; + this.frictionEquations = []; + + /** + * @property int quatNormalizeSkip + * @brief How often to normalize quaternions. Set to 0 for every step, 1 for every second etc.. A larger value increases performance. If bodies tend to explode, set to a smaller value (zero to be sure nothing can go wrong). + * @memberof CANNON.World + */ + this.quatNormalizeSkip = 0; + + /** + * @property bool quatNormalizeFast + * @brief Set to true to use fast quaternion normalization. It is often enough accurate to use. If bodies tend to explode, set to false. + * @memberof CANNON.World + * @see CANNON.Quaternion.normalizeFast + * @see CANNON.Quaternion.normalize + */ + this.quatNormalizeFast = false; + + /** + * @property float time + * @brief The wall-clock time since simulation start + * @memberof CANNON.World + */ + this.time = 0.0; + + /** + * @property int stepnumber + * @brief Number of timesteps taken since start + * @memberof CANNON.World + */ + this.stepnumber = 0; + + /// Default and last timestep sizes + this.default_dt = 1/60; + this.last_dt = this.default_dt; + + this.nextId = 0; + /** + * @property CANNON.Vec3 gravity + * @memberof CANNON.World + */ + this.gravity = new CANNON.Vec3(); + + /** + * @property CANNON.Broadphase broadphase + * @memberof CANNON.World + */ + this.broadphase = null; + + /** + * @property Array bodies + * @memberof CANNON.World + */ + this.bodies = []; + + var th = this; + + /** + * @property CANNON.Solver solver + * @memberof CANNON.World + */ + this.solver = new CANNON.GSSolver(); + + /** + * @property Array constraints + * @memberof CANNON.World + */ + this.constraints = []; + + /** + * @property CANNON.ContactGenerator contactgen + * @memberof CANNON.World + */ + this.contactgen = new CANNON.ContactGenerator(); + + /** @property Collision "matrix", size (Nbodies * (Nbodies.length + 1))/2 + * @brief It's actually a triangular-shaped array of whether two bodies are touching this step, for reference next step + * @memberof CANNON.World + */ + this.collisionMatrix = []; + /** @property Collision "matrix", size (Nbodies * (Nbodies.length + 1))/2 + * @brief collisionMatrix from the previous step + * @memberof CANNON.World + */ + this.collisionMatrixPrevious = []; + + /** + * @property Array materials + * @memberof CANNON.World + */ + this.materials = []; // References to all added materials + + /** + * @property Array contactmaterials + * @memberof CANNON.World + */ + this.contactmaterials = []; // All added contact materials + + this.mats2cmat = []; // Hash: (mat1_id, mat2_id) => contactmat_id + + this.defaultMaterial = new CANNON.Material("default"); + + /** + * @property CANNON.ContactMaterial defaultContactMaterial + * @brief This contact material is used if no suitable contactmaterial is found for a contact. + * @memberof CANNON.World + */ + this.defaultContactMaterial = new CANNON.ContactMaterial(this.defaultMaterial,this.defaultMaterial,0.3,0.0); + + /** + * @property bool doProfiling + * @memberof CANNON.World + */ + this.doProfiling = false; + + /** + * @property Object profile + * @memberof CANNON.World + */ + this.profile = { + solve:0, + makeContactConstraints:0, + broadphase:0, + integrate:0, + nearphase:0, + }; + + /** + * @property Array subystems + * @memberof CANNON.World + */ + this.subsystems = []; +}; + +/** + * @method getContactMaterial + * @memberof CANNON.World + * @brief Get the contact material between materials m1 and m2 + * @param CANNON.Material m1 + * @param CANNON.Material m2 + * @return CANNON.Contactmaterial The contact material if it was found. + */ +CANNON.World.prototype.getContactMaterial = function(m1,m2){ + if((m1 instanceof CANNON.Material) && (m2 instanceof CANNON.Material)){ + + var i = m1.id; + var j = m2.id; + + if(i i){ + var temp = j; + j = i; + i = temp; + } + // Reuse i for the index + i = (i*(i + 1)>>1) + j-1; + return (typeof(current)==="undefined" || current) ? this.collisionMatrix[i] : this.collisionMatrixPrevious[i]; +}; + +CANNON.World.prototype.collisionMatrixSet = function(i,j,value,current){ + if(j > i){ + var temp = j; + j = i; + i = temp; + } + // Reuse i for the index + i = (i*(i + 1)>>1) + j-1; + if (typeof(current)==="undefined" || current) { + this.collisionMatrix[i] = value; + } + else { + this.collisionMatrixPrevious[i] = value; + } +}; + +// transfer old contact state data to T-1 +CANNON.World.prototype.collisionMatrixTick = function(){ + var temp = this.collisionMatrixPrevious; + this.collisionMatrixPrevious = this.collisionMatrix; + this.collisionMatrix = temp; + for (var i=0,l=this.collisionMatrix.length;i!==l;i++) { + this.collisionMatrix[i]=0; + } +}; + +/** + * @method add + * @memberof CANNON.World + * @brief Add a rigid body to the simulation. + * @param CANNON.Body body + * @todo If the simulation has not yet started, why recrete and copy arrays for each body? Accumulate in dynamic arrays in this case. + * @todo Adding an array of bodies should be possible. This would save some loops too + */ +CANNON.World.prototype.add = function(body){ + body.id = this.id(); + body.index = this.bodies.length; + this.bodies.push(body); + body.world = this; + body.position.copy(body.initPosition); + body.velocity.copy(body.initVelocity); + body.timeLastSleepy = this.time; + if(body instanceof CANNON.RigidBody){ + body.angularVelocity.copy(body.initAngularVelocity); + body.quaternion.copy(body.initQuaternion); + } + + var n = this.numObjects(); + this.collisionMatrix.length = n*(n-1)>>1; +}; + +/** + * @method addConstraint + * @memberof CANNON.World + * @brief Add a constraint to the simulation. + * @param CANNON.Constraint c + */ +CANNON.World.prototype.addConstraint = function(c){ + this.constraints.push(c); + c.id = this.id(); +}; + +/** + * @method removeConstraint + * @memberof CANNON.World + * @brief Removes a constraint + * @param CANNON.Constraint c + */ +CANNON.World.prototype.removeConstraint = function(c){ + var idx = this.constraints.indexOf(c); + if(idx!==-1){ + this.constraints.splice(idx,1); + } +}; + +/** + * @method id + * @memberof CANNON.World + * @brief Generate a new unique integer identifyer + * @return int + */ +CANNON.World.prototype.id = function(){ + return this.nextId++; +}; + +/** + * @method remove + * @memberof CANNON.World + * @brief Remove a rigid body from the simulation. + * @param CANNON.Body body + */ +CANNON.World.prototype.remove = function(body){ + body.world = null; + var n = this.numObjects()-1; + var bodies = this.bodies; + bodies.splice(body.index, 1); + for(var i=body.index; i>1; +}; + +/** + * @method addMaterial + * @memberof CANNON.World + * @brief Adds a material to the World. A material can only be added once, it's added more times then nothing will happen. + * @param CANNON.Material m + */ +CANNON.World.prototype.addMaterial = function(m){ + if(m.id === -1){ + var n = this.materials.length; + this.materials.push(m); + m.id = this.materials.length-1; + + // Increase size of collision matrix to (n+1)*(n+1)=n*n+2*n+1 elements, it was n*n last. + for(var i=0; i!==2*n+1; i++){ + this.mats2cmat.push(-1); + } + } +}; + +/** + * @method addContactMaterial + * @memberof CANNON.World + * @brief Adds a contact material to the World + * @param CANNON.ContactMaterial cmat + */ +CANNON.World.prototype.addContactMaterial = function(cmat) { + + // Add materials if they aren't already added + this.addMaterial(cmat.materials[0]); + this.addMaterial(cmat.materials[1]); + + // Save (material1,material2) -> (contact material) reference for easy access later + // Make sure i>j, ie upper right matrix + var i,j; + if(cmat.materials[0].id > cmat.materials[1].id){ + i = cmat.materials[0].id; + j = cmat.materials[1].id; + } else { + j = cmat.materials[0].id; + i = cmat.materials[1].id; + } + + // Add contact material + this.contactmaterials.push(cmat); + cmat.id = this.contactmaterials.length-1; + + // Add current contact material to the material table + this.mats2cmat[i+this.materials.length*j] = cmat.id; // index of the contact material +}; + +CANNON.World.prototype._now = function(){ + if(window.performance.webkitNow){ + return window.performance.webkitNow(); + } else { + return Date.now(); + } +}; + +/** + * @method step + * @memberof CANNON.World + * @brief Step the simulation + * @param float dt + */ +var World_step_postStepEvent = {type:"postStep"}, // Reusable event objects to save memory + World_step_preStepEvent = {type:"preStep"}, + World_step_collideEvent = {type:"collide", "with":null, contact:null }, + World_step_oldContacts = [], // Pools for unused objects + World_step_frictionEquationPool = [], + World_step_p1 = [], // Reusable arrays for collision pairs + World_step_p2 = [], + World_step_gvec = new CANNON.Vec3(), // Temporary vectors and quats + World_step_vi = new CANNON.Vec3(), + World_step_vj = new CANNON.Vec3(), + World_step_wi = new CANNON.Vec3(), + World_step_wj = new CANNON.Vec3(), + World_step_t1 = new CANNON.Vec3(), + World_step_t2 = new CANNON.Vec3(), + World_step_rixn = new CANNON.Vec3(), + World_step_rjxn = new CANNON.Vec3(), + World_step_step_q = new CANNON.Quaternion(), + World_step_step_w = new CANNON.Quaternion(), + World_step_step_wq = new CANNON.Quaternion(); +CANNON.World.prototype.step = function(dt){ + var world = this, + that = this, + contacts = this.contacts, + p1 = World_step_p1, + p2 = World_step_p2, + N = this.numObjects(), + bodies = this.bodies, + solver = this.solver, + gravity = this.gravity, + doProfiling = this.doProfiling, + profile = this.profile, + DYNAMIC = CANNON.Body.DYNAMIC, + now = this._now, + profilingStart, + constraints = this.constraints, + FrictionEquation = CANNON.FrictionEquation, + frictionEquationPool = World_step_frictionEquationPool, + gnorm = gravity.norm(), + gx = gravity.x, + gy = gravity.y, + gz = gravity.z, + i=0; + + + if(doProfiling){ + profilingStart = now(); + } + + if(dt===undefined){ + dt = this.last_dt || this.default_dt; + } + + // Add gravity to all objects + for(i=0; i!==N; i++){ + var bi = bodies[i]; + if(bi.motionstate & DYNAMIC){ // Only for dynamic bodies + var f = bi.force, m = bi.mass; + f.x += m*gx; + f.y += m*gy; + f.z += m*gz; + } + } + + // Update subsystems + for(var i=0, Nsubsystems=this.subsystems.length; i!==Nsubsystems; i++){ + this.subsystems[i].update(); + } + + // 1. Collision detection + if(doProfiling){ profilingStart = now(); } + p1.length = 0; // Clean up pair arrays from last step + p2.length = 0; + this.broadphase.collisionPairs(this,p1,p2); + if(doProfiling){ profile.broadphase = now() - profilingStart; } + + this.collisionMatrixTick(); + + // Generate contacts + if(doProfiling){ profilingStart = now(); } + var oldcontacts = World_step_oldContacts; + var NoldContacts = contacts.length; + + for(i=0; i!==NoldContacts; i++){ + oldcontacts.push(contacts[i]); + } + contacts.length = 0; + + this.contactgen.getContacts(p1,p2, + this, + contacts, + oldcontacts // To be reused + ); + if(doProfiling){ + profile.nearphase = now() - profilingStart; + } + + // Loop over all collisions + if(doProfiling){ + profilingStart = now(); + } + var ncontacts = contacts.length; + + // Transfer FrictionEquation from current list to the pool for reuse + var NoldFrictionEquations = this.frictionEquations.length; + for(i=0; i!==NoldFrictionEquations; i++){ + frictionEquationPool.push(this.frictionEquations[i]); + } + this.frictionEquations.length = 0; + + for(var k=0; k!==ncontacts; k++){ + + // Current contact + var c = contacts[k]; + + // Get current collision indeces + var bi=c.bi, bj=c.bj; + + // Resolve indeces + var i = bodies.indexOf(bi), j = bodies.indexOf(bj); + + // Get collision properties + var cm = this.getContactMaterial(bi.material,bj.material) || this.defaultContactMaterial; + var mu = cm.friction; + var e = cm.restitution; + + // g = ( xj + rj - xi - ri ) .dot ( ni ) + var gvec = World_step_gvec; + gvec.set(bj.position.x + c.rj.x - bi.position.x - c.ri.x, + bj.position.y + c.rj.y - bi.position.y - c.ri.y, + bj.position.z + c.rj.z - bi.position.z - c.ri.z); + var g = gvec.dot(c.ni); // Gap, negative if penetration + + // Action if penetration + if(g<0.0){ + c.restitution = cm.restitution; + c.penetration = g; + c.stiffness = cm.contactEquationStiffness; + c.regularizationTime = cm.contactEquationRegularizationTime; + + solver.addEquation(c); + + // Add friction constraint equation + if(mu > 0){ + + // Create 2 tangent equations + var mug = mu*gnorm; + var reducedMass = (bi.invMass + bj.invMass); + if(reducedMass > 0){ + reducedMass = 1/reducedMass; + } + var pool = frictionEquationPool; + var c1 = pool.length ? pool.pop() : new FrictionEquation(bi,bj,mug*reducedMass); + var c2 = pool.length ? pool.pop() : new FrictionEquation(bi,bj,mug*reducedMass); + this.frictionEquations.push(c1); + this.frictionEquations.push(c2); + + c1.bi = c2.bi = bi; + c1.bj = c2.bj = bj; + c1.minForce = c2.minForce = -mug*reducedMass; + c1.maxForce = c2.maxForce = mug*reducedMass; + + // Copy over the relative vectors + c.ri.copy(c1.ri); + c.rj.copy(c1.rj); + c.ri.copy(c2.ri); + c.rj.copy(c2.rj); + + // Construct tangents + c.ni.tangents(c1.t,c2.t); + + // Add equations to solver + solver.addEquation(c1); + solver.addEquation(c2); + } + + // Now we know that i and j are in contact. Set collision matrix state + this.collisionMatrixSet(i,j,1,true); + + if(this.collisionMatrixGet(i,j,true)!==this.collisionMatrixGet(i,j,false)){ + // First contact! + // We reuse the collideEvent object, otherwise we will end up creating new objects for each new contact, even if there's no event listener attached. + World_step_collideEvent.with = bj; + World_step_collideEvent.contact = c; + bi.dispatchEvent(World_step_collideEvent); + + World_step_collideEvent.with = bi; + bj.dispatchEvent(World_step_collideEvent); + + bi.wakeUp(); + bj.wakeUp(); + } + } + } + if(doProfiling){ + profile.makeContactConstraints = now() - profilingStart; + } + + if(doProfiling){ + profilingStart = now(); + } + + // Add user-added constraints + var Nconstraints = constraints.length; + for(i=0; i!==Nconstraints; i++){ + var c = constraints[i]; + c.update(); + for(var j=0, Neq=c.equations.length; j!==Neq; j++){ + var eq = c.equations[j]; + solver.addEquation(eq); + } + } + + // Solve the constrained system + solver.solve(dt,this); + + if(doProfiling){ + profile.solve = now() - profilingStart; + } + + // Remove all contacts from solver + solver.removeAllEquations(); + + // Apply damping, see http://code.google.com/p/bullet/issues/detail?id=74 for details + var pow = Math.pow; + for(i=0; i!==N; i++){ + var bi = bodies[i]; + if(bi.motionstate & DYNAMIC){ // Only for dynamic bodies + var ld = pow(1.0 - bi.linearDamping,dt); + var v = bi.velocity; + v.mult(ld,v); + var av = bi.angularVelocity; + if(av){ + var ad = pow(1.0 - bi.angularDamping,dt); + av.mult(ad,av); + } + } + } + + this.dispatchEvent(World_step_postStepEvent); + + // Invoke pre-step callbacks + for(i=0; i!==N; i++){ + var bi = bodies[i]; + if(bi.preStep){ + bi.preStep.call(bi); + } + } + + // Leap frog + // vnew = v + h*f/m + // xnew = x + h*vnew + if(doProfiling){ + profilingStart = now(); + } + var q = World_step_step_q; + var w = World_step_step_w; + var wq = World_step_step_wq; + var stepnumber = this.stepnumber; + var DYNAMIC_OR_KINEMATIC = CANNON.Body.DYNAMIC | CANNON.Body.KINEMATIC; + var quatNormalize = stepnumber % (this.quatNormalizeSkip+1) === 0; + var quatNormalizeFast = this.quatNormalizeFast; + var half_dt = dt * 0.5; + var PLANE = CANNON.Shape.types.PLANE, + CONVEX = CANNON.Shape.types.CONVEXPOLYHEDRON; + + for(i=0; i!==N; i++){ + var b = bodies[i], + s = b.shape, + force = b.force, + tau = b.tau; + if((b.motionstate & DYNAMIC_OR_KINEMATIC)){ // Only for dynamic + var velo = b.velocity, + angularVelo = b.angularVelocity, + pos = b.position, + quat = b.quaternion, + invMass = b.invMass, + invInertia = b.invInertia; + velo.x += force.x * invMass * dt; + velo.y += force.y * invMass * dt; + velo.z += force.z * invMass * dt; + + if(b.angularVelocity){ + angularVelo.x += tau.x * invInertia.x * dt; + angularVelo.y += tau.y * invInertia.y * dt; + angularVelo.z += tau.z * invInertia.z * dt; + } + + // Use new velocity - leap frog + if(!b.isSleeping()){ + pos.x += velo.x * dt; + pos.y += velo.y * dt; + pos.z += velo.z * dt; + + if(b.angularVelocity){ + w.set(angularVelo.x, angularVelo.y, angularVelo.z, 0); + w.mult(quat,wq); + quat.x += half_dt * wq.x; + quat.y += half_dt * wq.y; + quat.z += half_dt * wq.z; + quat.w += half_dt * wq.w; + if(quatNormalize){ + if(quatNormalizeFast){ + quat.normalizeFast(); + } else { + quat.normalize(); + } + } + } + + if(b.aabbmin){ + b.aabbNeedsUpdate = true; + } + } + + if(s){ + switch(s.type){ + case PLANE: + s.worldNormalNeedsUpdate = true; + break; + case CONVEX: + s.worldFaceNormalsNeedsUpdate = true; + s.worldVerticesNeedsUpdate = true; + break; + } + } + } + b.force.set(0,0,0); + if(b.tau){ + b.tau.set(0,0,0); + } + } + + if(doProfiling){ + profile.integrate = now() - profilingStart; + } + + // Update world time + this.time += dt; + this.stepnumber += 1; + + this.dispatchEvent(World_step_postStepEvent); + + // Invoke post-step callbacks + for(i=0; i!==N; i++){ + var bi = bodies[i]; + var postStep = bi.postStep; + if(postStep){ + postStep.call(bi); + } + } + + // Update world inertias + // @todo should swap autoUpdate mechanism for .xxxNeedsUpdate + for(i=0; i!==N; i++){ + var b = bodies[i]; + if(b.inertiaWorldAutoUpdate){ + b.quaternion.vmult(b.inertia,b.inertiaWorld); + } + if(b.invInertiaWorldAutoUpdate){ + b.quaternion.vmult(b.invInertia,b.invInertiaWorld); + } + } + + // Sleeping update + if(this.allowSleep){ + for(i=0; i!==N; i++){ + bodies[i].sleepTick(this.time); + } + } +}; + + +/** + * @class CANNON.ContactGenerator + * @brief Helper class for the World. Generates ContactEquations. + * @todo Sphere-ConvexPolyhedron contacts + * @todo Contact reduction + */ +CANNON.ContactGenerator = function(){ + + /** + * @property bool contactReduction + * @memberof CANNON.ContactGenerator + * @brief Turns on or off contact reduction. Can be handy to turn off when debugging new collision types. + */ + this.contactReduction = false; + + // Contact point objects that can be reused + var contactPointPool = []; + + var v3pool = new CANNON.Vec3Pool(); + + /* + * Make a contact object. + * @return object + * @todo reuse old contact point objects + */ + function makeResult(bi,bj){ + if(contactPointPool.length){ + var c = contactPointPool.pop(); + c.bi = bi; + c.bj = bj; + return c; + } else { + return new CANNON.ContactEquation(bi,bj); + } + } + + /* + * Swaps the body references in the contact + * @param object r + */ + function swapResult(r){ + var temp; + temp = r.ri; + r.ri = r.rj; + r.rj = temp; + r.ni.negate(r.ni); + temp = r.bi; + r.bi = r.bj; + r.bj = temp; + } + + function sphereSphere(result,si,sj,xi,xj,qi,qj,bi,bj){ + // We will have only one contact in this case + var r = makeResult(bi,bj); + + // Contact normal + bj.position.vsub(xi, r.ni); + r.ni.normalize(); + + // Contact point locations + r.ni.copy(r.ri); + r.ni.copy(r.rj); + r.ri.mult(si.radius, r.ri); + r.rj.mult(-sj.radius, r.rj); + result.push(r); + } + + var point_on_plane_to_sphere = new CANNON.Vec3(); + var plane_to_sphere_ortho = new CANNON.Vec3(); + function spherePlane(result,si,sj,xi,xj,qi,qj,bi,bj){ + // We will have one contact in this case + var r = makeResult(bi,bj); + + // Contact normal + r.ni.set(0,0,1); + qj.vmult(r.ni,r.ni); + r.ni.negate(r.ni); // body i is the sphere, flip normal + r.ni.normalize(); + + // Vector from sphere center to contact point + r.ni.mult(si.radius,r.ri); + + // Project down sphere on plane + xi.vsub(xj,point_on_plane_to_sphere); + r.ni.mult(r.ni.dot(point_on_plane_to_sphere),plane_to_sphere_ortho); + point_on_plane_to_sphere.vsub(plane_to_sphere_ortho,r.rj); // The sphere position projected to plane + if(plane_to_sphere_ortho.norm2() <= si.radius*si.radius){ + result.push(r); + } + } + + // See http://bulletphysics.com/Bullet/BulletFull/SphereTriangleDetector_8cpp_source.html + var pointInPolygon_edge = new CANNON.Vec3(); + var pointInPolygon_edge_x_normal = new CANNON.Vec3(); + var pointInPolygon_vtp = new CANNON.Vec3(); + function pointInPolygon(verts, normal, p){ + var positiveResult = null; + var N = verts.length; + for(var i=0; i!==N; i++){ + var v = verts[i]; + + // Get edge to the next vertex + var edge = pointInPolygon_edge; + verts[(i+1) % (N)].vsub(v,edge); + + // Get cross product between polygon normal and the edge + var edge_x_normal = pointInPolygon_edge_x_normal; + //var edge_x_normal = new CANNON.Vec3(); + edge.cross(normal,edge_x_normal); + + // Get vector between point and current vertex + var vertex_to_p = pointInPolygon_vtp; + p.vsub(v,vertex_to_p); + + // This dot product determines which side of the edge the point is + var r = edge_x_normal.dot(vertex_to_p); + + // If all such dot products have same sign, we are inside the polygon. + if(positiveResult===null || (r>0 && positiveResult===true) || (r<=0 && positiveResult===false)){ + if(positiveResult===null){ + positiveResult = r>0; + } + continue; + } else { + return false; // Encountered some other sign. Exit. + } + } + + // If we got here, all dot products were of the same sign. + return true; + } + + var box_to_sphere = new CANNON.Vec3(); + var sphereBox_ns = new CANNON.Vec3(); + var sphereBox_ns1 = new CANNON.Vec3(); + var sphereBox_ns2 = new CANNON.Vec3(); + var sphereBox_sides = [new CANNON.Vec3(),new CANNON.Vec3(),new CANNON.Vec3(),new CANNON.Vec3(),new CANNON.Vec3(),new CANNON.Vec3()]; + var sphereBox_sphere_to_corner = new CANNON.Vec3(); + var sphereBox_side_ns = new CANNON.Vec3(); + var sphereBox_side_ns1 = new CANNON.Vec3(); + var sphereBox_side_ns2 = new CANNON.Vec3(); + function sphereBox(result,si,sj,xi,xj,qi,qj,bi,bj){ + // we refer to the box as body j + var sides = sphereBox_sides; + xi.vsub(xj,box_to_sphere); + sj.getSideNormals(sides,qj); + var R = si.radius; + var penetrating_sides = []; + + // Check side (plane) intersections + var found = false; + + // Store the resulting side penetration info + var side_ns = sphereBox_side_ns; + var side_ns1 = sphereBox_side_ns1; + var side_ns2 = sphereBox_side_ns2; + var side_h = null; + var side_penetrations = 0; + var side_dot1 = 0; + var side_dot2 = 0; + var side_distance = null; + for(var idx=0,nsides=sides.length; idx!==nsides && found===false; idx++){ + // Get the plane side normal (ns) + var ns = sphereBox_ns; + sides[idx].copy(ns); + + var h = ns.norm(); + ns.normalize(); + + // The normal/distance dot product tells which side of the plane we are + var dot = box_to_sphere.dot(ns); + + if(dot0){ + // Intersects plane. Now check the other two dimensions + var ns1 = sphereBox_ns1; + var ns2 = sphereBox_ns2; + sides[(idx+1)%3].copy(ns1); + sides[(idx+2)%3].copy(ns2); + var h1 = ns1.norm(); + var h2 = ns2.norm(); + ns1.normalize(); + ns2.normalize(); + var dot1 = box_to_sphere.dot(ns1); + var dot2 = box_to_sphere.dot(ns2); + if(dot1

-h1 && dot2

-h2){ + var dist = Math.abs(dot-h-R); + if(side_distance===null || dist < side_distance){ + side_distance = dist; + side_dot1 = dot1; + side_dot2 = dot2; + side_h = h; + ns.copy(side_ns); + ns1.copy(side_ns1); + ns2.copy(side_ns2); + side_penetrations++; + } + } + } + } + if(side_penetrations){ + found = true; + var r = makeResult(bi,bj); + side_ns.mult(-R,r.ri); // Sphere r + side_ns.copy(r.ni); + r.ni.negate(r.ni); // Normal should be out of sphere + side_ns.mult(side_h,side_ns); + side_ns1.mult(side_dot1,side_ns1); + side_ns.vadd(side_ns1,side_ns); + side_ns2.mult(side_dot2,side_ns2); + side_ns.vadd(side_ns2,r.rj); + result.push(r); + } + + // Check corners + var rj = v3pool.get(); + var sphere_to_corner = sphereBox_sphere_to_corner; + for(var j=0; j!==2 && !found; j++){ + for(var k=0; k!==2 && !found; k++){ + for(var l=0; l!==2 && !found; l++){ + rj.set(0,0,0); + if(j){ + rj.vadd(sides[0],rj); + } else { + rj.vsub(sides[0],rj); + } + if(k){ + rj.vadd(sides[1],rj); + } else { + rj.vsub(sides[1],rj); + } + if(l){ + rj.vadd(sides[2],rj); + } else { + rj.vsub(sides[2],rj); + } + + // World position of corner + xj.vadd(rj,sphere_to_corner); + sphere_to_corner.vsub(xi,sphere_to_corner); + + if(sphere_to_corner.norm2() < R*R){ + found = true; + var r = makeResult(bi,bj); + sphere_to_corner.copy(r.ri); + r.ri.normalize(); + r.ri.copy(r.ni); + r.ri.mult(R,r.ri); + rj.copy(r.rj); + result.push(r); + } + } + } + } + v3pool.release(rj); + rj = null; + + // Check edges + var edgeTangent = v3pool.get(); + var edgeCenter = v3pool.get(); + var r = v3pool.get(); // r = edge center to sphere center + var orthogonal = v3pool.get(); + var dist = v3pool.get(); + var Nsides = sides.length; + for(var j=0; j!==Nsides && !found; j++){ + for(var k=0; k!==Nsides && !found; k++){ + if(j%3 !== k%3){ + // Get edge tangent + sides[k].cross(sides[j],edgeTangent); + edgeTangent.normalize(); + sides[j].vadd(sides[k], edgeCenter); + xi.copy(r); + r.vsub(edgeCenter,r); + r.vsub(xj,r); + var orthonorm = r.dot(edgeTangent); // distance from edge center to sphere center in the tangent direction + edgeTangent.mult(orthonorm,orthogonal); // Vector from edge center to sphere center in the tangent direction + + // Find the third side orthogonal to this one + var l = 0; + while(l===j%3 || l===k%3){ + l++; + } + + // vec from edge center to sphere projected to the plane orthogonal to the edge tangent + xi.copy(dist); + dist.vsub(orthogonal,dist); + dist.vsub(edgeCenter,dist); + dist.vsub(xj,dist); + + // Distances in tangent direction and distance in the plane orthogonal to it + var tdist = Math.abs(orthonorm); + var ndist = dist.norm(); + + if(tdist < sides[l].norm() && ndist0){ + // Intersects plane. Now check if the sphere is inside the face polygon + var faceVerts = []; // Face vertices, in world coords + for(var j=0, Nverts=face.length; j!==Nverts; j++){ + var worldVertex = v3pool.get(); + qj.vmult(verts[face[j]], worldVertex); + xj.vadd(worldVertex,worldVertex); + faceVerts.push(worldVertex); + } + + if(pointInPolygon(faceVerts,worldNormal,xi)){ // Is the sphere center in the face polygon? + found = true; + var r = makeResult(bi,bj); + worldNormal.mult(-R,r.ri); // Sphere r + worldNormal.negate(r.ni); // Normal should be out of sphere + + var penetrationVec2 = v3pool.get(); + worldNormal.mult(-penetration,penetrationVec2); + var penetrationSpherePoint = v3pool.get(); + worldNormal.mult(-R,penetrationSpherePoint); + + //xi.vsub(xj).vadd(penetrationSpherePoint).vadd(penetrationVec2 , r.rj); + xi.vsub(xj,r.rj); + r.rj.vadd(penetrationSpherePoint,r.rj); + r.rj.vadd(penetrationVec2 , r.rj); + + v3pool.release(penetrationVec2); + v3pool.release(penetrationSpherePoint); + + result.push(r); + + // Release world vertices + for(var j=0, Nfaceverts=faceVerts.length; j!==Nfaceverts; j++){ + v3pool.release(faceVerts[j]); + } + + return; // We only expect *one* face contact + } else { + // Edge? + for(var j=0; j!==face.length; j++){ + + // Get two world transformed vertices + var v1 = v3pool.get(); + var v2 = v3pool.get(); + qj.vmult(verts[face[(j+1)%face.length]], v1); + qj.vmult(verts[face[(j+2)%face.length]], v2); + xj.vadd(v1, v1); + xj.vadd(v2, v2); + + // Construct edge vector + var edge = sphereConvex_edge; + v2.vsub(v1,edge); + + // Construct the same vector, but normalized + var edgeUnit = sphereConvex_edgeUnit; + edge.unit(edgeUnit); + + // p is xi projected onto the edge + var p = v3pool.get(); + var v1_to_xi = v3pool.get(); + xi.vsub(v1, v1_to_xi); + var dot = v1_to_xi.dot(edgeUnit); + edgeUnit.mult(dot, p); + p.vadd(v1, p); + + // Compute a vector from p to the center of the sphere + var xi_to_p = v3pool.get(); + p.vsub(xi, xi_to_p); + + // Collision if the edge-sphere distance is less than the radius + // AND if p is in between v1 and v2 + if(dot > 0 && dot*dot sj.type){ + var temp; + temp=sj; + sj=si; + si=temp; + + temp=xj; + xj=xi; + xi=temp; + + temp=qj; + qj=qi; + qi=temp; + + temp=bj; + bj=bi; + bi=temp; + + swapped = true; + } + } else { + // Particle! + if(si && !sj){ + var temp; + temp=sj; + sj=si; + si=temp; + + temp=xj; + xj=xi; + xi=temp; + + temp=qj; + qj=qi; + qi=temp; + + temp=bj; + bj=bi; + bi=temp; + + swapped = true; + } + } + + if(si && sj){ + if(si.type === SPHERE){ + + switch(sj.type){ + case SPHERE: // sphere-sphere + sphereSphere(result,si,sj,xi,xj,qi,qj,bi,bj); + break; + case PLANE: // sphere-plane + spherePlane(result,si,sj,xi,xj,qi,qj,bi,bj); + break; + case BOX: // sphere-box + sphereBox(result,si,sj,xi,xj,qi,qj,bi,bj); + break; + case COMPOUND: // sphere-compound + recurseCompound(result,si,sj,xi,xj,qi,qj,bi,bj); + break; + case CONVEXPOLYHEDRON: // sphere-convexpolyhedron + sphereConvex(result,si,sj,xi,xj,qi,qj,bi,bj); + break; + default: + console.warn("Collision between CANNON.Shape.types.SPHERE and "+sj.type+" not implemented yet."); + break; + } + + } else if(si.type === types.PLANE){ + + switch(sj.type){ + case types.PLANE: // plane-plane + throw new Error("Plane-plane collision... wait, you did WHAT?"); + case types.BOX: // plane-box + planeBox(result,si,sj,xi,xj,qi,qj,bi,bj); + break; + case types.COMPOUND: // plane-compound + recurseCompound(result,si,sj,xi,xj,qi,qj,bi,bj); + break; + case types.CONVEXPOLYHEDRON: // plane-convex polyhedron + planeConvex(result,si,sj,xi,xj,qi,qj,bi,bj); + break; + default: + console.warn("Collision between CANNON.Shape.types.PLANE and "+sj.type+" not implemented yet."); + break; + } + + } else if(si.type===types.BOX){ + + switch(sj.type){ + case types.BOX: // box-box + // Do convex/convex instead + nearPhase(result,si.convexPolyhedronRepresentation,sj.convexPolyhedronRepresentation,xi,xj,qi,qj,bi,bj); + break; + case types.COMPOUND: // box-compound + recurseCompound(result,si,sj,xi,xj,qi,qj,bi,bj); + break; + case types.CONVEXPOLYHEDRON: // box-convexpolyhedron + // Do convex/convex instead + nearPhase(result,si.convexPolyhedronRepresentation,sj,xi,xj,qi,qj,bi,bj); + break; + default: + console.warn("Collision between CANNON.Shape.types.BOX and "+sj.type+" not implemented yet."); + break; + } + + } else if(si.type===types.COMPOUND){ + + switch(sj.type){ + case types.COMPOUND: // compound-compound + recurseCompound(result,si,sj,xi,xj,qi,qj,bi,bj); + break; + case types.CONVEXPOLYHEDRON: // compound-convex polyhedron + // Must swap + var r = []; + recurseCompound(r,sj,si,xj,xi,qj,qi,bj,bi); + for(var ri=0; ri!==r.length; ri++){ + swapResult(r[ri]); + result.push(r[ri]); + } + break; + default: + console.warn("Collision between CANNON.Shape.types.COMPOUND and "+sj.type+" not implemented yet."); + break; + } + + } else if(si.type===types.CONVEXPOLYHEDRON){ + + switch(sj.type){ + case types.CONVEXPOLYHEDRON: // convex polyhedron - convex polyhedron + convexConvex(result,si,sj,xi,xj,qi,qj,bi,bj); + break; + default: + console.warn("Collision between CANNON.Shape.types.CONVEXPOLYHEDRON and "+sj.type+" not implemented yet."); + break; + } + + } + + } else { + + // Particle! + switch(sj.type){ + case types.PLANE: // Particle vs plane + particlePlane(result,si,sj,xi,xj,qi,qj,bi,bj); + break; + case types.SPHERE: // Particle vs sphere + particleSphere(result,si,sj,xi,xj,qi,qj,bi,bj); + break; + case types.BOX: // Particle vs box + particleConvex(result,si,sj.convexPolyhedronRepresentation,xi,xj,qi,qj,bi,bj); + break; + case types.CONVEXPOLYHEDRON: // particle-convex + particleConvex(result,si,sj,xi,xj,qi,qj,bi,bj); + break; + case types.COMPOUND: // particle-compound + recurseCompound(result,si,sj,xi,xj,qi,qj,bi,bj); + break; + default: + console.warn("Collision between CANNON.Particle and "+sj.type+" not implemented yet."); + break; + } + } + + // Swap back if we swapped bodies in the beginning + for(var i=0, Nresults=result.length; swapped && i!==Nresults; i++){ + swapResult(result[i]); + } + } + + /** + * @method reduceContacts + * @memberof CANNON.ContactGenerator + * @brief Removes unnecessary members of an array of CANNON.ContactPoint. + */ + this.reduceContacts = function(contacts){ + + }; + + /** + * @method getContacts + * @memberof CANNON.ContactGenerator + * @param array p1 Array of body indices + * @param array p2 Array of body indices + * @param CANNON.World world + * @param array result Array to store generated contacts + * @param array oldcontacts Optional. Array of reusable contact objects + */ + this.getContacts = function(p1,p2,world,result,oldcontacts){ + // Save old contact objects + contactPointPool = oldcontacts; + + for(var k=0, N=p1.length; k!==N; k++){ + // Get current collision indeces + var bi = p1[k], + bj = p2[k]; + + // Get contacts + nearPhase( result, + bi.shape, + bj.shape, + bi.position, + bj.position, + bi.quaternion, + bj.quaternion, + bi, + bj + ); + } + }; +}; + +/** + * @class CANNON.Equation + * @brief Equation base class + * @author schteppe + * @param CANNON.Body bi + * @param CANNON.Body bj + * @param float minForce Minimum (read: negative max) force to be applied by the constraint. + * @param float maxForce Maximum (read: positive max) force to be applied by the constraint. + */ +CANNON.Equation = function(bi,bj,minForce,maxForce){ + this.id = -1; + + /** + * @property float minForce + * @memberof CANNON.Equation + */ + this.minForce = typeof(minForce)==="undefined" ? -1e6 : minForce; + + /** + * @property float maxForce + * @memberof CANNON.Equation + */ + this.maxForce = typeof(maxForce)==="undefined" ? 1e6 : maxForce; + + /** + * @property CANNON.Body bi + * @memberof CANNON.Equation + */ + this.bi = bi; + + /** + * @property CANNON.Body bj + * @memberof CANNON.Equation + */ + this.bj = bj; + + /** + * @property float stiffness + * @brief Corresponds to spring stiffness. Makes constraints stiffer, but harder to solve. + * @memberof CANNON.Equation + */ + this.stiffness = 1e7; + + /** + * @property float regularizationTime + * @brief Similar to damping. Represents the number of timesteps needed to stabilize the constraint. + * @memberof CANNON.Equation + */ + this.regularizationTime = 5; + + /** + * @property float a + * @brief SPOOK parameter + * @memberof CANNON.Equation + */ + this.a = 0.0; + + /** + * @property float b + * @brief SPOOK parameter + * @memberof CANNON.Equation + */ + this.b = 0.0; + + /** + * @property float eps + * @brief SPOOK parameter + * @memberof CANNON.Equation + */ + this.eps = 0.0; + + /** + * @property bool spookParamsNeedsUpdate + * @brief Set to true if you just changed stiffness or regularization. The parameters a,b,eps will be recalculated by the solver before solve. + * @memberof CANNON.Equation + */ + this.spookParamsNeedsUpdate = true; +}; +CANNON.Equation.prototype.constructor = CANNON.Equation; + +/** + * @method updateSpookParams + * @brief Recalculates a,b,eps. + * @memberof CANNON.Equation + */ +CANNON.Equation.prototype.updateSpookParams = function(h){ + var d = this.regularizationTime, + k = this.stiffness; + this.a = 4.0 / (h * (1 + 4 * d)); + this.b = (4.0 * d) / (1 + 4 * d); + this.eps = 4.0 / (h * h * k * (1 + 4 * d)); +}; + + +/** + * @class CANNON.ContactEquation + * @brief Contact/non-penetration constraint equation + * @author schteppe + * @param CANNON.Body bj + * @param CANNON.Body bi + * @extends CANNON.Equation + */ +CANNON.ContactEquation = function(bi,bj){ + CANNON.Equation.call(this,bi,bj,0,1e6); + + /** + * @property float restitution + * @memberof CANNON.ContactEquation + */ + this.restitution = 0.0; // "bounciness": u1 = -e*u0 + + /** + * @property CANNON.Vec3 ri + * @memberof CANNON.ContactEquation + * @brief World-oriented vector that goes from the center of bi to the contact point in bi. + */ + this.ri = new CANNON.Vec3(); + + /** + * @property CANNON.Vec3 rj + * @memberof CANNON.ContactEquation + */ + this.rj = new CANNON.Vec3(); + + this.penetrationVec = new CANNON.Vec3(); + + this.ni = new CANNON.Vec3(); + this.rixn = new CANNON.Vec3(); + this.rjxn = new CANNON.Vec3(); + + this.invIi = new CANNON.Mat3(); + this.invIj = new CANNON.Mat3(); + + // Cache + this.biInvInertiaTimesRixn = new CANNON.Vec3(); + this.bjInvInertiaTimesRjxn = new CANNON.Vec3(); +}; + +CANNON.ContactEquation.prototype = new CANNON.Equation(); +CANNON.ContactEquation.prototype.constructor = CANNON.ContactEquation; + +/** + * @method reset + * @memberof CANNON.ContactEquation + * @brief To be run before object reuse + */ +CANNON.ContactEquation.prototype.reset = function(){ + this.invInertiaTimesRxnNeedsUpdate = true; +}; + +var ContactEquation_computeB_temp1 = new CANNON.Vec3(); // Temp vectors +var ContactEquation_computeB_temp2 = new CANNON.Vec3(); +var ContactEquation_computeB_zero = new CANNON.Vec3(); +CANNON.ContactEquation.prototype.computeB = function(h){ + var a = this.a, + b = this.b; + var bi = this.bi; + var bj = this.bj; + var ri = this.ri; + var rj = this.rj; + var rixn = this.rixn; + var rjxn = this.rjxn; + + var zero = ContactEquation_computeB_zero; + + var vi = bi.velocity; + var wi = bi.angularVelocity ? bi.angularVelocity : zero; + var fi = bi.force; + var taui = bi.tau ? bi.tau : zero; + + var vj = bj.velocity; + var wj = bj.angularVelocity ? bj.angularVelocity : zero; + var fj = bj.force; + var tauj = bj.tau ? bj.tau : zero; + + var penetrationVec = this.penetrationVec; + var invMassi = bi.invMass; + var invMassj = bj.invMass; + + var invIi = this.invIi; + var invIj = this.invIj; + + if(bi.invInertia){ + invIi.setTrace(bi.invInertia); + } else { + invIi.identity(); // ok? + } + if(bj.invInertia){ + invIj.setTrace(bj.invInertia); + } else { + invIj.identity(); // ok? + } + + var n = this.ni; + + // Caluclate cross products + ri.cross(n,rixn); + rj.cross(n,rjxn); + + // Calculate q = xj+rj -(xi+ri) i.e. the penetration vector + var penetrationVec = this.penetrationVec; + penetrationVec.set(0,0,0); + penetrationVec.vadd(bj.position,penetrationVec); + penetrationVec.vadd(rj,penetrationVec); + penetrationVec.vsub(bi.position,penetrationVec); + penetrationVec.vsub(ri,penetrationVec); + + var Gq = n.dot(penetrationVec);//-Math.abs(this.penetration); + + var invIi_vmult_taui = ContactEquation_computeB_temp1; + var invIj_vmult_tauj = ContactEquation_computeB_temp2; + invIi.vmult(taui,invIi_vmult_taui); + invIj.vmult(tauj,invIj_vmult_tauj); + + // Compute iteration + var ePlusOne = this.restitution+1; + var GW = ePlusOne*vj.dot(n) - ePlusOne*vi.dot(n) + wj.dot(rjxn) - wi.dot(rixn); + var GiMf = fj.dot(n)*invMassj - fi.dot(n)*invMassi + rjxn.dot(invIj_vmult_tauj) - rixn.dot(invIi_vmult_taui); + + var B = - Gq * a - GW * b - h*GiMf; + + return B; +}; + +// Compute C = GMG+eps in the SPOOK equation +var computeC_temp1 = new CANNON.Vec3(); +var computeC_temp2 = new CANNON.Vec3(); +CANNON.ContactEquation.prototype.computeC = function(){ + var bi = this.bi; + var bj = this.bj; + var rixn = this.rixn; + var rjxn = this.rjxn; + var invMassi = bi.invMass; + var invMassj = bj.invMass; + + var C = invMassi + invMassj + this.eps; + + var invIi = this.invIi; + var invIj = this.invIj; + + /* + if(bi.invInertia){ + invIi.setTrace(bi.invInertia); + } else { + invIi.identity(); // ok? + } + if(bj.invInertia){ + invIj.setTrace(bj.invInertia); + } else { + invIj.identity(); // ok? + } + */ + + // Compute rxn * I * rxn for each body + invIi.vmult(rixn, this.biInvInertiaTimesRixn); + invIj.vmult(rjxn, this.bjInvInertiaTimesRjxn); + + /* + invIi.vmult(rixn,computeC_temp1); + invIj.vmult(rjxn,computeC_temp2); + + C += computeC_temp1.dot(rixn); + C += computeC_temp2.dot(rjxn); + */ + C += this.biInvInertiaTimesRixn.dot(rixn); + C += this.bjInvInertiaTimesRjxn.dot(rjxn); + + return C; +}; + +var computeGWlambda_ulambda = new CANNON.Vec3(); +CANNON.ContactEquation.prototype.computeGWlambda = function(){ + var bi = this.bi; + var bj = this.bj; + var ulambda = computeGWlambda_ulambda; + + var GWlambda = 0.0; + + bj.vlambda.vsub(bi.vlambda, ulambda); + GWlambda += ulambda.dot(this.ni); + + // Angular + if(bi.wlambda){ + GWlambda -= bi.wlambda.dot(this.rixn); + } + if(bj.wlambda){ + GWlambda += bj.wlambda.dot(this.rjxn); + } + + return GWlambda; +}; + +var ContactEquation_addToWlambda_temp1 = new CANNON.Vec3(); +var ContactEquation_addToWlambda_temp2 = new CANNON.Vec3(); +CANNON.ContactEquation.prototype.addToWlambda = function(deltalambda){ + var bi = this.bi, + bj = this.bj, + rixn = this.rixn, + rjxn = this.rjxn, + invMassi = bi.invMass, + invMassj = bj.invMass, + n = this.ni, + temp1 = ContactEquation_addToWlambda_temp1, + temp2 = ContactEquation_addToWlambda_temp2; + + + // Add to linear velocity + n.mult(invMassi * deltalambda, temp2); + bi.vlambda.vsub(temp2,bi.vlambda); + n.mult(invMassj * deltalambda, temp2); + bj.vlambda.vadd(temp2,bj.vlambda); + + // Add to angular velocity + if(bi.wlambda !== undefined){ + this.biInvInertiaTimesRixn.mult(deltalambda,temp1); + + bi.wlambda.vsub(temp1,bi.wlambda); + } + if(bj.wlambda !== undefined){ + this.bjInvInertiaTimesRjxn.mult(deltalambda,temp1); + bj.wlambda.vadd(temp1,bj.wlambda); + } +}; + + +/** + * @class CANNON.FrictionEquation + * @brief Constrains the slipping in a contact along a tangent + * @author schteppe + * @param CANNON.Body bi + * @param CANNON.Body bj + * @param float slipForce should be +-F_friction = +-mu * F_normal = +-mu * m * g + * @extends CANNON.Equation + */ +CANNON.FrictionEquation = function(bi,bj,slipForce){ + CANNON.Equation.call(this,bi,bj,-slipForce,slipForce); + this.ri = new CANNON.Vec3(); + this.rj = new CANNON.Vec3(); + this.t = new CANNON.Vec3(); // tangent + + + // The following is just cache + this.rixt = new CANNON.Vec3(); + this.rjxt = new CANNON.Vec3(); + this.wixri = new CANNON.Vec3(); + this.wjxrj = new CANNON.Vec3(); + + this.invIi = new CANNON.Mat3(); + this.invIj = new CANNON.Mat3(); + + this.relVel = new CANNON.Vec3(); + this.relForce = new CANNON.Vec3(); + + this.biInvInertiaTimesRixt = new CANNON.Vec3(); + this.bjInvInertiaTimesRjxt = new CANNON.Vec3(); +}; + +CANNON.FrictionEquation.prototype = new CANNON.Equation(); +CANNON.FrictionEquation.prototype.constructor = CANNON.FrictionEquation; + +var FrictionEquation_computeB_temp1 = new CANNON.Vec3(); +var FrictionEquation_computeB_temp2 = new CANNON.Vec3(); +var FrictionEquation_computeB_zero = new CANNON.Vec3(); +CANNON.FrictionEquation.prototype.computeB = function(h){ + var a = this.a, + b = this.b, + bi = this.bi, + bj = this.bj, + ri = this.ri, + rj = this.rj, + rixt = this.rixt, + rjxt = this.rjxt, + wixri = this.wixri, + wjxrj = this.wjxrj, + zero = FrictionEquation_computeB_zero; + + var vi = bi.velocity, + wi = bi.angularVelocity ? bi.angularVelocity : zero, + fi = bi.force, + taui = bi.tau ? bi.tau : zero, + + vj = bj.velocity, + wj = bj.angularVelocity ? bj.angularVelocity : zero, + fj = bj.force, + tauj = bj.tau ? bj.tau : zero, + + relVel = this.relVel, + relForce = this.relForce, + invMassi = bi.invMass, + invMassj = bj.invMass, + + invIi = this.invIi, + invIj = this.invIj, + + t = this.t, + + invIi_vmult_taui = FrictionEquation_computeB_temp1, + invIj_vmult_tauj = FrictionEquation_computeB_temp2; + + if(bi.invInertia){ + invIi.setTrace(bi.invInertia); + } + if(bj.invInertia){ + invIj.setTrace(bj.invInertia); + } + + + // Caluclate cross products + ri.cross(t,rixt); + rj.cross(t,rjxt); + + wi.cross(ri,wixri); + wj.cross(rj,wjxrj); + + invIi.vmult(taui,invIi_vmult_taui); + invIj.vmult(tauj,invIj_vmult_tauj); + + var Gq = 0; // we do only want to constrain motion + var GW = vj.dot(t) - vi.dot(t) + wjxrj.dot(t) - wixri.dot(t); // eq. 40 + var GiMf = fj.dot(t)*invMassj - fi.dot(t)*invMassi + rjxt.dot(invIj_vmult_tauj) - rixt.dot(invIi_vmult_taui); + + var B = - Gq * a - GW * b - h*GiMf; + + return B; +}; + +// Compute C = G * Minv * G + eps +//var FEcomputeC_temp1 = new CANNON.Vec3(); +//var FEcomputeC_temp2 = new CANNON.Vec3(); +CANNON.FrictionEquation.prototype.computeC = function(){ + var bi = this.bi, + bj = this.bj, + rixt = this.rixt, + rjxt = this.rjxt, + invMassi = bi.invMass, + invMassj = bj.invMass, + C = invMassi + invMassj + this.eps, + invIi = this.invIi, + invIj = this.invIj; + + /* + if(bi.invInertia){ + invIi.setTrace(bi.invInertia); + } + if(bj.invInertia){ + invIj.setTrace(bj.invInertia); + } + */ + + // Compute rxt * I * rxt for each body + /* + invIi.vmult(rixt,FEcomputeC_temp1); + invIj.vmult(rjxt,FEcomputeC_temp2); + C += FEcomputeC_temp1.dot(rixt); + C += FEcomputeC_temp2.dot(rjxt); + */ + invIi.vmult(rixt,this.biInvInertiaTimesRixt); + invIj.vmult(rjxt,this.bjInvInertiaTimesRjxt); + C += this.biInvInertiaTimesRixt.dot(rixt); + C += this.bjInvInertiaTimesRjxt.dot(rjxt); + + return C; +}; + +var FrictionEquation_computeGWlambda_ulambda = new CANNON.Vec3(); +CANNON.FrictionEquation.prototype.computeGWlambda = function(){ + + // Correct at all ??? + + var bi = this.bi; + var bj = this.bj; + + var GWlambda = 0.0; + var ulambda = FrictionEquation_computeGWlambda_ulambda; + bj.vlambda.vsub(bi.vlambda,ulambda); + GWlambda += ulambda.dot(this.t); + + // Angular + if(bi.wlambda){ + GWlambda -= bi.wlambda.dot(this.rixt); + } + if(bj.wlambda){ + GWlambda += bj.wlambda.dot(this.rjxt); + } + + return GWlambda; +}; + +var FrictionEquation_addToWlambda_tmp = new CANNON.Vec3(); +CANNON.FrictionEquation.prototype.addToWlambda = function(deltalambda){ + var bi = this.bi, + bj = this.bj, + rixt = this.rixt, + rjxt = this.rjxt, + invMassi = bi.invMass, + invMassj = bj.invMass, + t = this.t, + tmp = FrictionEquation_addToWlambda_tmp, + wi = bi.wlambda, + wj = bj.wlambda; + + // Add to linear velocity + t.mult(invMassi * deltalambda, tmp); + bi.vlambda.vsub(tmp,bi.vlambda); + + t.mult(invMassj * deltalambda, tmp); + bj.vlambda.vadd(tmp,bj.vlambda); + + // Add to angular velocity + if(wi){ + /* + var I = this.invIi; + I.vmult(rixt,tmp); + tmp.mult(deltalambda,tmp); + */ + this.biInvInertiaTimesRixt.mult(deltalambda,tmp); + wi.vsub(tmp,wi); + } + if(wj){ + /* + var I = this.invIj; + I.vmult(rjxt,tmp); + tmp.mult(deltalambda,tmp); + */ + this.bjInvInertiaTimesRjxt.mult(deltalambda,tmp); + wj.vadd(tmp,wj); + } +}; + +/** + * @class CANNON.RotationalEquation + * @brief Rotational constraint. Works to keep the local vectors orthogonal to each other. + * @author schteppe + * @param CANNON.RigidBody bj + * @param CANNON.Vec3 localVectorInBodyA + * @param CANNON.RigidBody bi + * @param CANNON.Vec3 localVectorInBodyB + * @extends CANNON.Equation + */ +CANNON.RotationalEquation = function(bodyA, bodyB){ + CANNON.Equation.call(this,bodyA,bodyB,-1e6,1e6); + this.ni = new CANNON.Vec3(); // World oriented localVectorInBodyA + this.nj = new CANNON.Vec3(); // ...and B + + this.nixnj = new CANNON.Vec3(); + this.njxni = new CANNON.Vec3(); + + this.invIi = new CANNON.Mat3(); + this.invIj = new CANNON.Mat3(); + + this.relVel = new CANNON.Vec3(); + this.relForce = new CANNON.Vec3(); +}; + +CANNON.RotationalEquation.prototype = new CANNON.Equation(); +CANNON.RotationalEquation.prototype.constructor = CANNON.RotationalEquation; + +CANNON.RotationalEquation.prototype.computeB = function(h){ + var a = this.a, + b = this.b; + var bi = this.bi; + var bj = this.bj; + + var ni = this.ni; + var nj = this.nj; + + var nixnj = this.nixnj; + var njxni = this.njxni; + + var vi = bi.velocity; + var wi = bi.angularVelocity ? bi.angularVelocity : new CANNON.Vec3(); + var fi = bi.force; + var taui = bi.tau ? bi.tau : new CANNON.Vec3(); + + var vj = bj.velocity; + var wj = bj.angularVelocity ? bj.angularVelocity : new CANNON.Vec3(); + var fj = bj.force; + var tauj = bj.tau ? bj.tau : new CANNON.Vec3(); + + var invMassi = bi.invMass; + var invMassj = bj.invMass; + + var invIi = this.invIi; + var invIj = this.invIj; + + if(bi.invInertia){ + invIi.setTrace(bi.invInertia); + } else { + invIi.identity(); // ok? + } + if(bj.invInertia) { + invIj.setTrace(bj.invInertia); + } else { + invIj.identity(); // ok? + } + + // Caluclate cross products + ni.cross(nj,nixnj); + nj.cross(ni,njxni); + + // g = ni * nj + // gdot = (nj x ni) * wi + (ni x nj) * wj + // G = [0 njxni 0 nixnj] + // W = [vi wi vj wj] + var Gq = -ni.dot(nj); + var GW = njxni.dot(wi) + nixnj.dot(wj); + var GiMf = 0;//njxni.dot(invIi.vmult(taui)) + nixnj.dot(invIj.vmult(tauj)); + + var B = - Gq * a - GW * b - h*GiMf; + + return B; +}; + +// Compute C = GMG+eps +CANNON.RotationalEquation.prototype.computeC = function(){ + var bi = this.bi; + var bj = this.bj; + var nixnj = this.nixnj; + var njxni = this.njxni; + var invMassi = bi.invMass; + var invMassj = bj.invMass; + + var C = /*invMassi + invMassj +*/ this.eps; + + var invIi = this.invIi; + var invIj = this.invIj; + + if(bi.invInertia){ + invIi.setTrace(bi.invInertia); + } else { + invIi.identity(); // ok? + } + if(bj.invInertia){ + invIj.setTrace(bj.invInertia); + } else { + invIj.identity(); // ok? + } + + C += invIi.vmult(njxni).dot(njxni); + C += invIj.vmult(nixnj).dot(nixnj); + + return C; +}; + +var computeGWlambda_ulambda = new CANNON.Vec3(); +CANNON.RotationalEquation.prototype.computeGWlambda = function(){ + var bi = this.bi; + var bj = this.bj; + var ulambda = computeGWlambda_ulambda; + + var GWlambda = 0.0; + //bj.vlambda.vsub(bi.vlambda, ulambda); + //GWlambda += ulambda.dot(this.ni); + + // Angular + if(bi.wlambda){ + GWlambda += bi.wlambda.dot(this.njxni); + } + if(bj.wlambda){ + GWlambda += bj.wlambda.dot(this.nixnj); + } + + //console.log("GWlambda:",GWlambda); + + return GWlambda; +}; + +CANNON.RotationalEquation.prototype.addToWlambda = function(deltalambda){ + var bi = this.bi; + var bj = this.bj; + var nixnj = this.nixnj; + var njxni = this.njxni; + var invMassi = bi.invMass; + var invMassj = bj.invMass; + + // Add to linear velocity + //bi.vlambda.vsub(n.mult(invMassi * deltalambda),bi.vlambda); + //bj.vlambda.vadd(n.mult(invMassj * deltalambda),bj.vlambda); + + // Add to angular velocity + if(bi.wlambda){ + var I = this.invIi; + bi.wlambda.vsub(I.vmult(nixnj).mult(deltalambda),bi.wlambda); + } + if(bj.wlambda){ + var I = this.invIj; + bj.wlambda.vadd(I.vmult(nixnj).mult(deltalambda),bj.wlambda); + } +}; + + +/** + * @class CANNON.Constraint + * @brief Constraint base class + * @author schteppe + * @param CANNON.Body bodyA + * @param CANNON.Body bodyB + */ +CANNON.Constraint = function(bodyA,bodyB){ + + /** + * @property Array equations + * @memberOf CANNON.Constraint + * @brief Equations to be solved in this constraint + */ + this.equations = []; + + /** + * @property CANNON.Body bodyA + * @memberOf CANNON.Constraint + */ + this.bodyA = bodyA; + + /** + * @property CANNON.Body bodyB + * @memberOf CANNON.Constraint + */ + this.bodyB = bodyB; +}; + +/** + * @method update + * @memberOf CANNON.Constraint + */ +CANNON.Constraint.prototype.update = function(){ + throw new Error("method update() not implmemented in this Constraint subclass!"); +}; + +/** + * @class CANNON.DistanceConstraint + * @brief Constrains two bodies to be at a constant distance from each other. + * @author schteppe + * @param CANNON.Body bodyA + * @param CANNON.Body bodyB + * @param float distance + * @param float maxForce + */ +CANNON.DistanceConstraint = function(bodyA,bodyB,distance,maxForce){ + CANNON.Constraint.call(this,bodyA,bodyB); + + if(typeof(maxForce)==="undefined" ) { + maxForce = 1e6; + } + + // Equations to be fed to the solver + var eqs = this.equations = [ + new CANNON.ContactEquation(bodyA,bodyB), // Just in the normal direction + ]; + + var normal = eqs[0]; + + normal.minForce = -maxForce; + normal.maxForce = maxForce; + + // Update + this.update = function(){ + bodyB.position.vsub(bodyA.position,normal.ni); + normal.ni.normalize(); + /*bodyA.quaternion.vmult(pivotA,normal.ri); + bodyB.quaternion.vmult(pivotB,normal.rj);*/ + normal.ni.mult( distance*0.5,normal.ri); + normal.ni.mult( -distance*0.5,normal.rj); + }; +}; +CANNON.DistanceConstraint.prototype = new CANNON.Constraint(); + + +/** + * @class CANNON.RotationalMotorEquation + * @brief Rotational motor constraint. Works to keep the relative angular velocity of the bodies to a given value + * @author schteppe + * @param CANNON.RigidBody bodyA + * @param CANNON.RigidBody bodyB + * @extends CANNON.Equation + */ +CANNON.RotationalMotorEquation = function(bodyA, bodyB, maxForce){ + maxForce = maxForce || 1e6; + CANNON.Equation.call(this,bodyA,bodyB,-maxForce,maxForce); + this.axisA = new CANNON.Vec3(); // World oriented rotational axis + this.axisB = new CANNON.Vec3(); // World oriented rotational axis + + this.invIi = new CANNON.Mat3(); + this.invIj = new CANNON.Mat3(); + this.targetVelocity = 0; +}; + +CANNON.RotationalMotorEquation.prototype = new CANNON.Equation(); +CANNON.RotationalMotorEquation.prototype.constructor = CANNON.RotationalMotorEquation; + +CANNON.RotationalMotorEquation.prototype.computeB = function(h){ + var a = this.a, + b = this.b; + var bi = this.bi; + var bj = this.bj; + + var axisA = this.axisA; + var axisB = this.axisB; + + var vi = bi.velocity; + var wi = bi.angularVelocity ? bi.angularVelocity : new CANNON.Vec3(); + var fi = bi.force; + var taui = bi.tau ? bi.tau : new CANNON.Vec3(); + + var vj = bj.velocity; + var wj = bj.angularVelocity ? bj.angularVelocity : new CANNON.Vec3(); + var fj = bj.force; + var tauj = bj.tau ? bj.tau : new CANNON.Vec3(); + + var invMassi = bi.invMass; + var invMassj = bj.invMass; + + var invIi = this.invIi; + var invIj = this.invIj; + + if(bi.invInertia){ + invIi.setTrace(bi.invInertia); + } else { + invIi.identity(); // ok? + } + if(bj.invInertia){ + invIj.setTrace(bj.invInertia); + } else { + invIj.identity(); // ok? + } + + // g = 0 + // gdot = axisA * wi - axisB * wj + // G = [0 axisA 0 -axisB] + // W = [vi wi vj wj] + var Gq = 0; + var GW = axisA.dot(wi) + axisB.dot(wj) + this.targetVelocity; + var GiMf = 0;//axis.dot(invIi.vmult(taui)) + axis.dot(invIj.vmult(tauj)); + + var B = - Gq * a - GW * b - h*GiMf; + + return B; +}; + +// Compute C = GMG+eps +CANNON.RotationalMotorEquation.prototype.computeC = function(){ + var bi = this.bi; + var bj = this.bj; + var axisA = this.axisA; + var axisB = this.axisB; + var invMassi = bi.invMass; + var invMassj = bj.invMass; + + var C = this.eps; + + var invIi = this.invIi; + var invIj = this.invIj; + + if(bi.invInertia){ + invIi.setTrace(bi.invInertia); + } else { + invIi.identity(); // ok? + } + if(bj.invInertia){ + invIj.setTrace(bj.invInertia); + } else { + invIj.identity(); // ok? + } + + C += invIi.vmult(axisA).dot(axisB); + C += invIj.vmult(axisB).dot(axisB); + + return C; +}; + +var computeGWlambda_ulambda = new CANNON.Vec3(); +CANNON.RotationalMotorEquation.prototype.computeGWlambda = function(){ + var bi = this.bi; + var bj = this.bj; + var ulambda = computeGWlambda_ulambda; + var axisA = this.axisA; + var axisB = this.axisB; + + var GWlambda = 0.0; + //bj.vlambda.vsub(bi.vlambda, ulambda); + //GWlambda += ulambda.dot(this.ni); + + // Angular + if(bi.wlambda){ + GWlambda += bi.wlambda.dot(axisA); + } + if(bj.wlambda){ + GWlambda += bj.wlambda.dot(axisB); + } + + //console.log("GWlambda:",GWlambda); + + return GWlambda; +}; + +CANNON.RotationalMotorEquation.prototype.addToWlambda = function(deltalambda){ + var bi = this.bi; + var bj = this.bj; + var axisA = this.axisA; + var axisB = this.axisB; + var invMassi = bi.invMass; + var invMassj = bj.invMass; + + // Add to linear velocity + //bi.vlambda.vsub(n.mult(invMassi * deltalambda),bi.vlambda); + //bj.vlambda.vadd(n.mult(invMassj * deltalambda),bj.vlambda); + + // Add to angular velocity + if(bi.wlambda){ + var I = this.invIi; + bi.wlambda.vsub(I.vmult(axisA).mult(deltalambda),bi.wlambda); + } + if(bj.wlambda){ + var I = this.invIj; + bj.wlambda.vadd(I.vmult(axisB).mult(deltalambda),bj.wlambda); + } +}; + + +/** + * @class CANNON.HingeConstraint + * @brief Hinge constraint. Tries to keep the local body axes equal. + * @author schteppe + * @param CANNON.RigidBody bodyA + * @param CANNON.Vec3 pivotA A point defined locally in bodyA. This defines the offset of axisA. + * @param CANNON.Vec3 axisA an axis that bodyA can rotate around. + * @param CANNON.RigidBody bodyB + * @param CANNON.Vec3 pivotB + * @param CANNON.Vec3 axisB + * @param float maxForce + */ +CANNON.HingeConstraint = function(bodyA, pivotA, axisA, bodyB, pivotB, axisB, maxForce){ + CANNON.Constraint.call(this,bodyA,bodyB); + + maxForce = maxForce || 1e6; + var that = this; + // Equations to be fed to the solver + var eqs = this.equations = [ + new CANNON.RotationalEquation(bodyA,bodyB), // rotational1 + new CANNON.RotationalEquation(bodyA,bodyB), // rotational2 + new CANNON.ContactEquation(bodyA,bodyB), // p2pNormal + new CANNON.ContactEquation(bodyA,bodyB), // p2pTangent1 + new CANNON.ContactEquation(bodyA,bodyB), // p2pTangent2 + ]; + + this.getRotationalEquation1 = function(){ return eqs[0]; }; + this.getRotationalEquation2 = function(){ return eqs[1]; }; + this.getPointToPointEquation1 = function(){ return eqs[2]; }; + this.getPointToPointEquation2 = function(){ return eqs[3]; }; + this.getPointToPointEquation3 = function(){ return eqs[4]; }; + + var r1 = this.getRotationalEquation1(); + var r2 = this.getRotationalEquation2(); + var normal = this.getPointToPointEquation1(); + var t1 = this.getPointToPointEquation2(); + var t2 = this.getPointToPointEquation3(); + var motor; // not activated by default + + t1.minForce = t2.minForce = normal.minForce = -maxForce; + t1.maxForce = t2.maxForce = normal.maxForce = maxForce; + + var unitPivotA = pivotA.unit(); + var unitPivotB = pivotB.unit(); + + var axisA_x_pivotA = new CANNON.Vec3(); + var axisA_x_axisA_x_pivotA = new CANNON.Vec3(); + var axisB_x_pivotB = new CANNON.Vec3(); + axisA.cross(unitPivotA,axisA_x_pivotA); + axisA.cross(axisA_x_pivotA,axisA_x_axisA_x_pivotA); + axisB.cross(unitPivotB,axisB_x_pivotB); + + axisA_x_pivotA.normalize(); + axisB_x_pivotB.normalize(); + + // Motor stuff + var motorEnabled = false; + this.motorTargetVelocity = 0; + this.motorMinForce = -maxForce; + this.motorMaxForce = maxForce; + this.enableMotor = function(){ + if(!motorEnabled){ + motor = new CANNON.RotationalMotorEquation(bodyA,bodyB,maxForce); + eqs.push(motor); + motorEnabled = true; + } + }; + this.disableMotor = function(){ + if(motorEnabled){ + motorEnabled = false; + motor = null; + eqs.pop(); + } + }; + + // Update + this.update = function(){ + // Update world positions of pivots + /* + bodyB.position.vsub(bodyA.position,normal.ni); + normal.ni.normalize(); + */ + normal.ni.set(1,0,0); + t1.ni.set(0,1,0); + t2.ni.set(0,0,1); + bodyA.quaternion.vmult(pivotA,normal.ri); + bodyB.quaternion.vmult(pivotB,normal.rj); + + //normal.ni.tangents(t1.ni,t2.ni); + normal.ri.copy(t1.ri); + normal.rj.copy(t1.rj); + normal.ri.copy(t2.ri); + normal.rj.copy(t2.rj); + + // update rotational constraints + bodyA.quaternion.vmult(axisA_x_pivotA, r1.ni); + bodyB.quaternion.vmult(axisB, r1.nj); + bodyA.quaternion.vmult(axisA_x_axisA_x_pivotA, r2.ni); + bodyB.quaternion.vmult(axisB, r2.nj); + + if(motorEnabled){ + bodyA.quaternion.vmult(axisA,motor.axisA); + bodyB.quaternion.vmult(axisB,motor.axisB); + motor.targetVelocity = that.motorTargetVelocity; + motor.maxForce = that.motorMaxForce; + motor.minForce = that.motorMinForce; + } + }; +}; +CANNON.HingeConstraint.prototype = new CANNON.Constraint(); + +/** + * @class CANNON.PointToPointConstraint + * @brief Connects two bodies at given offset points + * @author schteppe + * @param CANNON.Body bodyA + * @param CANNON.Vec3 pivotA The point relative to the center of mass of bodyA which bodyA is constrained to. + * @param CANNON.Body bodyB Body that will be constrained in a similar way to the same point as bodyA. We will therefore get sort of a link between bodyA and bodyB. If not specified, bodyA will be constrained to a static point. + * @param CANNON.Vec3 pivotB See pivotA. + * @param float maxForce The maximum force that should be applied to constrain the bodies. + * @extends CANNON.Constraint + */ +CANNON.PointToPointConstraint = function(bodyA,pivotA,bodyB,pivotB,maxForce){ + CANNON.Constraint.call(this,bodyA,bodyB); + + // Equations to be fed to the solver + var eqs = this.equations = [ + new CANNON.ContactEquation(bodyA,bodyB), // Normal + new CANNON.ContactEquation(bodyA,bodyB), // Tangent2 + new CANNON.ContactEquation(bodyA,bodyB), // Tangent2 + ]; + + var normal = eqs[0]; + var t1 = eqs[1]; + var t2 = eqs[2]; + + t1.minForce = t2.minForce = normal.minForce = -maxForce; + t1.maxForce = t2.maxForce = normal.maxForce = maxForce; + + // Update + this.update = function(){ + bodyB.position.vsub(bodyA.position,normal.ni); + normal.ni.normalize(); + bodyA.quaternion.vmult(pivotA,normal.ri); + bodyB.quaternion.vmult(pivotB,normal.rj); + + normal.ni.tangents(t1.ni,t2.ni); + normal.ri.copy(t1.ri); + normal.rj.copy(t1.rj); + normal.ri.copy(t2.ri); + normal.rj.copy(t2.rj); + }; +}; +CANNON.PointToPointConstraint.prototype = new CANNON.Constraint(); + + +if (typeof module !== 'undefined') { + // export for node + module.exports = CANNON; +} else { + // assign to window + this.CANNON = CANNON; +} + +}).apply(this); \ No newline at end of file diff --git a/Samples/index.css b/Samples/index.css index 3929e8660ab..347f4fcfc2c 100644 --- a/Samples/index.css +++ b/Samples/index.css @@ -10,8 +10,13 @@ a { color: black; + text-decoration: none; } + a:hover { + text-decoration: underline; + } + a:visited { color: black; } @@ -26,6 +31,23 @@ a { -webkit-transform: scale3d(0.9, 0.9, 0.9); } +#footer { + position: absolute; + width: 100%; + height: 25px; + bottom: 0; + background: white; + text-align: center; +} + +.footerLink { + color: #2E7F80; +} + +.footerLink:visited { + color: #2E7F80; +} + .buttonControlPanel { height: 40px; width: 200px; @@ -178,13 +200,13 @@ button { } .movedLeft { - transform: translateX(-2000px); - -webkit-transform: translateX(-2000px); + transform: translateX(-100%); + -webkit-transform: translateX(-100%); } .movedRight { - transform: translateX(2000px); - -webkit-transform: translateX(2000px); + transform: translateX(100%); + -webkit-transform: translateX(100%); } #babylonLink { @@ -223,7 +245,7 @@ button { left: 0; right: 0; top: 136px; - bottom: 0px; + bottom: 25px; overflow-y: auto; overflow-x: hidden; width: 100%; @@ -313,9 +335,12 @@ button { .item-text-right { position: absolute; right: 10px; - bottom: 15px; + bottom: 0px; font-size: 16px; color: white; + max-width: 300px; + text-align: right; + height: 50px; } #notSupported { diff --git a/Samples/index.html b/Samples/index.html index 0086c55dfa7..2326ce5f0ab 100644 --- a/Samples/index.html +++ b/Samples/index.html @@ -30,11 +30,13 @@ + + + --> @@ -106,6 +109,7 @@ + @@ -152,7 +156,6 @@

Credits

3D engine: David CATUHE (@deltakosh)
Scenes: Michel ROUSSEAU (@rousseau_michel)
Game FX: Pierre LAGARDE (@pierlag)
- Game FX: Sébastien PERTUS (@sebastienpertus)
Game FX: David ROUSSET (@davrous)

Train scene: Romuald ROUHIER and Progiss
@@ -168,6 +171,7 @@

About babylon.js

  • Complete scene graph with lights, cameras, materials and meshes
  • Collisions engine
  • +
  • Physics engine (thanks to cannon.js)
  • Scene picking
  • Antialiasing
  • Animations engine
  • @@ -215,6 +219,7 @@

    About babylon.js

  • Rendering layers
  • Post-processes (blur, refraction, black'n'white, fxaa, customs...)
  • Lens flares
  • +
  • Multi-views
  • @@ -247,12 +252,20 @@

    About babylon.js

    • Babylon scene file can be converted from .OBJ, .FBX, .MXB
    • Exporter for Blender
    • +
    • Support for drag'n'drop
  • +
    @@ -276,7 +289,7 @@

    About babylon.js

    - +

    @@ -290,6 +303,9 @@

    About babylon.js

    +

    + +

    Control panel
    diff --git a/Samples/index.js b/Samples/index.js index 14270c10a05..e2bc1065887 100644 --- a/Samples/index.js +++ b/Samples/index.js @@ -7,8 +7,18 @@ var onload = function () { // Demos var demos = [ + //{ + // title: "HILLVALLEY", scene: "hillvalley", screenshot: "hill.jpg", size: "150 MB
    (high-end device recommanded)", incremental: true, big: true, onload: function () { + // scene.collisionsEnabled = false; + // scene.lightsEnabled = false; + // scene.createOrUpdateSelectionOctree(); + // for (var matIndex = 0; matIndex < scene.materials.length; matIndex++) { + // scene.materials[matIndex].checkReadyOnEveryCall = false; + // } + // } + //}, { - title: "TRAIN", scene: "Train", screenshot: "train.jpg", size: "70 MB", big: true, onload: function () { + title: "TRAIN", scene: "Train", screenshot: "train.jpg", size: "70 MB", onload: function () { scene.collisionsEnabled = false; for (var index = 0; index < scene.cameras.length; index++) { scene.cameras[index].minZ = 10; @@ -48,7 +58,7 @@ var onload = function () { var postProcess = new BABYLON.RefractionPostProcess("Refraction", "/scenes/customs/refMap.jpg", new BABYLON.Color3(1.0, 1.0, 1.0), 0.5, 0.5, 1.0, scene.cameras[1]); } }, - { title: "WINDOWS CAFE", scene: "WCafe", screenshot: "wcafe.jpg", size: "28 MB", anchor:"WCAFE" }, + { title: "WINDOWS CAFE", scene: "WCafe", screenshot: "wcafe.jpg", size: "28 MB", anchor: "WCAFE" }, { title: "FLAT 2009", scene: "Flat2009", @@ -60,20 +70,21 @@ var onload = function () { scene.createOrUpdateSelectionOctree(); } }, - { title: "THE CAR", scene: "TheCar", screenshot: "thecar.jpg", size: "100 MB", incremental: true, anchor:"THECAR" }, + { title: "THE CAR", scene: "TheCar", screenshot: "thecar.jpg", size: "100 MB", incremental: true, anchor: "THECAR" }, { title: "VIPER", scene: "Viper", screenshot: "viper.jpg", size: "18 MB" }, { title: "SPACESHIP", scene: "Spaceship", screenshot: "spaceship.jpg", size: "1 MB" }, { - title: "OMEGA CRUSHER", scene: "SpaceDek", screenshot: "omegacrusher.jpg", size: "10 MB", anchor:"OMEGA", onload: function () { + title: "OMEGA CRUSHER", scene: "SpaceDek", screenshot: "omegacrusher.jpg", size: "10 MB", anchor: "OMEGA", onload: function () { scene.collisionsEnabled = false; } }]; var tests = [ + { title: "PHYSICS", id: 13, screenshot: "physics.jpg", size: "1.0 MB", anchor: "PHYSICS" }, { title: "LENS FLARES", id: 12, screenshot: "lens.jpg", size: "1.0 MB", anchor: "LENS" }, - { title: "POSTPROCESS - REFRACTION", id: 11, screenshot: "postprocessRefraction.jpg", size: "1.0 MB", anchor:"PPREF" }, + { title: "POSTPROCESS - REFRACTION", id: 11, screenshot: "postprocessRefraction.jpg", size: "1.0 MB", anchor: "PPREF" }, { title: "POSTPROCESS - BLOOM", id: 10, screenshot: "postprocessBloom.jpg", size: "1.0 MB", anchor: "PPBLOOM" }, - { title: "OCTREE - 8000 spheres", id: 8, screenshot: "octree.jpg", size: "0.1 MB", anchor:"OCTREE" }, + { title: "OCTREE - 8000 spheres", id: 8, screenshot: "octree.jpg", size: "0.1 MB", anchor: "OCTREE" }, { title: "BONES", id: 9, screenshot: "bones.jpg", size: "10 MB" }, { title: "CHARTING", id: 7, screenshot: "charting.jpg", size: "0.1 MB" }, { title: "SHADOWS", id: 6, screenshot: "shadows.jpg", size: "1.0 MB" }, @@ -87,6 +98,7 @@ var onload = function () { ]; var thirdParties = [ + { title: "BING 3D MAPS", url: "http://babylonbing.azurewebsites.net/", screenshot: "bing3D.jpg", size: "by A. Beaulieu" }, { title: "CAR GAME", url: "http://babylon.azurewebsites.net", screenshot: "car.jpg", size: "by G. Carlander" }, { title: "CYCLE GAME", url: "http://tronbabylon.azurewebsites.net/", screenshot: "tron.jpg", size: "by G. Carlander" }, { title: "GALLERY", url: "http://guillaume.carlander.fr/Babylon/Gallery/", screenshot: "gallery.png", size: "by G. Carlander" }, @@ -113,6 +125,7 @@ var onload = function () { var hardwareScalingLevel = document.getElementById("hardwareScalingLevel"); var collisions = document.getElementById("collisions"); var postProcess = document.getElementById("postProcess"); + var mirrors = document.getElementById("mirrors"); var status = document.getElementById("status"); var fullscreen = document.getElementById("fullscreen"); var touchCamera = document.getElementById("touchCamera"); @@ -324,6 +337,9 @@ var onload = function () { case 12: newScene = CreateLensFlaresTestScene(engine); break; + case 13: + newScene = CreatePhysicsScene(engine); + break; } scene = newScene; @@ -506,7 +522,7 @@ var onload = function () { } }); - canvas.addEventListener("click", function (evt) { + canvas.addEventListener("mousedown", function (evt) { if (!panelIsClosed) { panelIsClosed = true; cameraPanelIsClosed = true; @@ -516,14 +532,14 @@ var onload = function () { cameraPanel.style.transform = "translateX(300px)"; } - if (evt.ctrlKey) { - if (!scene) - return; + if (!scene) + return; - var pickResult = scene.pick(evt.clientX, evt.clientY); + var pickResult = scene.pick(evt.clientX, evt.clientY); - if (pickResult.hit) { - status.innerHTML = "Selected object: " + pickResult.pickedMesh.name + "(" + pickResult.pickedPoint.x + "," + pickResult.pickedPoint.y + "," + pickResult.pickedPoint.z + ")"; + if (pickResult.hit) { + if (evt.ctrlKey) { + status.innerHTML = "Selected object: " + pickResult.pickedMesh.name + "(" + pickResult.pickedPoint.x + "," + pickResult.pickedPoint.y + "," + pickResult.pickedPoint.z + ")"; // Animations scene.beginAnimation(pickResult.pickedMesh, 0, 100, true, 1.0); @@ -558,6 +574,9 @@ var onload = function () { particleSystem.start(); } else { + var dir = pickResult.pickedPoint.subtract(scene.activeCamera.position); + dir.normalize(); + pickResult.pickedMesh.applyImpulse(dir.scale(10), pickResult.pickedPoint); status.innerHTML = ""; } } @@ -641,6 +660,12 @@ var onload = function () { } }); + mirrors.addEventListener("change", function () { + if (scene) { + scene.renderTargetsEnabled = mirrors.checked; + } + }); + toggleBandW.addEventListener("click", function () { if (scene && scene.activeCamera) { if (scene.activeCamera.__bandw_cookie) { @@ -653,7 +678,7 @@ var onload = function () { } } }); - + toggleFxaa.addEventListener("click", function () { if (scene && scene.activeCamera) { if (scene.activeCamera.__fxaa_cookie) { diff --git a/babylon.1.7.3.js b/babylon.1.7.3.js deleted file mode 100644 index ea4ecbb6ed2..00000000000 --- a/babylon.1.7.3.js +++ /dev/null @@ -1,22 +0,0 @@ -var BABYLON=BABYLON||{};(function(){BABYLON.Ray=function(origin,direction){this.origin=origin;this.direction=direction;};BABYLON.Ray.prototype.intersectsBox=function(box){var d=0.0;var maxValue=Number.MAX_VALUE;if(Math.abs(this.direction.x)<0.0000001){if(this.origin.xbox.maximum.x){return false;}}else{var inv=1.0/this.direction.x;var min=(box.minimum.x-this.origin.x)*inv;var max=(box.maximum.x-this.origin.x)*inv;if(min>max){var temp=min;min=max;max=temp;}d=Math.max(min,d);maxValue=Math.min(max,maxValue);if(d>maxValue){return false;}}if(Math.abs(this.direction.y)<0.0000001){if(this.origin.ybox.maximum.y){return false;}}else{var inv=1.0/this.direction.y;var min=(box.minimum.y-this.origin.y)*inv;var max=(box.maximum.y-this.origin.y)*inv;if(min>max){var temp=min;min=max;max=temp;}d=Math.max(min,d);maxValue=Math.min(max,maxValue);if(d>maxValue){return false;}}if(Math.abs(this.direction.z)<0.0000001){if(this.origin.zbox.maximum.z){return false;}}else{var inv=1.0/this.direction.z;var min=(box.minimum.z-this.origin.z)*inv;var max=(box.maximum.z-this.origin.z)*inv;if(min>max){var temp=min;min=max;max=temp;}d=Math.max(min,d);maxValue=Math.min(max,maxValue);if(d>maxValue){return false;}}return true;};BABYLON.Ray.prototype.intersectsSphere=function(sphere){var x=sphere.center.x-this.origin.x;var y=sphere.center.y-this.origin.y;var z=sphere.center.z-this.origin.z;var pyth=(x*x)+(y*y)+(z*z);var rr=sphere.radius*sphere.radius;if(pyth<=rr){return true;}var dot=(x*this.direction.x)+(y*this.direction.y)+(z*this.direction.z);if(dot<0.0){return false;}var temp=pyth-(dot*dot);return temp<=rr;};BABYLON.Ray.prototype.intersectsTriangle=function(vertex0,vertex1,vertex2){if(!this._edge1){this._edge1=BABYLON.Vector3.Zero();this._edge2=BABYLON.Vector3.Zero();this._pvec=BABYLON.Vector3.Zero();this._tvec=BABYLON.Vector3.Zero();this._qvec=BABYLON.Vector3.Zero();}vertex1.subtractToRef(vertex0,this._edge1);vertex2.subtractToRef(vertex0,this._edge2);BABYLON.Vector3.CrossToRef(this.direction,this._edge2,this._pvec);var det=BABYLON.Vector3.Dot(this._edge1,this._pvec);if(det===0){return 0;}var invdet=1/det;this.origin.subtractToRef(vertex0,this._tvec);var bu=BABYLON.Vector3.Dot(this._tvec,this._pvec)*invdet;if(bu<0||bu>1.0){return 0;}BABYLON.Vector3.CrossToRef(this._tvec,this._edge1,this._qvec);var bv=BABYLON.Vector3.Dot(this.direction,this._qvec)*invdet;if(bv<0||bu+bv>1.0){return 0;}return BABYLON.Vector3.Dot(this._edge2,this._qvec)*invdet;};BABYLON.Ray.CreateNew=function(x,y,viewportWidth,viewportHeight,world,view,projection){var start=BABYLON.Vector3.Unproject(new BABYLON.Vector3(x,y,0),viewportWidth,viewportHeight,world,view,projection);var end=BABYLON.Vector3.Unproject(new BABYLON.Vector3(x,y,1),viewportWidth,viewportHeight,world,view,projection);var direction=end.subtract(start);direction.normalize();return new BABYLON.Ray(start,direction);};BABYLON.Ray.Transform=function(ray,matrix){var newOrigin=BABYLON.Vector3.TransformCoordinates(ray.origin,matrix);var newDirection=BABYLON.Vector3.TransformNormal(ray.direction,matrix);return new BABYLON.Ray(newOrigin,newDirection);};BABYLON.Color3=function(initialR,initialG,initialB){this.r=initialR;this.g=initialG;this.b=initialB;};BABYLON.Color3.prototype.toString=function(){return"{R: "+this.r+" G:"+this.g+" B:"+this.b+"}";};BABYLON.Color3.prototype.multiply=function(otherColor){return new BABYLON.Color3(this.r*otherColor.r,this.g*otherColor.g,this.b*otherColor.b);};BABYLON.Color3.prototype.multiplyToRef=function(otherColor,result){result.r=this.r*otherColor.r;result.g=this.g*otherColor.g;result.b=this.b*otherColor.b;};BABYLON.Color3.prototype.equals=function(otherColor){return this.r===otherColor.r&&this.g===otherColor.g&&this.b===otherColor.b;};BABYLON.Color3.prototype.scale=function(scale){return new BABYLON.Color3(this.r*scale,this.g*scale,this.b*scale);};BABYLON.Color3.prototype.scaleToRef=function(scale,result){result.r=this.r*scale;result.g=this.g*scale;result.b=this.b*scale;};BABYLON.Color3.prototype.clone=function(){return new BABYLON.Color3(this.r,this.g,this.b);};BABYLON.Color3.prototype.copyFrom=function(source){this.r=source.r;this.g=source.g;this.b=source.b;};BABYLON.Color3.prototype.copyFromFloats=function(r,g,b){this.r=r;this.g=g;this.b=b;};BABYLON.Color3.FromArray=function(array){return new BABYLON.Color3(array[0],array[1],array[2]);};BABYLON.Color4=function(initialR,initialG,initialB,initialA){this.r=initialR;this.g=initialG;this.b=initialB;this.a=initialA;};BABYLON.Color4.prototype.addInPlace=function(right){this.r+=right.r;this.g+=right.g;this.b+=right.b;this.a+=right.a;};BABYLON.Color4.prototype.add=function(right){return new BABYLON.Color4(this.r+right.r,this.g+right.g,this.b+right.b,this.a+right.a);};BABYLON.Color4.prototype.subtract=function(right){return new BABYLON.Color4(this.r-right.r,this.g-right.g,this.b-right.b,this.a-right.a);};BABYLON.Color4.prototype.subtractToRef=function(right,result){result.r=this.r-right.r;result.g=this.g-right.g;result.b=this.b-right.b;result.a=this.a-right.a;};BABYLON.Color4.prototype.scale=function(scale){return new BABYLON.Color4(this.r*scale,this.g*scale,this.b*scale,this.a*scale);};BABYLON.Color4.prototype.scaleToRef=function(scale,result){result.r=this.r*scale;result.g=this.g*scale;result.b=this.b*scale;result.a=this.a*scale;};BABYLON.Color4.prototype.toString=function(){return"{R: "+this.r+" G:"+this.g+" B:"+this.b+" A:"+this.a+"}";};BABYLON.Color4.prototype.clone=function(){return new BABYLON.Color4(this.r,this.g,this.b,this.a);};BABYLON.Color4.Lerp=function(left,right,amount){var result=new BABYLON.Color4(0,0,0,0);BABYLON.Color4.LerpToRef(left,right,amount,result);return result;};BABYLON.Color4.LerpToRef=function(left,right,amount,result){result.r=left.r+(right.r-left.r)*amount;result.g=left.g+(right.g-left.g)*amount;result.b=left.b+(right.b-left.b)*amount;result.a=left.a+(right.a-left.a)*amount;};BABYLON.Color4.FromArray=function(array,offset){if(!offset){offset=0;}return new BABYLON.Color4(array[offset],array[offset+1],array[offset+2],array[offset+3]);};BABYLON.Vector2=function(initialX,initialY){this.x=initialX;this.y=initialY;};BABYLON.Vector2.prototype.toString=function(){return"{X: "+this.x+" Y:"+this.y+"}";};BABYLON.Vector2.prototype.add=function(otherVector){return new BABYLON.Vector2(this.x+otherVector.x,this.y+otherVector.y);};BABYLON.Vector2.prototype.subtract=function(otherVector){return new BABYLON.Vector2(this.x-otherVector.x,this.y-otherVector.y);};BABYLON.Vector2.prototype.negate=function(){return new BABYLON.Vector2(-this.x,-this.y);};BABYLON.Vector2.prototype.scaleInPlace=function(scale){this.x*=scale;this.y*=scale;};BABYLON.Vector2.prototype.scale=function(scale){return new BABYLON.Vector2(this.x*scale,this.y*scale);};BABYLON.Vector2.prototype.equals=function(otherVector){return this.x===otherVector.x&&this.y===otherVector.y;};BABYLON.Vector2.prototype.length=function(){return Math.sqrt(this.x*this.x+this.y*this.y);};BABYLON.Vector2.prototype.lengthSquared=function(){return(this.x*this.x+this.y*this.y);};BABYLON.Vector2.prototype.normalize=function(){var len=this.length();if(len===0)return;var num=1.0/len;this.x*=num;this.y*=num;};BABYLON.Vector2.prototype.clone=function(){return new BABYLON.Vector2(this.x,this.y);};BABYLON.Vector2.Zero=function(){return new BABYLON.Vector2(0,0);};BABYLON.Vector2.CatmullRom=function(value1,value2,value3,value4,amount){var squared=amount*amount;var cubed=amount*squared;var x=0.5*((((2.0*value2.x)+((-value1.x+value3.x)*amount))+(((((2.0*value1.x)-(5.0*value2.x))+(4.0*value3.x))-value4.x)*squared))+((((-value1.x+(3.0*value2.x))-(3.0*value3.x))+value4.x)*cubed));var y=0.5*((((2.0*value2.y)+((-value1.y+value3.y)*amount))+(((((2.0*value1.y)-(5.0*value2.y))+(4.0*value3.y))-value4.y)*squared))+((((-value1.y+(3.0*value2.y))-(3.0*value3.y))+value4.y)*cubed));return new BABYLON.Vector2(x,y);};BABYLON.Vector2.Clamp=function(value,min,max){var x=value.x;x=(x>max.x)?max.x:x;x=(xmax.y)?max.y:y;y=(yright.x)?left.x:right.x;var y=(left.y>right.y)?left.y:right.y;return new BABYLON.Vector2(x,y);};BABYLON.Vector2.Transform=function(vector,transformation){var x=(vector.x*transformation.m[0])+(vector.y*transformation.m[4]);var y=(vector.x*transformation.m[1])+(vector.y*transformation.m[5]);return new BABYLON.Vector2(x,y);};BABYLON.Vector2.Distance=function(value1,value2){return Math.sqrt(BABYLON.Vector2.DistanceSquared(value1,value2));};BABYLON.Vector2.DistanceSquared=function(value1,value2){var x=value1.x-value2.x;var y=value1.y-value2.y;return(x*x)+(y*y);};BABYLON.Vector3=function(initialX,initialY,initialZ){this.x=initialX;this.y=initialY;this.z=initialZ;};BABYLON.Vector3.prototype.toString=function(){return"{X: "+this.x+" Y:"+this.y+" Z:"+this.z+"}";};BABYLON.Vector3.prototype.toArray=function(array,index){array[index]=this.x;array[index+1]=this.y;array[index+2]=this.z;};BABYLON.Vector3.prototype.addInPlace=function(otherVector){this.x+=otherVector.x;this.y+=otherVector.y;this.z+=otherVector.z;};BABYLON.Vector3.prototype.add=function(otherVector){return new BABYLON.Vector3(this.x+otherVector.x,this.y+otherVector.y,this.z+otherVector.z);};BABYLON.Vector3.prototype.addToRef=function(otherVector,result){result.x=this.x+otherVector.x;result.y=this.y+otherVector.y;result.z=this.z+otherVector.z;};BABYLON.Vector3.prototype.subtractInPlace=function(otherVector){this.x-=otherVector.x;this.y-=otherVector.y;this.z-=otherVector.z;};BABYLON.Vector3.prototype.subtract=function(otherVector){return new BABYLON.Vector3(this.x-otherVector.x,this.y-otherVector.y,this.z-otherVector.z);};BABYLON.Vector3.prototype.subtractToRef=function(otherVector,result){result.x=this.x-otherVector.x;result.y=this.y-otherVector.y;result.z=this.z-otherVector.z;};BABYLON.Vector3.prototype.subtractFromFloats=function(x,y,z){return new BABYLON.Vector3(this.x-x,this.y-y,this.z-z);};BABYLON.Vector3.prototype.subtractFromFloatsToRef=function(x,y,z,result){result.x=this.x-x;result.y=this.y-y;result.z=this.z-z;};BABYLON.Vector3.prototype.negate=function(){return new BABYLON.Vector3(-this.x,-this.y,-this.z);};BABYLON.Vector3.prototype.scaleInPlace=function(scale){this.x*=scale;this.y*=scale;this.z*=scale;};BABYLON.Vector3.prototype.scale=function(scale){return new BABYLON.Vector3(this.x*scale,this.y*scale,this.z*scale);};BABYLON.Vector3.prototype.scaleToRef=function(scale,result){result.x=this.x*scale;result.y=this.y*scale;result.z=this.z*scale;};BABYLON.Vector3.prototype.equals=function(otherVector){return this.x===otherVector.x&&this.y===otherVector.y&&this.z===otherVector.z;};BABYLON.Vector3.prototype.equalsToFloats=function(x,y,z){return this.x===x&&this.y===y&&this.z===z;};BABYLON.Vector3.prototype.multiplyInPlace=function(otherVector){this.x*=otherVector.x;this.y*=otherVector.y;this.z*=otherVector.z;};BABYLON.Vector3.prototype.multiply=function(otherVector){return new BABYLON.Vector3(this.x*otherVector.x,this.y*otherVector.y,this.z*otherVector.z);};BABYLON.Vector3.prototype.multiplyToRef=function(otherVector,result){result.x=this.x*otherVector.x;result.y=this.y*otherVector.y;result.z=this.z*otherVector.z;};BABYLON.Vector3.prototype.multiplyByFloats=function(x,y,z){return new BABYLON.Vector3(this.x*x,this.y*y,this.z*z);};BABYLON.Vector3.prototype.divide=function(otherVector){return new BABYLON.Vector3(this.x/otherVector.x,this.y/otherVector.y,this.z/otherVector.z);};BABYLON.Vector3.prototype.divideToRef=function(otherVector,result){result.x=this.x/otherVector.x;result.y=this.y/otherVector.y;result.z=this.z/otherVector.z;};BABYLON.Vector3.prototype.length=function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z);};BABYLON.Vector3.prototype.lengthSquared=function(){return(this.x*this.x+this.y*this.y+this.z*this.z);};BABYLON.Vector3.prototype.normalize=function(){var len=this.length();if(len===0)return;var num=1.0/len;this.x*=num;this.y*=num;this.z*=num;};BABYLON.Vector3.prototype.clone=function(){return new BABYLON.Vector3(this.x,this.y,this.z);};BABYLON.Vector3.prototype.copyFrom=function(source){this.x=source.x;this.y=source.y;this.z=source.z;};BABYLON.Vector3.prototype.copyFromFloats=function(x,y,z){this.x=x;this.y=y;this.z=z;};BABYLON.Vector3.FromArray=function(array,offset){if(!offset){offset=0;}return new BABYLON.Vector3(array[offset],array[offset+1],array[offset+2]);};BABYLON.Vector3.FromArrayToRef=function(array,offset,result){if(!offset){offset=0;}result.x=array[offset];result.y=array[offset+1];result.z=array[offset+2];};BABYLON.Vector3.FromFloatsToRef=function(x,y,z,result){result.x=x;result.y=y;result.z=z;};BABYLON.Vector3.Zero=function(){return new BABYLON.Vector3(0,0,0);};BABYLON.Vector3.Up=function(){return new BABYLON.Vector3(0,1.0,0);};BABYLON.Vector3.TransformCoordinates=function(vector,transformation){var result=BABYLON.Vector3.Zero();BABYLON.Vector3.TransformCoordinatesToRef(vector,transformation,result);return result;};BABYLON.Vector3.TransformCoordinatesToRef=function(vector,transformation,result){var x=(vector.x*transformation.m[0])+(vector.y*transformation.m[4])+(vector.z*transformation.m[8])+transformation.m[12];var y=(vector.x*transformation.m[1])+(vector.y*transformation.m[5])+(vector.z*transformation.m[9])+transformation.m[13];var z=(vector.x*transformation.m[2])+(vector.y*transformation.m[6])+(vector.z*transformation.m[10])+transformation.m[14];var w=(vector.x*transformation.m[3])+(vector.y*transformation.m[7])+(vector.z*transformation.m[11])+transformation.m[15];result.x=x/w;result.y=y/w;result.z=z/w;};BABYLON.Vector3.TransformCoordinatesFromFloatsToRef=function(x,y,z,transformation,result){var rx=(x*transformation.m[0])+(y*transformation.m[4])+(z*transformation.m[8])+transformation.m[12];var ry=(x*transformation.m[1])+(y*transformation.m[5])+(z*transformation.m[9])+transformation.m[13];var rz=(x*transformation.m[2])+(y*transformation.m[6])+(z*transformation.m[10])+transformation.m[14];var rw=(x*transformation.m[3])+(y*transformation.m[7])+(z*transformation.m[11])+transformation.m[15];result.x=rx/rw;result.y=ry/rw;result.z=rz/rw;};BABYLON.Vector3.TransformNormal=function(vector,transformation){var result=BABYLON.Vector3.Zero();BABYLON.Vector3.TransformNormalToRef(vector,transformation,result);return result;};BABYLON.Vector3.TransformNormalToRef=function(vector,transformation,result){result.x=(vector.x*transformation.m[0])+(vector.y*transformation.m[4])+(vector.z*transformation.m[8]);result.y=(vector.x*transformation.m[1])+(vector.y*transformation.m[5])+(vector.z*transformation.m[9]);result.z=(vector.x*transformation.m[2])+(vector.y*transformation.m[6])+(vector.z*transformation.m[10]);};BABYLON.Vector3.TransformNormalFromFloatsToRef=function(x,y,z,transformation,result){result.x=(x*transformation.m[0])+(y*transformation.m[4])+(z*transformation.m[8]);result.y=(x*transformation.m[1])+(y*transformation.m[5])+(z*transformation.m[9]);result.z=(x*transformation.m[2])+(y*transformation.m[6])+(z*transformation.m[10]);};BABYLON.Vector3.CatmullRom=function(value1,value2,value3,value4,amount){var squared=amount*amount;var cubed=amount*squared;var x=0.5*((((2.0*value2.x)+((-value1.x+value3.x)*amount))+(((((2.0*value1.x)-(5.0*value2.x))+(4.0*value3.x))-value4.x)*squared))+((((-value1.x+(3.0*value2.x))-(3.0*value3.x))+value4.x)*cubed));var y=0.5*((((2.0*value2.y)+((-value1.y+value3.y)*amount))+(((((2.0*value1.y)-(5.0*value2.y))+(4.0*value3.y))-value4.y)*squared))+((((-value1.y+(3.0*value2.y))-(3.0*value3.y))+value4.y)*cubed));var z=0.5*((((2.0*value2.z)+((-value1.z+value3.z)*amount))+(((((2.0*value1.z)-(5.0*value2.z))+(4.0*value3.z))-value4.z)*squared))+((((-value1.z+(3.0*value2.z))-(3.0*value3.z))+value4.z)*cubed));return new BABYLON.Vector3(x,y,z);};BABYLON.Vector3.Clamp=function(value,min,max){var x=value.x;x=(x>max.x)?max.x:x;x=(xmax.y)?max.y:y;y=(ymax.z)?max.z:z;z=(zright.x)?left.x:right.x;var y=(left.y>right.y)?left.y:right.y;var z=(left.z>right.z)?left.z:right.z;return new BABYLON.Vector3(x,y,z);};BABYLON.Vector3.Distance=function(value1,value2){return Math.sqrt(BABYLON.Vector3.DistanceSquared(value1,value2));};BABYLON.Vector3.DistanceSquared=function(value1,value2){var x=value1.x-value2.x;var y=value1.y-value2.y;var z=value1.z-value2.z;return(x*x)+(y*y)+(z*z);};BABYLON.Quaternion=function(initialX,initialY,initialZ,initialW){this.x=initialX;this.y=initialY;this.z=initialZ;this.w=initialW;};BABYLON.Quaternion.prototype.toString=function(){return"{X: "+this.x+" Y:"+this.y+" Z:"+this.z+" W:"+this.w+"}";};BABYLON.Quaternion.prototype.equals=function(otherQuaternion){return this.x===otherQuaternion.x&&this.y===otherQuaternion.y&&this.z===otherQuaternion.z&&this.w===otherQuaternion.w;};BABYLON.Quaternion.prototype.clone=function(){return new BABYLON.Quaternion(this.x,this.y,this.z,this.w);};BABYLON.Quaternion.prototype.copyFrom=function(other){this.x=other.x;this.y=other.y;this.z=other.z;this.w=other.w;};BABYLON.Quaternion.prototype.add=function(other){return new BABYLON.Quaternion(this.x+other.x,this.y+other.y,this.z+other.z,this.w+other.w);};BABYLON.Quaternion.prototype.scale=function(value){return new BABYLON.Quaternion(this.x*value,this.y*value,this.z*value,this.w*value);};BABYLON.Quaternion.prototype.multiply=function(q1){var result=new BABYLON.Quaternion(0,0,0,1.0);this.multiplyToRef(q1,result);return result;};BABYLON.Quaternion.prototype.multiplyToRef=function(q1,result){result.x=this.x*q1.w+this.y*q1.z-this.z*q1.y+this.w*q1.x;result.y=-this.x*q1.z+this.y*q1.w+this.z*q1.x+this.w*q1.y;result.z=this.x*q1.y-this.y*q1.x+this.z*q1.w+this.w*q1.z;result.w=-this.x*q1.x-this.y*q1.y-this.z*q1.z+this.w*q1.w;};BABYLON.Quaternion.prototype.length=function(){return Math.sqrt((this.x*this.x)+(this.y*this.y)+(this.z*this.z)+(this.w*this.w));};BABYLON.Quaternion.prototype.normalize=function(){var length=1.0/this.length();this.x*=length;this.y*=length;this.z*=length;this.w*=length;};BABYLON.Quaternion.prototype.toEulerAngles=function(){var qx=this.x;var qy=this.y;var qz=this.z;var qw=this.w;var sqx=qx*qx;var sqy=qy*qy;var sqz=qz*qz;var yaw=Math.atan2(2.0*(qy*qw-qx*qz),1.0-2.0*(sqy+sqz));var pitch=Math.asin(2.0*(qx*qy+qz*qw));var roll=Math.atan2(2.0*(qx*qw-qy*qz),1.0-2.0*(sqx+sqz));var gimbaLockTest=qx*qy+qz*qw;if(gimbaLockTest>0.499){yaw=2.0*Math.atan2(qx,qw);roll=0;}else if(gimbaLockTest<-0.499){yaw=-2.0*Math.atan2(qx,qw);roll=0;}return new BABYLON.Vector3(pitch,yaw,roll);};BABYLON.Quaternion.prototype.toRotationMatrix=function(result){var xx=this.x*this.x;var yy=this.y*this.y;var zz=this.z*this.z;var xy=this.x*this.y;var zw=this.z*this.w;var zx=this.z*this.x;var yw=this.y*this.w;var yz=this.y*this.z;var xw=this.x*this.w;result.m[0]=1.0-(2.0*(yy+zz));result.m[1]=2.0*(xy+zw);result.m[2]=2.0*(zx-yw);result.m[3]=0;result.m[4]=2.0*(xy-zw);result.m[5]=1.0-(2.0*(zz+xx));result.m[6]=2.0*(yz+xw);result.m[7]=0;result.m[8]=2.0*(zx+yw);result.m[9]=2.0*(yz-xw);result.m[10]=1.0-(2.0*(yy+xx));result.m[11]=0;result.m[12]=0;result.m[13]=0;result.m[14]=0;result.m[15]=1.0;};BABYLON.Quaternion.FromArray=function(array,offset){if(!offset){offset=0;}return new BABYLON.Quaternion(array[offset],array[offset+1],array[offset+2],array[offset+3]);};BABYLON.Quaternion.RotationYawPitchRoll=function(yaw,pitch,roll){var result=new BABYLON.Quaternion();BABYLON.Quaternion.RotationYawPitchRollToRef(yaw,pitch,roll,result);return result;};BABYLON.Quaternion.RotationYawPitchRollToRef=function(yaw,pitch,roll,result){var halfRoll=roll*0.5;var halfPitch=pitch*0.5;var halfYaw=yaw*0.5;var sinRoll=Math.sin(halfRoll);var cosRoll=Math.cos(halfRoll);var sinPitch=Math.sin(halfPitch);var cosPitch=Math.cos(halfPitch);var sinYaw=Math.sin(halfYaw);var cosYaw=Math.cos(halfYaw);result.x=(cosYaw*sinPitch*cosRoll)+(sinYaw*cosPitch*sinRoll);result.y=(sinYaw*cosPitch*cosRoll)-(cosYaw*sinPitch*sinRoll);result.z=(cosYaw*cosPitch*sinRoll)-(sinYaw*sinPitch*cosRoll);result.w=(cosYaw*cosPitch*cosRoll)+(sinYaw*sinPitch*sinRoll);};BABYLON.Quaternion.Slerp=function(left,right,amount){var num2;var num3;var num=amount;var num4=(((left.x*right.x)+(left.y*right.y))+(left.z*right.z))+(left.w*right.w);var flag=false;if(num4<0){flag=true;num4=-num4;}if(num4>0.999999){num3=1-num;num2=flag?-num:num;}else{var num5=Math.acos(num4);var num6=(1.0/Math.sin(num5));num3=(Math.sin((1.0-num)*num5))*num6;num2=flag?((-Math.sin(num*num5))*num6):((Math.sin(num*num5))*num6);}return new BABYLON.Quaternion((num3*left.x)+(num2*right.x),(num3*left.y)+(num2*right.y),(num3*left.z)+(num2*right.z),(num3*left.w)+(num2*right.w));};if(!BABYLON.MatrixType){BABYLON.MatrixType=(typeof Float32Array!=='undefined')?Float32Array:Array;}BABYLON.Matrix=function(){this.m=new BABYLON.MatrixType(16);};BABYLON.Matrix.prototype.isIdentity=function(){if(this.m[0]!=1.0||this.m[5]!=1.0||this.m[10]!=1.0||this.m[15]!=1.0)return false;if(this.m[1]!=0.0||this.m[2]!=0.0||this.m[3]!=0.0||this.m[4]!=0.0||this.m[6]!=0.0||this.m[7]!=0.0||this.m[8]!=0.0||this.m[9]!=0.0||this.m[11]!=0.0||this.m[12]!=0.0||this.m[13]!=0.0||this.m[14]!=0.0)return false;return true;};BABYLON.Matrix.prototype.determinant=function(){var temp1=(this.m[10]*this.m[15])-(this.m[11]*this.m[14]);var temp2=(this.m[9]*this.m[15])-(this.m[11]*this.m[13]);var temp3=(this.m[9]*this.m[14])-(this.m[10]*this.m[13]);var temp4=(this.m[8]*this.m[15])-(this.m[11]*this.m[12]);var temp5=(this.m[8]*this.m[14])-(this.m[10]*this.m[12]);var temp6=(this.m[8]*this.m[13])-(this.m[9]*this.m[12]);return((((this.m[0]*(((this.m[5]*temp1)-(this.m[6]*temp2))+(this.m[7]*temp3)))-(this.m[1]*(((this.m[4]*temp1)-(this.m[6]*temp4))+(this.m[7]*temp5))))+(this.m[2]*(((this.m[4]*temp2)-(this.m[5]*temp4))+(this.m[7]*temp6))))-(this.m[3]*(((this.m[4]*temp3)-(this.m[5]*temp5))+(this.m[6]*temp6))));};BABYLON.Matrix.prototype.toArray=function(){return this.m;};BABYLON.Matrix.prototype.invert=function(){this.invertToRef(this);};BABYLON.Matrix.prototype.invertToRef=function(other){var l1=this.m[0];var l2=this.m[1];var l3=this.m[2];var l4=this.m[3];var l5=this.m[4];var l6=this.m[5];var l7=this.m[6];var l8=this.m[7];var l9=this.m[8];var l10=this.m[9];var l11=this.m[10];var l12=this.m[11];var l13=this.m[12];var l14=this.m[13];var l15=this.m[14];var l16=this.m[15];var l17=(l11*l16)-(l12*l15);var l18=(l10*l16)-(l12*l14);var l19=(l10*l15)-(l11*l14);var l20=(l9*l16)-(l12*l13);var l21=(l9*l15)-(l11*l13);var l22=(l9*l14)-(l10*l13);var l23=((l6*l17)-(l7*l18))+(l8*l19);var l24=-(((l5*l17)-(l7*l20))+(l8*l21));var l25=((l5*l18)-(l6*l20))+(l8*l22);var l26=-(((l5*l19)-(l6*l21))+(l7*l22));var l27=1.0/((((l1*l23)+(l2*l24))+(l3*l25))+(l4*l26));var l28=(l7*l16)-(l8*l15);var l29=(l6*l16)-(l8*l14);var l30=(l6*l15)-(l7*l14);var l31=(l5*l16)-(l8*l13);var l32=(l5*l15)-(l7*l13);var l33=(l5*l14)-(l6*l13);var l34=(l7*l12)-(l8*l11);var l35=(l6*l12)-(l8*l10);var l36=(l6*l11)-(l7*l10);var l37=(l5*l12)-(l8*l9);var l38=(l5*l11)-(l7*l9);var l39=(l5*l10)-(l6*l9);other.m[0]=l23*l27;other.m[4]=l24*l27;other.m[8]=l25*l27;other.m[12]=l26*l27;other.m[1]=-(((l2*l17)-(l3*l18))+(l4*l19))*l27;other.m[5]=(((l1*l17)-(l3*l20))+(l4*l21))*l27;other.m[9]=-(((l1*l18)-(l2*l20))+(l4*l22))*l27;other.m[13]=(((l1*l19)-(l2*l21))+(l3*l22))*l27;other.m[2]=(((l2*l28)-(l3*l29))+(l4*l30))*l27;other.m[6]=-(((l1*l28)-(l3*l31))+(l4*l32))*l27;other.m[10]=(((l1*l29)-(l2*l31))+(l4*l33))*l27;other.m[14]=-(((l1*l30)-(l2*l32))+(l3*l33))*l27;other.m[3]=-(((l2*l34)-(l3*l35))+(l4*l36))*l27;other.m[7]=(((l1*l34)-(l3*l37))+(l4*l38))*l27;other.m[11]=-(((l1*l35)-(l2*l37))+(l4*l39))*l27;other.m[15]=(((l1*l36)-(l2*l38))+(l3*l39))*l27;};BABYLON.Matrix.prototype.setTranslation=function(vector3){this.m[12]=vector3.x;this.m[13]=vector3.y;this.m[14]=vector3.z;};BABYLON.Matrix.prototype.multiply=function(other){var result=new BABYLON.Matrix();this.multiplyToRef(other,result);return result;};BABYLON.Matrix.prototype.copyFrom=function(other){for(var index=0;index<16;index++){this.m[index]=other.m[index];}};BABYLON.Matrix.prototype.multiplyToRef=function(other,result){this.multiplyToArray(other,result.m,0);};BABYLON.Matrix.prototype.multiplyToArray=function(other,result,offset){result[offset]=this.m[0]*other.m[0]+this.m[1]*other.m[4]+this.m[2]*other.m[8]+this.m[3]*other.m[12];result[offset+1]=this.m[0]*other.m[1]+this.m[1]*other.m[5]+this.m[2]*other.m[9]+this.m[3]*other.m[13];result[offset+2]=this.m[0]*other.m[2]+this.m[1]*other.m[6]+this.m[2]*other.m[10]+this.m[3]*other.m[14];result[offset+3]=this.m[0]*other.m[3]+this.m[1]*other.m[7]+this.m[2]*other.m[11]+this.m[3]*other.m[15];result[offset+4]=this.m[4]*other.m[0]+this.m[5]*other.m[4]+this.m[6]*other.m[8]+this.m[7]*other.m[12];result[offset+5]=this.m[4]*other.m[1]+this.m[5]*other.m[5]+this.m[6]*other.m[9]+this.m[7]*other.m[13];result[offset+6]=this.m[4]*other.m[2]+this.m[5]*other.m[6]+this.m[6]*other.m[10]+this.m[7]*other.m[14];result[offset+7]=this.m[4]*other.m[3]+this.m[5]*other.m[7]+this.m[6]*other.m[11]+this.m[7]*other.m[15];result[offset+8]=this.m[8]*other.m[0]+this.m[9]*other.m[4]+this.m[10]*other.m[8]+this.m[11]*other.m[12];result[offset+9]=this.m[8]*other.m[1]+this.m[9]*other.m[5]+this.m[10]*other.m[9]+this.m[11]*other.m[13];result[offset+10]=this.m[8]*other.m[2]+this.m[9]*other.m[6]+this.m[10]*other.m[10]+this.m[11]*other.m[14];result[offset+11]=this.m[8]*other.m[3]+this.m[9]*other.m[7]+this.m[10]*other.m[11]+this.m[11]*other.m[15];result[offset+12]=this.m[12]*other.m[0]+this.m[13]*other.m[4]+this.m[14]*other.m[8]+this.m[15]*other.m[12];result[offset+13]=this.m[12]*other.m[1]+this.m[13]*other.m[5]+this.m[14]*other.m[9]+this.m[15]*other.m[13];result[offset+14]=this.m[12]*other.m[2]+this.m[13]*other.m[6]+this.m[14]*other.m[10]+this.m[15]*other.m[14];result[offset+15]=this.m[12]*other.m[3]+this.m[13]*other.m[7]+this.m[14]*other.m[11]+this.m[15]*other.m[15];};BABYLON.Matrix.prototype.equals=function(value){return(this.m[0]===value.m[0]&&this.m[1]===value.m[1]&&this.m[2]===value.m[2]&&this.m[3]===value.m[3]&&this.m[4]===value.m[4]&&this.m[5]===value.m[5]&&this.m[6]===value.m[6]&&this.m[7]===value.m[7]&&this.m[8]===value.m[8]&&this.m[9]===value.m[9]&&this.m[10]===value.m[10]&&this.m[11]===value.m[11]&&this.m[12]===value.m[12]&&this.m[13]===value.m[13]&&this.m[14]===value.m[14]&&this.m[15]===value.m[15]);};BABYLON.Matrix.prototype.clone=function(){return BABYLON.Matrix.FromValues(this.m[0],this.m[1],this.m[2],this.m[3],this.m[4],this.m[5],this.m[6],this.m[7],this.m[8],this.m[9],this.m[10],this.m[11],this.m[12],this.m[13],this.m[14],this.m[15]);};BABYLON.Matrix.FromArray=function(array,offset){var result=new BABYLON.Matrix();BABYLON.Matrix.FromArrayToRef(array,offset,result);return result;};BABYLON.Matrix.FromArrayToRef=function(array,offset,result){if(!offset){offset=0;}for(var index=0;index<16;index++){result.m[index]=array[index+offset];}};BABYLON.Matrix.FromValuesToRef=function(initialM11,initialM12,initialM13,initialM14,initialM21,initialM22,initialM23,initialM24,initialM31,initialM32,initialM33,initialM34,initialM41,initialM42,initialM43,initialM44,result){result.m[0]=initialM11;result.m[1]=initialM12;result.m[2]=initialM13;result.m[3]=initialM14;result.m[4]=initialM21;result.m[5]=initialM22;result.m[6]=initialM23;result.m[7]=initialM24;result.m[8]=initialM31;result.m[9]=initialM32;result.m[10]=initialM33;result.m[11]=initialM34;result.m[12]=initialM41;result.m[13]=initialM42;result.m[14]=initialM43;result.m[15]=initialM44;};BABYLON.Matrix.FromValues=function(initialM11,initialM12,initialM13,initialM14,initialM21,initialM22,initialM23,initialM24,initialM31,initialM32,initialM33,initialM34,initialM41,initialM42,initialM43,initialM44){var result=new BABYLON.Matrix();result.m[0]=initialM11;result.m[1]=initialM12;result.m[2]=initialM13;result.m[3]=initialM14;result.m[4]=initialM21;result.m[5]=initialM22;result.m[6]=initialM23;result.m[7]=initialM24;result.m[8]=initialM31;result.m[9]=initialM32;result.m[10]=initialM33;result.m[11]=initialM34;result.m[12]=initialM41;result.m[13]=initialM42;result.m[14]=initialM43;result.m[15]=initialM44;return result;};BABYLON.Matrix.Identity=function(){return BABYLON.Matrix.FromValues(1.0,0,0,0,0,1.0,0,0,0,0,1.0,0,0,0,0,1.0);};BABYLON.Matrix.IdentityToRef=function(result){BABYLON.Matrix.FromValuesToRef(1.0,0,0,0,0,1.0,0,0,0,0,1.0,0,0,0,0,1.0,result);};BABYLON.Matrix.Zero=function(){return BABYLON.Matrix.FromValues(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);};BABYLON.Matrix.RotationX=function(angle){var result=new BABYLON.Matrix();BABYLON.Matrix.RotationXToRef(angle,result);return result;};BABYLON.Matrix.RotationXToRef=function(angle,result){var s=Math.sin(angle);var c=Math.cos(angle);result.m[0]=1.0;result.m[15]=1.0;result.m[5]=c;result.m[10]=c;result.m[9]=-s;result.m[6]=s;result.m[1]=0;result.m[2]=0;result.m[3]=0;result.m[4]=0;result.m[7]=0;result.m[8]=0;result.m[11]=0;result.m[12]=0;result.m[13]=0;result.m[14]=0;};BABYLON.Matrix.RotationY=function(angle){var result=new BABYLON.Matrix();BABYLON.Matrix.RotationYToRef(angle,result);return result;};BABYLON.Matrix.RotationYToRef=function(angle,result){var s=Math.sin(angle);var c=Math.cos(angle);result.m[5]=1.0;result.m[15]=1.0;result.m[0]=c;result.m[2]=-s;result.m[8]=s;result.m[10]=c;result.m[1]=0;result.m[3]=0;result.m[4]=0;result.m[6]=0;result.m[7]=0;result.m[9]=0;result.m[11]=0;result.m[12]=0;result.m[13]=0;result.m[14]=0;};BABYLON.Matrix.RotationZ=function(angle){var result=new BABYLON.Matrix();BABYLON.Matrix.RotationZToRef(angle,result);return result;};BABYLON.Matrix.RotationZToRef=function(angle,result){var s=Math.sin(angle);var c=Math.cos(angle);result.m[10]=1.0;result.m[15]=1.0;result.m[0]=c;result.m[1]=s;result.m[4]=-s;result.m[5]=c;result.m[2]=0;result.m[3]=0;result.m[6]=0;result.m[7]=0;result.m[8]=0;result.m[9]=0;result.m[11]=0;result.m[12]=0;result.m[13]=0;result.m[14]=0;};BABYLON.Matrix.RotationAxis=function(axis,angle){var s=Math.sin(-angle);var c=Math.cos(-angle);var c1=1-c;axis.normalize();var result=BABYLON.Matrix.Zero();result.m[0]=(axis.x*axis.x)*c1+c;result.m[1]=(axis.x*axis.y)*c1-(axis.z*s);result.m[2]=(axis.x*axis.z)*c1+(axis.y*s);result.m[3]=0.0;result.m[4]=(axis.y*axis.x)*c1+(axis.z*s);result.m[5]=(axis.y*axis.y)*c1+c;result.m[6]=(axis.y*axis.z)*c1-(axis.x*s);result.m[7]=0.0;result.m[8]=(axis.z*axis.x)*c1-(axis.y*s);result.m[9]=(axis.z*axis.y)*c1+(axis.x*s);result.m[10]=(axis.z*axis.z)*c1+c;result.m[11]=0.0;result.m[15]=1.0;return result;};BABYLON.Matrix.RotationYawPitchRoll=function(yaw,pitch,roll){var result=new BABYLON.Matrix();BABYLON.Matrix.RotationYawPitchRollToRef(yaw,pitch,roll,result);return result;};var tempQuaternion=new BABYLON.Quaternion();BABYLON.Matrix.RotationYawPitchRollToRef=function(yaw,pitch,roll,result){BABYLON.Quaternion.RotationYawPitchRollToRef(yaw,pitch,roll,tempQuaternion);tempQuaternion.toRotationMatrix(result);};BABYLON.Matrix.Scaling=function(x,y,z){var result=BABYLON.Matrix.Zero();BABYLON.Matrix.ScalingToRef(x,y,z,result);return result;};BABYLON.Matrix.ScalingToRef=function(x,y,z,result){result.m[0]=x;result.m[1]=0;result.m[2]=0;result.m[3]=0;result.m[4]=0;result.m[5]=y;result.m[6]=0;result.m[7]=0;result.m[8]=0;result.m[9]=0;result.m[10]=z;result.m[11]=0;result.m[12]=0;result.m[13]=0;result.m[14]=0;result.m[15]=1.0;};BABYLON.Matrix.Translation=function(x,y,z){var result=BABYLON.Matrix.Identity();BABYLON.Matrix.TranslationToRef(x,y,z,result);return result;};BABYLON.Matrix.TranslationToRef=function(x,y,z,result){BABYLON.Matrix.FromValuesToRef(1.0,0,0,0,0,1.0,0,0,0,0,1.0,0,x,y,z,1.0,result);};BABYLON.Matrix.LookAtLH=function(eye,target,up){var result=BABYLON.Matrix.Zero();BABYLON.Matrix.LookAtLHToRef(eye,target,up,result);return result;};var xAxis=BABYLON.Vector3.Zero();var yAxis=BABYLON.Vector3.Zero();var zAxis=BABYLON.Vector3.Zero();BABYLON.Matrix.LookAtLHToRef=function(eye,target,up,result){target.subtractToRef(eye,zAxis);zAxis.normalize();BABYLON.Vector3.CrossToRef(up,zAxis,xAxis);xAxis.normalize();BABYLON.Vector3.CrossToRef(zAxis,xAxis,yAxis);yAxis.normalize();var ex=-BABYLON.Vector3.Dot(xAxis,eye);var ey=-BABYLON.Vector3.Dot(yAxis,eye);var ez=-BABYLON.Vector3.Dot(zAxis,eye);return BABYLON.Matrix.FromValuesToRef(xAxis.x,yAxis.x,zAxis.x,0,xAxis.y,yAxis.y,zAxis.y,0,xAxis.z,yAxis.z,zAxis.z,0,ex,ey,ez,1,result);};BABYLON.Matrix.OrthoLH=function(width,height,znear,zfar){var hw=2.0/width;var hh=2.0/height;var id=1.0/(zfar-znear);var nid=znear/(znear-zfar);return BABYLON.Matrix.FromValues(hw,0,0,0,0,hh,0,0,0,0,id,0,0,0,nid,1);};BABYLON.Matrix.OrthoOffCenterLH=function(left,right,bottom,top,znear,zfar){var matrix=BABYLON.Matrix.Zero();BABYLON.Matrix.OrthoOffCenterLHToRef(left,right,bottom,top,znear,zfar,matrix);return matrix;};BABYLON.Matrix.OrthoOffCenterLHToRef=function(left,right,bottom,top,znear,zfar,result){result.m[0]=2.0/(right-left);result.m[1]=result.m[2]=result.m[3]=0;result.m[5]=2.0/(top-bottom);result.m[4]=result.m[6]=result.m[7]=0;result.m[10]=-1.0/(znear-zfar);result.m[8]=result.m[9]=result.m[11]=0;result.m[12]=(left+right)/(left-right);result.m[13]=(top+bottom)/(bottom-top);result.m[14]=znear/(znear-zfar);result.m[15]=1.0;};BABYLON.Matrix.PerspectiveLH=function(width,height,znear,zfar){var matrix=BABYLON.Matrix.Zero();matrix.m[0]=(2.0*znear)/width;matrix.m[1]=matrix.m[2]=matrix.m[3]=0.0;matrix.m[5]=(2.0*znear)/height;matrix.m[4]=matrix.m[6]=matrix.m[7]=0.0;matrix.m[10]=-zfar/(znear-zfar);matrix.m[8]=matrix.m[9]=0.0;matrix.m[11]=1.0;matrix.m[12]=matrix.m[13]=matrix.m[15]=0.0;matrix.m[14]=(znear*zfar)/(znear-zfar);return matrix;};BABYLON.Matrix.PerspectiveFovLH=function(fov,aspect,znear,zfar){var matrix=BABYLON.Matrix.Zero();BABYLON.Matrix.PerspectiveFovLHToRef(fov,aspect,znear,zfar,matrix);return matrix;};BABYLON.Matrix.PerspectiveFovLHToRef=function(fov,aspect,znear,zfar,result){var tan=1.0/(Math.tan(fov*0.5));result.m[0]=tan/aspect;result.m[1]=result.m[2]=result.m[3]=0.0;result.m[5]=tan;result.m[4]=result.m[6]=result.m[7]=0.0;result.m[8]=result.m[9]=0.0;result.m[10]=-zfar/(znear-zfar);result.m[11]=1.0;result.m[12]=result.m[13]=result.m[15]=0.0;result.m[14]=(znear*zfar)/(znear-zfar);};BABYLON.Matrix.AffineTransformation=function(scaling,rotationCenter,rotation,translation){return BABYLON.Matrix.Scaling(scaling,scaling,scaling)*BABYLON.Matrix.Translation(-rotationCenter)*BABYLON.Matrix.RotationQuaternion(rotation)*BABYLON.Matrix.Translation(rotationCenter)*BABYLON.Matrix.Translation(translation);};BABYLON.Matrix.GetFinalMatrix=function(viewport,world,view,projection,zmin,zmax){var cw=viewport.width;var ch=viewport.height;var cx=viewport.x;var cy=viewport.y;var viewportMatrix=new BABYLON.Matrix(cw/2.0,0,0,0,0,-ch/2.0,0,0,0,0,zmax-zmin,0,cx+cw/2.0,ch/2.0+cy,zmin,1);return world.multiply(view).multiply(projection).multiply(viewportMatrix);};BABYLON.Matrix.Transpose=function(matrix){var result=new BABYLON.Matrix();result.m[0]=matrix.m[0];result.m[1]=matrix.m[4];result.m[2]=matrix.m[8];result.m[3]=matrix.m[12];result.m[4]=matrix.m[1];result.m[5]=matrix.m[5];result.m[6]=matrix.m[9];result.m[7]=matrix.m[13];result.m[8]=matrix.m[2];result.m[9]=matrix.m[6];result.m[10]=matrix.m[10];result.m[11]=matrix.m[14];result.m[12]=matrix.m[3];result.m[13]=matrix.m[7];result.m[14]=matrix.m[11];result.m[15]=matrix.m[15];return result;};BABYLON.Matrix.Reflection=function(plane){var matrix=new BABYLON.Matrix();BABYLON.Matrix.ReflectionToRef(plane,matrix);return matrix;};BABYLON.Matrix.ReflectionToRef=function(plane,result){plane.normalize();var x=plane.normal.x;var y=plane.normal.y;var z=plane.normal.z;var temp=-2*x;var temp2=-2*y;var temp3=-2*z;result.m[0]=(temp*x)+1;result.m[1]=temp2*x;result.m[2]=temp3*x;result.m[3]=0.0;result.m[4]=temp*y;result.m[5]=(temp2*y)+1;result.m[6]=temp3*y;result.m[7]=0.0;result.m[8]=temp*z;result.m[9]=temp2*z;result.m[10]=(temp3*z)+1;result.m[11]=0.0;result.m[12]=temp*plane.d;result.m[13]=temp2*plane.d;result.m[14]=temp3*plane.d;result.m[15]=1.0;};BABYLON.Plane=function(a,b,c,d){this.normal=new BABYLON.Vector3(a,b,c);this.d=d;};BABYLON.Plane.prototype.normalize=function(){var norm=(Math.sqrt((this.normal.x*this.normal.x)+(this.normal.y*this.normal.y)+(this.normal.z*this.normal.z)));var magnitude=0;if(norm!=0){magnitude=1.0/norm;}this.normal.x*=magnitude;this.normal.y*=magnitude;this.normal.z*=magnitude;this.d*=magnitude;};BABYLON.Plane.prototype.transform=function(transformation){var transposedMatrix=BABYLON.Matrix.Transpose(transformation);var x=this.normal.x;var y=this.normal.y;var z=this.normal.z;var d=this.d;var normalX=(((x*transposedMatrix.m[0])+(y*transposedMatrix.m[1]))+(z*transposedMatrix.m[2]))+(d*transposedMatrix.m[3]);var normalY=(((x*transposedMatrix.m[4])+(y*transposedMatrix.m[5]))+(z*transposedMatrix.m[6]))+(d*transposedMatrix.m[7]);var normalZ=(((x*transposedMatrix.m[8])+(y*transposedMatrix.m[9]))+(z*transposedMatrix.m[10]))+(d*transposedMatrix.m[11]);var finalD=(((x*transposedMatrix.m[12])+(y*transposedMatrix.m[13]))+(z*transposedMatrix.m[14]))+(d*transposedMatrix.m[15]);return new BABYLON.Plane(normalX,normalY,normalZ,finalD);};BABYLON.Plane.prototype.dotCoordinate=function(point){return((((this.normal.x*point.x)+(this.normal.y*point.y))+(this.normal.z*point.z))+this.d);};BABYLON.Plane.prototype.copyFromPoints=function(point1,point2,point3){var x1=point2.x-point1.x;var y1=point2.y-point1.y;var z1=point2.z-point1.z;var x2=point3.x-point1.x;var y2=point3.y-point1.y;var z2=point3.z-point1.z;var yz=(y1*z2)-(z1*y2);var xz=(z1*x2)-(x1*z2);var xy=(x1*y2)-(y1*x2);var pyth=(Math.sqrt((yz*yz)+(xz*xz)+(xy*xy)));var invPyth;if(pyth!=0){invPyth=1.0/pyth;}else{invPyth=0;}this.normal.x=yz*invPyth;this.normal.y=xz*invPyth;this.normal.z=xy*invPyth;this.d=-((this.normal.x*point1.x)+(this.normal.y*point1.y)+(this.normal.z*point1.z));};BABYLON.Plane.prototype.isFrontFacingTo=function(direction,epsilon){var dot=BABYLON.Vector3.Dot(this.normal,direction);return(dot<=epsilon);};BABYLON.Plane.prototype.signedDistanceTo=function(point){return BABYLON.Vector3.Dot(point,this.normal)+this.d;};BABYLON.Plane.FromArray=function(array){return new BABYLON.Plane(array[0],array[1],array[2],array[3]);};BABYLON.Plane.FromPoints=function(point1,point2,point3){var result=new BABYLON.Plane(0,0,0,0);result.copyFromPoints(point1,point2,point3);return result;};BABYLON.Plane.FromPositionAndNormal=function(origin,normal){var result=new BABYLON.Plane(0,0,0,0);normal.normalize();result.normal=normal;result.d=-(normal.x*origin.x+normal.y*origin.y+normal.z*origin.z);return result;};BABYLON.Plane.SignedDistanceToPlaneFromPositionAndNormal=function(origin,normal,point){var d=-(normal.x*origin.x+normal.y*origin.y+normal.z*origin.z);return BABYLON.Vector3.Dot(point,normal)+d;};BABYLON.Frustum={};BABYLON.Frustum.GetPlanes=function(transform){var frustumPlanes=[];for(var index=0;index<6;index++){frustumPlanes.push(new BABYLON.Plane(0,0,0,0));}BABYLON.Frustum.GetPlanesToRef(transform,frustumPlanes);return frustumPlanes;};BABYLON.Frustum.GetPlanesToRef=function(transform,frustumPlanes){frustumPlanes[0].normal.x=transform.m[3]+transform.m[2];frustumPlanes[0].normal.y=transform.m[7]+transform.m[6];frustumPlanes[0].normal.z=transform.m[10]+transform.m[10];frustumPlanes[0].d=transform.m[15]+transform.m[14];frustumPlanes[0].normalize();frustumPlanes[1].normal.x=transform.m[3]-transform.m[2];frustumPlanes[1].normal.y=transform.m[7]-transform.m[6];frustumPlanes[1].normal.z=transform.m[11]-transform.m[10];frustumPlanes[1].d=transform.m[15]-transform.m[14];frustumPlanes[1].normalize();frustumPlanes[2].normal.x=transform.m[3]+transform.m[0];frustumPlanes[2].normal.y=transform.m[7]+transform.m[4];frustumPlanes[2].normal.z=transform.m[11]+transform.m[8];frustumPlanes[2].d=transform.m[15]+transform.m[12];frustumPlanes[2].normalize();frustumPlanes[3].normal.x=transform.m[3]-transform.m[0];frustumPlanes[3].normal.y=transform.m[7]-transform.m[4];frustumPlanes[3].normal.z=transform.m[11]-transform.m[8];frustumPlanes[3].d=transform.m[15]-transform.m[12];frustumPlanes[3].normalize();frustumPlanes[4].normal.x=transform.m[3]-transform.m[1];frustumPlanes[4].normal.y=transform.m[7]-transform.m[5];frustumPlanes[4].normal.z=transform.m[11]-transform.m[9];frustumPlanes[4].d=transform.m[15]-transform.m[13];frustumPlanes[4].normalize();frustumPlanes[5].normal.x=transform.m[3]+transform.m[1];frustumPlanes[5].normal.y=transform.m[7]+transform.m[5];frustumPlanes[5].normal.z=transform.m[11]+transform.m[9];frustumPlanes[5].d=transform.m[15]+transform.m[13];frustumPlanes[5].normalize();};BABYLON.Viewport={};BABYLON.Viewport=function(x,y,width,height){this.width=width;this.height=height;this.x=x;this.y=y;};BABYLON.Viewport.prototype.toGlobal=function(engine){var width=engine.getRenderWidth()*engine.getHardwareScalingLevel();var height=engine.getRenderHeight()*engine.getHardwareScalingLevel();return new BABYLON.Viewport(this.x*width,this.y*height,this.width*width,this.height*height);};})();var BABYLON=BABYLON||{};(function(){BABYLON.Tools={};BABYLON.Tools.ExtractMinAndMax=function(positions,start,count){var minimum=new BABYLON.Vector3(Number.MAX_VALUE,Number.MAX_VALUE,Number.MAX_VALUE);var maximum=new BABYLON.Vector3(-Number.MAX_VALUE,-Number.MAX_VALUE,-Number.MAX_VALUE);for(var index=start;indexthis.data.length){this.data.length*=2;}};BABYLON.Tools.SmartArray.prototype.pushNoDuplicate=function(value){if(this.indexOf(value)>-1){return;}this.push(value);};BABYLON.Tools.SmartArray.prototype.sort=function(compareFn){this.data.sort(compareFn);};BABYLON.Tools.SmartArray.prototype.reset=function(){this.length=0;};BABYLON.Tools.SmartArray.prototype.concat=function(array){if(array.length===0){return;}if(this.length+array.length>this.data.length){this.data.length=(this.length+array.length)*2;}for(var index=0;indexthis.data.length){this.data.length=(this.length+array.length)*2;}for(var index=0;index=this.length){this.data[this.length++]=item;}}};BABYLON.Tools.SmartArray.prototype.indexOf=function(value){var position=this.data.indexOf(value);if(position>=this.length){return-1;}return position;};BABYLON.Tools.GetPointerPrefix=function(){var eventPrefix="pointer";if(!navigator.pointerEnabled){eventPrefix="mouse";}return eventPrefix;};BABYLON.Tools.QueueNewFrame=function(func){if(window.requestAnimationFrame)window.requestAnimationFrame(func);else if(window.msRequestAnimationFrame)window.msRequestAnimationFrame(func);else if(window.webkitRequestAnimationFrame)window.webkitRequestAnimationFrame(func);else if(window.mozRequestAnimationFrame)window.mozRequestAnimationFrame(func);else if(window.oRequestAnimationFrame)window.oRequestAnimationFrame(func);else{window.setTimeout(func,16);}};BABYLON.Tools.RequestFullscreen=function(element){if(element.requestFullscreen)element.requestFullscreen();else if(element.msRequestFullscreen)element.msRequestFullscreen();else if(element.webkitRequestFullscreen)element.webkitRequestFullscreen();else if(element.mozRequestFullScreen)element.mozRequestFullScreen();};BABYLON.Tools.ExitFullscreen=function(){if(document.exitFullscreen){document.exitFullscreen();}else if(document.mozCancelFullScreen){document.mozCancelFullScreen();}else if(document.webkitCancelFullScreen){document.webkitCancelFullScreen();}else if(document.msCancelFullScreen){document.msCancelFullScreen();}};BABYLON.Tools.BaseUrl="";BABYLON.Tools.LoadImage=function(url,onload,onerror,database){var img=new Image();img.onload=function(){onload(img);};img.onerror=function(err){onerror(img,err);};var noIndexedDB=function(){img.src=url;};var loadFromIndexedDB=function(){database.loadImageFromDB(url,img);};if(database&&database.enableTexturesOffline&&BABYLON.Database.isUASupportingBlobStorage){database.openAsync(loadFromIndexedDB,noIndexedDB);}else{if(url.indexOf("file:")===-1){noIndexedDB();}else{try{var textureName=url.substring(5);var blobURL;try{blobURL=URL.createObjectURL(BABYLON.FilesTextures[textureName],{oneTimeOnly:true});}catch(ex){blobURL=URL.createObjectURL(BABYLON.FilesTextures[textureName]);}img.src=blobURL;}catch(e){console.log("Error while trying to load texture: "+textureName);img.src=null;}}}return img;};BABYLON.Tools.LoadFile=function(url,callback,progressCallBack,database){var noIndexedDB=function(){var request=new XMLHttpRequest();var loadUrl=BABYLON.Tools.BaseUrl+url;request.open('GET',loadUrl,true);request.onprogress=progressCallBack;request.onreadystatechange=function(){if(request.readyState==4){if(request.status==200){callback(request.responseText);}else{throw new Error(request.status,"Unable to load "+loadUrl);}}};request.send(null);};var loadFromIndexedDB=function(){database.loadSceneFromDB(url,callback,progressCallBack,noIndexedDB);};if(database&&url.indexOf(".babylon")!==-1&&(database.enableSceneOffline)){database.openAsync(loadFromIndexedDB,noIndexedDB);}else{noIndexedDB();}};BABYLON.Tools.ReadFile=function(fileToLoad,callback,progressCallBack){var reader=new FileReader();reader.onload=function(e){callback(e.target.result);};reader.onprogress=progressCallBack;reader.readAsText(fileToLoad);};BABYLON.Tools.isIE=function(){return window.ActiveXObject!==undefined;};BABYLON.Tools.WithinEpsilon=function(a,b){var num=a-b;return-1.401298E-45<=num&&num<=1.401298E-45;};var cloneValue=function(source,destinationObject){if(!source)return null;if(source instanceof BABYLON.Mesh){return null;}if(source instanceof BABYLON.SubMesh){return source.clone(destinationObject);}else if(source.clone){return source.clone();}return null;};BABYLON.Tools.DeepCopy=function(source,destination,doNotCopyList,mustCopyList){for(var prop in source){if(prop[0]==="_"&&(!mustCopyList||mustCopyList.indexOf(prop)===-1)){continue;}if(doNotCopyList&&doNotCopyList.indexOf(prop)!==-1){continue;}var sourceValue=source[prop];var typeOfSourceValue=typeof sourceValue;if(typeOfSourceValue=="function"){continue;}if(typeOfSourceValue=="object"){if(sourceValue instanceof Array){destination[prop]=[];if(sourceValue.length>0){if(typeof sourceValue[0]=="object"){for(var index=0;index=2){deltaTime=previousFramesDuration[length-1]-previousFramesDuration[length-2];}if(length>=fpsRange){if(length>fpsRange){previousFramesDuration.splice(0,1);length=previousFramesDuration.length;}var sum=0;for(var id=0;id=0){this._gl.vertexAttribPointer(order,vertexDeclaration[index],this._gl.FLOAT,false,vertexStrideSize,offset);}offset+=vertexDeclaration[index]*4;}}if(this._cachedIndexBuffer!==indexBuffer){this._cachedIndexBuffer=indexBuffer;this._gl.bindBuffer(this._gl.ELEMENT_ARRAY_BUFFER,indexBuffer);}};BABYLON.Engine.prototype.bindMultiBuffers=function(vertexBuffers,indexBuffer,effect){if(this._cachedVertexBuffers!==vertexBuffers||this._cachedEffectForVertexBuffers!==effect){this._cachedVertexBuffers=vertexBuffers;this._cachedEffectForVertexBuffers=effect;var attributes=effect.getAttributesNames();for(var index=0;index=0){var vertexBuffer=vertexBuffers[attributes[index]];var stride=vertexBuffer.getStrideSize();this._gl.bindBuffer(this._gl.ARRAY_BUFFER,vertexBuffer._buffer);this._gl.vertexAttribPointer(order,stride,this._gl.FLOAT,false,stride*4,0);}}}if(this._cachedIndexBuffer!==indexBuffer){this._cachedIndexBuffer=indexBuffer;this._gl.bindBuffer(this._gl.ELEMENT_ARRAY_BUFFER,indexBuffer);}};BABYLON.Engine.prototype._releaseBuffer=function(buffer){buffer.references--;if(buffer.references===0){this._gl.deleteBuffer(buffer);}};BABYLON.Engine.prototype.draw=function(useTriangles,indexStart,indexCount){this._gl.drawElements(useTriangles?this._gl.TRIANGLES:this._gl.LINES,indexCount,this._gl.UNSIGNED_SHORT,indexStart*2);};BABYLON.Engine.prototype.createEffect=function(baseName,attributesNames,uniformsNames,samplers,defines,optionalDefines){var vertex=baseName.vertex||baseName;var fragment=baseName.fragment||baseName;var name=vertex+"+"+fragment+"@"+defines;if(this._compiledEffects[name]){return this._compiledEffects[name];}var effect=new BABYLON.Effect(baseName,attributesNames,uniformsNames,samplers,this,defines,optionalDefines);this._compiledEffects[name]=effect;return effect;};var compileShader=function(gl,source,type,defines){var shader=gl.createShader(type==="vertex"?gl.VERTEX_SHADER:gl.FRAGMENT_SHADER);gl.shaderSource(shader,(defines?defines+"\n":"")+source);gl.compileShader(shader);if(!gl.getShaderParameter(shader,gl.COMPILE_STATUS)){throw new Error(gl.getShaderInfoLog(shader));}return shader;};BABYLON.Engine.prototype.createShaderProgram=function(vertexCode,fragmentCode,defines){var vertexShader=compileShader(this._gl,vertexCode,"vertex",defines);var fragmentShader=compileShader(this._gl,fragmentCode,"fragment",defines);var shaderProgram=this._gl.createProgram();this._gl.attachShader(shaderProgram,vertexShader);this._gl.attachShader(shaderProgram,fragmentShader);this._gl.linkProgram(shaderProgram);var error=this._gl.getProgramInfoLog(shaderProgram);if(error){throw new Error(error);}this._gl.deleteShader(vertexShader);this._gl.deleteShader(fragmentShader);return shaderProgram;};BABYLON.Engine.prototype.getUniforms=function(shaderProgram,uniformsNames){var results=[];for(var index=0;index=0){this._gl.enableVertexAttribArray(effect.getAttribute(index));}}this._currentEffect=effect;};BABYLON.Engine.prototype.setMatrices=function(uniform,matrices){if(!uniform)return;this._gl.uniformMatrix4fv(uniform,false,matrices);};BABYLON.Engine.prototype.setMatrix=function(uniform,matrix){if(!uniform)return;this._gl.uniformMatrix4fv(uniform,false,matrix.toArray());};BABYLON.Engine.prototype.setFloat=function(uniform,value){if(!uniform)return;this._gl.uniform1f(uniform,value);};BABYLON.Engine.prototype.setFloat2=function(uniform,x,y){if(!uniform)return;this._gl.uniform2f(uniform,x,y);};BABYLON.Engine.prototype.setFloat3=function(uniform,x,y,z){if(!uniform)return;this._gl.uniform3f(uniform,x,y,z);};BABYLON.Engine.prototype.setBool=function(uniform,bool){if(!uniform)return;this._gl.uniform1i(uniform,bool);};BABYLON.Engine.prototype.setFloat4=function(uniform,x,y,z,w){if(!uniform)return;this._gl.uniform4f(uniform,x,y,z,w);};BABYLON.Engine.prototype.setColor3=function(uniform,color3){if(!uniform)return;this._gl.uniform3f(uniform,color3.r,color3.g,color3.b);};BABYLON.Engine.prototype.setColor4=function(uniform,color3,alpha){if(!uniform)return;this._gl.uniform4f(uniform,color3.r,color3.g,color3.b,alpha);};BABYLON.Engine.prototype.setState=function(culling){if(this._currentState.culling!==culling){if(culling){this._gl.cullFace(this.cullBackFaces?this._gl.BACK:this._gl.FRONT);this._gl.enable(this._gl.CULL_FACE);}else{this._gl.disable(this._gl.CULL_FACE);}this._currentState.culling=culling;}};BABYLON.Engine.prototype.setDepthBuffer=function(enable){if(enable){this._gl.enable(this._gl.DEPTH_TEST);}else{this._gl.disable(this._gl.DEPTH_TEST);}};BABYLON.Engine.prototype.setDepthWrite=function(enable){this._gl.depthMask(enable);};BABYLON.Engine.prototype.setColorWrite=function(enable){this._gl.colorMask(enable,enable,enable,enable);};BABYLON.Engine.prototype.setAlphaMode=function(mode){switch(mode){case BABYLON.Engine.ALPHA_DISABLE:this.setDepthWrite(true);this._gl.disable(this._gl.BLEND);break;case BABYLON.Engine.ALPHA_COMBINE:this.setDepthWrite(false);this._gl.blendFuncSeparate(this._gl.SRC_ALPHA,this._gl.ONE_MINUS_SRC_ALPHA,this._gl.ZERO,this._gl.ONE);this._gl.enable(this._gl.BLEND);break;case BABYLON.Engine.ALPHA_ADD:this.setDepthWrite(false);this._gl.blendFuncSeparate(this._gl.ONE,this._gl.ONE,this._gl.ZERO,this._gl.ONE);this._gl.enable(this._gl.BLEND);break;}};BABYLON.Engine.prototype.setAlphaTesting=function(enable){this._alphaTest=enable;};BABYLON.Engine.prototype.getAlphaTesting=function(){return this._alphaTest;};BABYLON.Engine.prototype.wipeCaches=function(){this._activeTexturesCache=[];this._currentEffect=null;this._currentState={culling:null};this._cachedVertexBuffers=null;this._cachedVertexBuffers=null;this._cachedEffectForVertexBuffers=null;};var getExponantOfTwo=function(value,max){var count=1;do{count*=2;}while(countmax)count=max;return count;};BABYLON.Engine.prototype.createTexture=function(url,noMipmap,invertY,scene){var texture=this._gl.createTexture();var that=this;var onload=function(img){var potWidth=getExponantOfTwo(img.width,that._caps.maxTextureSize);var potHeight=getExponantOfTwo(img.height,that._caps.maxTextureSize);var isPot=(img.width==potWidth&&img.height==potHeight);if(!isPot){that._workingCanvas.width=potWidth;that._workingCanvas.height=potHeight;that._workingContext.drawImage(img,0,0,img.width,img.height,0,0,potWidth,potHeight);};that._gl.bindTexture(that._gl.TEXTURE_2D,texture);that._gl.pixelStorei(that._gl.UNPACK_FLIP_Y_WEBGL,invertY===undefined?true:invertY);that._gl.texImage2D(that._gl.TEXTURE_2D,0,that._gl.RGBA,that._gl.RGBA,that._gl.UNSIGNED_BYTE,isPot?img:that._workingCanvas);that._gl.texParameteri(that._gl.TEXTURE_2D,that._gl.TEXTURE_MAG_FILTER,that._gl.LINEAR);if(noMipmap){that._gl.texParameteri(that._gl.TEXTURE_2D,that._gl.TEXTURE_MIN_FILTER,that._gl.LINEAR);}else{that._gl.texParameteri(that._gl.TEXTURE_2D,that._gl.TEXTURE_MIN_FILTER,that._gl.LINEAR_MIPMAP_LINEAR);that._gl.generateMipmap(that._gl.TEXTURE_2D);}that._gl.bindTexture(that._gl.TEXTURE_2D,null);that._activeTexturesCache=[];texture._baseWidth=img.width;texture._baseHeight=img.height;texture._width=potWidth;texture._height=potHeight;texture.isReady=true;scene._removePendingData(texture);};var onerror=function(){scene._removePendingData(texture);};scene._addPendingData(texture);BABYLON.Tools.LoadImage(url,onload,onerror,scene.database);texture.url=url;texture.noMipmap=noMipmap;texture.references=1;this._loadedTexturesCache.push(texture);return texture;};BABYLON.Engine.prototype.createDynamicTexture=function(width,height,generateMipMaps){var texture=this._gl.createTexture();width=getExponantOfTwo(width,this._caps.maxTextureSize);height=getExponantOfTwo(height,this._caps.maxTextureSize);this._gl.bindTexture(this._gl.TEXTURE_2D,texture);this._gl.texParameteri(this._gl.TEXTURE_2D,this._gl.TEXTURE_MAG_FILTER,this._gl.LINEAR);if(!generateMipMaps){this._gl.texParameteri(this._gl.TEXTURE_2D,this._gl.TEXTURE_MIN_FILTER,this._gl.LINEAR);}else{this._gl.texParameteri(this._gl.TEXTURE_2D,this._gl.TEXTURE_MIN_FILTER,this._gl.LINEAR_MIPMAP_LINEAR);}this._gl.bindTexture(this._gl.TEXTURE_2D,null);this._activeTexturesCache=[];texture._baseWidth=width;texture._baseHeight=height;texture._width=width;texture._height=height;texture.isReady=false;texture.generateMipMaps=generateMipMaps;texture.references=1;this._loadedTexturesCache.push(texture);return texture;};BABYLON.Engine.prototype.updateDynamicTexture=function(texture,canvas,invertY){this._gl.bindTexture(this._gl.TEXTURE_2D,texture);this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL,invertY);this._gl.texImage2D(this._gl.TEXTURE_2D,0,this._gl.RGBA,this._gl.RGBA,this._gl.UNSIGNED_BYTE,canvas);if(texture.generateMipMaps){this._gl.generateMipmap(this._gl.TEXTURE_2D);}this._gl.bindTexture(this._gl.TEXTURE_2D,null);this._activeTexturesCache=[];texture.isReady=true;};BABYLON.Engine.prototype.updateVideoTexture=function(texture,video){this._gl.bindTexture(this._gl.TEXTURE_2D,texture);this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL,false);if(video.videoWidth!==texture._width||video.videoHeight!==texture._height){if(!texture._workingCanvas){texture._workingCanvas=document.createElement("canvas");texture._workingContext=texture._workingCanvas.getContext("2d");texture._workingCanvas.width=texture._width;texture._workingCanvas.height=texture._height;}texture._workingContext.drawImage(video,0,0,video.videoWidth,video.videoHeight,0,0,texture._width,texture._height);this._gl.texImage2D(this._gl.TEXTURE_2D,0,this._gl.RGBA,this._gl.RGBA,this._gl.UNSIGNED_BYTE,texture._workingCanvas);}else{this._gl.texImage2D(this._gl.TEXTURE_2D,0,this._gl.RGBA,this._gl.RGBA,this._gl.UNSIGNED_BYTE,video);}if(texture.generateMipMaps){this._gl.generateMipmap(this._gl.TEXTURE_2D);}this._gl.bindTexture(this._gl.TEXTURE_2D,null);this._activeTexturesCache=[];texture.isReady=true;};BABYLON.Engine.prototype.createRenderTargetTexture=function(size,options){var generateMipMaps=false;var generateDepthBuffer=true;var samplingMode=BABYLON.Texture.TRILINEAR_SAMPLINGMODE;if(options!==undefined){generateMipMaps=options.generateMipMaps===undefined?options:options.generateMipmaps;generateDepthBuffer=options.generateDepthBuffer===undefined?true:options.generateDepthBuffer;if(options.samplingMode!==undefined){samplingMode=options.samplingMode;}}var gl=this._gl;var texture=gl.createTexture();gl.bindTexture(gl.TEXTURE_2D,texture);var width=size.width||size;var height=size.height||size;var magFilter=gl.NEAREST;var minFilter=gl.NEAREST;if(samplingMode===BABYLON.Texture.BILINEAR_SAMPLINGMODE){magFilter=gl.LINEAR;if(generateMipMaps){minFilter=gl.LINEAR_MIPMAP_NEAREST;}else{minFilter=gl.LINEAR;}}else if(samplingMode===BABYLON.Texture.TRILINEAR_SAMPLINGMODE){magFilter=gl.LINEAR;if(generateMipMaps){minFilter=gl.LINEAR_MIPMAP_LINEAR;}else{minFilter=gl.LINEAR;}}gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,magFilter);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,minFilter);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.CLAMP_TO_EDGE);gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,width,height,0,gl.RGBA,gl.UNSIGNED_BYTE,null);var depthBuffer;if(generateDepthBuffer){depthBuffer=gl.createRenderbuffer();gl.bindRenderbuffer(gl.RENDERBUFFER,depthBuffer);gl.renderbufferStorage(gl.RENDERBUFFER,gl.DEPTH_COMPONENT16,width,height);}var framebuffer=gl.createFramebuffer();gl.bindFramebuffer(gl.FRAMEBUFFER,framebuffer);gl.framebufferTexture2D(gl.FRAMEBUFFER,gl.COLOR_ATTACHMENT0,gl.TEXTURE_2D,texture,0);if(generateDepthBuffer){gl.framebufferRenderbuffer(gl.FRAMEBUFFER,gl.DEPTH_ATTACHMENT,gl.RENDERBUFFER,depthBuffer);}gl.bindTexture(gl.TEXTURE_2D,null);gl.bindRenderbuffer(gl.RENDERBUFFER,null);gl.bindFramebuffer(gl.FRAMEBUFFER,null);texture._framebuffer=framebuffer;if(generateDepthBuffer){texture._depthBuffer=depthBuffer;}texture._width=width;texture._height=height;texture.isReady=true;texture.generateMipMaps=generateMipMaps;texture.references=1;this._activeTexturesCache=[];this._loadedTexturesCache.push(texture);return texture;};var extensions=["_px.jpg","_py.jpg","_pz.jpg","_nx.jpg","_ny.jpg","_nz.jpg"];var cascadeLoad=function(rootUrl,index,loadedImages,scene,onfinish){var img;var onload=function(){loadedImages.push(img);scene._removePendingData(img);if(index!=extensions.length-1){cascadeLoad(rootUrl,index+1,loadedImages,scene,onfinish);}else{onfinish(loadedImages);}};var onerror=function(){scene._removePendingData(img);};img=BABYLON.Tools.LoadImage(rootUrl+extensions[index],onload,onerror,scene.database);scene._addPendingData(img);};BABYLON.Engine.prototype.createCubeTexture=function(rootUrl,scene){var gl=this._gl;var texture=gl.createTexture();texture.isCube=true;texture.url=rootUrl;texture.references=1;this._loadedTexturesCache.push(texture);var that=this;cascadeLoad(rootUrl,0,[],scene,function(imgs){var width=getExponantOfTwo(imgs[0].width);var height=width;that._workingCanvas.width=width;that._workingCanvas.height=height;var faces=[gl.TEXTURE_CUBE_MAP_POSITIVE_X,gl.TEXTURE_CUBE_MAP_POSITIVE_Y,gl.TEXTURE_CUBE_MAP_POSITIVE_Z,gl.TEXTURE_CUBE_MAP_NEGATIVE_X,gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,gl.TEXTURE_CUBE_MAP_NEGATIVE_Z];gl.bindTexture(gl.TEXTURE_CUBE_MAP,texture);gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,false);for(var index=0;indexthis.maximumWorld.x)this.maximumWorld.x=v.x;if(v.y>this.maximumWorld.y)this.maximumWorld.y=v.y;if(v.z>this.maximumWorld.z)this.maximumWorld.z=v.z;}this.maximumWorld.addToRef(this.minimumWorld,this.center);this.center.scaleInPlace(0.5);BABYLON.Vector3.FromArrayToRef(world.m,0,this.directions[0]);BABYLON.Vector3.FromArrayToRef(world.m,4,this.directions[1]);BABYLON.Vector3.FromArrayToRef(world.m,8,this.directions[2]);};BABYLON.BoundingBox.prototype.isInFrustrum=function(frustumPlanes){return BABYLON.BoundingBox.IsInFrustrum(this.vectorsWorld,frustumPlanes);};BABYLON.BoundingBox.prototype.intersectsPoint=function(point){if(this.maximumWorld.xpoint.x)return false;if(this.maximumWorld.ypoint.y)return false;if(this.maximumWorld.zpoint.z)return false;return true;};BABYLON.BoundingBox.prototype.intersectsSphere=function(sphere){var vector=BABYLON.Vector3.Clamp(sphere.centerWorld,this.minimumWorld,this.maximumWorld);var num=BABYLON.Vector3.DistanceSquared(sphere.centerWorld,vector);return(num<=(sphere.radiusWorld*sphere.radiusWorld));};BABYLON.BoundingBox.prototype.intersectsMinMax=function(min,max){if(this.maximumWorld.xmax.x)return false;if(this.maximumWorld.ymax.y)return false;if(this.maximumWorld.zmax.z)return false;return true;};BABYLON.BoundingBox.intersects=function(box0,box1){if(box0.maximumWorld.xbox1.maximumWorld.x)return false;if(box0.maximumWorld.ybox1.maximumWorld.y)return false;if(box0.maximumWorld.zbox1.maximumWorld.z)return false;return true;};BABYLON.BoundingBox.IsInFrustrum=function(boundingVectors,frustumPlanes){for(var p=0;p<6;p++){var inCount=8;for(var i=0;i<8;i++){if(frustumPlanes[p].dotCoordinate(boundingVectors[i])<0){--inCount;}else{break;}}if(inCount==0)return false;}return true;};})();var BABYLON=BABYLON||{};(function(){BABYLON.BoundingInfo=function(minimum,maximum){this.boundingBox=new BABYLON.BoundingBox(minimum,maximum);this.boundingSphere=new BABYLON.BoundingSphere(minimum,maximum);};BABYLON.BoundingInfo.prototype._update=function(world,scale){this.boundingBox._update(world);this.boundingSphere._update(world,scale);};var extentsOverlap=function(min0,max0,min1,max1){return!(min0>max1||min1>max0);};var computeBoxExtents=function(axis,box){var p=BABYLON.Vector3.Dot(box.center,axis);var r0=Math.abs(BABYLON.Vector3.Dot(box.directions[0],axis))*box.extends.x;var r1=Math.abs(BABYLON.Vector3.Dot(box.directions[1],axis))*box.extends.y;var r2=Math.abs(BABYLON.Vector3.Dot(box.directions[2],axis))*box.extends.z;var r=r0+r1+r2;return{min:p-r,max:p+r};};var axisOverlap=function(axis,box0,box1){var result0=computeBoxExtents(axis,box0);var result1=computeBoxExtents(axis,box1);return extentsOverlap(result0.min,result0.max,result1.min,result1.max);};BABYLON.BoundingInfo.prototype.isInFrustrum=function(frustumPlanes){if(!this.boundingSphere.isInFrustrum(frustumPlanes))return false;return this.boundingBox.isInFrustrum(frustumPlanes);};BABYLON.BoundingInfo.prototype._checkCollision=function(collider){return collider._canDoCollision(this.boundingSphere.centerWorld,this.boundingSphere.radiusWorld,this.boundingBox.minimumWorld,this.boundingBox.maximumWorld);};BABYLON.BoundingInfo.prototype.intersectsPoint=function(point){if(!this.boundingSphere.centerWorld){return false;}if(!this.boundingSphere.intersectsPoint(point)){return false;}if(!this.boundingBox.intersectsPoint(point)){return false;}return true;};BABYLON.BoundingInfo.prototype.intersects=function(boundingInfo,precise){if(!this.boundingSphere.centerWorld||!boundingInfo.boundingSphere.centerWorld){return false;}if(!BABYLON.BoundingSphere.intersects(this.boundingSphere,boundingInfo.boundingSphere)){return false;}if(!BABYLON.BoundingBox.intersects(this.boundingBox,boundingInfo.boundingBox)){return false;}if(!precise){return true;}var box0=this.boundingBox;var box1=boundingInfo.boundingBox;if(!axisOverlap(box0.directions[0],box0,box1))return false;if(!axisOverlap(box0.directions[1],box0,box1))return false;if(!axisOverlap(box0.directions[2],box0,box1))return false;if(!axisOverlap(box1.directions[0],box0,box1))return false;if(!axisOverlap(box1.directions[1],box0,box1))return false;if(!axisOverlap(box1.directions[2],box0,box1))return false;if(!axisOverlap(BABYLON.Vector3.Cross(box0.directions[0],box1.directions[0]),box0,box1))return false;if(!axisOverlap(BABYLON.Vector3.Cross(box0.directions[0],box1.directions[1]),box0,box1))return false;if(!axisOverlap(BABYLON.Vector3.Cross(box0.directions[0],box1.directions[2]),box0,box1))return false;if(!axisOverlap(BABYLON.Vector3.Cross(box0.directions[1],box1.directions[0]),box0,box1))return false;if(!axisOverlap(BABYLON.Vector3.Cross(box0.directions[1],box1.directions[1]),box0,box1))return false;if(!axisOverlap(BABYLON.Vector3.Cross(box0.directions[1],box1.directions[2]),box0,box1))return false;if(!axisOverlap(BABYLON.Vector3.Cross(box0.directions[2],box1.directions[0]),box0,box1))return false;if(!axisOverlap(BABYLON.Vector3.Cross(box0.directions[2],box1.directions[1]),box0,box1))return false;if(!axisOverlap(BABYLON.Vector3.Cross(box0.directions[2],box1.directions[2]),box0,box1))return false;return true;};})();var BABYLON=BABYLON||{};(function(){BABYLON.Light=function(name,scene){this.name=name;this.id=name;this._childrenFlag=true;this._scene=scene;scene.lights.push(this);this.animations=[];this.excludedMeshes=[];};BABYLON.Light.prototype=Object.create(BABYLON.Node.prototype);BABYLON.Light.prototype.intensity=1.0;BABYLON.Light.prototype.getScene=function(){return this._scene;};BABYLON.Light.prototype.getShadowGenerator=function(){return this._shadowGenerator;};BABYLON.Light.prototype.transferToEffect=function(){};BABYLON.Light.prototype.getWorldMatrix=function(){var worldMatrix=this._getWorldMatrix();if(this.parent&&this.parent.getWorldMatrix){if(!this._parentedWorldMatrix){this._parentedWorldMatrix=BABYLON.Matrix.Identity();}worldMatrix.multiplyToRef(this.parent.getWorldMatrix(),this._parentedWorldMatrix);return this._parentedWorldMatrix;}return worldMatrix;};BABYLON.Light.prototype.dispose=function(){if(this._shadowGenerator){this._shadowGenerator.dispose();this._shadowGenerator=null;}var index=this._scene.lights.indexOf(this);this._scene.lights.splice(index,1);};})();var BABYLON=BABYLON||{};(function(){BABYLON.PointLight=function(name,position,scene){BABYLON.Light.call(this,name,scene);this.position=position;this.diffuse=new BABYLON.Color3(1.0,1.0,1.0);this.specular=new BABYLON.Color3(1.0,1.0,1.0);};BABYLON.PointLight.prototype=Object.create(BABYLON.Light.prototype);BABYLON.Light.prototype.transferToEffect=function(effect,positionUniformName){if(this.parent&&this.parent.getWorldMatrix){if(!this._transformedPosition){this._transformedPosition=BABYLON.Vector3.Zero();}BABYLON.Vector3.TransformCoordinatesToRef(this.position,this.parent.getWorldMatrix(),this._transformedPosition);effect.setFloat4(positionUniformName,this._transformedPosition.x,this._transformedPosition.y,this._transformedPosition.z,0);return;}effect.setFloat4(positionUniformName,this.position.x,this.position.y,this.position.z,0);};BABYLON.PointLight.prototype.getShadowGenerator=function(){return null;};BABYLON.PointLight.prototype._getWorldMatrix=function(){if(!this._worldMatrix){this._worldMatrix=BABYLON.Matrix.Identity();}BABYLON.Matrix.TranslationToRef(this.position.x,this.position.y,this.position.z,this._worldMatrix);return this._worldMatrix;};})();var BABYLON=BABYLON||{};(function(){BABYLON.SpotLight=function(name,position,direction,angle,exponent,scene){BABYLON.Light.call(this,name,scene);this.position=position;this.direction=direction;this.angle=angle;this.exponent=exponent;this.diffuse=new BABYLON.Color3(1.0,1.0,1.0);this.specular=new BABYLON.Color3(1.0,1.0,1.0);};BABYLON.SpotLight.prototype=Object.create(BABYLON.Light.prototype);BABYLON.SpotLight.prototype.transferToEffect=function(effect,positionUniformName,directionUniformName){var normalizeDirection;if(this.parent&&this.parent.getWorldMatrix){if(!this._transformedDirection){this._transformedDirection=BABYLON.Vector3.Zero();}if(!this._transformedPosition){this._transformedPosition=BABYLON.Vector3.Zero();}var parentWorldMatrix=this.parent.getWorldMatrix();BABYLON.Vector3.TransformCoordinatesToRef(this.position,parentWorldMatrix,this._transformedPosition);BABYLON.Vector3.TransformNormalToRef(this.direction,parentWorldMatrix,this._transformedDirection);effect.setFloat4(positionUniformName,this._transformedPosition.x,this._transformedPosition.y,this._transformedPosition.z,this.exponent);normalizeDirection=BABYLON.Vector3.Normalize(this._transformedDirection);}else{effect.setFloat4(positionUniformName,this.position.x,this.position.y,this.position.z,this.exponent);normalizeDirection=BABYLON.Vector3.Normalize(this.direction);}effect.setFloat4(directionUniformName,normalizeDirection.x,normalizeDirection.y,normalizeDirection.z,Math.cos(this.angle*0.5));};BABYLON.SpotLight.prototype._getWorldMatrix=function(){if(!this._worldMatrix){this._worldMatrix=BABYLON.Matrix.Identity();}BABYLON.Matrix.TranslationToRef(this.position.x,this.position.y,this.position.z,this._worldMatrix);return this._worldMatrix;};})();var BABYLON=BABYLON||{};(function(){BABYLON.DirectionalLight=function(name,direction,scene){BABYLON.Light.call(this,name,scene);this.position=direction.scale(-1);this.direction=direction;this.diffuse=new BABYLON.Color3(1.0,1.0,1.0);this.specular=new BABYLON.Color3(1.0,1.0,1.0);};BABYLON.DirectionalLight.prototype=Object.create(BABYLON.Light.prototype);BABYLON.DirectionalLight.prototype._computeTransformedPosition=function(){if(this.parent&&this.parent.getWorldMatrix){if(!this._transformedPosition){this._transformedPosition=BABYLON.Vector3.Zero();}BABYLON.Vector3.TransformCoordinatesToRef(this.position,this.parent.getWorldMatrix(),this._transformedPosition);return true;}return false;};BABYLON.DirectionalLight.prototype.transferToEffect=function(effect,directionUniformName){if(this.parent&&this.parent.getWorldMatrix){if(!this._transformedDirection){this._transformedDirection=BABYLON.Vector3.Zero();}BABYLON.Vector3.TransformNormalToRef(this.direction,this.parent.getWorldMatrix(),this._transformedDirection);effect.setFloat4(directionUniformName,this._transformedDirection.x,this._transformedDirection.y,this._transformedDirection.z,1);return;}effect.setFloat4(directionUniformName,this.direction.x,this.direction.y,this.direction.z,1);};BABYLON.DirectionalLight.prototype._getWorldMatrix=function(){if(!this._worldMatrix){this._worldMatrix=BABYLON.Matrix.Identity();}BABYLON.Matrix.TranslationToRef(this.position.x,this.position.y,this.position.z,this._worldMatrix);return this._worldMatrix;};})();var BABYLON=BABYLON||{};(function(){BABYLON.ShadowGenerator=function(mapSize,light){this._light=light;this._scene=light.getScene();light._shadowGenerator=this;this._shadowMap=new BABYLON.RenderTargetTexture(light.name+"_shadowMap",mapSize,this._scene,false);this._shadowMap.wrapU=BABYLON.Texture.CLAMP_ADDRESSMODE;this._shadowMap.wrapV=BABYLON.Texture.CLAMP_ADDRESSMODE;this._shadowMap.renderParticles=false;var that=this;var renderSubMesh=function(subMesh){var mesh=subMesh.getMesh();var world=mesh.getWorldMatrix();var engine=that._scene.getEngine();if(that.isReady(mesh)){engine.enableEffect(that._effect);if(mesh.skeleton&&mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind)&&mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind)){that._effect.setMatrix("world",world);that._effect.setMatrix("viewProjection",that.getTransformMatrix());that._effect.setMatrices("mBones",mesh.skeleton.getTransformMatrices());}else{world.multiplyToRef(that.getTransformMatrix(),that._worldViewProjection);that._effect.setMatrix("worldViewProjection",that._worldViewProjection);}mesh.bindAndDraw(subMesh,that._effect,false);}};this._shadowMap.customRenderFunction=function(opaqueSubMeshes,alphaTestSubMeshes){var index;for(index=0;index=0;};var intersectBoxAASphere=function(boxMin,boxMax,sphereCenter,sphereRadius){if(boxMin.x>sphereCenter.x+sphereRadius)return false;if(sphereCenter.x-sphereRadius>boxMax.x)return false;if(boxMin.y>sphereCenter.y+sphereRadius)return false;if(sphereCenter.y-sphereRadius>boxMax.y)return false;if(boxMin.z>sphereCenter.z+sphereRadius)return false;if(sphereCenter.z-sphereRadius>boxMax.z)return false;return true;};var getLowestRoot=function(a,b,c,maxR){var determinant=b*b-4.0*a*c;var result={root:0,found:false};if(determinant<0)return result;var sqrtD=Math.sqrt(determinant);var r1=(-b-sqrtD)/(2.0*a);var r2=(-b+sqrtD)/(2.0*a);if(r1>r2){var temp=r2;r2=r1;r1=temp;}if(r1>0&&r10&&r2this.velocityWorldLength+max+sphereRadius){return false;}if(!intersectBoxAASphere(vecMin,vecMax,this.basePointWorld,this.velocityWorldLength+max))return false;return true;};BABYLON.Collider.prototype._testTriangle=function(faceIndex,subMesh,p1,p2,p3){var t0;var embeddedInPlane=false;if(!subMesh._trianglePlanes){subMesh._trianglePlanes=[];}if(!subMesh._trianglePlanes[faceIndex]){subMesh._trianglePlanes[faceIndex]=new BABYLON.Plane(0,0,0,0);subMesh._trianglePlanes[faceIndex].copyFromPoints(p1,p2,p3);}var trianglePlane=subMesh._trianglePlanes[faceIndex];if((!subMesh.getMaterial())&&!trianglePlane.isFrontFacingTo(this.normalizedVelocity,0))return;var signedDistToTrianglePlane=trianglePlane.signedDistanceTo(this.basePoint);var normalDotVelocity=BABYLON.Vector3.Dot(trianglePlane.normal,this.velocity);if(normalDotVelocity==0){if(Math.abs(signedDistToTrianglePlane)>=1.0)return;embeddedInPlane=true;t0=0;}else{t0=(-1.0-signedDistToTrianglePlane)/normalDotVelocity;var t1=(1.0-signedDistToTrianglePlane)/normalDotVelocity;if(t0>t1){var temp=t1;t1=t0;t0=temp;}if(t0>1.0||t1<0.0)return;if(t0<0)t0=0;if(t0>1.0)t0=1.0;}this._collisionPoint.copyFromFloats(0,0,0);var found=false;var t=1.0;if(!embeddedInPlane){this.basePoint.subtractToRef(trianglePlane.normal,this._planeIntersectionPoint);this.velocity.scaleToRef(t0,this._tempVector);this._planeIntersectionPoint.addInPlace(this._tempVector);if(this._checkPointInTriangle(this._planeIntersectionPoint,p1,p2,p3,trianglePlane.normal)){found=true;t=t0;this._collisionPoint.copyFrom(this._planeIntersectionPoint);}}if(!found){var velocitySquaredLength=this.velocity.lengthSquared();var a=velocitySquaredLength;this.basePoint.subtractToRef(p1,this._tempVector);var b=2.0*(BABYLON.Vector3.Dot(this.velocity,this._tempVector));var c=this._tempVector.lengthSquared-1.0;var lowestRoot=getLowestRoot(a,b,c,t);if(lowestRoot.found){t=lowestRoot.root;found=true;this._collisionPoint.copyFrom(p1);}this.basePoint.subtractToRef(p2,this._tempVector);b=2.0*(BABYLON.Vector3.Dot(this.velocity,this._tempVector));c=this._tempVector.lengthSquared-1.0;lowestRoot=getLowestRoot(a,b,c,t);if(lowestRoot.found){t=lowestRoot.root;found=true;this._collisionPoint.copyFrom(p2);}this.basePoint.subtractToRef(p3,this._tempVector);b=2.0*(BABYLON.Vector3.Dot(this.velocity,this._tempVector));c=this._tempVector.lengthSquared-1.0;lowestRoot=getLowestRoot(a,b,c,t);if(lowestRoot.found){t=lowestRoot.root;found=true;this._collisionPoint.copyFrom(p3);}p2.subtractToRef(p1,this._edge);p1.subtractToRef(this.basePoint,this._baseToVertex);var edgeSquaredLength=this._edge.lengthSquared();var edgeDotVelocity=BABYLON.Vector3.Dot(this._edge,this.velocity);var edgeDotBaseToVertex=BABYLON.Vector3.Dot(this._edge,this._baseToVertex);a=edgeSquaredLength*(-velocitySquaredLength)+edgeDotVelocity*edgeDotVelocity;b=edgeSquaredLength*(2.0*BABYLON.Vector3.Dot(this.velocity,this._baseToVertex))-2.0*edgeDotVelocity*edgeDotBaseToVertex;c=edgeSquaredLength*(1.0-this._baseToVertex.lengthSquared())+edgeDotBaseToVertex*edgeDotBaseToVertex;lowestRoot=getLowestRoot(a,b,c,t);if(lowestRoot.found){var f=(edgeDotVelocity*lowestRoot.root-edgeDotBaseToVertex)/edgeSquaredLength;if(f>=0.0&&f<=1.0){t=lowestRoot.root;found=true;this._edge.scaleInPlace(f);p1.addToRef(this._edge,this._collisionPoint);}}p3.subtractToRef(p2,this._edge);p2.subtractToRef(this.basePoint,this._baseToVertex);edgeSquaredLength=this._edge.lengthSquared();edgeDotVelocity=BABYLON.Vector3.Dot(this._edge,this.velocity);edgeDotBaseToVertex=BABYLON.Vector3.Dot(this._edge,this._baseToVertex);a=edgeSquaredLength*(-velocitySquaredLength)+edgeDotVelocity*edgeDotVelocity;b=edgeSquaredLength*(2.0*BABYLON.Vector3.Dot(this.velocity,this._baseToVertex))-2.0*edgeDotVelocity*edgeDotBaseToVertex;c=edgeSquaredLength*(1.0-this._baseToVertex.lengthSquared())+edgeDotBaseToVertex*edgeDotBaseToVertex;lowestRoot=getLowestRoot(a,b,c,t);if(lowestRoot.found){var f=(edgeDotVelocity*lowestRoot.root-edgeDotBaseToVertex)/edgeSquaredLength;if(f>=0.0&&f<=1.0){t=lowestRoot.root;found=true;this._edge.scaleInPlace(f);p2.addToRef(this._edge,this._collisionPoint);}}p1.subtractToRef(p3,this._edge);p3.subtractToRef(this.basePoint,this._baseToVertex);edgeSquaredLength=this._edge.lengthSquared();edgeDotVelocity=BABYLON.Vector3.Dot(this._edge,this.velocity);edgeDotBaseToVertex=BABYLON.Vector3.Dot(this._edge,this._baseToVertex);a=edgeSquaredLength*(-velocitySquaredLength)+edgeDotVelocity*edgeDotVelocity;b=edgeSquaredLength*(2.0*BABYLON.Vector3.Dot(this.velocity,this._baseToVertex))-2.0*edgeDotVelocity*edgeDotBaseToVertex;c=edgeSquaredLength*(1.0-this._baseToVertex.lengthSquared())+edgeDotBaseToVertex*edgeDotBaseToVertex;lowestRoot=getLowestRoot(a,b,c,t);if(lowestRoot.found){var f=(edgeDotVelocity*lowestRoot.root-edgeDotBaseToVertex)/edgeSquaredLength;if(f>=0.0&&f<=1.0){t=lowestRoot.root;found=true;this._edge.scaleInPlace(f);p3.addToRef(this._edge,this._collisionPoint);}}}if(found){var distToCollision=t*this.velocity.length();if(!this.collisionFound||distToCollision=0.0){this.rotation.y=(-Math.atan(vDir.z/vDir.x)+Math.PI/2.0);}else{this.rotation.y=(-Math.atan(vDir.z/vDir.x)-Math.PI/2.0);}this.rotation.z=-Math.acos(BABYLON.Vector3.Dot(new BABYLON.Vector3(0,1.0,0),this.upVector));if(isNaN(this.rotation.x))this.rotation.x=0;if(isNaN(this.rotation.y))this.rotation.y=0;if(isNaN(this.rotation.z))this.rotation.z=0;};BABYLON.FreeCamera.prototype.attachControl=function(canvas,noPreventDefault){var previousPosition;var that=this;var engine=this._scene.getEngine();if(this._attachedCanvas){return;}this._attachedCanvas=canvas;if(this._onMouseDown===undefined){this._onMouseDown=function(evt){previousPosition={x:evt.clientX,y:evt.clientY};if(!noPreventDefault){evt.preventDefault();}};this._onMouseUp=function(evt){previousPosition=null;if(!noPreventDefault){evt.preventDefault();}};this._onMouseOut=function(evt){previousPosition=null;that._keys=[];if(!noPreventDefault){evt.preventDefault();}};this._onMouseMove=function(evt){if(!previousPosition&&!engine.isPointerLock){return;}var offsetX;var offsetY;if(!engine.isPointerLock){offsetX=evt.clientX-previousPosition.x;offsetY=evt.clientY-previousPosition.y;}else{offsetX=evt.movementX||evt.mozMovementX||evt.webkitMovementX||evt.msMovementX||0;offsetY=evt.movementY||evt.mozMovementY||evt.webkitMovementY||evt.msMovementY||0;}that.cameraRotation.y+=offsetX/that.angularSensibility;that.cameraRotation.x+=offsetY/that.angularSensibility;previousPosition={x:evt.clientX,y:evt.clientY};if(!noPreventDefault){evt.preventDefault();}};this._onKeyDown=function(evt){if(that.keysUp.indexOf(evt.keyCode)!==-1||that.keysDown.indexOf(evt.keyCode)!==-1||that.keysLeft.indexOf(evt.keyCode)!==-1||that.keysRight.indexOf(evt.keyCode)!==-1){var index=that._keys.indexOf(evt.keyCode);if(index===-1){that._keys.push(evt.keyCode);}if(!noPreventDefault){evt.preventDefault();}}};this._onKeyUp=function(evt){if(that.keysUp.indexOf(evt.keyCode)!==-1||that.keysDown.indexOf(evt.keyCode)!==-1||that.keysLeft.indexOf(evt.keyCode)!==-1||that.keysRight.indexOf(evt.keyCode)!==-1){var index=that._keys.indexOf(evt.keyCode);if(index>=0){that._keys.splice(index,1);}if(!noPreventDefault){evt.preventDefault();}}};this._onLostFocus=function(){that._keys=[];};this._reset=function(){that._keys=[];previousPosition=null;that.cameraDirection=new BABYLON.Vector3(0,0,0);that.cameraRotation=new BABYLON.Vector2(0,0);};}canvas.addEventListener("mousedown",this._onMouseDown,false);canvas.addEventListener("mouseup",this._onMouseUp,false);canvas.addEventListener("mouseout",this._onMouseOut,false);canvas.addEventListener("mousemove",this._onMouseMove,false);window.addEventListener("keydown",this._onKeyDown,false);window.addEventListener("keyup",this._onKeyUp,false);window.addEventListener("blur",this._onLostFocus,false);};BABYLON.FreeCamera.prototype.detachControl=function(canvas){if(this._attachedCanvas!=canvas){return;}canvas.removeEventListener("mousedown",this._onMouseDown);canvas.removeEventListener("mouseup",this._onMouseUp);canvas.removeEventListener("mouseout",this._onMouseOut);canvas.removeEventListener("mousemove",this._onMouseMove);window.removeEventListener("keydown",this._onKeyDown);window.removeEventListener("keyup",this._onKeyUp);window.removeEventListener("blur",this._onLostFocus);this._attachedCanvas=null;if(this._reset){this._reset();}};BABYLON.FreeCamera.prototype._collideWithWorld=function(velocity){this.position.subtractFromFloatsToRef(0,this.ellipsoid.y,0,this._oldPosition);this._collider.radius=this.ellipsoid;this._scene._getNewPosition(this._oldPosition,velocity,this._collider,3,this._newPosition);this._newPosition.subtractToRef(this._oldPosition,this._diffPosition);if(this._diffPosition.length()>BABYLON.Engine.collisionsEpsilon){this.position.addInPlace(this._diffPosition);}};BABYLON.FreeCamera.prototype._checkInputs=function(){if(!this._localDirection){this._localDirection=BABYLON.Vector3.Zero();this._transformedDirection=BABYLON.Vector3.Zero();}for(var index=0;index0||Math.abs(this.cameraDirection.y)>0||Math.abs(this.cameraDirection.z)>0;var needToRotate=Math.abs(this.cameraRotation.x)>0||Math.abs(this.cameraRotation.y)>0;if(needToMove){if(this.checkCollisions&&this._scene.collisionsEnabled){this._collideWithWorld(this.cameraDirection);if(this.applyGravity){var oldPosition=this.position;this._collideWithWorld(this._scene.gravity);this._needMoveForGravity=(BABYLON.Vector3.DistanceSquared(oldPosition,this.position)!=0);}}else{this.position.addInPlace(this.cameraDirection);}}if(needToRotate){this.rotation.x+=this.cameraRotation.x;this.rotation.y+=this.cameraRotation.y;if(!this.noRotationConstraint){var limit=(Math.PI/2)*0.95;if(this.rotation.x>limit)this.rotation.x=limit;if(this.rotation.x<-limit)this.rotation.x=-limit;}}if(needToMove){this.cameraDirection.scaleInPlace(this.inertia);}if(needToRotate){this.cameraRotation.scaleInPlace(this.inertia);}};BABYLON.FreeCamera.prototype._getViewMatrix=function(){BABYLON.Vector3.FromFloatsToRef(0,0,1,this._referencePoint);if(!this.lockedTarget){if(this.upVector.x!=0||this.upVector.y!=1.0||this.upVector.z!=0){BABYLON.Matrix.LookAtLHToRef(BABYLON.Vector3.Zero(),this._referencePoint,this.upVector,this._lookAtTemp);BABYLON.Matrix.RotationYawPitchRollToRef(this.rotation.y,this.rotation.x,this.rotation.z,this._cameraRotationMatrix);this._lookAtTemp.multiplyToRef(this._cameraRotationMatrix,this._tempMatrix);this._lookAtTemp.invert();this._tempMatrix.multiplyToRef(this._lookAtTemp,this._cameraRotationMatrix);}else{BABYLON.Matrix.RotationYawPitchRollToRef(this.rotation.y,this.rotation.x,this.rotation.z,this._cameraRotationMatrix);}BABYLON.Vector3.TransformCoordinatesToRef(this._referencePoint,this._cameraRotationMatrix,this._transformedReferencePoint);this.position.addToRef(this._transformedReferencePoint,this._currentTarget);}else{if(this.lockedTarget.position){this._currentTarget.copyFrom(this.lockedTarget.position);}else{this._currentTarget.copyFrom(this.lockedTarget);}}BABYLON.Matrix.LookAtLHToRef(this.position,this._currentTarget,this.upVector,this._viewMatrix);return this._viewMatrix;};})();var BABYLON=BABYLON||{};(function(){BABYLON.TouchCamera=function(name,position,scene){BABYLON.FreeCamera.call(this,name,position,scene);this._offsetX=null;this._offsetY=null;this._pointerCount=0;this._pointerPressed=[];};BABYLON.TouchCamera.prototype=Object.create(BABYLON.FreeCamera.prototype);BABYLON.TouchCamera.prototype.angularSensibility=200000.0;BABYLON.TouchCamera.prototype.moveSensibility=500.0;BABYLON.TouchCamera.prototype.attachControl=function(canvas,noPreventDefault){var previousPosition;var that=this;if(this._attachedCanvas){return;}this._attachedCanvas=canvas;if(this._onPointerDown===undefined){this._onPointerDown=function(evt){if(!noPreventDefault){evt.preventDefault();}that._pointerPressed.push(evt.pointerId);if(that._pointerPressed.length!==1){return;}previousPosition={x:evt.clientX,y:evt.clientY};};this._onPointerUp=function(evt){if(!noPreventDefault){evt.preventDefault();}var index=that._pointerPressed.indexOf(evt.pointerId);if(index===-1){return;}that._pointerPressed.splice(index,1);if(index!=0){return;}previousPosition=null;that._offsetX=null;that._offsetY=null;};this._onPointerMove=function(evt){if(!noPreventDefault){evt.preventDefault();}if(!previousPosition){return;}var index=that._pointerPressed.indexOf(evt.pointerId);if(index!=0){return;}that._offsetX=evt.clientX-previousPosition.x;that._offsetY=-(evt.clientY-previousPosition.y);};this._onLostFocus=function(){that._offsetX=null;that._offsetY=null;};}canvas.addEventListener("pointerdown",this._onPointerDown);canvas.addEventListener("pointerup",this._onPointerUp);canvas.addEventListener("pointerout",this._onPointerUp);canvas.addEventListener("pointermove",this._onPointerMove);window.addEventListener("blur",this._onLostFocus);};BABYLON.TouchCamera.prototype.detachControl=function(canvas){if(this._attachedCanvas!=canvas){return;}canvas.removeEventListener("pointerdown",this._onPointerDown);canvas.removeEventListener("pointerup",this._onPointerUp);canvas.removeEventListener("pointerout",this._onPointerUp);canvas.removeEventListener("pointermove",this._onPointerMove);window.removeEventListener("blur",this._onLostFocus);this._attachedCanvas=null;};BABYLON.TouchCamera.prototype._checkInputs=function(){if(!this._offsetX){return;}this.cameraRotation.y+=this._offsetX/this.angularSensibility;if(this._pointerPressed.length>1){this.cameraRotation.x+=-this._offsetY/this.angularSensibility;}else{var speed=this._computeLocalCameraSpeed();var direction=new BABYLON.Vector3(0,0,speed*this._offsetY/this.moveSensibility);BABYLON.Matrix.RotationYawPitchRollToRef(this.rotation.y,this.rotation.x,0,this._cameraRotationMatrix);this.cameraDirection.addInPlace(BABYLON.Vector3.TransformCoordinates(direction,this._cameraRotationMatrix));}};})();var BABYLON=BABYLON||{};(function(){BABYLON.DeviceOrientationCamera=function(name,position,scene){BABYLON.FreeCamera.call(this,name,position,scene);this._offsetX=null;this._offsetY=null;this._orientationGamma=0;this._orientationBeta=0;this._initialOrientationGamma=0;this._initialOrientationBeta=0;};BABYLON.DeviceOrientationCamera.prototype=Object.create(BABYLON.FreeCamera.prototype);BABYLON.DeviceOrientationCamera.prototype.angularSensibility=10000.0;BABYLON.DeviceOrientationCamera.prototype.moveSensibility=50.0;BABYLON.DeviceOrientationCamera.prototype.attachControl=function(canvas,noPreventDefault){if(this._attachedCanvas){return;}this._attachedCanvas=canvas;var that=this;if(!this._orientationChanged){this._orientationChanged=function(evt){if(!that._initialOrientationGamma){that._initialOrientationGamma=evt.gamma;that._initialOrientationBeta=evt.beta;}that._orientationGamma=evt.gamma;that._orientationBeta=evt.beta;that._offsetY=(that._initialOrientationBeta-that._orientationBeta);that._offsetX=(that._initialOrientationGamma-that._orientationGamma);};}window.addEventListener("deviceorientation",this._orientationChanged);};BABYLON.DeviceOrientationCamera.prototype.detachControl=function(canvas){if(this._attachedCanvas!=canvas){return;}window.removeEventListener("deviceorientation",this._orientationChanged);this._attachedCanvas=null;this._orientationGamma=0;this._orientationBeta=0;this._initialOrientationGamma=0;this._initialOrientationBeta=0;};BABYLON.DeviceOrientationCamera.prototype._checkInputs=function(){if(!this._offsetX){return;}this.cameraRotation.y-=this._offsetX/this.angularSensibility;var speed=this._computeLocalCameraSpeed();var direction=new BABYLON.Vector3(0,0,speed*this._offsetY/this.moveSensibility);BABYLON.Matrix.RotationYawPitchRollToRef(this.rotation.y,this.rotation.x,0,this._cameraRotationMatrix);this.cameraDirection.addInPlace(BABYLON.Vector3.TransformCoordinates(direction,this._cameraRotationMatrix));};})();var BABYLON=BABYLON||{};(function(){var eventPrefix=BABYLON.Tools.GetPointerPrefix();BABYLON.ArcRotateCamera=function(name,alpha,beta,radius,target,scene){BABYLON.Camera.call(this,name,BABYLON.Vector3.Zero(),scene);this.alpha=alpha;this.beta=beta;this.radius=radius;this.target=target;this._keys=[];this.keysUp=[38];this.keysDown=[40];this.keysLeft=[37];this.keysRight=[39];this._viewMatrix=new BABYLON.Matrix();this.getViewMatrix();};BABYLON.ArcRotateCamera.prototype=Object.create(BABYLON.Camera.prototype);BABYLON.ArcRotateCamera.prototype.inertialAlphaOffset=0;BABYLON.ArcRotateCamera.prototype.inertialBetaOffset=0;BABYLON.ArcRotateCamera.prototype.lowerAlphaLimit=null;BABYLON.ArcRotateCamera.prototype.upperAlphaLimit=null;BABYLON.ArcRotateCamera.prototype.lowerBetaLimit=null;BABYLON.ArcRotateCamera.prototype.upperBetaLimit=null;BABYLON.ArcRotateCamera.prototype.lowerRadiusLimit=null;BABYLON.ArcRotateCamera.prototype.upperRadiusLimit=null;BABYLON.ArcRotateCamera.prototype.angularSensibility=1000.0;BABYLON.ArcRotateCamera.prototype.attachControl=function(canvas,noPreventDefault){var previousPosition;var that=this;var pointerId;if(this._attachedCanvas){return;}this._attachedCanvas=canvas;var engine=this._scene.getEngine();if(this._onPointerDown===undefined){this._onPointerDown=function(evt){if(pointerId){return;}pointerId=evt.pointerId;previousPosition={x:evt.clientX,y:evt.clientY};if(!noPreventDefault){evt.preventDefault();}};this._onPointerUp=function(evt){previousPosition=null;pointerId=null;if(!noPreventDefault){evt.preventDefault();}};this._onPointerMove=function(evt){if(!previousPosition){return;}if(pointerId!==evt.pointerId){return;}var offsetX=evt.clientX-previousPosition.x;var offsetY=evt.clientY-previousPosition.y;that.inertialAlphaOffset-=offsetX/that.angularSensibility;that.inertialBetaOffset-=offsetY/that.angularSensibility;previousPosition={x:evt.clientX,y:evt.clientY};if(!noPreventDefault){evt.preventDefault();}};this._onMouseMove=function(evt){if(!engine.isPointerLock){return;}var offsetX=evt.movementX||evt.mozMovementX||evt.webkitMovementX||evt.msMovementX||0;var offsetY=evt.movementY||evt.mozMovementY||evt.webkitMovementY||evt.msMovementY||0;that.inertialAlphaOffset-=offsetX/that.angularSensibility;that.inertialBetaOffset-=offsetY/that.angularSensibility;if(!noPreventDefault){evt.preventDefault();}};this._wheel=function(event){var delta=0;if(event.wheelDelta){delta=event.wheelDelta/120;}else if(event.detail){delta=-event.detail/3;}if(delta)that.radius-=delta;if(event.preventDefault){if(!noPreventDefault){event.preventDefault();}}};this._onKeyDown=function(evt){if(that.keysUp.indexOf(evt.keyCode)!==-1||that.keysDown.indexOf(evt.keyCode)!==-1||that.keysLeft.indexOf(evt.keyCode)!==-1||that.keysRight.indexOf(evt.keyCode)!==-1){var index=that._keys.indexOf(evt.keyCode);if(index===-1){that._keys.push(evt.keyCode);}if(evt.preventDefault){if(!noPreventDefault){evt.preventDefault();}}}};this._onKeyUp=function(evt){if(that.keysUp.indexOf(evt.keyCode)!==-1||that.keysDown.indexOf(evt.keyCode)!==-1||that.keysLeft.indexOf(evt.keyCode)!==-1||that.keysRight.indexOf(evt.keyCode)!==-1){var index=that._keys.indexOf(evt.keyCode);if(index>=0){that._keys.splice(index,1);}if(evt.preventDefault){if(!noPreventDefault){evt.preventDefault();}}}};this._onLostFocus=function(){that._keys=[];pointerId=null;};this._onGestureStart=function(e){if(window.MSGesture===undefined){return;}if(!that._MSGestureHandler){that._MSGestureHandler=new MSGesture();that._MSGestureHandler.target=canvas;}that._MSGestureHandler.addPointer(e.pointerId);};this._onGesture=function(e){that.radius*=e.scale;if(e.preventDefault){if(!noPreventDefault){e.stopPropagation();e.preventDefault();}}};this._reset=function(){that._keys=[];that.inertialAlphaOffset=0;that.inertialBetaOffset=0;previousPosition=null;pointerId=null;};}canvas.addEventListener(eventPrefix+"down",this._onPointerDown,false);canvas.addEventListener(eventPrefix+"up",this._onPointerUp,false);canvas.addEventListener(eventPrefix+"out",this._onPointerUp,false);canvas.addEventListener(eventPrefix+"move",this._onPointerMove,false);canvas.addEventListener("mousemove",this._onMouseMove,false);canvas.addEventListener("MSPointerDown",this._onGestureStart,false);canvas.addEventListener("MSGestureChange",this._onGesture,false);window.addEventListener("keydown",this._onKeyDown,false);window.addEventListener("keyup",this._onKeyUp,false);window.addEventListener('mousewheel',this._wheel,false);window.addEventListener("blur",this._onLostFocus,false);};BABYLON.ArcRotateCamera.prototype.detachControl=function(canvas){if(this._attachedCanvas!=canvas){return;}canvas.removeEventListener(eventPrefix+"down",this._onPointerDown);canvas.removeEventListener(eventPrefix+"up",this._onPointerUp);canvas.removeEventListener(eventPrefix+"out",this._onPointerUp);canvas.removeEventListener(eventPrefix+"move",this._onPointerMove);canvas.removeEventListener("mousemove",this._onMouseMove);canvas.removeEventListener("MSPointerDown",this._onGestureStart);canvas.removeEventListener("MSGestureChange",this._onGesture);window.removeEventListener("keydown",this._onKeyDown);window.removeEventListener("keyup",this._onKeyUp);window.removeEventListener('mousewheel',this._wheel);window.removeEventListener("blur",this._onLostFocus);this._MSGestureHandler=null;this._attachedCanvas=null;if(this._reset){this._reset();}};BABYLON.ArcRotateCamera.prototype._update=function(){for(var index=0;indexthis.upperAlphaLimit){this.alpha=this.upperAlphaLimit;}if(this.lowerBetaLimit&&this.betathis.upperBetaLimit){this.beta=this.upperBetaLimit;}if(this.lowerRadiusLimit&&this.radiusthis.upperRadiusLimit){this.radius=this.upperRadiusLimit;}};BABYLON.ArcRotateCamera.prototype.setPosition=function(position){var radiusv3=position.subtract(this.target.position?this.target.position:this.target);this.radius=radiusv3.length();this.alpha=Math.atan(radiusv3.z/radiusv3.x);this.beta=Math.acos(radiusv3.y/this.radius);};BABYLON.ArcRotateCamera.prototype._getViewMatrix=function(){if(this.beta>Math.PI)this.beta=Math.PI;if(this.beta<=0)this.beta=0.01;var cosa=Math.cos(this.alpha);var sina=Math.sin(this.alpha);var cosb=Math.cos(this.beta);var sinb=Math.sin(this.beta);this.target.addToRef(new BABYLON.Vector3(this.radius*cosa*sinb,this.radius*cosb,this.radius*sina*sinb),this.position);BABYLON.Matrix.LookAtLHToRef(this.position,this.target,this.upVector,this._viewMatrix);return this._viewMatrix;};})();var BABYLON=BABYLON||{};(function(){BABYLON.Scene=function(engine){this._engine=engine;this.autoClear=true;this.clearColor=new BABYLON.Color3(0.2,0.2,0.3);this.ambientColor=new BABYLON.Color3(0,0,0);engine.scenes.push(this);this._totalVertices=0;this._activeVertices=0;this._activeParticles=0;this._lastFrameDuration=0;this._evaluateActiveMeshesDuration=0;this._renderTargetsDuration=0;this._renderDuration=0;this._renderId=0;this._executeWhenReadyTimeoutId=-1;this._toBeDisposed=new BABYLON.Tools.SmartArray(256);this._onReadyCallbacks=[];this._pendingData=[];this._onBeforeRenderCallbacks=[];this.fogMode=BABYLON.Scene.FOGMODE_NONE;this.fogColor=new BABYLON.Color3(0.2,0.2,0.3);this.fogDensity=0.1;this.fogStart=0;this.fogEnd=1000.0;this.lightsEnabled=true;this.lights=[];this.cameras=[];this.activeCamera=null;this.meshes=[];this._activeMeshes=new BABYLON.Tools.SmartArray(256);this._processedMaterials=new BABYLON.Tools.SmartArray(256);this._renderTargets=new BABYLON.Tools.SmartArray(256);this._activeParticleSystems=new BABYLON.Tools.SmartArray(256);this._activeSkeletons=new BABYLON.Tools.SmartArray(32);this._renderingManager=new BABYLON.RenderingManager(this);this.materials=[];this.multiMaterials=[];this.defaultMaterial=new BABYLON.StandardMaterial("default material",this);this.texturesEnabled=true;this.textures=[];this.particlesEnabled=true;this.particleSystems=[];this.spriteManagers=[];this.layers=[];this.skeletons=[];this.lensFlareSystems=[];this.collisionsEnabled=true;this.gravity=new BABYLON.Vector3(0,-9.0,0);this._activeAnimatables=[];this._transformMatrix=BABYLON.Matrix.Zero();this._scaledPosition=BABYLON.Vector3.Zero();this._scaledVelocity=BABYLON.Vector3.Zero();this.postProcessesEnabled=true;this.postProcessManager=new BABYLON.PostProcessManager(this);this.renderTargetsEnabled=true;this.customRenderTargets=[];this.activeCameras=[];};BABYLON.Scene.prototype.getEngine=function(){return this._engine;};BABYLON.Scene.prototype.getTotalVertices=function(){return this._totalVertices;};BABYLON.Scene.prototype.getActiveVertices=function(){return this._activeVertices;};BABYLON.Scene.prototype.getTotalVertices=function(){return this._totalVertices;};BABYLON.Scene.prototype.getActiveParticles=function(){return this._activeParticles;};BABYLON.Scene.prototype.getLastFrameDuration=function(){return this._lastFrameDuration;};BABYLON.Scene.prototype.getEvaluateActiveMeshesDuration=function(){return this._evaluateActiveMeshesDuration;};BABYLON.Scene.prototype.getRenderTargetsDuration=function(){return this._renderTargetsDuration;};BABYLON.Scene.prototype.getRenderDuration=function(){return this._renderDuration;};BABYLON.Scene.prototype.getParticlesDuration=function(){return this._particlesDuration;};BABYLON.Scene.prototype.getSpritesDuration=function(){return this._spritesDuration;};BABYLON.Scene.prototype.getAnimationRatio=function(){return this._animationRatio;};BABYLON.Scene.prototype.getRenderId=function(){return this._renderId;};BABYLON.Scene.prototype.isReady=function(){if(this._pendingData.length>0){return false;}for(var index=0;index-1){this._onBeforeRenderCallbacks.splice(index,1);}};BABYLON.Scene.prototype._addPendingData=function(data){this._pendingData.push(data);};BABYLON.Scene.prototype._removePendingData=function(data){var index=this._pendingData.indexOf(data);if(index!==-1){this._pendingData.splice(index,1);}};BABYLON.Scene.prototype.getWaitingItemsCount=function(){return this._pendingData.length;};BABYLON.Scene.prototype.executeWhenReady=function(func){this._onReadyCallbacks.push(func);if(this._executeWhenReadyTimeoutId!==-1){return;}var that=this;this._executeWhenReadyTimeoutId=setTimeout(function(){that._checkIsReady();},150);};BABYLON.Scene.prototype._checkIsReady=function(){if(this.isReady()){this._onReadyCallbacks.forEach(function(func){func();});this._onReadyCallbacks=[];this._executeWhenReadyTimeoutId=-1;return;}var that=this;this._executeWhenReadyTimeoutId=setTimeout(function(){that._checkIsReady();},150);};BABYLON.Scene.prototype.beginAnimation=function(target,from,to,loop,speedRatio,onAnimationEnd){if(speedRatio===undefined){speedRatio=1.0;}if(target.animations){this.stopAnimation(target);var animatable=new BABYLON._Animatable(target,from,to,loop,speedRatio,onAnimationEnd);this._activeAnimatables.push(animatable);}if(target.getAnimatables){var animatables=target.getAnimatables();for(var index=0;index=0;index--){if(this.meshes[index].id===id){return this.meshes[index];}}return null;};BABYLON.Scene.prototype.getLastEntryByID=function(id){for(var index=this.meshes.length-1;index>=0;index--){if(this.meshes[index].id===id){return this.meshes[index];}}for(var index=this.cameras.length-1;index>=0;index--){if(this.cameras[index].id===id){return this.cameras[index];}}for(var index=this.lights.length-1;index>=0;index--){if(this.lights[index].id===id){return this.lights[index];}}return null;};BABYLON.Scene.prototype.getMeshByName=function(name){for(var index=0;index=0;index--){if(this.skeletons[index].id===id){return this.skeletons[index];}}return null;};BABYLON.Scene.prototype.getSkeletonById=function(id){for(var index=0;index0&&mesh.isInFrustrum(this._frustumPlanes))){if(mesh._renderId===0){this._activeMeshes.push(mesh);}mesh._renderId=this._renderId;if(mesh.skeleton){this._activeSkeletons.pushNoDuplicate(mesh.skeleton);}var subMeshes=block.subMeshes[meshIndex];for(var subIndex=0;subIndex0&&mesh.isInFrustrum(this._frustumPlanes)){this._activeMeshes.push(mesh);if(mesh.skeleton){this._activeSkeletons.pushNoDuplicate(mesh.skeleton);}for(var subIndex=0;subIndex0){engine.restoreDefaultFramebuffer();}this._renderTargetsDuration=new Date()-beforeRenderTargetDate;this.postProcessManager._prepareFrame();var beforeRenderDate=new Date();if(this.layers.length){engine.setDepthBuffer(false);var layerIndex;var layer;for(layerIndex=0;layerIndex0){var currentRenderId=this._renderId;for(var cameraIndex=0;cameraIndex=maximumRetry){finalPosition.copyFrom(position);return;}collider._initialize(position,velocity,closeDistance);for(var index=0;indexmax.x)max.x=v.x;if(v.y>max.y)max.y=v.y;if(v.z>max.z)max.z=v.z;};var min=new BABYLON.Vector3(Number.MAX_VALUE,Number.MAX_VALUE,Number.MAX_VALUE);var max=new BABYLON.Vector3(-Number.MAX_VALUE,-Number.MAX_VALUE,-Number.MAX_VALUE);for(var index=0;index=pickingInfo.distance)continue;pickingInfo=result;if(fastCheck){break;}}return pickingInfo||new BABYLON.PickingInfo();};BABYLON.Scene.prototype.pick=function(x,y,predicate,fastCheck){var that=this;return this._internalPick(function(world){return that.createPickingRay(x,y,world);},predicate,fastCheck);};BABYLON.Scene.prototype.pickWithRay=function(ray,predicate,fastCheck){var that=this;return this._internalPick(function(world){if(!that._pickWithRayInverseMatrix){that._pickWithRayInverseMatrix=BABYLON.Matrix.Identity();}world.invertToRef(that._pickWithRayInverseMatrix);return BABYLON.Ray.Transform(ray,that._pickWithRayInverseMatrix);},predicate,fastCheck);};BABYLON.Scene.FOGMODE_NONE=0;BABYLON.Scene.FOGMODE_EXP=1;BABYLON.Scene.FOGMODE_EXP2=2;BABYLON.Scene.FOGMODE_LINEAR=3;})();var BABYLON=BABYLON||{};(function(){BABYLON.VertexBuffer=function(mesh,data,kind,updatable){this._mesh=mesh;this._engine=mesh.getScene().getEngine();this._updatable=updatable;if(updatable){this._buffer=this._engine.createDynamicVertexBuffer(data.length*4);this._engine.updateDynamicVertexBuffer(this._buffer,data);}else{this._buffer=this._engine.createVertexBuffer(data);}this._data=data;this._kind=kind;switch(kind){case BABYLON.VertexBuffer.PositionKind:this._strideSize=3;this._mesh._resetPointsArrayCache();break;case BABYLON.VertexBuffer.NormalKind:this._strideSize=3;break;case BABYLON.VertexBuffer.UVKind:this._strideSize=2;break;case BABYLON.VertexBuffer.UV2Kind:this._strideSize=2;break;case BABYLON.VertexBuffer.ColorKind:this._strideSize=3;break;case BABYLON.VertexBuffer.MatricesIndicesKind:this._strideSize=4;break;case BABYLON.VertexBuffer.MatricesWeightsKind:this._strideSize=4;break;}};BABYLON.VertexBuffer.prototype.isUpdatable=function(){return this._updatable;};BABYLON.VertexBuffer.prototype.getData=function(){return this._data;};BABYLON.VertexBuffer.prototype.getStrideSize=function(){return this._strideSize;};BABYLON.VertexBuffer.prototype.update=function(data){this._engine.updateDynamicVertexBuffer(this._buffer,data);this._data=data;if(this._kind===BABYLON.VertexBuffer.PositionKind){this._mesh._resetPointsArrayCache();}};BABYLON.VertexBuffer.prototype.dispose=function(){this._engine._releaseBuffer(this._buffer);};BABYLON.VertexBuffer.PositionKind="position";BABYLON.VertexBuffer.NormalKind="normal";BABYLON.VertexBuffer.UVKind="uv";BABYLON.VertexBuffer.UV2Kind="uv2";BABYLON.VertexBuffer.ColorKind="color";BABYLON.VertexBuffer.MatricesIndicesKind="matricesIndices";BABYLON.VertexBuffer.MatricesWeightsKind="matricesWeights";})();var BABYLON=BABYLON||{};(function(){BABYLON.Mesh=function(name,scene){this.name=name;this.id=name;this._scene=scene;this._totalVertices=0;this._worldMatrix=BABYLON.Matrix.Identity();scene.meshes.push(this);this.position=new BABYLON.Vector3(0,0,0);this.rotation=new BABYLON.Vector3(0,0,0);this.rotationQuaternion=null;this.scaling=new BABYLON.Vector3(1,1,1);this._pivotMatrix=BABYLON.Matrix.Identity();this._indices=[];this.subMeshes=[];this._renderId=0;this._onBeforeRenderCallbacks=[];this.animations=[];this._positions=null;this._cache={localMatrixUpdated:false,position:BABYLON.Vector3.Zero(),scaling:BABYLON.Vector3.Zero(),rotation:BABYLON.Vector3.Zero(),rotationQuaternion:new BABYLON.Quaternion(0,0,0,0)};this._childrenFlag=false;this._localScaling=BABYLON.Matrix.Zero();this._localRotation=BABYLON.Matrix.Zero();this._localTranslation=BABYLON.Matrix.Zero();this._localBillboard=BABYLON.Matrix.Zero();this._localPivotScaling=BABYLON.Matrix.Zero();this._localPivotScalingRotation=BABYLON.Matrix.Zero();this._localWorld=BABYLON.Matrix.Zero();this._worldMatrix=BABYLON.Matrix.Zero();this._rotateYByPI=BABYLON.Matrix.RotationY(Math.PI);this._collisionsTransformMatrix=BABYLON.Matrix.Zero();this._collisionsScalingMatrix=BABYLON.Matrix.Zero();this._absolutePosition=BABYLON.Vector3.Zero();};BABYLON.Mesh.prototype=Object.create(BABYLON.Node.prototype);BABYLON.Mesh.BILLBOARDMODE_NONE=0;BABYLON.Mesh.BILLBOARDMODE_X=1;BABYLON.Mesh.BILLBOARDMODE_Y=2;BABYLON.Mesh.BILLBOARDMODE_Z=4;BABYLON.Mesh.BILLBOARDMODE_ALL=7;BABYLON.Mesh.prototype.delayLoadState=BABYLON.Engine.DELAYLOADSTATE_NONE;BABYLON.Mesh.prototype.material=null;BABYLON.Mesh.prototype.isVisible=true;BABYLON.Mesh.prototype.isPickable=true;BABYLON.Mesh.prototype.visibility=1.0;BABYLON.Mesh.prototype.billboardMode=BABYLON.Mesh.BILLBOARDMODE_NONE;BABYLON.Mesh.prototype.checkCollisions=false;BABYLON.Mesh.prototype.receiveShadows=false;BABYLON.Mesh.prototype._isDisposed=false;BABYLON.Mesh.prototype.onDispose=null;BABYLON.Mesh.prototype.skeleton=null;BABYLON.Mesh.prototype.renderingGroupId=0;BABYLON.Mesh.prototype.infiniteDistance=false;BABYLON.Mesh.prototype.getBoundingInfo=function(){return this._boundingInfo;};BABYLON.Mesh.prototype.getScene=function(){return this._scene;};BABYLON.Mesh.prototype.getWorldMatrix=function(){if(this._currentRenderId!==this._scene.getRenderId()){this.computeWorldMatrix();}return this._worldMatrix;};BABYLON.Mesh.prototype.getAbsolutePosition=function(){return this._absolutePosition;};BABYLON.Mesh.prototype.getTotalVertices=function(){return this._totalVertices;};BABYLON.Mesh.prototype.getVerticesData=function(kind){return this._vertexBuffers[kind].getData();};BABYLON.Mesh.prototype.isVerticesDataPresent=function(kind){if(!this._vertexBuffers&&this._delayInfo){return this._delayInfo.indexOf(kind)!==-1;}return this._vertexBuffers[kind]!==undefined;};BABYLON.Mesh.prototype.getTotalIndices=function(){return this._indices.length;};BABYLON.Mesh.prototype.getIndices=function(){return this._indices;};BABYLON.Mesh.prototype.getVertexStrideSize=function(){return this._vertexStrideSize;};BABYLON.Mesh.prototype.setPivotMatrix=function(matrix){this._pivotMatrix=matrix;this._cache.pivotMatrixUpdated=true;};BABYLON.Mesh.prototype.getPivotMatrix=function(){return this._localMatrix;};BABYLON.Mesh.prototype.isSynchronized=function(){if(this.billboardMode!==BABYLON.Mesh.BILLBOARDMODE_NONE)return false;if(this._cache.pivotMatrixUpdated){return false;}if(this.infiniteDistance){return false;}if(!this._cache.position.equals(this.position))return false;if(this.rotationQuaternion){if(!this._cache.rotationQuaternion.equals(this.rotationQuaternion))return false;}else{if(!this._cache.rotation.equals(this.rotation))return false;}if(!this._cache.scaling.equals(this.scaling))return false;if(this.parent)return!this.parent._needToSynchonizeChildren();return true;};BABYLON.Mesh.prototype.isReady=function(){return this._isReady;};BABYLON.Mesh.prototype.isAnimated=function(){return this._animationStarted;};BABYLON.Mesh.prototype.isDisposed=function(){return this._isDisposed;};BABYLON.Mesh.prototype.markAsDirty=function(property){if(property==="rotation"){this.rotationQuaternion=null;}this._childrenFlag=true;};BABYLON.Mesh.prototype.refreshBoundingInfo=function(){var data=this.getVerticesData(BABYLON.VertexBuffer.PositionKind);if(!data){return;}var extend=BABYLON.Tools.ExtractMinAndMax(data,0,this._totalVertices);this._boundingInfo=new BABYLON.BoundingInfo(extend.minimum,extend.maximum);for(var index=0;index-1){this._onBeforeRenderCallbacks.splice(index,1);}};BABYLON.Mesh.prototype.render=function(subMesh){if(!this._vertexBuffers||!this._indexBuffer){return;}for(var callbackIndex=0;callbackIndex1&&!subMesh._checkCollision(collider))continue;this._collideForSubMesh(subMesh,transformMatrix,collider);}};BABYLON.Mesh.prototype._checkCollision=function(collider){if(!this._boundingInfo._checkCollision(collider))return;BABYLON.Matrix.ScalingToRef(1.0/collider.radius.x,1.0/collider.radius.y,1.0/collider.radius.z,this._collisionsScalingMatrix);this._worldMatrix.multiplyToRef(this._collisionsScalingMatrix,this._collisionsTransformMatrix);this._processCollisionsForSubModels(collider,this._collisionsTransformMatrix);};BABYLON.Mesh.prototype.intersectsMesh=function(mesh,precise){if(!this._boundingInfo||!mesh._boundingInfo){return false;}return this._boundingInfo.intersects(mesh._boundingInfo,precise);};BABYLON.Mesh.prototype.intersectsPoint=function(point){if(!this._boundingInfo){return false;}return this._boundingInfo.intersectsPoint(point);};BABYLON.Mesh.prototype.intersects=function(ray,fastCheck){var pickingInfo=new BABYLON.PickingInfo();if(!this._boundingInfo||!ray.intersectsSphere(this._boundingInfo.boundingSphere)||!ray.intersectsBox(this._boundingInfo.boundingBox)){return pickingInfo;}this._generatePointsArray();var distance=Number.MAX_VALUE;for(var index=0;index1&&!subMesh.canIntersects(ray))continue;var currentDistance=subMesh.intersects(ray,this._positions,this._indices,fastCheck);if(currentDistance>0){if(fastCheck||currentDistance=0&&distance0){var verticesCount=positions.length/3;for(var firstIndex=verticesCount-2*(totalYRotationSteps+1);(firstIndex+totalYRotationSteps+2)0){if(fastCheck||currentDistance0&&distancemaxVertexIndex)maxVertexIndex=vertexIndex;}return new BABYLON.SubMesh(materialIndex,minVertexIndex,maxVertexIndex-minVertexIndex,startIndex,indexCount,mesh);};})();var BABYLON=BABYLON||{};(function(){BABYLON.BaseTexture=function(url,scene){this._scene=scene;this._scene.textures.push(this);};BABYLON.BaseTexture.prototype.delayLoadState=BABYLON.Engine.DELAYLOADSTATE_NONE;BABYLON.BaseTexture.prototype.hasAlpha=false;BABYLON.BaseTexture.prototype.hasAlpha=false;BABYLON.BaseTexture.prototype.level=1;BABYLON.BaseTexture.prototype._texture=null;BABYLON.BaseTexture.prototype.onDispose=null;BABYLON.BaseTexture.prototype.getInternalTexture=function(){return this._texture;};BABYLON.BaseTexture.prototype.isReady=function(){if(this.delayLoadState===BABYLON.Engine.DELAYLOADSTATE_NOTLOADED){return true;}if(this._texture){return this._texture.isReady;}return false;};BABYLON.BaseTexture.prototype.getSize=function(){if(this._texture._width){return{width:this._texture._width,height:this._texture._height};}if(this._texture._size){return{width:this._texture._size,height:this._texture._size};}return{width:0,height:0};};BABYLON.BaseTexture.prototype.getBaseSize=function(){if(!this.isReady())return{width:0,height:0};if(this._texture._size){return{width:this._texture._size,height:this._texture._size};}return{width:this._texture._baseWidth,height:this._texture._baseHeight};};BABYLON.BaseTexture.prototype._getFromCache=function(url,noMipmap){var texturesCache=this._scene.getEngine().getLoadedTexturesCache();for(var index=0;index=0){this._scene.textures.splice(index,1);}if(this._texture===undefined){return;}this.releaseInternalTexture();if(this.onDispose){this.onDispose();}};})();var BABYLON=BABYLON||{};(function(){BABYLON.RenderingGroup=function(index,scene){this.index=index;this._scene=scene;this._opaqueSubMeshes=new BABYLON.Tools.SmartArray(256);this._transparentSubMeshes=new BABYLON.Tools.SmartArray(256);this._alphaTestSubMeshes=new BABYLON.Tools.SmartArray(256);};BABYLON.RenderingGroup.prototype.render=function(customRenderFunction,beforeTransparents){if(customRenderFunction){customRenderFunction(this._opaqueSubMeshes,this._alphaTestSubMeshes,this._transparentSubMeshes,beforeTransparents);return true;}if(this._opaqueSubMeshes.length===0&&this._alphaTestSubMeshes.length===0&&this._transparentSubMeshes===0){return false;}var engine=this._scene.getEngine();var subIndex;var submesh;for(subIndex=0;subIndexb._distanceToCamera){return-1;}return 0;});engine.setAlphaMode(BABYLON.Engine.ALPHA_COMBINE);for(subIndex=0;subIndex0||mesh.visibility<1.0){this._transparentSubMeshes.push(subMesh);}}else if(material.needAlphaTesting()){this._alphaTestSubMeshes.push(subMesh);}else{this._opaqueSubMeshes.push(subMesh);}};})();var BABYLON=BABYLON||{};(function(){BABYLON.RenderingManager=function(scene){this._scene=scene;this._renderingGroups=[];};BABYLON.RenderingManager.prototype._renderParticles=function(index,activeMeshes){if(this._scene._activeParticleSystems.length===0){return;}var beforeParticlesDate=new Date();for(var particleIndex=0;particleIndex 1.0 || uv.y < 0. || uv.y > 1.0)\n {\n return 1.0;\n }\n\n float shadow = unpack(texture2D(shadowSampler, uv));\n\n if (depth.z > shadow)\n {\n return 0.;\n }\n return 1.;\n}\n\n// Thanks to http://devmaster.net/\nfloat ChebychevInequality(vec2 moments, float t)\n{\n if (t <= moments.x)\n {\n return 1.0;\n }\n\n float variance = moments.y - (moments.x * moments.x);\n variance = max(variance, 0.);\n\n float d = t - moments.x;\n return variance / (variance + d * d);\n}\n\nfloat computeShadowWithVSM(vec4 vPositionFromLight, sampler2D shadowSampler)\n{\n vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;\n vec2 uv = 0.5 * depth.xy + vec2(0.5, 0.5);\n\n if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0)\n {\n return 1.0;\n }\n\n vec4 texel = texture2D(shadowSampler, uv);\n\n vec2 moments = vec2(unpackHalf(texel.xy), unpackHalf(texel.zw));\n return clamp(1.3 - ChebychevInequality(moments, depth.z), 0., 1.0);\n}\n#endif\n\n// Bump\n#ifdef BUMP\n#extension GL_OES_standard_derivatives : enable\nvarying vec2 vBumpUV;\nuniform vec2 vBumpInfos;\nuniform sampler2D bumpSampler;\n\n// Thanks to http://www.thetenthplanet.de/archives/1180\nmat3 cotangent_frame(vec3 normal, vec3 p, vec2 uv)\n{\n // get edge vectors of the pixel triangle\n vec3 dp1 = dFdx(p);\n vec3 dp2 = dFdy(p);\n vec2 duv1 = dFdx(uv);\n vec2 duv2 = dFdy(uv);\n\n // solve the linear system\n vec3 dp2perp = cross(dp2, normal);\n vec3 dp1perp = cross(normal, dp1);\n vec3 tangent = dp2perp * duv1.x + dp1perp * duv2.x;\n vec3 binormal = dp2perp * duv1.y + dp1perp * duv2.y;\n\n // construct a scale-invariant frame \n float invmax = inversesqrt(max(dot(tangent, tangent), dot(binormal, binormal)));\n return mat3(tangent * invmax, binormal * invmax, normal);\n}\n\nvec3 perturbNormal(vec3 viewDir)\n{\n vec3 map = texture2D(bumpSampler, vBumpUV).xyz * vBumpInfos.y;\n map = map * 255. / 127. - 128. / 127.;\n mat3 TBN = cotangent_frame(vNormalW, -viewDir, vBumpUV);\n return normalize(TBN * map);\n}\n#endif\n\n#ifdef CLIPPLANE\nvarying float fClipDistance;\n#endif\n\n// Fog\n#ifdef FOG\n\n#define FOGMODE_NONE 0.\n#define FOGMODE_EXP 1.\n#define FOGMODE_EXP2 2.\n#define FOGMODE_LINEAR 3.\n#define E 2.71828\n\nuniform vec4 vFogInfos;\nuniform vec3 vFogColor;\nvarying float fFogDistance;\n\nfloat CalcFogFactor()\n{\n float fogCoeff = 1.0;\n float fogStart = vFogInfos.y;\n float fogEnd = vFogInfos.z;\n float fogDensity = vFogInfos.w;\n\n if (FOGMODE_LINEAR == vFogInfos.x)\n {\n fogCoeff = (fogEnd - fFogDistance) / (fogEnd - fogStart);\n }\n else if (FOGMODE_EXP == vFogInfos.x)\n {\n fogCoeff = 1.0 / pow(E, fFogDistance * fogDensity);\n }\n else if (FOGMODE_EXP2 == vFogInfos.x)\n {\n fogCoeff = 1.0 / pow(E, fFogDistance * fFogDistance * fogDensity * fogDensity);\n }\n\n return clamp(fogCoeff, 0.0, 1.0);\n}\n#endif\n\n// Light Computing\nstruct lightingInfo\n{\n vec3 diffuse;\n vec3 specular;\n};\n\nlightingInfo computeLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, vec3 specularColor) {\n lightingInfo result;\n\n vec3 lightVectorW;\n if (lightData.w == 0.)\n {\n lightVectorW = normalize(lightData.xyz - vPositionW);\n }\n else\n {\n lightVectorW = normalize(-lightData.xyz);\n }\n\n // diffuse\n float ndl = max(0., dot(vNormal, lightVectorW));\n\n // Specular\n vec3 angleW = normalize(viewDirectionW + lightVectorW);\n float specComp = max(0., dot(vNormal, angleW));\n specComp = pow(specComp, vSpecularColor.a);\n\n result.diffuse = ndl * diffuseColor;\n result.specular = specComp * specularColor;\n\n return result;\n}\n\nlightingInfo computeSpotLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec4 lightDirection, vec3 diffuseColor, vec3 specularColor) {\n lightingInfo result;\n\n vec3 lightVectorW = normalize(lightData.xyz - vPositionW);\n\n // diffuse\n float cosAngle = max(0., dot(-lightDirection.xyz, lightVectorW));\n float spotAtten = 0.0;\n\n if (cosAngle >= lightDirection.w)\n {\n cosAngle = max(0., pow(cosAngle, lightData.w));\n spotAtten = max(0., (cosAngle - lightDirection.w) / (1. - cosAngle));\n\n // Diffuse\n float ndl = max(0., dot(vNormal, -lightDirection.xyz));\n\n // Specular\n vec3 angleW = normalize(viewDirectionW - lightDirection.xyz);\n float specComp = max(0., dot(vNormal, angleW));\n specComp = pow(specComp, vSpecularColor.a);\n\n result.diffuse = ndl * spotAtten * diffuseColor;\n result.specular = specComp * specularColor * spotAtten;\n\n return result;\n }\n\n result.diffuse = vec3(0.);\n result.specular = vec3(0.);\n\n return result;\n}\n\nlightingInfo computeHemisphericLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, vec3 specularColor, vec3 groundColor) {\n lightingInfo result;\n\n // Diffuse\n float ndl = dot(vNormal, lightData.xyz) * 0.5 + 0.5;\n\n // Specular\n vec3 angleW = normalize(viewDirectionW + lightData.xyz);\n float specComp = max(0., dot(vNormal, angleW));\n specComp = pow(specComp, vSpecularColor.a);\n\n result.diffuse = mix(groundColor, diffuseColor, ndl);\n result.specular = specComp * specularColor;\n\n return result;\n}\n\nvoid main(void) {\n // Clip plane\n#ifdef CLIPPLANE\n if (fClipDistance > 0.0)\n discard;\n#endif\n\n vec3 viewDirectionW = normalize(vEyePosition - vPositionW);\n\n // Base color\n vec4 baseColor = vec4(1., 1., 1., 1.);\n vec3 diffuseColor = vDiffuseColor.rgb;\n\n#ifdef VERTEXCOLOR\n diffuseColor *= vColor;\n#endif\n\n#ifdef DIFFUSE\n baseColor = texture2D(diffuseSampler, vDiffuseUV);\n\n#ifdef ALPHATEST\n if (baseColor.a < 0.4)\n discard;\n#endif\n\n baseColor.rgb *= vDiffuseInfos.y;\n#endif\n\n // Bump\n vec3 normalW = vNormalW;\n\n#ifdef BUMP\n normalW = perturbNormal(viewDirectionW);\n#endif\n\n // Ambient color\n vec3 baseAmbientColor = vec3(1., 1., 1.);\n\n#ifdef AMBIENT\n baseAmbientColor = texture2D(ambientSampler, vAmbientUV).rgb * vAmbientInfos.y;\n#endif\n\n // Lighting\n vec3 diffuseBase = vec3(0., 0., 0.);\n vec3 specularBase = vec3(0., 0., 0.);\n float shadow = 1.;\n\n#ifdef LIGHT0\n#ifdef SPOTLIGHT0\n lightingInfo info = computeSpotLighting(viewDirectionW, normalW, vLightData0, vLightDirection0, vLightDiffuse0, vLightSpecular0);\n#endif\n#ifdef HEMILIGHT0\n lightingInfo info = computeHemisphericLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0, vLightSpecular0, vLightGround0);\n#endif\n#ifdef POINTDIRLIGHT0\n lightingInfo info = computeLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0, vLightSpecular0);\n#endif\n#ifdef SHADOW0\n#ifdef SHADOWVSM0\n shadow = computeShadowWithVSM(vPositionFromLight0, shadowSampler0);\n#else\n shadow = computeShadow(vPositionFromLight0, shadowSampler0);\n#endif\n#else\n shadow = 1.;\n#endif\n diffuseBase += info.diffuse * shadow;\n specularBase += info.specular * shadow;\n#endif\n\n#ifdef LIGHT1\n#ifdef SPOTLIGHT1\n info = computeSpotLighting(viewDirectionW, normalW, vLightData1, vLightDirection1, vLightDiffuse1, vLightSpecular1);\n#endif\n#ifdef HEMILIGHT1\n info = computeHemisphericLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1, vLightSpecular1, vLightGround1);\n#endif\n#ifdef POINTDIRLIGHT1\n info = computeLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1, vLightSpecular1);\n#endif\n#ifdef SHADOW1\n#ifdef SHADOWVSM1\n shadow = computeShadowWithVSM(vPositionFromLight1, shadowSampler1);\n#else\n shadow = computeShadow(vPositionFromLight1, shadowSampler1);\n#endif\n#else\n shadow = 1.;\n#endif\n diffuseBase += info.diffuse * shadow;\n specularBase += info.specular * shadow;\n#endif\n\n#ifdef LIGHT2\n#ifdef SPOTLIGHT2\n info = computeSpotLighting(viewDirectionW, normalW, vLightData2, vLightDirection2, vLightDiffuse2, vLightSpecular2);\n#endif\n#ifdef HEMILIGHT2\n info = computeHemisphericLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2, vLightSpecular2, vLightGround2);\n#endif\n#ifdef POINTDIRLIGHT2\n info = computeLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2, vLightSpecular2);\n#endif\n#ifdef SHADOW2\n#ifdef SHADOWVSM2\n shadow = computeShadowWithVSM(vPositionFromLight2, shadowSampler2);\n#else\n shadow = computeShadow(vPositionFromLight2, shadowSampler2);\n#endif \n#else\n shadow = 1.;\n#endif\n diffuseBase += info.diffuse * shadow;\n specularBase += info.specular * shadow;\n#endif\n\n#ifdef LIGHT3\n#ifdef SPOTLIGHT3\n info = computeSpotLighting(viewDirectionW, normalW, vLightData3, vLightDirection3, vLightDiffuse3, vLightSpecular3);\n#endif\n#ifdef HEMILIGHT3\n info = computeHemisphericLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3, vLightSpecular3, vLightGround3);\n#endif\n#ifdef POINTDIRLIGHT3\n info = computeLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3, vLightSpecular3);\n#endif\n#ifdef SHADOW3\n#ifdef SHADOWVSM3\n shadow = computeShadowWithVSM(vPositionFromLight3, shadowSampler3);\n#else\n shadow = computeShadow(vPositionFromLight3, shadowSampler3);\n#endif \n#else\n shadow = 1.;\n#endif\n diffuseBase += info.diffuse * shadow;\n specularBase += info.specular * shadow;\n#endif\n\n // Reflection\n vec3 reflectionColor = vec3(0., 0., 0.);\n\n#ifdef REFLECTION\n vec3 vReflectionUVW = computeReflectionCoords(vReflectionInfos.x, vec4(vPositionW, 1.0), normalW);\n\n if (vReflectionInfos.z != 0.0)\n {\n reflectionColor = textureCube(reflectionCubeSampler, vReflectionUVW).rgb * vReflectionInfos.y;\n }\n else\n {\n vec2 coords = vReflectionUVW.xy;\n\n if (vReflectionInfos.x == MAP_PROJECTION)\n {\n coords /= vReflectionUVW.z;\n }\n\n coords.y = 1.0 - coords.y;\n\n reflectionColor = texture2D(reflection2DSampler, coords).rgb * vReflectionInfos.y;\n }\n#endif\n\n // Alpha\n float alpha = vDiffuseColor.a;\n\n#ifdef OPACITY\n vec4 opacityMap = texture2D(opacitySampler, vOpacityUV);\n opacityMap.rgb = opacityMap.rgb * vec3(0.3, 0.59, 0.11) * opacityMap.a;\n alpha *= (opacityMap.x + opacityMap.y + opacityMap.z)* vOpacityInfos.y;\n#endif\n\n // Emissive\n vec3 emissiveColor = vEmissiveColor;\n#ifdef EMISSIVE\n emissiveColor += texture2D(emissiveSampler, vEmissiveUV).rgb * vEmissiveInfos.y;\n#endif\n\n // Specular map\n vec3 specularColor = vSpecularColor.rgb;\n#ifdef SPECULAR\n specularColor = texture2D(specularSampler, vSpecularUV).rgb * vSpecularInfos.y;\n#endif\n\n // Composition\n vec3 finalDiffuse = clamp(diffuseBase * diffuseColor + emissiveColor + vAmbientColor, 0.0, 1.0) * baseColor.rgb;\n vec3 finalSpecular = specularBase * specularColor;\n\n vec4 color = vec4(finalDiffuse * baseAmbientColor + finalSpecular + reflectionColor, alpha);\n\n#ifdef FOG\n float fog = CalcFogFactor();\n color.rgb = fog * color.rgb + (1.0 - fog) * vFogColor;\n#endif\n\n gl_FragColor = color;\n}", -defaultVertexShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n// Attributes\nattribute vec3 position;\nattribute vec3 normal;\n#ifdef UV1\nattribute vec2 uv;\n#endif\n#ifdef UV2\nattribute vec2 uv2;\n#endif\n#ifdef VERTEXCOLOR\nattribute vec3 color;\n#endif\n#ifdef BONES\nattribute vec4 matricesIndices;\nattribute vec4 matricesWeights;\n#endif\n\n// Uniforms\nuniform mat4 world;\nuniform mat4 view;\nuniform mat4 viewProjection;\n\n#ifdef DIFFUSE\nvarying vec2 vDiffuseUV;\nuniform mat4 diffuseMatrix;\nuniform vec2 vDiffuseInfos;\n#endif\n\n#ifdef AMBIENT\nvarying vec2 vAmbientUV;\nuniform mat4 ambientMatrix;\nuniform vec2 vAmbientInfos;\n#endif\n\n#ifdef OPACITY\nvarying vec2 vOpacityUV;\nuniform mat4 opacityMatrix;\nuniform vec2 vOpacityInfos;\n#endif\n\n#ifdef EMISSIVE\nvarying vec2 vEmissiveUV;\nuniform vec2 vEmissiveInfos;\nuniform mat4 emissiveMatrix;\n#endif\n\n#ifdef SPECULAR\nvarying vec2 vSpecularUV;\nuniform vec2 vSpecularInfos;\nuniform mat4 specularMatrix;\n#endif\n\n#ifdef BUMP\nvarying vec2 vBumpUV;\nuniform vec2 vBumpInfos;\nuniform mat4 bumpMatrix;\n#endif\n\n#ifdef BONES\nuniform mat4 mBones[BonesPerMesh];\n#endif\n\n// Output\nvarying vec3 vPositionW;\nvarying vec3 vNormalW;\n\n#ifdef VERTEXCOLOR\nvarying vec3 vColor;\n#endif\n\n#ifdef CLIPPLANE\nuniform vec4 vClipPlane;\nvarying float fClipDistance;\n#endif\n\n#ifdef FOG\nvarying float fFogDistance;\n#endif\n\n#ifdef SHADOWS\n#ifdef LIGHT0\nuniform mat4 lightMatrix0;\nvarying vec4 vPositionFromLight0;\n#endif\n#ifdef LIGHT1\nuniform mat4 lightMatrix1;\nvarying vec4 vPositionFromLight1;\n#endif\n#ifdef LIGHT2\nuniform mat4 lightMatrix2;\nvarying vec4 vPositionFromLight2;\n#endif\n#ifdef LIGHT3\nuniform mat4 lightMatrix3;\nvarying vec4 vPositionFromLight3;\n#endif\n#endif\n\n#ifdef REFLECTION\nvarying vec3 vPositionUVW;\n#endif\n\nvoid main(void) {\n mat4 finalWorld;\n\n#ifdef REFLECTION\n vPositionUVW = position;\n#endif \n\n#ifdef BONES\n mat4 m0 = mBones[int(matricesIndices.x)] * matricesWeights.x;\n mat4 m1 = mBones[int(matricesIndices.y)] * matricesWeights.y;\n mat4 m2 = mBones[int(matricesIndices.z)] * matricesWeights.z;\n\n#ifdef BONES4\n mat4 m3 = mBones[int(matricesIndices.w)] * matricesWeights.w;\n finalWorld = world * (m0 + m1 + m2 + m3);\n#else\n finalWorld = world * (m0 + m1 + m2);\n#endif \n\n#else\n finalWorld = world;\n#endif\n gl_Position = viewProjection * finalWorld * vec4(position, 1.0);\n\n vec4 worldPos = finalWorld * vec4(position, 1.0);\n vPositionW = vec3(worldPos);\n vNormalW = normalize(vec3(finalWorld * vec4(normal, 0.0)));\n\n // Texture coordinates\n#ifndef UV1\n vec2 uv = vec2(0., 0.);\n#endif\n#ifndef UV2\n vec2 uv2 = vec2(0., 0.);\n#endif\n\n#ifdef DIFFUSE\n if (vDiffuseInfos.x == 0.)\n {\n vDiffuseUV = vec2(diffuseMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vDiffuseUV = vec2(diffuseMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n#ifdef AMBIENT\n if (vAmbientInfos.x == 0.)\n {\n vAmbientUV = vec2(ambientMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vAmbientUV = vec2(ambientMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n#ifdef OPACITY\n if (vOpacityInfos.x == 0.)\n {\n vOpacityUV = vec2(opacityMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vOpacityUV = vec2(opacityMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n#ifdef EMISSIVE\n if (vEmissiveInfos.x == 0.)\n {\n vEmissiveUV = vec2(emissiveMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vEmissiveUV = vec2(emissiveMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n#ifdef SPECULAR\n if (vSpecularInfos.x == 0.)\n {\n vSpecularUV = vec2(specularMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vSpecularUV = vec2(specularMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n#ifdef BUMP\n if (vBumpInfos.x == 0.)\n {\n vBumpUV = vec2(bumpMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vBumpUV = vec2(bumpMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n // Clip plane\n#ifdef CLIPPLANE\n fClipDistance = dot(worldPos, vClipPlane);\n#endif\n\n // Fog\n#ifdef FOG\n fFogDistance = (view * worldPos).z;\n#endif\n\n // Shadows\n#ifdef SHADOWS\n#ifdef LIGHT0\n vPositionFromLight0 = lightMatrix0 * vec4(position, 1.0);\n#endif\n#ifdef LIGHT1\n vPositionFromLight1 = lightMatrix1 * vec4(position, 1.0);\n#endif\n#ifdef LIGHT2\n vPositionFromLight2 = lightMatrix2 * vec4(position, 1.0);\n#endif\n#ifdef LIGHT3\n vPositionFromLight3 = lightMatrix3 * vec4(position, 1.0);\n#endif\n#endif\n\n // Vertex color\n#ifdef VERTEXCOLOR\n vColor = color;\n#endif\n}", -fxaaPixelShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n#define FXAA_REDUCE_MIN (1.0/128.0)\n#define FXAA_REDUCE_MUL (1.0/8.0)\n#define FXAA_SPAN_MAX 8.0\n\nvarying vec2 vUV;\nuniform sampler2D textureSampler;\nuniform vec2 texelSize;\n\nvoid main(){\n vec2 localTexelSize = texelSize;\n vec3 rgbNW = texture2D(textureSampler, (vUV + vec2(-1.0, -1.0) * localTexelSize)).xyz;\n vec3 rgbNE = texture2D(textureSampler, (vUV + vec2(1.0, -1.0) * localTexelSize)).xyz;\n vec3 rgbSW = texture2D(textureSampler, (vUV + vec2(-1.0, 1.0) * localTexelSize)).xyz;\n vec3 rgbSE = texture2D(textureSampler, (vUV + vec2(1.0, 1.0) * localTexelSize)).xyz;\n vec3 rgbM = texture2D(textureSampler, vUV ).xyz;\n vec3 luma = vec3(0.299, 0.587, 0.114);\n float lumaNW = dot(rgbNW, luma);\n float lumaNE = dot(rgbNE, luma);\n float lumaSW = dot(rgbSW, luma);\n float lumaSE = dot(rgbSE, luma);\n float lumaM = dot(rgbM, luma);\n float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));\n float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));\n\n vec2 dir = vec2(-((lumaNW + lumaNE) - (lumaSW + lumaSE)), ((lumaNW + lumaSW) - (lumaNE + lumaSE)));\n\n float dirReduce = max(\n (lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL),\n FXAA_REDUCE_MIN);\n\n float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce);\n dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX),\n max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),\n dir * rcpDirMin)) * localTexelSize;\n\n vec3 rgbA = 0.5 * (\n texture2D(textureSampler, vUV + dir * (1.0 / 3.0 - 0.5)).xyz +\n texture2D(textureSampler, vUV + dir * (2.0 / 3.0 - 0.5)).xyz);\n\n vec3 rgbB = rgbA * 0.5 + 0.25 * (\n texture2D(textureSampler, vUV + dir * -0.5).xyz +\n texture2D(textureSampler, vUV + dir * 0.5).xyz);\n float lumaB = dot(rgbB, luma);\n if ((lumaB < lumaMin) || (lumaB > lumaMax)) {\n gl_FragColor = vec4(rgbA, 1.0);\n }\n else {\n gl_FragColor = vec4(rgbB, 1.0);\n }\n}", -iedefaultPixelShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n#define MAP_PROJECTION 4.\n\n// Constants\nuniform vec3 vEyePosition;\nuniform vec3 vAmbientColor;\nuniform vec4 vDiffuseColor;\nuniform vec4 vSpecularColor;\nuniform vec3 vEmissiveColor;\n\n// Input\nvarying vec3 vPositionW;\nvarying vec3 vNormalW;\n\n#ifdef VERTEXCOLOR\nvarying vec3 vColor;\n#endif\n\n// Lights\n#ifdef LIGHT0\nuniform vec4 vLightData0;\nuniform vec3 vLightDiffuse0;\nuniform vec3 vLightSpecular0;\n#ifdef SHADOW0\nvarying vec4 vPositionFromLight0;\nuniform sampler2D shadowSampler0;\n#endif\n#ifdef SPOTLIGHT0\nuniform vec4 vLightDirection0;\n#endif\n#ifdef HEMILIGHT0\nuniform vec3 vLightGround0;\n#endif\n#endif\n\n#ifdef LIGHT1\nuniform vec4 vLightData1;\nuniform vec3 vLightDiffuse1;\nuniform vec3 vLightSpecular1;\n#ifdef SHADOW1\nvarying vec4 vPositionFromLight1;\nuniform sampler2D shadowSampler1;\n#endif\n#ifdef SPOTLIGHT1\nuniform vec4 vLightDirection1;\n#endif\n#ifdef HEMILIGHT1\nuniform vec3 vLightGround1;\n#endif\n#endif\n\n#ifdef LIGHT2\nuniform vec4 vLightData2;\nuniform vec3 vLightDiffuse2;\nuniform vec3 vLightSpecular2;\n#ifdef SHADOW2\nvarying vec4 vPositionFromLight2;\nuniform sampler2D shadowSampler2;\n#endif\n#ifdef SPOTLIGHT2\nuniform vec4 vLightDirection2;\n#endif\n#ifdef HEMILIGHT2\nuniform vec3 vLightGround2;\n#endif\n#endif\n\n#ifdef LIGHT3\nuniform vec4 vLightData3;\nuniform vec3 vLightDiffuse3;\nuniform vec3 vLightSpecular3;\n#ifdef SHADOW3\nvarying vec4 vPositionFromLight3;\nuniform sampler2D shadowSampler3;\n#endif\n#ifdef SPOTLIGHT3\nuniform vec4 vLightDirection3;\n#endif\n#ifdef HEMILIGHT3\nuniform vec3 vLightGround3;\n#endif\n#endif\n\n// Samplers\n#ifdef DIFFUSE\nvarying vec2 vDiffuseUV;\nuniform sampler2D diffuseSampler;\nuniform vec2 vDiffuseInfos;\n#endif\n\n#ifdef AMBIENT\nvarying vec2 vAmbientUV;\nuniform sampler2D ambientSampler;\nuniform vec2 vAmbientInfos;\n#endif\n\n#ifdef OPACITY \nvarying vec2 vOpacityUV;\nuniform sampler2D opacitySampler;\nuniform vec2 vOpacityInfos;\n#endif\n\n#ifdef REFLECTION\nvarying vec3 vReflectionUVW;\nuniform samplerCube reflectionCubeSampler;\nuniform sampler2D reflection2DSampler;\nuniform vec3 vReflectionInfos;\n#endif\n\n#ifdef EMISSIVE\nvarying vec2 vEmissiveUV;\nuniform vec2 vEmissiveInfos;\nuniform sampler2D emissiveSampler;\n#endif\n\n#ifdef SPECULAR\nvarying vec2 vSpecularUV;\nuniform vec2 vSpecularInfos;\nuniform sampler2D specularSampler;\n#endif\n\n// Shadows\n#ifdef SHADOWS\n\nfloat unpack(vec4 color)\n{\n const vec4 bitShift = vec4(1. / (255. * 255. * 255.), 1. / (255. * 255.), 1. / 255., 1.);\n return dot(color, bitShift);\n}\n\nfloat unpackHalf(vec2 color)\n{\n return color.x + (color.y / 255.0);\n}\n\nfloat computeShadow(vec4 vPositionFromLight, sampler2D shadowSampler)\n{\n vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;\n vec2 uv = 0.5 * depth.xy + vec2(0.5, 0.5);\n\n if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0)\n {\n return 1.0;\n }\n\n float shadow = unpack(texture2D(shadowSampler, uv));\n\n if (depth.z > shadow)\n {\n return 0.;\n }\n return 1.;\n}\n\n// Thanks to http://devmaster.net/\nfloat ChebychevInequality(vec2 moments, float t)\n{\n if (t <= moments.x)\n {\n return 1.0;\n }\n\n float variance = moments.y - (moments.x * moments.x);\n variance = max(variance, 0.);\n\n float d = t - moments.x;\n return variance / (variance + d * d);\n}\n\nfloat computeShadowWithVSM(vec4 vPositionFromLight, sampler2D shadowSampler)\n{\n vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;\n vec2 uv = 0.5 * depth.xy + vec2(0.5, 0.5);\n\n if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0)\n {\n return 1.0;\n }\n\n vec4 texel = texture2D(shadowSampler, uv);\n\n vec2 moments = vec2(unpackHalf(texel.xy), unpackHalf(texel.zw));\n return clamp(1.3 - ChebychevInequality(moments, depth.z), 0., 1.0);\n}\n#endif\n\n#ifdef CLIPPLANE\nvarying float fClipDistance;\n#endif\n\n// Fog\n#ifdef FOG\n\n#define FOGMODE_NONE 0.\n#define FOGMODE_EXP 1.\n#define FOGMODE_EXP2 2.\n#define FOGMODE_LINEAR 3.\n#define E 2.71828\n\nuniform vec4 vFogInfos;\nuniform vec3 vFogColor;\nvarying float fFogDistance;\n\nfloat CalcFogFactor()\n{\n float fogCoeff = 1.0;\n float fogStart = vFogInfos.y;\n float fogEnd = vFogInfos.z;\n float fogDensity = vFogInfos.w;\n\n if (FOGMODE_LINEAR == vFogInfos.x)\n {\n fogCoeff = (fogEnd - fFogDistance) / (fogEnd - fogStart);\n }\n else if (FOGMODE_EXP == vFogInfos.x)\n {\n fogCoeff = 1.0 / pow(E, fFogDistance * fogDensity);\n }\n else if (FOGMODE_EXP2 == vFogInfos.x)\n {\n fogCoeff = 1.0 / pow(E, fFogDistance * fFogDistance * fogDensity * fogDensity);\n }\n\n return clamp(fogCoeff, 0.0, 1.0);\n}\n#endif\n\n// Light Computing\nmat3 computeLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, vec3 specularColor) {\n mat3 result;\n\n vec3 lightVectorW;\n if (lightData.w == 0.)\n {\n lightVectorW = normalize(lightData.xyz - vPositionW);\n }\n else\n {\n lightVectorW = normalize(-lightData.xyz);\n }\n\n // diffuse\n float ndl = max(0., dot(vNormal, lightVectorW));\n\n // Specular\n vec3 angleW = normalize(viewDirectionW + lightVectorW);\n float specComp = max(0., dot(vNormal, angleW));\n specComp = max(0., pow(specComp, max(1.0, vSpecularColor.a)));\n\n result[0] = ndl * diffuseColor;\n result[1] = specComp * specularColor;\n result[2] = vec3(0.);\n\n return result;\n}\n\nmat3 computeSpotLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec4 lightDirection, vec3 diffuseColor, vec3 specularColor) {\n mat3 result;\n\n vec3 lightVectorW = normalize(lightData.xyz - vPositionW);\n\n // diffuse\n float cosAngle = max(0., dot(-lightDirection.xyz, lightVectorW));\n float spotAtten = 0.0;\n\n if (cosAngle >= lightDirection.w)\n {\n cosAngle = max(0., pow(cosAngle, lightData.w));\n spotAtten = max(0., (cosAngle - lightDirection.w) / (1. - cosAngle));\n\n // Diffuse\n float ndl = max(0., dot(vNormal, -lightDirection.xyz));\n\n // Specular\n vec3 angleW = normalize(viewDirectionW - lightDirection.xyz);\n float specComp = max(0., dot(vNormal, angleW));\n specComp = pow(specComp, vSpecularColor.a);\n\n result[0] = ndl * spotAtten * diffuseColor;\n result[1] = specComp * specularColor * spotAtten;\n result[2] = vec3(0.);\n\n return result;\n }\n\n result[0] = vec3(0.);\n result[1] = vec3(0.);\n result[2] = vec3(0.);\n\n return result;\n}\n\nmat3 computeHemisphericLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, vec3 specularColor, vec3 groundColor) {\n mat3 result;\n\n // Diffuse\n float ndl = dot(vNormal, lightData.xyz) * 0.5 + 0.5;\n\n // Specular\n vec3 angleW = normalize(viewDirectionW + lightData.xyz);\n float specComp = max(0., dot(vNormal, angleW));\n specComp = pow(specComp, vSpecularColor.a);\n\n result[0] = mix(groundColor, diffuseColor, ndl);\n result[1] = specComp * specularColor;\n result[2] = vec3(0.);\n\n return result;\n}\n\nvoid main(void) {\n // Clip plane\n#ifdef CLIPPLANE\n if (fClipDistance > 0.0)\n discard;\n#endif\n\n vec3 viewDirectionW = normalize(vEyePosition - vPositionW);\n\n // Base color\n vec4 baseColor = vec4(1., 1., 1., 1.);\n vec3 diffuseColor = vDiffuseColor.rgb;\n\n#ifdef VERTEXCOLOR\n diffuseColor *= vColor;\n#endif\n\n#ifdef DIFFUSE\n baseColor = texture2D(diffuseSampler, vDiffuseUV);\n\n#ifdef ALPHATEST\n if (baseColor.a < 0.4)\n discard;\n#endif\n\n baseColor.rgb *= vDiffuseInfos.y;\n#endif\n\n // Bump\n vec3 normalW = vNormalW;\n\n // Ambient color\n vec3 baseAmbientColor = vec3(1., 1., 1.);\n\n#ifdef AMBIENT\n baseAmbientColor = texture2D(ambientSampler, vAmbientUV).rgb * vAmbientInfos.y;\n#endif\n\n // Lighting\n vec3 diffuseBase = vec3(0., 0., 0.);\n vec3 specularBase = vec3(0., 0., 0.);\n float shadow = 1.;\n\n#ifdef LIGHT0\n#ifdef SPOTLIGHT0\n mat3 info = computeSpotLighting(viewDirectionW, normalW, vLightData0, vLightDirection0, vLightDiffuse0, vLightSpecular0);\n#endif\n#ifdef HEMILIGHT0\n mat3 info = computeHemisphericLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0, vLightSpecular0, vLightGround0);\n#endif\n#ifdef POINTDIRLIGHT0\n mat3 info = computeLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0, vLightSpecular0);\n#endif\n#ifdef SHADOW0\n#ifdef SHADOWVSM0\n shadow = computeShadowWithVSM(vPositionFromLight0, shadowSampler0);\n#else\n shadow = computeShadow(vPositionFromLight0, shadowSampler0);\n#endif\n#else\n shadow = 1.;\n#endif\n diffuseBase += info[0] * shadow;\n specularBase += info[1] * shadow;\n#endif\n\n#ifdef LIGHT1\n#ifdef SPOTLIGHT1\n info = computeSpotLighting(viewDirectionW, normalW, vLightData1, vLightDirection1, vLightDiffuse1, vLightSpecular1);\n#endif\n#ifdef HEMILIGHT1\n info = computeHemisphericLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1, vLightSpecular1, vLightGround1);\n#endif\n#ifdef POINTDIRLIGHT1\n info = computeLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1, vLightSpecular1);\n#endif\n#ifdef SHADOW1\n#ifdef SHADOWVSM1\n shadow = computeShadowWithVSM(vPositionFromLight1, shadowSampler1);\n#else\n shadow = computeShadow(vPositionFromLight1, shadowSampler1);\n#endif\n#else\n shadow = 1.;\n#endif\n diffuseBase += info[0] * shadow;\n specularBase += info[1] * shadow;\n#endif\n\n#ifdef LIGHT2\n#ifdef SPOTLIGHT2\n info = computeSpotLighting(viewDirectionW, normalW, vLightData2, vLightDirection2, vLightDiffuse2, vLightSpecular2);\n#endif\n#ifdef HEMILIGHT2\n info = computeHemisphericLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2, vLightSpecular2, vLightGround2);\n#endif\n#ifdef POINTDIRLIGHT2\n info = computeLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2, vLightSpecular2);\n#endif\n#ifdef SHADOW2\n#ifdef SHADOWVSM2\n shadow = computeShadowWithVSM(vPositionFromLight2, shadowSampler2);\n#else\n shadow = computeShadow(vPositionFromLight2, shadowSampler2);\n#endif \n#else\n shadow = 1.;\n#endif\n diffuseBase += info[0] * shadow;\n specularBase += info[1] * shadow;\n#endif\n\n#ifdef LIGHT3\n#ifdef SPOTLIGHT3\n info = computeSpotLighting(viewDirectionW, normalW, vLightData3, vLightDirection3, vLightDiffuse3, vLightSpecular3);\n#endif\n#ifdef HEMILIGHT3\n info = computeHemisphericLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3, vLightSpecular3, vLightGround3);\n#endif\n#ifdef POINTDIRLIGHT3\n info = computeLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3, vLightSpecular3);\n#endif\n#ifdef SHADOW3\n#ifdef SHADOWVSM3\n shadow = computeShadowWithVSM(vPositionFromLight3, shadowSampler3);\n#else\n shadow = computeShadow(vPositionFromLight3, shadowSampler3);\n#endif \n#else\n shadow = 1.;\n#endif\n diffuseBase += info[0] * shadow;\n specularBase += info[1] * shadow;\n#endif\n\n // Reflection\n vec3 reflectionColor = vec3(0., 0., 0.);\n\n#ifdef REFLECTION\n if (vReflectionInfos.z != 0.0)\n {\n reflectionColor = textureCube(reflectionCubeSampler, vReflectionUVW).rgb * vReflectionInfos.y;\n }\n else\n {\n vec2 coords = vReflectionUVW.xy;\n\n if (vReflectionInfos.x == MAP_PROJECTION)\n {\n coords /= vReflectionUVW.z;\n }\n\n coords.y = 1.0 - coords.y;\n\n reflectionColor = texture2D(reflection2DSampler, coords).rgb * vReflectionInfos.y;\n }\n#endif\n\n // Alpha\n float alpha = vDiffuseColor.a;\n\n#ifdef OPACITY\n vec4 opacityMap = texture2D(opacitySampler, vOpacityUV);\n opacityMap.rgb = opacityMap.rgb * vec3(0.3, 0.59, 0.11) * opacityMap.a;\n alpha *= (opacityMap.x + opacityMap.y + opacityMap.z)* vOpacityInfos.y;\n#endif\n\n // Emissive\n vec3 emissiveColor = vEmissiveColor;\n#ifdef EMISSIVE\n emissiveColor += texture2D(emissiveSampler, vEmissiveUV).rgb * vEmissiveInfos.y;\n#endif\n\n // Specular map\n vec3 specularColor = vSpecularColor.rgb;\n#ifdef SPECULAR\n specularColor = texture2D(specularSampler, vSpecularUV).rgb * vSpecularInfos.y;\n#endif\n\n // Composition\n vec3 finalDiffuse = clamp(diffuseBase * diffuseColor + emissiveColor + vAmbientColor, 0.0, 1.0) * baseColor.rgb;\n vec3 finalSpecular = specularBase * specularColor;\n\n vec4 color = vec4(finalDiffuse * baseAmbientColor + finalSpecular + reflectionColor, alpha);\n\n#ifdef FOG\n float fog = CalcFogFactor();\n color.rgb = fog * color.rgb + (1.0 - fog) * vFogColor;\n#endif\n\n gl_FragColor = color;\n}", -iedefaultVertexShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n#define MAP_EXPLICIT 0.\n#define MAP_SPHERICAL 1.\n#define MAP_PLANAR 2.\n#define MAP_CUBIC 3.\n#define MAP_PROJECTION 4.\n#define MAP_SKYBOX 5.\n\n// Attributes\nattribute vec3 position;\nattribute vec3 normal;\n#ifdef UV1\nattribute vec2 uv;\n#endif\n#ifdef UV2\nattribute vec2 uv2;\n#endif\n#ifdef VERTEXCOLOR\nattribute vec3 color;\n#endif\n#ifdef BONES\nattribute vec4 matricesIndices;\nattribute vec4 matricesWeights;\n#endif\n\n// Uniforms\nuniform mat4 world;\nuniform mat4 view;\nuniform mat4 viewProjection;\n\n#ifdef DIFFUSE\nvarying vec2 vDiffuseUV;\nuniform mat4 diffuseMatrix;\nuniform vec2 vDiffuseInfos;\n#endif\n\n#ifdef AMBIENT\nvarying vec2 vAmbientUV;\nuniform mat4 ambientMatrix;\nuniform vec2 vAmbientInfos;\n#endif\n\n#ifdef OPACITY\nvarying vec2 vOpacityUV;\nuniform mat4 opacityMatrix;\nuniform vec2 vOpacityInfos;\n#endif\n\n#ifdef REFLECTION\nuniform vec3 vEyePosition;\nvarying vec3 vReflectionUVW;\nuniform vec3 vReflectionInfos;\nuniform mat4 reflectionMatrix;\n#endif\n\n#ifdef EMISSIVE\nvarying vec2 vEmissiveUV;\nuniform vec2 vEmissiveInfos;\nuniform mat4 emissiveMatrix;\n#endif\n\n#ifdef SPECULAR\nvarying vec2 vSpecularUV;\nuniform vec2 vSpecularInfos;\nuniform mat4 specularMatrix;\n#endif\n\n#ifdef BUMP\nvarying vec2 vBumpUV;\nuniform vec2 vBumpInfos;\nuniform mat4 bumpMatrix;\n#endif\n\n#ifdef BONES\nuniform mat4 mBones[BonesPerMesh];\n#endif\n\n// Output\nvarying vec3 vPositionW;\nvarying vec3 vNormalW;\n\n#ifdef VERTEXCOLOR\nvarying vec3 vColor;\n#endif\n\n#ifdef CLIPPLANE\nuniform vec4 vClipPlane;\nvarying float fClipDistance;\n#endif\n\n#ifdef FOG\nvarying float fFogDistance;\n#endif\n\n#ifdef SHADOWS\n#ifdef LIGHT0\nuniform mat4 lightMatrix0;\nvarying vec4 vPositionFromLight0;\n#endif\n#ifdef LIGHT1\nuniform mat4 lightMatrix1;\nvarying vec4 vPositionFromLight1;\n#endif\n#ifdef LIGHT2\nuniform mat4 lightMatrix2;\nvarying vec4 vPositionFromLight2;\n#endif\n#ifdef LIGHT3\nuniform mat4 lightMatrix3;\nvarying vec4 vPositionFromLight3;\n#endif\n#endif\n\n#ifdef REFLECTION\nvec3 computeReflectionCoords(float mode, vec4 worldPos, vec3 worldNormal)\n{\n if (mode == MAP_SPHERICAL)\n {\n vec3 coords = vec3(view * vec4(worldNormal, 0.0));\n\n return vec3(reflectionMatrix * vec4(coords, 1.0));\n }\n else if (mode == MAP_PLANAR)\n {\n vec3 viewDir = worldPos.xyz - vEyePosition;\n vec3 coords = normalize(reflect(viewDir, worldNormal));\n\n return vec3(reflectionMatrix * vec4(coords, 1));\n }\n else if (mode == MAP_CUBIC)\n {\n vec3 viewDir = worldPos.xyz - vEyePosition;\n vec3 coords = reflect(viewDir, worldNormal);\n\n return vec3(reflectionMatrix * vec4(coords, 0));\n }\n else if (mode == MAP_PROJECTION)\n {\n return vec3(reflectionMatrix * (view * worldPos));\n }\n else if (mode == MAP_SKYBOX)\n {\n return position;\n }\n\n return vec3(0, 0, 0);\n}\n#endif\n\nvoid main(void) {\n mat4 finalWorld;\n\n#ifdef BONES\n mat4 m0 = mBones[int(matricesIndices.x)] * matricesWeights.x;\n mat4 m1 = mBones[int(matricesIndices.y)] * matricesWeights.y;\n mat4 m2 = mBones[int(matricesIndices.z)] * matricesWeights.z;\n\n#ifdef BONES4\n mat4 m3 = mBones[int(matricesIndices.w)] * matricesWeights.w;\n finalWorld = world * (m0 + m1 + m2 + m3);\n#else\n finalWorld = world * (m0 + m1 + m2);\n#endif \n\n#else\n finalWorld = world;\n#endif\n\n gl_Position = viewProjection * finalWorld * vec4(position, 1.0);\n\n vec4 worldPos = finalWorld * vec4(position, 1.0);\n vPositionW = vec3(worldPos);\n vNormalW = normalize(vec3(finalWorld * vec4(normal, 0.0)));\n\n // Texture coordinates\n#ifndef UV1\n vec2 uv = vec2(0., 0.);\n#endif\n#ifndef UV2\n vec2 uv2 = vec2(0., 0.);\n#endif\n\n#ifdef DIFFUSE\n if (vDiffuseInfos.x == 0.)\n {\n vDiffuseUV = vec2(diffuseMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vDiffuseUV = vec2(diffuseMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n#ifdef AMBIENT\n if (vAmbientInfos.x == 0.)\n {\n vAmbientUV = vec2(ambientMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vAmbientUV = vec2(ambientMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n#ifdef OPACITY\n if (vOpacityInfos.x == 0.)\n {\n vOpacityUV = vec2(opacityMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vOpacityUV = vec2(opacityMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n#ifdef REFLECTION\n vReflectionUVW = computeReflectionCoords(vReflectionInfos.x, vec4(vPositionW, 1.0), vNormalW);\n#endif\n\n#ifdef EMISSIVE\n if (vEmissiveInfos.x == 0.)\n {\n vEmissiveUV = vec2(emissiveMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vEmissiveUV = vec2(emissiveMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n#ifdef SPECULAR\n if (vSpecularInfos.x == 0.)\n {\n vSpecularUV = vec2(specularMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vSpecularUV = vec2(specularMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n#ifdef BUMP\n if (vBumpInfos.x == 0.)\n {\n vBumpUV = vec2(bumpMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vBumpUV = vec2(bumpMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n // Clip plane\n#ifdef CLIPPLANE\n fClipDistance = dot(worldPos, vClipPlane);\n#endif\n\n // Fog\n#ifdef FOG\n fFogDistance = (view * worldPos).z;\n#endif\n\n // Shadows\n#ifdef SHADOWS\n#ifdef LIGHT0\n vPositionFromLight0 = lightMatrix0 * vec4(position, 1.0);\n#endif\n#ifdef LIGHT1\n vPositionFromLight1 = lightMatrix1 * vec4(position, 1.0);\n#endif\n#ifdef LIGHT2\n vPositionFromLight2 = lightMatrix2 * vec4(position, 1.0);\n#endif\n#ifdef LIGHT3\n vPositionFromLight3 = lightMatrix3 * vec4(position, 1.0);\n#endif\n#endif\n\n // Vertex color\n#ifdef VERTEXCOLOR\n vColor = color;\n#endif\n}", -layerPixelShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n// Samplers\nvarying vec2 vUV;\nuniform sampler2D textureSampler;\n\n// Color\nuniform vec4 color;\n\nvoid main(void) {\n vec4 baseColor = texture2D(textureSampler, vUV);\n\n gl_FragColor = baseColor * color;\n}", -layerVertexShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n// Attributes\nattribute vec2 position;\n\n// Uniforms\nuniform mat4 textureMatrix;\n\n// Output\nvarying vec2 vUV;\n\nconst vec2 madd = vec2(0.5, 0.5);\n\nvoid main(void) { \n\n vUV = vec2(textureMatrix * vec4(position * madd + madd, 1.0, 0.0));\n gl_Position = vec4(position, 0.0, 1.0);\n}", -lensFlarePixelShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n// Samplers\nvarying vec2 vUV;\nuniform sampler2D textureSampler;\n\n// Color\nuniform vec4 color;\n\nvoid main(void) {\n vec4 baseColor = texture2D(textureSampler, vUV);\n\n gl_FragColor = baseColor * color;\n}", -lensFlareVertexShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n// Attributes\nattribute vec2 position;\n\n// Uniforms\nuniform mat4 viewportMatrix;\n\n// Output\nvarying vec2 vUV;\n\nconst vec2 madd = vec2(0.5, 0.5);\n\nvoid main(void) { \n\n vUV = position * madd + madd;\n gl_Position = viewportMatrix * vec4(position, 0.0, 1.0);\n}", -particlesPixelShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n// Samplers\nvarying vec2 vUV;\nvarying vec4 vColor;\nuniform vec4 textureMask;\nuniform sampler2D diffuseSampler;\n\n#ifdef CLIPPLANE\nvarying float fClipDistance;\n#endif\n\nvoid main(void) {\n#ifdef CLIPPLANE\n if (fClipDistance > 0.0)\n discard;\n#endif\n vec4 baseColor = texture2D(diffuseSampler, vUV);\n\n gl_FragColor = (baseColor * textureMask + (vec4(1., 1., 1., 1.) - textureMask)) * vColor;\n}", -particlesVertexShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n// Attributes\nattribute vec3 position;\nattribute vec4 color;\nattribute vec4 options;\n\n// Uniforms\nuniform mat4 view;\nuniform mat4 projection;\n\n// Output\nvarying vec2 vUV;\nvarying vec4 vColor;\n\n#ifdef CLIPPLANE\nuniform vec4 vClipPlane;\nuniform mat4 invView;\nvarying float fClipDistance;\n#endif\n\nvoid main(void) { \n vec3 viewPos = (view * vec4(position, 1.0)).xyz; \n vec3 cornerPos;\n float size = options.y;\n float angle = options.x;\n vec2 offset = options.zw;\n\n cornerPos = vec3(offset.x - 0.5, offset.y - 0.5, 0.) * size;\n\n // Rotate\n vec3 rotatedCorner;\n rotatedCorner.x = cornerPos.x * cos(angle) - cornerPos.y * sin(angle);\n rotatedCorner.y = cornerPos.x * sin(angle) + cornerPos.y * cos(angle);\n rotatedCorner.z = 0.;\n\n // Position\n viewPos += rotatedCorner;\n gl_Position = projection * vec4(viewPos, 1.0); \n \n vColor = color;\n vUV = offset;\n\n // Clip plane\n#ifdef CLIPPLANE\n vec4 worldPos = invView * vec4(viewPos, 1.0);\n fClipDistance = dot(worldPos, vClipPlane);\n#endif\n}", -passPixelShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n// Samplers\nvarying vec2 vUV;\nuniform sampler2D textureSampler;\n\nvoid main(void) \n{\n gl_FragColor = texture2D(textureSampler, vUV);\n}", -postprocessVertexShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n// Attributes\nattribute vec2 position;\n\n// Output\nvarying vec2 vUV;\n\nconst vec2 madd = vec2(0.5, 0.5);\n\nvoid main(void) { \n\n vUV = position * madd + madd;\n gl_Position = vec4(position, 0.0, 1.0);\n}", -refractionPixelShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n// Samplers\nvarying vec2 vUV;\nuniform sampler2D textureSampler;\nuniform sampler2D refractionSampler;\n\n// Parameters\nuniform vec3 baseColor;\nuniform float depth;\nuniform float colorLevel;\n\nvoid main() {\n float ref = 1.0 - texture2D(refractionSampler, vUV).r;\n\n vec2 uv = vUV - vec2(0.5);\n vec2 offset = uv * depth * ref;\n vec3 sourceColor = texture2D(textureSampler, vUV - offset).rgb;\n\n gl_FragColor = vec4(sourceColor + sourceColor * ref * colorLevel, 1.0);\n}", -shadowMapPixelShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\nvec4 pack(float depth)\n{\n const vec4 bitOffset = vec4(255. * 255. * 255., 255. * 255., 255., 1.);\n const vec4 bitMask = vec4(0., 1. / 255., 1. / 255., 1. / 255.);\n \n vec4 comp = fract(depth * bitOffset);\n comp -= comp.xxyz * bitMask;\n \n return comp;\n}\n\n// Thanks to http://devmaster.net/\nvec2 packHalf(float depth) \n{ \n const vec2 bitOffset = vec2(1.0 / 255., 0.);\n vec2 color = vec2(depth, fract(depth * 255.));\n\n return color - (color.yy * bitOffset);\n}\n\n\nvoid main(void)\n{\n#ifdef VSM\n float moment1 = gl_FragCoord.z / gl_FragCoord.w; \n float moment2 = moment1 * moment1;\n gl_FragColor = vec4(packHalf(moment1), packHalf(moment2));\n#else\n gl_FragColor = pack(gl_FragCoord.z / gl_FragCoord.w);\n#endif\n}", -shadowMapVertexShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n// Attribute\nattribute vec3 position;\n#ifdef BONES\nattribute vec4 matricesIndices;\nattribute vec4 matricesWeights;\n#endif\n\n// Uniform\n#ifdef BONES\nuniform mat4 world;\nuniform mat4 mBones[BonesPerMesh];\nuniform mat4 viewProjection;\n#else\nuniform mat4 worldViewProjection;\n#endif\n\nvoid main(void)\n{\n#ifdef BONES\n mat4 m0 = mBones[int(matricesIndices.x)] * matricesWeights.x;\n mat4 m1 = mBones[int(matricesIndices.y)] * matricesWeights.y;\n mat4 m2 = mBones[int(matricesIndices.z)] * matricesWeights.z;\n mat4 m3 = mBones[int(matricesIndices.w)] * matricesWeights.w;\n mat4 finalWorld = world * (m0 + m1 + m2 + m3);\n gl_Position = viewProjection * finalWorld * vec4(position, 1.0);\n#else\n gl_Position = worldViewProjection * vec4(position, 1.0);\n#endif\n}", -spritesPixelShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\nuniform bool alphaTest;\n\nvarying vec4 vColor;\n\n// Samplers\nvarying vec2 vUV;\nuniform sampler2D diffuseSampler;\n\n// Fog\n#ifdef FOG\n\n#define FOGMODE_NONE 0.\n#define FOGMODE_EXP 1.\n#define FOGMODE_EXP2 2.\n#define FOGMODE_LINEAR 3.\n#define E 2.71828\n\nuniform vec4 vFogInfos;\nuniform vec3 vFogColor;\nvarying float fFogDistance;\n\nfloat CalcFogFactor()\n{\n float fogCoeff = 1.0;\n float fogStart = vFogInfos.y;\n float fogEnd = vFogInfos.z;\n float fogDensity = vFogInfos.w;\n\n if (FOGMODE_LINEAR == vFogInfos.x)\n {\n fogCoeff = (fogEnd - fFogDistance) / (fogEnd - fogStart);\n }\n else if (FOGMODE_EXP == vFogInfos.x)\n {\n fogCoeff = 1.0 / pow(E, fFogDistance * fogDensity);\n }\n else if (FOGMODE_EXP2 == vFogInfos.x)\n {\n fogCoeff = 1.0 / pow(E, fFogDistance * fFogDistance * fogDensity * fogDensity);\n }\n\n return min(1., max(0., fogCoeff));\n}\n#endif\n\n\nvoid main(void) {\n vec4 baseColor = texture2D(diffuseSampler, vUV);\n\n if (alphaTest) \n {\n if (baseColor.a < 0.95)\n discard;\n }\n\n baseColor *= vColor;\n\n#ifdef FOG\n float fog = CalcFogFactor();\n baseColor.rgb = fog * baseColor.rgb + (1.0 - fog) * vFogColor;\n#endif\n\n gl_FragColor = baseColor;\n}", -spritesVertexShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n// Attributes\nattribute vec3 position;\nattribute vec4 options;\nattribute vec4 cellInfo;\nattribute vec4 color;\n\n// Uniforms\nuniform vec2 textureInfos;\nuniform mat4 view;\nuniform mat4 projection;\n\n// Output\nvarying vec2 vUV;\nvarying vec4 vColor;\n\n#ifdef FOG\nvarying float fFogDistance;\n#endif\n\nvoid main(void) { \n vec3 viewPos = (view * vec4(position, 1.0)).xyz; \n vec3 cornerPos;\n \n float angle = options.x;\n float size = options.y;\n vec2 offset = options.zw;\n vec2 uvScale = textureInfos.xy;\n\n cornerPos = vec3(offset.x - 0.5, offset.y - 0.5, 0.) * size;\n\n // Rotate\n vec3 rotatedCorner;\n rotatedCorner.x = cornerPos.x * cos(angle) - cornerPos.y * sin(angle);\n rotatedCorner.y = cornerPos.x * sin(angle) + cornerPos.y * cos(angle);\n rotatedCorner.z = 0.;\n\n // Position\n viewPos += rotatedCorner;\n gl_Position = projection * vec4(viewPos, 1.0); \n\n // Color\n vColor = color;\n \n // Texture\n vec2 uvOffset = vec2(abs(offset.x - cellInfo.x), 1.0 - abs(offset.y - cellInfo.y));\n\n vUV = (uvOffset + cellInfo.zw) * uvScale;\n\n // Fog\n#ifdef FOG\n fFogDistance = viewPos.z;\n#endif\n}", -};})();var BABYLON=BABYLON||{};(function(){BABYLON.Material=function(name,scene){this.name=name;this.id=name;this._scene=scene;scene.materials.push(this);};BABYLON.Material.prototype.checkReadyOnEveryCall=true;BABYLON.Material.prototype.checkReadyOnlyOnce=false;BABYLON.Material.prototype.alpha=1.0;BABYLON.Material.prototype.wireframe=false;BABYLON.Material.prototype.backFaceCulling=true;BABYLON.Material.prototype._effect=null;BABYLON.Material.prototype._wasPreviouslyReady=false;BABYLON.Material.prototype.onDispose=null;BABYLON.Material.prototype.isReady=function(mesh){return true;};BABYLON.Material.prototype.getEffect=function(){return this._effect;};BABYLON.Material.prototype.needAlphaBlending=function(){return(this.alpha<1.0);};BABYLON.Material.prototype.needAlphaTesting=function(){return false;};BABYLON.Material.prototype._preBind=function(){var engine=this._scene.getEngine();engine.enableEffect(this._effect);engine.setState(this.backFaceCulling);};BABYLON.Material.prototype.bind=function(world,mesh){};BABYLON.Material.prototype.unbind=function(){};BABYLON.Material.prototype.baseDispose=function(){var index=this._scene.materials.indexOf(this);this._scene.materials.splice(index,1);if(this.onDispose){this.onDispose();}};BABYLON.Material.prototype.dispose=function(){this.baseDispose();};})();var BABYLON=BABYLON||{};(function(){BABYLON.StandardMaterial=function(name,scene){BABYLON.Material.call(this,name,scene);this.diffuseTexture=null;this.ambientTexture=null;this.opacityTexture=null;this.reflectionTexture=null;this.emissiveTexture=null;this.specularTexture=null;this.bumpTexture=null;this.ambientColor=new BABYLON.Color3(0,0,0);this.diffuseColor=new BABYLON.Color3(1,1,1);this.specularColor=new BABYLON.Color3(1,1,1);this.specularPower=64;this.emissiveColor=new BABYLON.Color3(0,0,0);this._cachedDefines=null;this._renderTargets=new BABYLON.Tools.SmartArray(16);this._worldViewProjectionMatrix=BABYLON.Matrix.Zero();this._lightMatrix=BABYLON.Matrix.Zero();this._globalAmbientColor=new BABYLON.Color3(0,0,0);this._baseColor=new BABYLON.Color3();this._scaledDiffuse=new BABYLON.Color3();this._scaledSpecular=new BABYLON.Color3();};BABYLON.StandardMaterial.prototype=Object.create(BABYLON.Material.prototype);BABYLON.StandardMaterial.prototype.needAlphaBlending=function(){return(this.alpha<1.0)||(this.opacityTexture!=null);};BABYLON.StandardMaterial.prototype.needAlphaTesting=function(){return this.diffuseTexture!=null&&this.diffuseTexture.hasAlpha;};BABYLON.StandardMaterial.prototype.isReady=function(mesh){if(this.checkReadyOnlyOnce){if(this._wasPreviouslyReady){return true;}}if(!this.checkReadyOnEveryCall){if(this._renderId===this._scene.getRenderId()){return true;}}var engine=this._scene.getEngine();var defines=[];var optionalDefines=[];if(this._scene.texturesEnabled){if(this.diffuseTexture){if(!this.diffuseTexture.isReady()){return false;}else{defines.push("#define DIFFUSE");}}if(this.ambientTexture){if(!this.ambientTexture.isReady()){return false;}else{defines.push("#define AMBIENT");}}if(this.opacityTexture){if(!this.opacityTexture.isReady()){return false;}else{defines.push("#define OPACITY");}}if(this.reflectionTexture){if(!this.reflectionTexture.isReady()){return false;}else{defines.push("#define REFLECTION");}}if(this.emissiveTexture){if(!this.emissiveTexture.isReady()){return false;}else{defines.push("#define EMISSIVE");}}if(this.specularTexture){if(!this.specularTexture.isReady()){return false;}else{defines.push("#define SPECULAR");optionalDefines.push(defines[defines.length-1]);}}}if(this._scene.getEngine().getCaps().standardDerivatives&&this.bumpTexture){if(!this.bumpTexture.isReady()){return false;}else{defines.push("#define BUMP");optionalDefines.push(defines[defines.length-1]);}}if(BABYLON.clipPlane){defines.push("#define CLIPPLANE");}if(engine.getAlphaTesting()){defines.push("#define ALPHATEST");}if(this._scene.fogMode!==BABYLON.Scene.FOGMODE_NONE){defines.push("#define FOG");optionalDefines.push(defines[defines.length-1]);}var shadowsActivated=false;var lightIndex=0;if(this._scene.lightsEnabled){for(var index=0;index0){optionalDefines.push(defines[defines.length-1]);}var type;if(light instanceof BABYLON.SpotLight){type="#define SPOTLIGHT"+lightIndex;}else if(light instanceof BABYLON.HemisphericLight){type="#define HEMILIGHT"+lightIndex;}else{type="#define POINTDIRLIGHT"+lightIndex;}defines.push(type);if(lightIndex>0){optionalDefines.push(defines[defines.length-1]);}var shadowGenerator=light.getShadowGenerator();if(mesh&&mesh.receiveShadows&&shadowGenerator){defines.push("#define SHADOW"+lightIndex);if(lightIndex>0){optionalDefines.push(defines[defines.length-1]);}if(!shadowsActivated){defines.push("#define SHADOWS");shadowsActivated=true;}if(shadowGenerator.useVarianceShadowMap){defines.push("#define SHADOWVSM"+lightIndex);if(lightIndex>0){optionalDefines.push(defines[defines.length-1]);}}}lightIndex++;if(lightIndex==4)break;}}var attribs=[BABYLON.VertexBuffer.PositionKind,BABYLON.VertexBuffer.NormalKind];if(mesh){if(mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UVKind)){attribs.push(BABYLON.VertexBuffer.UVKind);defines.push("#define UV1");}if(mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UV2Kind)){attribs.push(BABYLON.VertexBuffer.UV2Kind);defines.push("#define UV2");}if(mesh.isVerticesDataPresent(BABYLON.VertexBuffer.ColorKind)){attribs.push(BABYLON.VertexBuffer.ColorKind);defines.push("#define VERTEXCOLOR");}if(mesh.skeleton&&mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind)&&mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind)){attribs.push(BABYLON.VertexBuffer.MatricesIndicesKind);attribs.push(BABYLON.VertexBuffer.MatricesWeightsKind);defines.push("#define BONES");defines.push("#define BonesPerMesh "+mesh.skeleton.bones.length);defines.push("#define BONES4");optionalDefines.push(defines[defines.length-1]);}}var join=defines.join("\n");if(this._cachedDefines!=join){this._cachedDefines=join;var shaderName="default";if(BABYLON.Tools.isIE()){shaderName="iedefault";}this._effect=this._scene.getEngine().createEffect(shaderName,attribs,["world","view","viewProjection","vEyePosition","vLightsType","vAmbientColor","vDiffuseColor","vSpecularColor","vEmissiveColor","vLightData0","vLightDiffuse0","vLightSpecular0","vLightDirection0","vLightGround0","lightMatrix0","vLightData1","vLightDiffuse1","vLightSpecular1","vLightDirection1","vLightGround1","lightMatrix1","vLightData2","vLightDiffuse2","vLightSpecular2","vLightDirection2","vLightGround2","lightMatrix2","vLightData3","vLightDiffuse3","vLightSpecular3","vLightDirection3","vLightGround3","lightMatrix3","vFogInfos","vFogColor","vDiffuseInfos","vAmbientInfos","vOpacityInfos","vReflectionInfos","vEmissiveInfos","vSpecularInfos","vBumpInfos","mBones","vClipPlane","diffuseMatrix","ambientMatrix","opacityMatrix","reflectionMatrix","emissiveMatrix","specularMatrix","bumpMatrix"],["diffuseSampler","ambientSampler","opacitySampler","reflectionCubeSampler","reflection2DSampler","emissiveSampler","specularSampler","bumpSampler","shadowSampler0","shadowSampler1","shadowSampler2","shadowSampler3"],join,optionalDefines);}if(!this._effect.isReady()){return false;}this._renderId=this._scene.getRenderId();this._wasPreviouslyReady=true;return true;};BABYLON.StandardMaterial.prototype.getRenderTargetTextures=function(){this._renderTargets.reset();if(this.reflectionTexture&&this.reflectionTexture.isRenderTarget){this._renderTargets.push(this.reflectionTexture);}return this._renderTargets;};BABYLON.StandardMaterial.prototype.unbind=function(){if(this.reflectionTexture&&this.reflectionTexture.isRenderTarget){this._effect.setTexture("reflection2DSampler",null);}};BABYLON.StandardMaterial.prototype.bind=function(world,mesh){this._baseColor.copyFrom(this.diffuseColor);this._effect.setMatrix("world",world);this._effect.setMatrix("viewProjection",this._scene.getTransformMatrix());if(mesh.skeleton&&mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind)&&mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind)){this._effect.setMatrices("mBones",mesh.skeleton.getTransformMatrices());}if(this.diffuseTexture){this._effect.setTexture("diffuseSampler",this.diffuseTexture);this._effect.setFloat2("vDiffuseInfos",this.diffuseTexture.coordinatesIndex,this.diffuseTexture.level);this._effect.setMatrix("diffuseMatrix",this.diffuseTexture._computeTextureMatrix());this._baseColor.copyFromFloats(1,1,1);}if(this.ambientTexture){this._effect.setTexture("ambientSampler",this.ambientTexture);this._effect.setFloat2("vAmbientInfos",this.ambientTexture.coordinatesIndex,this.ambientTexture.level);this._effect.setMatrix("ambientMatrix",this.ambientTexture._computeTextureMatrix());}if(this.opacityTexture){this._effect.setTexture("opacitySampler",this.opacityTexture);this._effect.setFloat2("vOpacityInfos",this.opacityTexture.coordinatesIndex,this.opacityTexture.level);this._effect.setMatrix("opacityMatrix",this.opacityTexture._computeTextureMatrix());}if(this.reflectionTexture){if(this.reflectionTexture.isCube){this._effect.setTexture("reflectionCubeSampler",this.reflectionTexture);}else{this._effect.setTexture("reflection2DSampler",this.reflectionTexture);}this._effect.setMatrix("reflectionMatrix",this.reflectionTexture._computeReflectionTextureMatrix());this._effect.setFloat3("vReflectionInfos",this.reflectionTexture.coordinatesMode,this.reflectionTexture.level,this.reflectionTexture.isCube?1:0);}if(this.emissiveTexture){this._effect.setTexture("emissiveSampler",this.emissiveTexture);this._effect.setFloat2("vEmissiveInfos",this.emissiveTexture.coordinatesIndex,this.emissiveTexture.level);this._effect.setMatrix("emissiveMatrix",this.emissiveTexture._computeTextureMatrix());}if(this.specularTexture){this._effect.setTexture("specularSampler",this.specularTexture);this._effect.setFloat2("vSpecularInfos",this.specularTexture.coordinatesIndex,this.specularTexture.level);this._effect.setMatrix("specularMatrix",this.specularTexture._computeTextureMatrix());}if(this.bumpTexture&&this._scene.getEngine().getCaps().standardDerivatives){this._effect.setTexture("bumpSampler",this.bumpTexture);this._effect.setFloat2("vBumpInfos",this.bumpTexture.coordinatesIndex,this.bumpTexture.level);this._effect.setMatrix("bumpMatrix",this.bumpTexture._computeTextureMatrix());}this._scene.ambientColor.multiplyToRef(this.ambientColor,this._globalAmbientColor);this._effect.setVector3("vEyePosition",this._scene.activeCamera.position);this._effect.setColor3("vAmbientColor",this._globalAmbientColor);this._effect.setColor4("vDiffuseColor",this._baseColor,this.alpha*mesh.visibility);this._effect.setColor4("vSpecularColor",this.specularColor,this.specularPower);this._effect.setColor3("vEmissiveColor",this.emissiveColor);if(this._scene.lightsEnabled){var lightIndex=0;for(var index=0;index0){results.push(this.diffuseTexture);}if(this.ambientTexture&&this.ambientTexture.animations&&this.ambientTexture.animations.length>0){results.push(this.ambientTexture);}if(this.opacityTexture&&this.opacityTexture.animations&&this.opacityTexture.animations.length>0){results.push(this.opacityTexture);}if(this.reflectionTexture&&this.reflectionTexture.animations&&this.reflectionTexture.animations.length>0){results.push(this.reflectionTexture);}if(this.emissiveTexture&&this.emissiveTexture.animations&&this.emissiveTexture.animations.length>0){results.push(this.emissiveTexture);}if(this.specularTexture&&this.specularTexture.animations&&this.specularTexture.animations.length>0){results.push(this.specularTexture);}if(this.bumpTexture&&this.bumpTexture.animations&&this.bumpTexture.animations.length>0){results.push(this.bumpTexture);}return results;};BABYLON.StandardMaterial.prototype.dispose=function(){if(this.diffuseTexture){this.diffuseTexture.dispose();}if(this.ambientTexture){this.ambientTexture.dispose();}if(this.opacityTexture){this.opacityTexture.dispose();}if(this.reflectionTexture){this.reflectionTexture.dispose();}if(this.emissiveTexture){this.emissiveTexture.dispose();}if(this.specularTexture){this.specularTexture.dispose();}if(this.bumpTexture){this.bumpTexture.dispose();}this.baseDispose();};BABYLON.StandardMaterial.prototype.clone=function(name){var newStandardMaterial=new BABYLON.StandardMaterial(name,this._scene);newStandardMaterial.checkReadyOnEveryCall=this.checkReadyOnEveryCall;newStandardMaterial.alpha=this.alpha;newStandardMaterial.wireframe=this.wireframe;newStandardMaterial.backFaceCulling=this.backFaceCulling;if(this.diffuseTexture&&this.diffuseTexture.clone){newStandardMaterial.diffuseTexture=this.diffuseTexture.clone();}if(this.ambientTexture&&this.ambientTexture.clone){newStandardMaterial.ambientTexture=this.ambientTexture.clone();}if(this.opacityTexture&&this.opacityTexture.clone){newStandardMaterial.opacityTexture=this.opacityTexture.clone();}if(this.reflectionTexture&&this.reflectionTexture.clone){newStandardMaterial.reflectionTexture=this.reflectionTexture.clone();}if(this.emissiveTexture&&this.emissiveTexture.clone){newStandardMaterial.emissiveTexture=this.emissiveTexture.clone();}if(this.specularTexture&&this.specularTexture.clone){newStandardMaterial.specularTexture=this.specularTexture.clone();}if(this.bumpTexture&&this.bumpTexture.clone){newStandardMaterial.bumpTexture=this.bumpTexture.clone();}newStandardMaterial.ambientColor=this.ambientColor.clone();newStandardMaterial.diffuseColor=this.diffuseColor.clone();newStandardMaterial.specularColor=this.specularColor.clone();newStandardMaterial.specularPower=this.specularPower;newStandardMaterial.emissiveColor=this.emissiveColor.clone();return newStandardMaterial;};})();var BABYLON=BABYLON||{};(function(){BABYLON.MultiMaterial=function(name,scene){this.name=name;this.id=name;this._scene=scene;scene.multiMaterials.push(this);this.subMaterials=[];};BABYLON.MultiMaterial.prototype.getSubMaterial=function(index){if(index<0||index>=this.subMaterials.length){return this._scene.defaultMaterial;}return this.subMaterials[index];};BABYLON.MultiMaterial.prototype.isReady=function(mesh){var result=true;for(var index=0;indexversion.data){that.mustUpdateRessources=true;updateInDBCallback();}else{callback(version.data);}}else{that.mustUpdateRessources=true;updateInDBCallback();}};transaction.onabort=function(event){callback(-1);};var getRequest=transaction.objectStore("versions").get(url);getRequest.onsuccess=function(event){version=event.target.result;};getRequest.onerror=function(event){console.log("Error loading version for scene "+url+" from DB.");callback(-1);};}catch(ex){console.log("Error while accessing 'versions' object store (READ OP). Exception: "+ex.message);callback(-1);}}else{console.log("Error: IndexedDB not supported by your browser or BabylonJS Database is not open.");callback(-1);}};BABYLON.Database.prototype._saveVersionIntoDBAsync=function(url,callback){if(this.isSupported&&!this.hasReachedQuota){var that=this;try{var transaction=this.db.transaction(["versions"],"readwrite");transaction.onabort=function(event){try{if(event.srcElement.error.name==="QuotaExceededError"){that.hasReachedQuota=true;}}catch(ex){}callback(-1);};transaction.oncomplete=function(event){callback(that.manifestVersionFound);};var newVersion={};newVersion.sceneUrl=url;newVersion.data=this.manifestVersionFound;var addRequest=transaction.objectStore("versions").put(newVersion);addRequest.onsuccess=function(event){console.log("");};addRequest.onerror=function(event){console.log("Error in DB add version request in BABYLON.Database.");};}catch(ex){console.log("Error while accessing 'versions' object store (WRITE OP). Exception: "+ex.message);callback(-1);}}else{callback(-1);}};BABYLON.Database.prototype.loadSceneFromDB=function(url,sceneLoaded,progressCallBack,errorCallback){var that=this;var completeUrl=BABYLON.Database.ReturnFullUrlLocation(url);var saveAndLoadScene=function(event){that._saveSceneIntoDBAsync(completeUrl,sceneLoaded,progressCallBack);};this._checkVersionFromDB(completeUrl,function(version){if(version!==-1){if(!that.mustUpdateRessources){that._loadSceneFromDBAsync(completeUrl,sceneLoaded,saveAndLoadScene);}else{that._saveSceneIntoDBAsync(completeUrl,sceneLoaded,progressCallBack);}}else{errorCallback();}});};BABYLON.Database.prototype._loadSceneFromDBAsync=function(url,callback,notInDBCallback){if(this.isSupported){var scene;var transaction=this.db.transaction(["scenes"]);transaction.oncomplete=function(event){if(scene){callback(scene.data);}else{notInDBCallback();}};transaction.onabort=function(event){notInDBCallback();};var getRequest=transaction.objectStore("scenes").get(url);getRequest.onsuccess=function(event){scene=event.target.result;};getRequest.onerror=function(event){console.log("Error loading scene "+url+" from DB.");notInDBCallback();};}else{console.log("Error: IndexedDB not supported by your browser or BabylonJS Database is not open.");callback();}};BABYLON.Database.prototype._saveSceneIntoDBAsync=function(url,callback,progressCallback){if(this.isSupported){var xhr=new XMLHttpRequest(),sceneText;var that=this;xhr.open("GET",url,true);xhr.onprogress=progressCallback;xhr.addEventListener("load",function(){if(xhr.status===200){sceneText=xhr.responseText;if(!that.hasReachedQuota){var transaction=that.db.transaction(["scenes"],"readwrite");transaction.onabort=function(event){try{if(event.srcElement.error.name==="QuotaExceededError"){that.hasReachedQuota=true;}}catch(ex){}callback(sceneText);};transaction.oncomplete=function(event){callback(sceneText);};var newScene={};newScene.sceneUrl=url;newScene.data=sceneText;newScene.version=that.manifestVersionFound;try{var addRequest=transaction.objectStore("scenes").put(newScene);addRequest.onsuccess=function(event){console.log("");};addRequest.onerror=function(event){console.log("Error in DB add scene request in BABYLON.Database.");};}catch(ex){callback(sceneText);}}else{callback(sceneText);}}else{callback();}},false);xhr.addEventListener("error",function(event){console.log("error on XHR request.");callback();},false);xhr.send();}else{console.log("Error: IndexedDB not supported by your browser or BabylonJS Database is not open.");callback();}};})();var BABYLON=BABYLON||{};(function(){var loadCubeTexture=function(rootUrl,parsedTexture,scene){var texture=new BABYLON.CubeTexture(rootUrl+parsedTexture.name,scene);texture.name=parsedTexture.name;texture.hasAlpha=parsedTexture.hasAlpha;texture.level=parsedTexture.level;texture.coordinatesMode=parsedTexture.coordinatesMode;return texture;};var loadTexture=function(rootUrl,parsedTexture,scene){if(!parsedTexture.name&&!parsedTexture.isRenderTarget){return null;}if(parsedTexture.isCube){return loadCubeTexture(rootUrl,parsedTexture,scene);}var texture;if(parsedTexture.mirrorPlane){texture=new BABYLON.MirrorTexture(parsedTexture.name,parsedTexture.renderTargetSize,scene);texture._waitingRenderList=parsedTexture.renderList;texture.mirrorPlane=BABYLON.Plane.FromArray(parsedTexture.mirrorPlane);}else if(parsedTexture.isRenderTarget){texture=new BABYLON.RenderTargetTexture(parsedTexture.name,parsedTexture.renderTargetSize,scene);texture._waitingRenderList=parsedTexture.renderList;}else{texture=new BABYLON.Texture(rootUrl+parsedTexture.name,scene);}texture.name=parsedTexture.name;texture.hasAlpha=parsedTexture.hasAlpha;texture.level=parsedTexture.level;texture.coordinatesIndex=parsedTexture.coordinatesIndex;texture.coordinatesMode=parsedTexture.coordinatesMode;texture.uOffset=parsedTexture.uOffset;texture.vOffset=parsedTexture.vOffset;texture.uScale=parsedTexture.uScale;texture.vScale=parsedTexture.vScale;texture.uAng=parsedTexture.uAng;texture.vAng=parsedTexture.vAng;texture.wAng=parsedTexture.wAng;texture.wrapU=parsedTexture.wrapU;texture.wrapV=parsedTexture.wrapV;if(parsedTexture.animations){for(var animationIndex=0;animationIndex-1){parentBone=skeleton.bones[parsedBone.parentBoneIndex];}var bone=new BABYLON.Bone(parsedBone.name,skeleton,parentBone,BABYLON.Matrix.FromArray(parsedBone.matrix));if(parsedBone.animation){bone.animations.push(parseAnimation(parsedBone.animation));}}return skeleton;};var parseMaterial=function(parsedMaterial,scene,rootUrl){var material;material=new BABYLON.StandardMaterial(parsedMaterial.name,scene);material.ambientColor=BABYLON.Color3.FromArray(parsedMaterial.ambient);material.diffuseColor=BABYLON.Color3.FromArray(parsedMaterial.diffuse);material.specularColor=BABYLON.Color3.FromArray(parsedMaterial.specular);material.specularPower=parsedMaterial.specularPower;material.emissiveColor=BABYLON.Color3.FromArray(parsedMaterial.emissive);material.alpha=parsedMaterial.alpha;material.id=parsedMaterial.id;material.backFaceCulling=parsedMaterial.backFaceCulling;if(parsedMaterial.diffuseTexture){material.diffuseTexture=loadTexture(rootUrl,parsedMaterial.diffuseTexture,scene);}if(parsedMaterial.ambientTexture){material.ambientTexture=loadTexture(rootUrl,parsedMaterial.ambientTexture,scene);}if(parsedMaterial.opacityTexture){material.opacityTexture=loadTexture(rootUrl,parsedMaterial.opacityTexture,scene);}if(parsedMaterial.reflectionTexture){material.reflectionTexture=loadTexture(rootUrl,parsedMaterial.reflectionTexture,scene);}if(parsedMaterial.emissiveTexture){material.emissiveTexture=loadTexture(rootUrl,parsedMaterial.emissiveTexture,scene);}if(parsedMaterial.specularTexture){material.specularTexture=loadTexture(rootUrl,parsedMaterial.specularTexture,scene);}if(parsedMaterial.bumpTexture){material.bumpTexture=loadTexture(rootUrl,parsedMaterial.bumpTexture,scene);}return material;};var parseMaterialById=function(id,parsedData,scene,rootUrl){for(var index=0;index-1){mesh.skeleton=scene.getLastSkeletonByID(parsedMesh.skeletonId);}if(parsedMesh.animations){for(var animationIndex=0;animationIndex>8);floatIndices.push((matricesIndex&0x00FF0000)>>16);floatIndices.push(matricesIndex>>24);}mesh.setVerticesData(floatIndices,BABYLON.VertexBuffer.MatricesIndicesKind,false);}if(parsedGeometry.matricesWeights){mesh.setVerticesData(parsedGeometry.matricesWeights,BABYLON.VertexBuffer.MatricesWeightsKind,false);}mesh.setIndices(parsedGeometry.indices);}if(parsedGeometry.subMeshes){mesh.subMeshes=[];for(var subIndex=0;subIndex-1&&scene.skeletons){var skeletonAlreadyLoaded=(loadedSkeletonsIds.indexOf(parsedMesh.skeletonId)>-1);if(!skeletonAlreadyLoaded){for(var skeletonIndex=0;skeletonIndex>0;this._vertices[arrayOffset+9]=sprite.cellIndex-offset*rowSize;this._vertices[arrayOffset+10]=offset;this._vertices[arrayOffset+11]=sprite.color.r;this._vertices[arrayOffset+12]=sprite.color.g;this._vertices[arrayOffset+13]=sprite.color.b;this._vertices[arrayOffset+14]=sprite.color.a;};BABYLON.SpriteManager.prototype.render=function(){if(!this._effectBase.isReady()||!this._effectFog.isReady()||!this._spriteTexture||!this._spriteTexture.isReady())return 0;var engine=this._scene.getEngine();var baseSize=this._spriteTexture.getBaseSize();var deltaTime=BABYLON.Tools.GetDeltaTime();var max=Math.min(this._capacity,this.sprites.length);var rowSize=baseSize.width/this.cellSize;var offset=0;for(var index=0;indexthis._delay){this._time=this._time%this._delay;this.cellIndex+=this._direction;if(this.cellIndex==this._toIndex){if(this._loopAnimation){this.cellIndex=this._fromIndex;}else{this._animationStarted=false;if(this.disposeWhenFinishedAnimating){this.dispose();}}}}};BABYLON.Sprite.prototype.dispose=function(){for(var i=0;i0;for(var index=0;index=particle.lifeTime){this._stockParticles.push(this.particles.splice(index,1)[0]);index--;continue;}else{particle.colorStep.scaleToRef(this._scaledUpdateSpeed,this._scaledColorStep);particle.color.addInPlace(this._scaledColorStep);if(particle.color.a<0)particle.color.a=0;particle.direction.scaleToRef(this._scaledUpdateSpeed,this._scaledDirection);particle.position.addInPlace(this._scaledDirection);particle.angle+=particle.angularSpeed*this._scaledUpdateSpeed;this.gravity.scaleToRef(this._scaledUpdateSpeed,this._scaledGravity);particle.direction.addInPlace(this._scaledGravity);}}var worldMatrix;if(this.emitter.position){worldMatrix=this.emitter.getWorldMatrix();}else{worldMatrix=BABYLON.Matrix.Translation(this.emitter.x,this.emitter.y,this.emitter.z);}for(var index=0;index-1){emitCout=this.manualEmitCount;this.manualEmitCount=0;}else{emitCout=this.emitRate;}var newParticles=((emitCout*this._scaledUpdateSpeed)>>0);this._newPartsExcess+=emitCout*this._scaledUpdateSpeed-newParticles;if(this._newPartsExcess>1.0){newParticles+=this._newPartsExcess>>0;this._newPartsExcess-=this._newPartsExcess>>0;}this._alive=false;if(!this._stopped){this._actualFrame+=this._scaledUpdateSpeed;if(this.targetStopDuration&&this._actualFrame>=this.targetStopDuration)this.stop();}else{newParticles=0;}this._update(newParticles);if(this._stopped){if(!this._alive){this._started=false;if(this.disposeOnStop){this._scene._toBeDisposed.push(this);}}}var offset=0;for(var index=0;index0){return highLimitValue.clone?highLimitValue.clone():highLimitValue;}for(var key=0;key=currentFrame){var startValue=this._keys[key].value;var endValue=this._keys[key+1].value;var gradient=(currentFrame-this._keys[key].frame)/(this._keys[key+1].frame-this._keys[key].frame);switch(this.dataType){case BABYLON.Animation.ANIMATIONTYPE_FLOAT:switch(loopMode){case BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE:case BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT:return startValue+(endValue-startValue)*gradient;case BABYLON.Animation.ANIMATIONLOOPMODE_RELATIVE:return offsetValue*repeatCount+(startValue+(endValue-startValue)*gradient);}break;case BABYLON.Animation.ANIMATIONTYPE_QUATERNION:var quaternion=null;switch(loopMode){case BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE:case BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT:quaternion=BABYLON.Quaternion.Slerp(startValue,endValue,gradient);break;case BABYLON.Animation.ANIMATIONLOOPMODE_RELATIVE:quaternion=BABYLON.Quaternion.Slerp(startValue,endValue,gradient).add(offsetValue.scale(repeatCount));break;}return quaternion;case BABYLON.Animation.ANIMATIONTYPE_VECTOR3:switch(loopMode){case BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE:case BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT:return BABYLON.Vector3.Lerp(startValue,endValue,gradient);case BABYLON.Animation.ANIMATIONLOOPMODE_RELATIVE:return BABYLON.Vector3.Lerp(startValue,endValue,gradient).add(offsetValue.scale(repeatCount));}case BABYLON.Animation.ANIMATIONTYPE_MATRIX:switch(loopMode){case BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE:case BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT:case BABYLON.Animation.ANIMATIONLOOPMODE_RELATIVE:return startValue;}default:break;}break;}}return this._keys[this._keys.length-1].value;};BABYLON.Animation.prototype.animate=function(target,delay,from,to,loop,speedRatio){if(!this.targetPropertyPath||this.targetPropertyPath.length<1){return false;}var returnValue=true;if(this._keys[0].frame!=0){var newKey={frame:0,value:this._keys[0].value};this._keys.splice(0,0,newKey);}if(fromthis._keys[this._keys.length-1].frame){from=this._keys[0].frame;}if(tothis._keys[this._keys.length-1].frame){to=this._keys[this._keys.length-1].frame;}var range=to-from;var ratio=delay*(this.framePerSecond*speedRatio)/1000.0;if(ratio>range&&!loop){offsetValue=0;returnValue=false;}else{var offsetValue=0;var highLimitValue=0;if(this.loopMode!=BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE){var keyOffset=to.toString()+from.toString();if(!this._offsetsCache[keyOffset]){var fromValue=this._interpolate(from,0,BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE);var toValue=this._interpolate(to,0,BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE);switch(this.dataType){case BABYLON.Animation.ANIMATIONTYPE_FLOAT:this._offsetsCache[keyOffset]=toValue-fromValue;break;case BABYLON.Animation.ANIMATIONTYPE_QUATERNION:this._offsetsCache[keyOffset]=toValue.subtract(fromValue);break;case BABYLON.Animation.ANIMATIONTYPE_VECTOR3:this._offsetsCache[keyOffset]=toValue.subtract(fromValue);default:break;}this._highLimitsCache[keyOffset]=toValue;}highLimitValue=this._highLimitsCache[keyOffset];offsetValue=this._offsetsCache[keyOffset];}}var repeatCount=(ratio/range)>>0;var currentFrame=returnValue?from+ratio%range:to;var currentValue=this._interpolate(currentFrame,repeatCount,this.loopMode,offsetValue,highLimitValue);if(this.targetPropertyPath.length>1){var property=target[this.targetPropertyPath[0]];for(var index=1;indexthis._capacity){BABYLON.Octree._CreateBlocks(this._minPoint,this._maxPoint,this.meshes,this._capacity,this);}};BABYLON.OctreeBlock.prototype.addEntries=function(meshes){for(var index=0;index0){this._camera.postProcesses[0].width=-1;}};})();var BABYLON=BABYLON||{};(function(){BABYLON.PostProcessManager=function(scene){this._scene=scene;var vertices=[];vertices.push(1,1);vertices.push(-1,1);vertices.push(-1,-1);vertices.push(1,-1);this._vertexDeclaration=[2];this._vertexStrideSize=2*4;this._vertexBuffer=scene.getEngine().createVertexBuffer(vertices);var indices=[];indices.push(0);indices.push(1);indices.push(2);indices.push(0);indices.push(2);indices.push(3);this._indexBuffer=scene.getEngine().createIndexBuffer(indices);};BABYLON.PostProcessManager.prototype._prepareFrame=function(){var postProcesses=this._scene.activeCamera.postProcesses;if(postProcesses.length===0||!this._scene.postProcessesEnabled){return;}postProcesses[0].activate();};BABYLON.PostProcessManager.prototype._finalizeFrame=function(){var postProcesses=this._scene.activeCamera.postProcesses;if(postProcesses.length===0||!this._scene.postProcessesEnabled){return;}var engine=this._scene.getEngine();for(var index=0;index0){if((this._positionX>globalViewport.x)&&(this._positionXglobalViewport.y)&&(this._positionYdistance;};BABYLON.LensFlareSystem.prototype.render=function(){if(!this._effect.isReady())return false;var engine=this._scene.getEngine();var viewport=this._scene.activeCamera.viewport;var globalViewport=viewport.toGlobal(engine);if(!this.computeEffectivePosition(globalViewport)){return false;}if(!this._isVisible()){return false;}var awayX;var awayY;if(this._positionXglobalViewport.x+globalViewport.width-this.borderLimit){awayX=this._positionX-globalViewport.x-globalViewport.width+this.borderLimit;}else{awayX=0;}if(this._positionYglobalViewport.y+globalViewport.height-this.borderLimit){awayY=this._positionY-globalViewport.y-globalViewport.height+this.borderLimit;}else{awayY=0;}var away=(awayX>awayY)?awayX:awayY;if(away>this.borderLimit){away=this.borderLimit;}var intensity=1.0-(away/this.borderLimit);if(intensity<0){return false;}if(intensity>1.0){intensity=1.0;}var centerX=globalViewport.x+globalViewport.width/2;var centerY=globalViewport.y+globalViewport.height/2;var distX=centerX-this._positionX;var distY=centerY-this._positionY;engine.enableEffect(this._effect);engine.setState(false);engine.setDepthBuffer(false);engine.setAlphaMode(BABYLON.Engine.ALPHA_ADD);engine.bindBuffers(this._vertexBuffer,this._indexBuffer,this._vertexDeclaration,this._vertexStrideSize,this._effect);for(var index=0;index0){that.textureLoadingCallback(remaining);}}that.currentScene.render();}};function drag(e){e.stopPropagation();e.preventDefault();};function drop(eventDrop){eventDrop.stopPropagation();eventDrop.preventDefault();that.loadFiles(eventDrop);};BABYLON.FilesInput.prototype.loadFiles=function(event){if(that.startingProcessingFilesCallback)that.startingProcessingFilesCallback();var sceneFileToLoad;var filesToLoad;BABYLON.FilesTextures={};if(event&&event.dataTransfer&&event.dataTransfer.files){filesToLoad=event.dataTransfer.files;}if(event&&event.target&&event.target.files){filesToLoad=event.target.files;}if(filesToLoad&&filesToLoad.length>0){for(var i=0;ibox.maximum.x){return false;}}else{var inv=1.0/this.direction.x;var min=(box.minimum.x-this.origin.x)*inv;var max=(box.maximum.x-this.origin.x)*inv;if(min>max){var temp=min;min=max;max=temp;}d=Math.max(min,d);maxValue=Math.min(max,maxValue);if(d>maxValue){return false;}}if(Math.abs(this.direction.y)<0.0000001){if(this.origin.ybox.maximum.y){return false;}}else{var inv=1.0/this.direction.y;var min=(box.minimum.y-this.origin.y)*inv;var max=(box.maximum.y-this.origin.y)*inv;if(min>max){var temp=min;min=max;max=temp;}d=Math.max(min,d);maxValue=Math.min(max,maxValue);if(d>maxValue){return false;}}if(Math.abs(this.direction.z)<0.0000001){if(this.origin.zbox.maximum.z){return false;}}else{var inv=1.0/this.direction.z;var min=(box.minimum.z-this.origin.z)*inv;var max=(box.maximum.z-this.origin.z)*inv;if(min>max){var temp=min;min=max;max=temp;}d=Math.max(min,d);maxValue=Math.min(max,maxValue);if(d>maxValue){return false;}}return true;};BABYLON.Ray.prototype.intersectsSphere=function(sphere){var x=sphere.center.x-this.origin.x;var y=sphere.center.y-this.origin.y;var z=sphere.center.z-this.origin.z;var pyth=(x*x)+(y*y)+(z*z);var rr=sphere.radius*sphere.radius;if(pyth<=rr){return true;}var dot=(x*this.direction.x)+(y*this.direction.y)+(z*this.direction.z);if(dot<0.0){return false;}var temp=pyth-(dot*dot);return temp<=rr;};BABYLON.Ray.prototype.intersectsTriangle=function(vertex0,vertex1,vertex2){if(!this._edge1){this._edge1=BABYLON.Vector3.Zero();this._edge2=BABYLON.Vector3.Zero();this._pvec=BABYLON.Vector3.Zero();this._tvec=BABYLON.Vector3.Zero();this._qvec=BABYLON.Vector3.Zero();}vertex1.subtractToRef(vertex0,this._edge1);vertex2.subtractToRef(vertex0,this._edge2);BABYLON.Vector3.CrossToRef(this.direction,this._edge2,this._pvec);var det=BABYLON.Vector3.Dot(this._edge1,this._pvec);if(det===0){return 0;}var invdet=1/det;this.origin.subtractToRef(vertex0,this._tvec);var bu=BABYLON.Vector3.Dot(this._tvec,this._pvec)*invdet;if(bu<0||bu>1.0){return 0;}BABYLON.Vector3.CrossToRef(this._tvec,this._edge1,this._qvec);var bv=BABYLON.Vector3.Dot(this.direction,this._qvec)*invdet;if(bv<0||bu+bv>1.0){return 0;}return BABYLON.Vector3.Dot(this._edge2,this._qvec)*invdet;};BABYLON.Ray.CreateNew=function(x,y,viewportWidth,viewportHeight,world,view,projection){var start=BABYLON.Vector3.Unproject(new BABYLON.Vector3(x,y,0),viewportWidth,viewportHeight,world,view,projection);var end=BABYLON.Vector3.Unproject(new BABYLON.Vector3(x,y,1),viewportWidth,viewportHeight,world,view,projection);var direction=end.subtract(start);direction.normalize();return new BABYLON.Ray(start,direction);};BABYLON.Ray.Transform=function(ray,matrix){var newOrigin=BABYLON.Vector3.TransformCoordinates(ray.origin,matrix);var newDirection=BABYLON.Vector3.TransformNormal(ray.direction,matrix);return new BABYLON.Ray(newOrigin,newDirection);};BABYLON.Color3=function(initialR,initialG,initialB){this.r=initialR;this.g=initialG;this.b=initialB;};BABYLON.Color3.prototype.toString=function(){return"{R: "+this.r+" G:"+this.g+" B:"+this.b+"}";};BABYLON.Color3.prototype.multiply=function(otherColor){return new BABYLON.Color3(this.r*otherColor.r,this.g*otherColor.g,this.b*otherColor.b);};BABYLON.Color3.prototype.multiplyToRef=function(otherColor,result){result.r=this.r*otherColor.r;result.g=this.g*otherColor.g;result.b=this.b*otherColor.b;};BABYLON.Color3.prototype.equals=function(otherColor){return this.r===otherColor.r&&this.g===otherColor.g&&this.b===otherColor.b;};BABYLON.Color3.prototype.scale=function(scale){return new BABYLON.Color3(this.r*scale,this.g*scale,this.b*scale);};BABYLON.Color3.prototype.scaleToRef=function(scale,result){result.r=this.r*scale;result.g=this.g*scale;result.b=this.b*scale;};BABYLON.Color3.prototype.clone=function(){return new BABYLON.Color3(this.r,this.g,this.b);};BABYLON.Color3.prototype.copyFrom=function(source){this.r=source.r;this.g=source.g;this.b=source.b;};BABYLON.Color3.prototype.copyFromFloats=function(r,g,b){this.r=r;this.g=g;this.b=b;};BABYLON.Color3.FromArray=function(array){return new BABYLON.Color3(array[0],array[1],array[2]);};BABYLON.Color4=function(initialR,initialG,initialB,initialA){this.r=initialR;this.g=initialG;this.b=initialB;this.a=initialA;};BABYLON.Color4.prototype.addInPlace=function(right){this.r+=right.r;this.g+=right.g;this.b+=right.b;this.a+=right.a;};BABYLON.Color4.prototype.add=function(right){return new BABYLON.Color4(this.r+right.r,this.g+right.g,this.b+right.b,this.a+right.a);};BABYLON.Color4.prototype.subtract=function(right){return new BABYLON.Color4(this.r-right.r,this.g-right.g,this.b-right.b,this.a-right.a);};BABYLON.Color4.prototype.subtractToRef=function(right,result){result.r=this.r-right.r;result.g=this.g-right.g;result.b=this.b-right.b;result.a=this.a-right.a;};BABYLON.Color4.prototype.scale=function(scale){return new BABYLON.Color4(this.r*scale,this.g*scale,this.b*scale,this.a*scale);};BABYLON.Color4.prototype.scaleToRef=function(scale,result){result.r=this.r*scale;result.g=this.g*scale;result.b=this.b*scale;result.a=this.a*scale;};BABYLON.Color4.prototype.toString=function(){return"{R: "+this.r+" G:"+this.g+" B:"+this.b+" A:"+this.a+"}";};BABYLON.Color4.prototype.clone=function(){return new BABYLON.Color4(this.r,this.g,this.b,this.a);};BABYLON.Color4.Lerp=function(left,right,amount){var result=new BABYLON.Color4(0,0,0,0);BABYLON.Color4.LerpToRef(left,right,amount,result);return result;};BABYLON.Color4.LerpToRef=function(left,right,amount,result){result.r=left.r+(right.r-left.r)*amount;result.g=left.g+(right.g-left.g)*amount;result.b=left.b+(right.b-left.b)*amount;result.a=left.a+(right.a-left.a)*amount;};BABYLON.Color4.FromArray=function(array,offset){if(!offset){offset=0;}return new BABYLON.Color4(array[offset],array[offset+1],array[offset+2],array[offset+3]);};BABYLON.Vector2=function(initialX,initialY){this.x=initialX;this.y=initialY;};BABYLON.Vector2.prototype.toString=function(){return"{X: "+this.x+" Y:"+this.y+"}";};BABYLON.Vector2.prototype.add=function(otherVector){return new BABYLON.Vector2(this.x+otherVector.x,this.y+otherVector.y);};BABYLON.Vector2.prototype.subtract=function(otherVector){return new BABYLON.Vector2(this.x-otherVector.x,this.y-otherVector.y);};BABYLON.Vector2.prototype.negate=function(){return new BABYLON.Vector2(-this.x,-this.y);};BABYLON.Vector2.prototype.scaleInPlace=function(scale){this.x*=scale;this.y*=scale;};BABYLON.Vector2.prototype.scale=function(scale){return new BABYLON.Vector2(this.x*scale,this.y*scale);};BABYLON.Vector2.prototype.equals=function(otherVector){return this.x===otherVector.x&&this.y===otherVector.y;};BABYLON.Vector2.prototype.length=function(){return Math.sqrt(this.x*this.x+this.y*this.y);};BABYLON.Vector2.prototype.lengthSquared=function(){return(this.x*this.x+this.y*this.y);};BABYLON.Vector2.prototype.normalize=function(){var len=this.length();if(len===0)return;var num=1.0/len;this.x*=num;this.y*=num;};BABYLON.Vector2.prototype.clone=function(){return new BABYLON.Vector2(this.x,this.y);};BABYLON.Vector2.Zero=function(){return new BABYLON.Vector2(0,0);};BABYLON.Vector2.CatmullRom=function(value1,value2,value3,value4,amount){var squared=amount*amount;var cubed=amount*squared;var x=0.5*((((2.0*value2.x)+((-value1.x+value3.x)*amount))+(((((2.0*value1.x)-(5.0*value2.x))+(4.0*value3.x))-value4.x)*squared))+((((-value1.x+(3.0*value2.x))-(3.0*value3.x))+value4.x)*cubed));var y=0.5*((((2.0*value2.y)+((-value1.y+value3.y)*amount))+(((((2.0*value1.y)-(5.0*value2.y))+(4.0*value3.y))-value4.y)*squared))+((((-value1.y+(3.0*value2.y))-(3.0*value3.y))+value4.y)*cubed));return new BABYLON.Vector2(x,y);};BABYLON.Vector2.Clamp=function(value,min,max){var x=value.x;x=(x>max.x)?max.x:x;x=(xmax.y)?max.y:y;y=(yright.x)?left.x:right.x;var y=(left.y>right.y)?left.y:right.y;return new BABYLON.Vector2(x,y);};BABYLON.Vector2.Transform=function(vector,transformation){var x=(vector.x*transformation.m[0])+(vector.y*transformation.m[4]);var y=(vector.x*transformation.m[1])+(vector.y*transformation.m[5]);return new BABYLON.Vector2(x,y);};BABYLON.Vector2.Distance=function(value1,value2){return Math.sqrt(BABYLON.Vector2.DistanceSquared(value1,value2));};BABYLON.Vector2.DistanceSquared=function(value1,value2){var x=value1.x-value2.x;var y=value1.y-value2.y;return(x*x)+(y*y);};BABYLON.Vector3=function(initialX,initialY,initialZ){this.x=initialX;this.y=initialY;this.z=initialZ;};BABYLON.Vector3.prototype.toString=function(){return"{X: "+this.x+" Y:"+this.y+" Z:"+this.z+"}";};BABYLON.Vector3.prototype.toArray=function(array,index){array[index]=this.x;array[index+1]=this.y;array[index+2]=this.z;};BABYLON.Vector3.prototype.addInPlace=function(otherVector){this.x+=otherVector.x;this.y+=otherVector.y;this.z+=otherVector.z;};BABYLON.Vector3.prototype.add=function(otherVector){return new BABYLON.Vector3(this.x+otherVector.x,this.y+otherVector.y,this.z+otherVector.z);};BABYLON.Vector3.prototype.addToRef=function(otherVector,result){result.x=this.x+otherVector.x;result.y=this.y+otherVector.y;result.z=this.z+otherVector.z;};BABYLON.Vector3.prototype.subtractInPlace=function(otherVector){this.x-=otherVector.x;this.y-=otherVector.y;this.z-=otherVector.z;};BABYLON.Vector3.prototype.subtract=function(otherVector){return new BABYLON.Vector3(this.x-otherVector.x,this.y-otherVector.y,this.z-otherVector.z);};BABYLON.Vector3.prototype.subtractToRef=function(otherVector,result){result.x=this.x-otherVector.x;result.y=this.y-otherVector.y;result.z=this.z-otherVector.z;};BABYLON.Vector3.prototype.subtractFromFloats=function(x,y,z){return new BABYLON.Vector3(this.x-x,this.y-y,this.z-z);};BABYLON.Vector3.prototype.subtractFromFloatsToRef=function(x,y,z,result){result.x=this.x-x;result.y=this.y-y;result.z=this.z-z;};BABYLON.Vector3.prototype.negate=function(){return new BABYLON.Vector3(-this.x,-this.y,-this.z);};BABYLON.Vector3.prototype.scaleInPlace=function(scale){this.x*=scale;this.y*=scale;this.z*=scale;};BABYLON.Vector3.prototype.scale=function(scale){return new BABYLON.Vector3(this.x*scale,this.y*scale,this.z*scale);};BABYLON.Vector3.prototype.scaleToRef=function(scale,result){result.x=this.x*scale;result.y=this.y*scale;result.z=this.z*scale;};BABYLON.Vector3.prototype.equals=function(otherVector){return this.x===otherVector.x&&this.y===otherVector.y&&this.z===otherVector.z;};BABYLON.Vector3.prototype.equalsToFloats=function(x,y,z){return this.x===x&&this.y===y&&this.z===z;};BABYLON.Vector3.prototype.multiplyInPlace=function(otherVector){this.x*=otherVector.x;this.y*=otherVector.y;this.z*=otherVector.z;};BABYLON.Vector3.prototype.multiply=function(otherVector){return new BABYLON.Vector3(this.x*otherVector.x,this.y*otherVector.y,this.z*otherVector.z);};BABYLON.Vector3.prototype.multiplyToRef=function(otherVector,result){result.x=this.x*otherVector.x;result.y=this.y*otherVector.y;result.z=this.z*otherVector.z;};BABYLON.Vector3.prototype.multiplyByFloats=function(x,y,z){return new BABYLON.Vector3(this.x*x,this.y*y,this.z*z);};BABYLON.Vector3.prototype.divide=function(otherVector){return new BABYLON.Vector3(this.x/otherVector.x,this.y/otherVector.y,this.z/otherVector.z);};BABYLON.Vector3.prototype.divideToRef=function(otherVector,result){result.x=this.x/otherVector.x;result.y=this.y/otherVector.y;result.z=this.z/otherVector.z;};BABYLON.Vector3.prototype.length=function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z);};BABYLON.Vector3.prototype.lengthSquared=function(){return(this.x*this.x+this.y*this.y+this.z*this.z);};BABYLON.Vector3.prototype.normalize=function(){var len=this.length();if(len===0)return;var num=1.0/len;this.x*=num;this.y*=num;this.z*=num;};BABYLON.Vector3.prototype.clone=function(){return new BABYLON.Vector3(this.x,this.y,this.z);};BABYLON.Vector3.prototype.copyFrom=function(source){this.x=source.x;this.y=source.y;this.z=source.z;};BABYLON.Vector3.prototype.copyFromFloats=function(x,y,z){this.x=x;this.y=y;this.z=z;};BABYLON.Vector3.FromArray=function(array,offset){if(!offset){offset=0;}return new BABYLON.Vector3(array[offset],array[offset+1],array[offset+2]);};BABYLON.Vector3.FromArrayToRef=function(array,offset,result){if(!offset){offset=0;}result.x=array[offset];result.y=array[offset+1];result.z=array[offset+2];};BABYLON.Vector3.FromFloatsToRef=function(x,y,z,result){result.x=x;result.y=y;result.z=z;};BABYLON.Vector3.Zero=function(){return new BABYLON.Vector3(0,0,0);};BABYLON.Vector3.Up=function(){return new BABYLON.Vector3(0,1.0,0);};BABYLON.Vector3.TransformCoordinates=function(vector,transformation){var result=BABYLON.Vector3.Zero();BABYLON.Vector3.TransformCoordinatesToRef(vector,transformation,result);return result;};BABYLON.Vector3.TransformCoordinatesToRef=function(vector,transformation,result){var x=(vector.x*transformation.m[0])+(vector.y*transformation.m[4])+(vector.z*transformation.m[8])+transformation.m[12];var y=(vector.x*transformation.m[1])+(vector.y*transformation.m[5])+(vector.z*transformation.m[9])+transformation.m[13];var z=(vector.x*transformation.m[2])+(vector.y*transformation.m[6])+(vector.z*transformation.m[10])+transformation.m[14];var w=(vector.x*transformation.m[3])+(vector.y*transformation.m[7])+(vector.z*transformation.m[11])+transformation.m[15];result.x=x/w;result.y=y/w;result.z=z/w;};BABYLON.Vector3.TransformCoordinatesFromFloatsToRef=function(x,y,z,transformation,result){var rx=(x*transformation.m[0])+(y*transformation.m[4])+(z*transformation.m[8])+transformation.m[12];var ry=(x*transformation.m[1])+(y*transformation.m[5])+(z*transformation.m[9])+transformation.m[13];var rz=(x*transformation.m[2])+(y*transformation.m[6])+(z*transformation.m[10])+transformation.m[14];var rw=(x*transformation.m[3])+(y*transformation.m[7])+(z*transformation.m[11])+transformation.m[15];result.x=rx/rw;result.y=ry/rw;result.z=rz/rw;};BABYLON.Vector3.TransformNormal=function(vector,transformation){var result=BABYLON.Vector3.Zero();BABYLON.Vector3.TransformNormalToRef(vector,transformation,result);return result;};BABYLON.Vector3.TransformNormalToRef=function(vector,transformation,result){result.x=(vector.x*transformation.m[0])+(vector.y*transformation.m[4])+(vector.z*transformation.m[8]);result.y=(vector.x*transformation.m[1])+(vector.y*transformation.m[5])+(vector.z*transformation.m[9]);result.z=(vector.x*transformation.m[2])+(vector.y*transformation.m[6])+(vector.z*transformation.m[10]);};BABYLON.Vector3.TransformNormalFromFloatsToRef=function(x,y,z,transformation,result){result.x=(x*transformation.m[0])+(y*transformation.m[4])+(z*transformation.m[8]);result.y=(x*transformation.m[1])+(y*transformation.m[5])+(z*transformation.m[9]);result.z=(x*transformation.m[2])+(y*transformation.m[6])+(z*transformation.m[10]);};BABYLON.Vector3.CatmullRom=function(value1,value2,value3,value4,amount){var squared=amount*amount;var cubed=amount*squared;var x=0.5*((((2.0*value2.x)+((-value1.x+value3.x)*amount))+(((((2.0*value1.x)-(5.0*value2.x))+(4.0*value3.x))-value4.x)*squared))+((((-value1.x+(3.0*value2.x))-(3.0*value3.x))+value4.x)*cubed));var y=0.5*((((2.0*value2.y)+((-value1.y+value3.y)*amount))+(((((2.0*value1.y)-(5.0*value2.y))+(4.0*value3.y))-value4.y)*squared))+((((-value1.y+(3.0*value2.y))-(3.0*value3.y))+value4.y)*cubed));var z=0.5*((((2.0*value2.z)+((-value1.z+value3.z)*amount))+(((((2.0*value1.z)-(5.0*value2.z))+(4.0*value3.z))-value4.z)*squared))+((((-value1.z+(3.0*value2.z))-(3.0*value3.z))+value4.z)*cubed));return new BABYLON.Vector3(x,y,z);};BABYLON.Vector3.Clamp=function(value,min,max){var x=value.x;x=(x>max.x)?max.x:x;x=(xmax.y)?max.y:y;y=(ymax.z)?max.z:z;z=(zright.x)?left.x:right.x;var y=(left.y>right.y)?left.y:right.y;var z=(left.z>right.z)?left.z:right.z;return new BABYLON.Vector3(x,y,z);};BABYLON.Vector3.Distance=function(value1,value2){return Math.sqrt(BABYLON.Vector3.DistanceSquared(value1,value2));};BABYLON.Vector3.DistanceSquared=function(value1,value2){var x=value1.x-value2.x;var y=value1.y-value2.y;var z=value1.z-value2.z;return(x*x)+(y*y)+(z*z);};BABYLON.Quaternion=function(initialX,initialY,initialZ,initialW){this.x=initialX;this.y=initialY;this.z=initialZ;this.w=initialW;};BABYLON.Quaternion.prototype.toString=function(){return"{X: "+this.x+" Y:"+this.y+" Z:"+this.z+" W:"+this.w+"}";};BABYLON.Quaternion.prototype.equals=function(otherQuaternion){return this.x===otherQuaternion.x&&this.y===otherQuaternion.y&&this.z===otherQuaternion.z&&this.w===otherQuaternion.w;};BABYLON.Quaternion.prototype.clone=function(){return new BABYLON.Quaternion(this.x,this.y,this.z,this.w);};BABYLON.Quaternion.prototype.copyFrom=function(other){this.x=other.x;this.y=other.y;this.z=other.z;this.w=other.w;};BABYLON.Quaternion.prototype.add=function(other){return new BABYLON.Quaternion(this.x+other.x,this.y+other.y,this.z+other.z,this.w+other.w);};BABYLON.Quaternion.prototype.scale=function(value){return new BABYLON.Quaternion(this.x*value,this.y*value,this.z*value,this.w*value);};BABYLON.Quaternion.prototype.multiply=function(q1){var result=new BABYLON.Quaternion(0,0,0,1.0);this.multiplyToRef(q1,result);return result;};BABYLON.Quaternion.prototype.multiplyToRef=function(q1,result){result.x=this.x*q1.w+this.y*q1.z-this.z*q1.y+this.w*q1.x;result.y=-this.x*q1.z+this.y*q1.w+this.z*q1.x+this.w*q1.y;result.z=this.x*q1.y-this.y*q1.x+this.z*q1.w+this.w*q1.z;result.w=-this.x*q1.x-this.y*q1.y-this.z*q1.z+this.w*q1.w;};BABYLON.Quaternion.prototype.length=function(){return Math.sqrt((this.x*this.x)+(this.y*this.y)+(this.z*this.z)+(this.w*this.w));};BABYLON.Quaternion.prototype.normalize=function(){var length=1.0/this.length();this.x*=length;this.y*=length;this.z*=length;this.w*=length;};BABYLON.Quaternion.prototype.toEulerAngles=function(){var qx=this.x;var qy=this.y;var qz=this.z;var qw=this.w;var sqx=qx*qx;var sqy=qy*qy;var sqz=qz*qz;var yaw=Math.atan2(2.0*(qy*qw-qx*qz),1.0-2.0*(sqy+sqz));var pitch=Math.asin(2.0*(qx*qy+qz*qw));var roll=Math.atan2(2.0*(qx*qw-qy*qz),1.0-2.0*(sqx+sqz));var gimbaLockTest=qx*qy+qz*qw;if(gimbaLockTest>0.499){yaw=2.0*Math.atan2(qx,qw);roll=0;}else if(gimbaLockTest<-0.499){yaw=-2.0*Math.atan2(qx,qw);roll=0;}return new BABYLON.Vector3(pitch,yaw,roll);};BABYLON.Quaternion.prototype.toRotationMatrix=function(result){var xx=this.x*this.x;var yy=this.y*this.y;var zz=this.z*this.z;var xy=this.x*this.y;var zw=this.z*this.w;var zx=this.z*this.x;var yw=this.y*this.w;var yz=this.y*this.z;var xw=this.x*this.w;result.m[0]=1.0-(2.0*(yy+zz));result.m[1]=2.0*(xy+zw);result.m[2]=2.0*(zx-yw);result.m[3]=0;result.m[4]=2.0*(xy-zw);result.m[5]=1.0-(2.0*(zz+xx));result.m[6]=2.0*(yz+xw);result.m[7]=0;result.m[8]=2.0*(zx+yw);result.m[9]=2.0*(yz-xw);result.m[10]=1.0-(2.0*(yy+xx));result.m[11]=0;result.m[12]=0;result.m[13]=0;result.m[14]=0;result.m[15]=1.0;};BABYLON.Quaternion.FromArray=function(array,offset){if(!offset){offset=0;}return new BABYLON.Quaternion(array[offset],array[offset+1],array[offset+2],array[offset+3]);};BABYLON.Quaternion.RotationYawPitchRoll=function(yaw,pitch,roll){var result=new BABYLON.Quaternion();BABYLON.Quaternion.RotationYawPitchRollToRef(yaw,pitch,roll,result);return result;};BABYLON.Quaternion.RotationYawPitchRollToRef=function(yaw,pitch,roll,result){var halfRoll=roll*0.5;var halfPitch=pitch*0.5;var halfYaw=yaw*0.5;var sinRoll=Math.sin(halfRoll);var cosRoll=Math.cos(halfRoll);var sinPitch=Math.sin(halfPitch);var cosPitch=Math.cos(halfPitch);var sinYaw=Math.sin(halfYaw);var cosYaw=Math.cos(halfYaw);result.x=(cosYaw*sinPitch*cosRoll)+(sinYaw*cosPitch*sinRoll);result.y=(sinYaw*cosPitch*cosRoll)-(cosYaw*sinPitch*sinRoll);result.z=(cosYaw*cosPitch*sinRoll)-(sinYaw*sinPitch*cosRoll);result.w=(cosYaw*cosPitch*cosRoll)+(sinYaw*sinPitch*sinRoll);};BABYLON.Quaternion.Slerp=function(left,right,amount){var num2;var num3;var num=amount;var num4=(((left.x*right.x)+(left.y*right.y))+(left.z*right.z))+(left.w*right.w);var flag=false;if(num4<0){flag=true;num4=-num4;}if(num4>0.999999){num3=1-num;num2=flag?-num:num;}else{var num5=Math.acos(num4);var num6=(1.0/Math.sin(num5));num3=(Math.sin((1.0-num)*num5))*num6;num2=flag?((-Math.sin(num*num5))*num6):((Math.sin(num*num5))*num6);}return new BABYLON.Quaternion((num3*left.x)+(num2*right.x),(num3*left.y)+(num2*right.y),(num3*left.z)+(num2*right.z),(num3*left.w)+(num2*right.w));};if(!BABYLON.MatrixType){BABYLON.MatrixType=(typeof Float32Array!=='undefined')?Float32Array:Array;}BABYLON.Matrix=function(){this.m=new BABYLON.MatrixType(16);};BABYLON.Matrix.prototype.isIdentity=function(){if(this.m[0]!=1.0||this.m[5]!=1.0||this.m[10]!=1.0||this.m[15]!=1.0)return false;if(this.m[1]!=0.0||this.m[2]!=0.0||this.m[3]!=0.0||this.m[4]!=0.0||this.m[6]!=0.0||this.m[7]!=0.0||this.m[8]!=0.0||this.m[9]!=0.0||this.m[11]!=0.0||this.m[12]!=0.0||this.m[13]!=0.0||this.m[14]!=0.0)return false;return true;};BABYLON.Matrix.prototype.determinant=function(){var temp1=(this.m[10]*this.m[15])-(this.m[11]*this.m[14]);var temp2=(this.m[9]*this.m[15])-(this.m[11]*this.m[13]);var temp3=(this.m[9]*this.m[14])-(this.m[10]*this.m[13]);var temp4=(this.m[8]*this.m[15])-(this.m[11]*this.m[12]);var temp5=(this.m[8]*this.m[14])-(this.m[10]*this.m[12]);var temp6=(this.m[8]*this.m[13])-(this.m[9]*this.m[12]);return((((this.m[0]*(((this.m[5]*temp1)-(this.m[6]*temp2))+(this.m[7]*temp3)))-(this.m[1]*(((this.m[4]*temp1)-(this.m[6]*temp4))+(this.m[7]*temp5))))+(this.m[2]*(((this.m[4]*temp2)-(this.m[5]*temp4))+(this.m[7]*temp6))))-(this.m[3]*(((this.m[4]*temp3)-(this.m[5]*temp5))+(this.m[6]*temp6))));};BABYLON.Matrix.prototype.toArray=function(){return this.m;};BABYLON.Matrix.prototype.invert=function(){this.invertToRef(this);};BABYLON.Matrix.prototype.invertToRef=function(other){var l1=this.m[0];var l2=this.m[1];var l3=this.m[2];var l4=this.m[3];var l5=this.m[4];var l6=this.m[5];var l7=this.m[6];var l8=this.m[7];var l9=this.m[8];var l10=this.m[9];var l11=this.m[10];var l12=this.m[11];var l13=this.m[12];var l14=this.m[13];var l15=this.m[14];var l16=this.m[15];var l17=(l11*l16)-(l12*l15);var l18=(l10*l16)-(l12*l14);var l19=(l10*l15)-(l11*l14);var l20=(l9*l16)-(l12*l13);var l21=(l9*l15)-(l11*l13);var l22=(l9*l14)-(l10*l13);var l23=((l6*l17)-(l7*l18))+(l8*l19);var l24=-(((l5*l17)-(l7*l20))+(l8*l21));var l25=((l5*l18)-(l6*l20))+(l8*l22);var l26=-(((l5*l19)-(l6*l21))+(l7*l22));var l27=1.0/((((l1*l23)+(l2*l24))+(l3*l25))+(l4*l26));var l28=(l7*l16)-(l8*l15);var l29=(l6*l16)-(l8*l14);var l30=(l6*l15)-(l7*l14);var l31=(l5*l16)-(l8*l13);var l32=(l5*l15)-(l7*l13);var l33=(l5*l14)-(l6*l13);var l34=(l7*l12)-(l8*l11);var l35=(l6*l12)-(l8*l10);var l36=(l6*l11)-(l7*l10);var l37=(l5*l12)-(l8*l9);var l38=(l5*l11)-(l7*l9);var l39=(l5*l10)-(l6*l9);other.m[0]=l23*l27;other.m[4]=l24*l27;other.m[8]=l25*l27;other.m[12]=l26*l27;other.m[1]=-(((l2*l17)-(l3*l18))+(l4*l19))*l27;other.m[5]=(((l1*l17)-(l3*l20))+(l4*l21))*l27;other.m[9]=-(((l1*l18)-(l2*l20))+(l4*l22))*l27;other.m[13]=(((l1*l19)-(l2*l21))+(l3*l22))*l27;other.m[2]=(((l2*l28)-(l3*l29))+(l4*l30))*l27;other.m[6]=-(((l1*l28)-(l3*l31))+(l4*l32))*l27;other.m[10]=(((l1*l29)-(l2*l31))+(l4*l33))*l27;other.m[14]=-(((l1*l30)-(l2*l32))+(l3*l33))*l27;other.m[3]=-(((l2*l34)-(l3*l35))+(l4*l36))*l27;other.m[7]=(((l1*l34)-(l3*l37))+(l4*l38))*l27;other.m[11]=-(((l1*l35)-(l2*l37))+(l4*l39))*l27;other.m[15]=(((l1*l36)-(l2*l38))+(l3*l39))*l27;};BABYLON.Matrix.prototype.setTranslation=function(vector3){this.m[12]=vector3.x;this.m[13]=vector3.y;this.m[14]=vector3.z;};BABYLON.Matrix.prototype.multiply=function(other){var result=new BABYLON.Matrix();this.multiplyToRef(other,result);return result;};BABYLON.Matrix.prototype.copyFrom=function(other){for(var index=0;index<16;index++){this.m[index]=other.m[index];}};BABYLON.Matrix.prototype.multiplyToRef=function(other,result){this.multiplyToArray(other,result.m,0);};BABYLON.Matrix.prototype.multiplyToArray=function(other,result,offset){result[offset]=this.m[0]*other.m[0]+this.m[1]*other.m[4]+this.m[2]*other.m[8]+this.m[3]*other.m[12];result[offset+1]=this.m[0]*other.m[1]+this.m[1]*other.m[5]+this.m[2]*other.m[9]+this.m[3]*other.m[13];result[offset+2]=this.m[0]*other.m[2]+this.m[1]*other.m[6]+this.m[2]*other.m[10]+this.m[3]*other.m[14];result[offset+3]=this.m[0]*other.m[3]+this.m[1]*other.m[7]+this.m[2]*other.m[11]+this.m[3]*other.m[15];result[offset+4]=this.m[4]*other.m[0]+this.m[5]*other.m[4]+this.m[6]*other.m[8]+this.m[7]*other.m[12];result[offset+5]=this.m[4]*other.m[1]+this.m[5]*other.m[5]+this.m[6]*other.m[9]+this.m[7]*other.m[13];result[offset+6]=this.m[4]*other.m[2]+this.m[5]*other.m[6]+this.m[6]*other.m[10]+this.m[7]*other.m[14];result[offset+7]=this.m[4]*other.m[3]+this.m[5]*other.m[7]+this.m[6]*other.m[11]+this.m[7]*other.m[15];result[offset+8]=this.m[8]*other.m[0]+this.m[9]*other.m[4]+this.m[10]*other.m[8]+this.m[11]*other.m[12];result[offset+9]=this.m[8]*other.m[1]+this.m[9]*other.m[5]+this.m[10]*other.m[9]+this.m[11]*other.m[13];result[offset+10]=this.m[8]*other.m[2]+this.m[9]*other.m[6]+this.m[10]*other.m[10]+this.m[11]*other.m[14];result[offset+11]=this.m[8]*other.m[3]+this.m[9]*other.m[7]+this.m[10]*other.m[11]+this.m[11]*other.m[15];result[offset+12]=this.m[12]*other.m[0]+this.m[13]*other.m[4]+this.m[14]*other.m[8]+this.m[15]*other.m[12];result[offset+13]=this.m[12]*other.m[1]+this.m[13]*other.m[5]+this.m[14]*other.m[9]+this.m[15]*other.m[13];result[offset+14]=this.m[12]*other.m[2]+this.m[13]*other.m[6]+this.m[14]*other.m[10]+this.m[15]*other.m[14];result[offset+15]=this.m[12]*other.m[3]+this.m[13]*other.m[7]+this.m[14]*other.m[11]+this.m[15]*other.m[15];};BABYLON.Matrix.prototype.equals=function(value){return(this.m[0]===value.m[0]&&this.m[1]===value.m[1]&&this.m[2]===value.m[2]&&this.m[3]===value.m[3]&&this.m[4]===value.m[4]&&this.m[5]===value.m[5]&&this.m[6]===value.m[6]&&this.m[7]===value.m[7]&&this.m[8]===value.m[8]&&this.m[9]===value.m[9]&&this.m[10]===value.m[10]&&this.m[11]===value.m[11]&&this.m[12]===value.m[12]&&this.m[13]===value.m[13]&&this.m[14]===value.m[14]&&this.m[15]===value.m[15]);};BABYLON.Matrix.prototype.clone=function(){return BABYLON.Matrix.FromValues(this.m[0],this.m[1],this.m[2],this.m[3],this.m[4],this.m[5],this.m[6],this.m[7],this.m[8],this.m[9],this.m[10],this.m[11],this.m[12],this.m[13],this.m[14],this.m[15]);};BABYLON.Matrix.FromArray=function(array,offset){var result=new BABYLON.Matrix();BABYLON.Matrix.FromArrayToRef(array,offset,result);return result;};BABYLON.Matrix.FromArrayToRef=function(array,offset,result){if(!offset){offset=0;}for(var index=0;index<16;index++){result.m[index]=array[index+offset];}};BABYLON.Matrix.FromValuesToRef=function(initialM11,initialM12,initialM13,initialM14,initialM21,initialM22,initialM23,initialM24,initialM31,initialM32,initialM33,initialM34,initialM41,initialM42,initialM43,initialM44,result){result.m[0]=initialM11;result.m[1]=initialM12;result.m[2]=initialM13;result.m[3]=initialM14;result.m[4]=initialM21;result.m[5]=initialM22;result.m[6]=initialM23;result.m[7]=initialM24;result.m[8]=initialM31;result.m[9]=initialM32;result.m[10]=initialM33;result.m[11]=initialM34;result.m[12]=initialM41;result.m[13]=initialM42;result.m[14]=initialM43;result.m[15]=initialM44;};BABYLON.Matrix.FromValues=function(initialM11,initialM12,initialM13,initialM14,initialM21,initialM22,initialM23,initialM24,initialM31,initialM32,initialM33,initialM34,initialM41,initialM42,initialM43,initialM44){var result=new BABYLON.Matrix();result.m[0]=initialM11;result.m[1]=initialM12;result.m[2]=initialM13;result.m[3]=initialM14;result.m[4]=initialM21;result.m[5]=initialM22;result.m[6]=initialM23;result.m[7]=initialM24;result.m[8]=initialM31;result.m[9]=initialM32;result.m[10]=initialM33;result.m[11]=initialM34;result.m[12]=initialM41;result.m[13]=initialM42;result.m[14]=initialM43;result.m[15]=initialM44;return result;};BABYLON.Matrix.Identity=function(){return BABYLON.Matrix.FromValues(1.0,0,0,0,0,1.0,0,0,0,0,1.0,0,0,0,0,1.0);};BABYLON.Matrix.IdentityToRef=function(result){BABYLON.Matrix.FromValuesToRef(1.0,0,0,0,0,1.0,0,0,0,0,1.0,0,0,0,0,1.0,result);};BABYLON.Matrix.Zero=function(){return BABYLON.Matrix.FromValues(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);};BABYLON.Matrix.RotationX=function(angle){var result=new BABYLON.Matrix();BABYLON.Matrix.RotationXToRef(angle,result);return result;};BABYLON.Matrix.RotationXToRef=function(angle,result){var s=Math.sin(angle);var c=Math.cos(angle);result.m[0]=1.0;result.m[15]=1.0;result.m[5]=c;result.m[10]=c;result.m[9]=-s;result.m[6]=s;result.m[1]=0;result.m[2]=0;result.m[3]=0;result.m[4]=0;result.m[7]=0;result.m[8]=0;result.m[11]=0;result.m[12]=0;result.m[13]=0;result.m[14]=0;};BABYLON.Matrix.RotationY=function(angle){var result=new BABYLON.Matrix();BABYLON.Matrix.RotationYToRef(angle,result);return result;};BABYLON.Matrix.RotationYToRef=function(angle,result){var s=Math.sin(angle);var c=Math.cos(angle);result.m[5]=1.0;result.m[15]=1.0;result.m[0]=c;result.m[2]=-s;result.m[8]=s;result.m[10]=c;result.m[1]=0;result.m[3]=0;result.m[4]=0;result.m[6]=0;result.m[7]=0;result.m[9]=0;result.m[11]=0;result.m[12]=0;result.m[13]=0;result.m[14]=0;};BABYLON.Matrix.RotationZ=function(angle){var result=new BABYLON.Matrix();BABYLON.Matrix.RotationZToRef(angle,result);return result;};BABYLON.Matrix.RotationZToRef=function(angle,result){var s=Math.sin(angle);var c=Math.cos(angle);result.m[10]=1.0;result.m[15]=1.0;result.m[0]=c;result.m[1]=s;result.m[4]=-s;result.m[5]=c;result.m[2]=0;result.m[3]=0;result.m[6]=0;result.m[7]=0;result.m[8]=0;result.m[9]=0;result.m[11]=0;result.m[12]=0;result.m[13]=0;result.m[14]=0;};BABYLON.Matrix.RotationAxis=function(axis,angle){var s=Math.sin(-angle);var c=Math.cos(-angle);var c1=1-c;axis.normalize();var result=BABYLON.Matrix.Zero();result.m[0]=(axis.x*axis.x)*c1+c;result.m[1]=(axis.x*axis.y)*c1-(axis.z*s);result.m[2]=(axis.x*axis.z)*c1+(axis.y*s);result.m[3]=0.0;result.m[4]=(axis.y*axis.x)*c1+(axis.z*s);result.m[5]=(axis.y*axis.y)*c1+c;result.m[6]=(axis.y*axis.z)*c1-(axis.x*s);result.m[7]=0.0;result.m[8]=(axis.z*axis.x)*c1-(axis.y*s);result.m[9]=(axis.z*axis.y)*c1+(axis.x*s);result.m[10]=(axis.z*axis.z)*c1+c;result.m[11]=0.0;result.m[15]=1.0;return result;};BABYLON.Matrix.RotationYawPitchRoll=function(yaw,pitch,roll){var result=new BABYLON.Matrix();BABYLON.Matrix.RotationYawPitchRollToRef(yaw,pitch,roll,result);return result;};var tempQuaternion=new BABYLON.Quaternion();BABYLON.Matrix.RotationYawPitchRollToRef=function(yaw,pitch,roll,result){BABYLON.Quaternion.RotationYawPitchRollToRef(yaw,pitch,roll,tempQuaternion);tempQuaternion.toRotationMatrix(result);};BABYLON.Matrix.Scaling=function(x,y,z){var result=BABYLON.Matrix.Zero();BABYLON.Matrix.ScalingToRef(x,y,z,result);return result;};BABYLON.Matrix.ScalingToRef=function(x,y,z,result){result.m[0]=x;result.m[1]=0;result.m[2]=0;result.m[3]=0;result.m[4]=0;result.m[5]=y;result.m[6]=0;result.m[7]=0;result.m[8]=0;result.m[9]=0;result.m[10]=z;result.m[11]=0;result.m[12]=0;result.m[13]=0;result.m[14]=0;result.m[15]=1.0;};BABYLON.Matrix.Translation=function(x,y,z){var result=BABYLON.Matrix.Identity();BABYLON.Matrix.TranslationToRef(x,y,z,result);return result;};BABYLON.Matrix.TranslationToRef=function(x,y,z,result){BABYLON.Matrix.FromValuesToRef(1.0,0,0,0,0,1.0,0,0,0,0,1.0,0,x,y,z,1.0,result);};BABYLON.Matrix.LookAtLH=function(eye,target,up){var result=BABYLON.Matrix.Zero();BABYLON.Matrix.LookAtLHToRef(eye,target,up,result);return result;};var xAxis=BABYLON.Vector3.Zero();var yAxis=BABYLON.Vector3.Zero();var zAxis=BABYLON.Vector3.Zero();BABYLON.Matrix.LookAtLHToRef=function(eye,target,up,result){target.subtractToRef(eye,zAxis);zAxis.normalize();BABYLON.Vector3.CrossToRef(up,zAxis,xAxis);xAxis.normalize();BABYLON.Vector3.CrossToRef(zAxis,xAxis,yAxis);yAxis.normalize();var ex=-BABYLON.Vector3.Dot(xAxis,eye);var ey=-BABYLON.Vector3.Dot(yAxis,eye);var ez=-BABYLON.Vector3.Dot(zAxis,eye);return BABYLON.Matrix.FromValuesToRef(xAxis.x,yAxis.x,zAxis.x,0,xAxis.y,yAxis.y,zAxis.y,0,xAxis.z,yAxis.z,zAxis.z,0,ex,ey,ez,1,result);};BABYLON.Matrix.OrthoLH=function(width,height,znear,zfar){var hw=2.0/width;var hh=2.0/height;var id=1.0/(zfar-znear);var nid=znear/(znear-zfar);return BABYLON.Matrix.FromValues(hw,0,0,0,0,hh,0,0,0,0,id,0,0,0,nid,1);};BABYLON.Matrix.OrthoOffCenterLH=function(left,right,bottom,top,znear,zfar){var matrix=BABYLON.Matrix.Zero();BABYLON.Matrix.OrthoOffCenterLHToRef(left,right,bottom,top,znear,zfar,matrix);return matrix;};BABYLON.Matrix.OrthoOffCenterLHToRef=function(left,right,bottom,top,znear,zfar,result){result.m[0]=2.0/(right-left);result.m[1]=result.m[2]=result.m[3]=0;result.m[5]=2.0/(top-bottom);result.m[4]=result.m[6]=result.m[7]=0;result.m[10]=-1.0/(znear-zfar);result.m[8]=result.m[9]=result.m[11]=0;result.m[12]=(left+right)/(left-right);result.m[13]=(top+bottom)/(bottom-top);result.m[14]=znear/(znear-zfar);result.m[15]=1.0;};BABYLON.Matrix.PerspectiveLH=function(width,height,znear,zfar){var matrix=BABYLON.Matrix.Zero();matrix.m[0]=(2.0*znear)/width;matrix.m[1]=matrix.m[2]=matrix.m[3]=0.0;matrix.m[5]=(2.0*znear)/height;matrix.m[4]=matrix.m[6]=matrix.m[7]=0.0;matrix.m[10]=-zfar/(znear-zfar);matrix.m[8]=matrix.m[9]=0.0;matrix.m[11]=1.0;matrix.m[12]=matrix.m[13]=matrix.m[15]=0.0;matrix.m[14]=(znear*zfar)/(znear-zfar);return matrix;};BABYLON.Matrix.PerspectiveFovLH=function(fov,aspect,znear,zfar){var matrix=BABYLON.Matrix.Zero();BABYLON.Matrix.PerspectiveFovLHToRef(fov,aspect,znear,zfar,matrix);return matrix;};BABYLON.Matrix.PerspectiveFovLHToRef=function(fov,aspect,znear,zfar,result){var tan=1.0/(Math.tan(fov*0.5));result.m[0]=tan/aspect;result.m[1]=result.m[2]=result.m[3]=0.0;result.m[5]=tan;result.m[4]=result.m[6]=result.m[7]=0.0;result.m[8]=result.m[9]=0.0;result.m[10]=-zfar/(znear-zfar);result.m[11]=1.0;result.m[12]=result.m[13]=result.m[15]=0.0;result.m[14]=(znear*zfar)/(znear-zfar);};BABYLON.Matrix.AffineTransformation=function(scaling,rotationCenter,rotation,translation){return BABYLON.Matrix.Scaling(scaling,scaling,scaling)*BABYLON.Matrix.Translation(-rotationCenter)*BABYLON.Matrix.RotationQuaternion(rotation)*BABYLON.Matrix.Translation(rotationCenter)*BABYLON.Matrix.Translation(translation);};BABYLON.Matrix.GetFinalMatrix=function(viewport,world,view,projection,zmin,zmax){var cw=viewport.width;var ch=viewport.height;var cx=viewport.x;var cy=viewport.y;var viewportMatrix=new BABYLON.Matrix(cw/2.0,0,0,0,0,-ch/2.0,0,0,0,0,zmax-zmin,0,cx+cw/2.0,ch/2.0+cy,zmin,1);return world.multiply(view).multiply(projection).multiply(viewportMatrix);};BABYLON.Matrix.Transpose=function(matrix){var result=new BABYLON.Matrix();result.m[0]=matrix.m[0];result.m[1]=matrix.m[4];result.m[2]=matrix.m[8];result.m[3]=matrix.m[12];result.m[4]=matrix.m[1];result.m[5]=matrix.m[5];result.m[6]=matrix.m[9];result.m[7]=matrix.m[13];result.m[8]=matrix.m[2];result.m[9]=matrix.m[6];result.m[10]=matrix.m[10];result.m[11]=matrix.m[14];result.m[12]=matrix.m[3];result.m[13]=matrix.m[7];result.m[14]=matrix.m[11];result.m[15]=matrix.m[15];return result;};BABYLON.Matrix.Reflection=function(plane){var matrix=new BABYLON.Matrix();BABYLON.Matrix.ReflectionToRef(plane,matrix);return matrix;};BABYLON.Matrix.ReflectionToRef=function(plane,result){plane.normalize();var x=plane.normal.x;var y=plane.normal.y;var z=plane.normal.z;var temp=-2*x;var temp2=-2*y;var temp3=-2*z;result.m[0]=(temp*x)+1;result.m[1]=temp2*x;result.m[2]=temp3*x;result.m[3]=0.0;result.m[4]=temp*y;result.m[5]=(temp2*y)+1;result.m[6]=temp3*y;result.m[7]=0.0;result.m[8]=temp*z;result.m[9]=temp2*z;result.m[10]=(temp3*z)+1;result.m[11]=0.0;result.m[12]=temp*plane.d;result.m[13]=temp2*plane.d;result.m[14]=temp3*plane.d;result.m[15]=1.0;};BABYLON.Plane=function(a,b,c,d){this.normal=new BABYLON.Vector3(a,b,c);this.d=d;};BABYLON.Plane.prototype.normalize=function(){var norm=(Math.sqrt((this.normal.x*this.normal.x)+(this.normal.y*this.normal.y)+(this.normal.z*this.normal.z)));var magnitude=0;if(norm!=0){magnitude=1.0/norm;}this.normal.x*=magnitude;this.normal.y*=magnitude;this.normal.z*=magnitude;this.d*=magnitude;};BABYLON.Plane.prototype.transform=function(transformation){var transposedMatrix=BABYLON.Matrix.Transpose(transformation);var x=this.normal.x;var y=this.normal.y;var z=this.normal.z;var d=this.d;var normalX=(((x*transposedMatrix.m[0])+(y*transposedMatrix.m[1]))+(z*transposedMatrix.m[2]))+(d*transposedMatrix.m[3]);var normalY=(((x*transposedMatrix.m[4])+(y*transposedMatrix.m[5]))+(z*transposedMatrix.m[6]))+(d*transposedMatrix.m[7]);var normalZ=(((x*transposedMatrix.m[8])+(y*transposedMatrix.m[9]))+(z*transposedMatrix.m[10]))+(d*transposedMatrix.m[11]);var finalD=(((x*transposedMatrix.m[12])+(y*transposedMatrix.m[13]))+(z*transposedMatrix.m[14]))+(d*transposedMatrix.m[15]);return new BABYLON.Plane(normalX,normalY,normalZ,finalD);};BABYLON.Plane.prototype.dotCoordinate=function(point){return((((this.normal.x*point.x)+(this.normal.y*point.y))+(this.normal.z*point.z))+this.d);};BABYLON.Plane.prototype.copyFromPoints=function(point1,point2,point3){var x1=point2.x-point1.x;var y1=point2.y-point1.y;var z1=point2.z-point1.z;var x2=point3.x-point1.x;var y2=point3.y-point1.y;var z2=point3.z-point1.z;var yz=(y1*z2)-(z1*y2);var xz=(z1*x2)-(x1*z2);var xy=(x1*y2)-(y1*x2);var pyth=(Math.sqrt((yz*yz)+(xz*xz)+(xy*xy)));var invPyth;if(pyth!=0){invPyth=1.0/pyth;}else{invPyth=0;}this.normal.x=yz*invPyth;this.normal.y=xz*invPyth;this.normal.z=xy*invPyth;this.d=-((this.normal.x*point1.x)+(this.normal.y*point1.y)+(this.normal.z*point1.z));};BABYLON.Plane.prototype.isFrontFacingTo=function(direction,epsilon){var dot=BABYLON.Vector3.Dot(this.normal,direction);return(dot<=epsilon);};BABYLON.Plane.prototype.signedDistanceTo=function(point){return BABYLON.Vector3.Dot(point,this.normal)+this.d;};BABYLON.Plane.FromArray=function(array){return new BABYLON.Plane(array[0],array[1],array[2],array[3]);};BABYLON.Plane.FromPoints=function(point1,point2,point3){var result=new BABYLON.Plane(0,0,0,0);result.copyFromPoints(point1,point2,point3);return result;};BABYLON.Plane.FromPositionAndNormal=function(origin,normal){var result=new BABYLON.Plane(0,0,0,0);normal.normalize();result.normal=normal;result.d=-(normal.x*origin.x+normal.y*origin.y+normal.z*origin.z);return result;};BABYLON.Plane.SignedDistanceToPlaneFromPositionAndNormal=function(origin,normal,point){var d=-(normal.x*origin.x+normal.y*origin.y+normal.z*origin.z);return BABYLON.Vector3.Dot(point,normal)+d;};BABYLON.Frustum={};BABYLON.Frustum.GetPlanes=function(transform){var frustumPlanes=[];for(var index=0;index<6;index++){frustumPlanes.push(new BABYLON.Plane(0,0,0,0));}BABYLON.Frustum.GetPlanesToRef(transform,frustumPlanes);return frustumPlanes;};BABYLON.Frustum.GetPlanesToRef=function(transform,frustumPlanes){frustumPlanes[0].normal.x=transform.m[3]+transform.m[2];frustumPlanes[0].normal.y=transform.m[7]+transform.m[6];frustumPlanes[0].normal.z=transform.m[10]+transform.m[10];frustumPlanes[0].d=transform.m[15]+transform.m[14];frustumPlanes[0].normalize();frustumPlanes[1].normal.x=transform.m[3]-transform.m[2];frustumPlanes[1].normal.y=transform.m[7]-transform.m[6];frustumPlanes[1].normal.z=transform.m[11]-transform.m[10];frustumPlanes[1].d=transform.m[15]-transform.m[14];frustumPlanes[1].normalize();frustumPlanes[2].normal.x=transform.m[3]+transform.m[0];frustumPlanes[2].normal.y=transform.m[7]+transform.m[4];frustumPlanes[2].normal.z=transform.m[11]+transform.m[8];frustumPlanes[2].d=transform.m[15]+transform.m[12];frustumPlanes[2].normalize();frustumPlanes[3].normal.x=transform.m[3]-transform.m[0];frustumPlanes[3].normal.y=transform.m[7]-transform.m[4];frustumPlanes[3].normal.z=transform.m[11]-transform.m[8];frustumPlanes[3].d=transform.m[15]-transform.m[12];frustumPlanes[3].normalize();frustumPlanes[4].normal.x=transform.m[3]-transform.m[1];frustumPlanes[4].normal.y=transform.m[7]-transform.m[5];frustumPlanes[4].normal.z=transform.m[11]-transform.m[9];frustumPlanes[4].d=transform.m[15]-transform.m[13];frustumPlanes[4].normalize();frustumPlanes[5].normal.x=transform.m[3]+transform.m[1];frustumPlanes[5].normal.y=transform.m[7]+transform.m[5];frustumPlanes[5].normal.z=transform.m[11]+transform.m[9];frustumPlanes[5].d=transform.m[15]+transform.m[13];frustumPlanes[5].normalize();};BABYLON.Viewport={};BABYLON.Viewport=function(x,y,width,height){this.width=width;this.height=height;this.x=x;this.y=y;};BABYLON.Viewport.prototype.toGlobal=function(engine){var width=engine.getRenderWidth()*engine.getHardwareScalingLevel();var height=engine.getRenderHeight()*engine.getHardwareScalingLevel();return new BABYLON.Viewport(this.x*width,this.y*height,this.width*width,this.height*height);};})();var BABYLON=BABYLON||{};(function(){BABYLON.Tools={};BABYLON.Tools.ExtractMinAndMax=function(positions,start,count){var minimum=new BABYLON.Vector3(Number.MAX_VALUE,Number.MAX_VALUE,Number.MAX_VALUE);var maximum=new BABYLON.Vector3(-Number.MAX_VALUE,-Number.MAX_VALUE,-Number.MAX_VALUE);for(var index=start;indexthis.data.length){this.data.length*=2;}};BABYLON.Tools.SmartArray.prototype.pushNoDuplicate=function(value){if(this.indexOf(value)>-1){return;}this.push(value);};BABYLON.Tools.SmartArray.prototype.sort=function(compareFn){this.data.sort(compareFn);};BABYLON.Tools.SmartArray.prototype.reset=function(){this.length=0;};BABYLON.Tools.SmartArray.prototype.concat=function(array){if(array.length===0){return;}if(this.length+array.length>this.data.length){this.data.length=(this.length+array.length)*2;}for(var index=0;indexthis.data.length){this.data.length=(this.length+array.length)*2;}for(var index=0;index=this.length){this.data[this.length++]=item;}}};BABYLON.Tools.SmartArray.prototype.indexOf=function(value){var position=this.data.indexOf(value);if(position>=this.length){return-1;}return position;};BABYLON.Tools.GetPointerPrefix=function(){var eventPrefix="pointer";if(!navigator.pointerEnabled){eventPrefix="mouse";}return eventPrefix;};BABYLON.Tools.QueueNewFrame=function(func){if(window.requestAnimationFrame)window.requestAnimationFrame(func);else if(window.msRequestAnimationFrame)window.msRequestAnimationFrame(func);else if(window.webkitRequestAnimationFrame)window.webkitRequestAnimationFrame(func);else if(window.mozRequestAnimationFrame)window.mozRequestAnimationFrame(func);else if(window.oRequestAnimationFrame)window.oRequestAnimationFrame(func);else{window.setTimeout(func,16);}};BABYLON.Tools.RequestFullscreen=function(element){if(element.requestFullscreen)element.requestFullscreen();else if(element.msRequestFullscreen)element.msRequestFullscreen();else if(element.webkitRequestFullscreen)element.webkitRequestFullscreen();else if(element.mozRequestFullScreen)element.mozRequestFullScreen();};BABYLON.Tools.ExitFullscreen=function(){if(document.exitFullscreen){document.exitFullscreen();}else if(document.mozCancelFullScreen){document.mozCancelFullScreen();}else if(document.webkitCancelFullScreen){document.webkitCancelFullScreen();}else if(document.msCancelFullScreen){document.msCancelFullScreen();}};BABYLON.Tools.BaseUrl="";BABYLON.Tools.LoadImage=function(url,onload,onerror,database){var img=new Image();img.onload=function(){onload(img);};img.onerror=function(err){onerror(img,err);};var noIndexedDB=function(){img.src=url;};var loadFromIndexedDB=function(){database.loadImageFromDB(url,img);};if(database&&database.enableTexturesOffline&&BABYLON.Database.isUASupportingBlobStorage){database.openAsync(loadFromIndexedDB,noIndexedDB);}else{if(url.indexOf("file:")===-1){noIndexedDB();}else{try{var textureName=url.substring(5);var blobURL;try{blobURL=URL.createObjectURL(BABYLON.FilesTextures[textureName],{oneTimeOnly:true});}catch(ex){blobURL=URL.createObjectURL(BABYLON.FilesTextures[textureName]);}img.src=blobURL;}catch(e){console.log("Error while trying to load texture: "+textureName);img.src=null;}}}return img;};BABYLON.Tools.LoadFile=function(url,callback,progressCallBack,database){var noIndexedDB=function(){var request=new XMLHttpRequest();var loadUrl=BABYLON.Tools.BaseUrl+url;request.open('GET',loadUrl,true);request.onprogress=progressCallBack;request.onreadystatechange=function(){if(request.readyState==4){if(request.status==200){callback(request.responseText);}else{throw new Error(request.status,"Unable to load "+loadUrl);}}};request.send(null);};var loadFromIndexedDB=function(){database.loadSceneFromDB(url,callback,progressCallBack,noIndexedDB);};if(database&&url.indexOf(".babylon")!==-1&&(database.enableSceneOffline)){database.openAsync(loadFromIndexedDB,noIndexedDB);}else{noIndexedDB();}};BABYLON.Tools.ReadFile=function(fileToLoad,callback,progressCallBack){var reader=new FileReader();reader.onload=function(e){callback(e.target.result);};reader.onprogress=progressCallBack;reader.readAsText(fileToLoad);};BABYLON.Tools.isIE=function(){return window.ActiveXObject!==undefined;};BABYLON.Tools.WithinEpsilon=function(a,b){var num=a-b;return-1.401298E-45<=num&&num<=1.401298E-45;};var cloneValue=function(source,destinationObject){if(!source)return null;if(source instanceof BABYLON.Mesh){return null;}if(source instanceof BABYLON.SubMesh){return source.clone(destinationObject);}else if(source.clone){return source.clone();}return null;};BABYLON.Tools.DeepCopy=function(source,destination,doNotCopyList,mustCopyList){for(var prop in source){if(prop[0]==="_"&&(!mustCopyList||mustCopyList.indexOf(prop)===-1)){continue;}if(doNotCopyList&&doNotCopyList.indexOf(prop)!==-1){continue;}var sourceValue=source[prop];var typeOfSourceValue=typeof sourceValue;if(typeOfSourceValue=="function"){continue;}if(typeOfSourceValue=="object"){if(sourceValue instanceof Array){destination[prop]=[];if(sourceValue.length>0){if(typeof sourceValue[0]=="object"){for(var index=0;index=2){deltaTime=previousFramesDuration[length-1]-previousFramesDuration[length-2];}if(length>=fpsRange){if(length>fpsRange){previousFramesDuration.splice(0,1);length=previousFramesDuration.length;}var sum=0;for(var id=0;id=0){this._gl.vertexAttribPointer(order,vertexDeclaration[index],this._gl.FLOAT,false,vertexStrideSize,offset);}offset+=vertexDeclaration[index]*4;}}if(this._cachedIndexBuffer!==indexBuffer){this._cachedIndexBuffer=indexBuffer;this._gl.bindBuffer(this._gl.ELEMENT_ARRAY_BUFFER,indexBuffer);}};BABYLON.Engine.prototype.bindMultiBuffers=function(vertexBuffers,indexBuffer,effect){if(this._cachedVertexBuffers!==vertexBuffers||this._cachedEffectForVertexBuffers!==effect){this._cachedVertexBuffers=vertexBuffers;this._cachedEffectForVertexBuffers=effect;var attributes=effect.getAttributesNames();for(var index=0;index=0){var vertexBuffer=vertexBuffers[attributes[index]];var stride=vertexBuffer.getStrideSize();this._gl.bindBuffer(this._gl.ARRAY_BUFFER,vertexBuffer._buffer);this._gl.vertexAttribPointer(order,stride,this._gl.FLOAT,false,stride*4,0);}}}if(this._cachedIndexBuffer!==indexBuffer){this._cachedIndexBuffer=indexBuffer;this._gl.bindBuffer(this._gl.ELEMENT_ARRAY_BUFFER,indexBuffer);}};BABYLON.Engine.prototype._releaseBuffer=function(buffer){buffer.references--;if(buffer.references===0){this._gl.deleteBuffer(buffer);}};BABYLON.Engine.prototype.draw=function(useTriangles,indexStart,indexCount){this._gl.drawElements(useTriangles?this._gl.TRIANGLES:this._gl.LINES,indexCount,this._gl.UNSIGNED_SHORT,indexStart*2);};BABYLON.Engine.prototype.createEffect=function(baseName,attributesNames,uniformsNames,samplers,defines,optionalDefines){var vertex=baseName.vertex||baseName;var fragment=baseName.fragment||baseName;var name=vertex+"+"+fragment+"@"+defines;if(this._compiledEffects[name]){return this._compiledEffects[name];}var effect=new BABYLON.Effect(baseName,attributesNames,uniformsNames,samplers,this,defines,optionalDefines);this._compiledEffects[name]=effect;return effect;};var compileShader=function(gl,source,type,defines){var shader=gl.createShader(type==="vertex"?gl.VERTEX_SHADER:gl.FRAGMENT_SHADER);gl.shaderSource(shader,(defines?defines+"\n":"")+source);gl.compileShader(shader);if(!gl.getShaderParameter(shader,gl.COMPILE_STATUS)){throw new Error(gl.getShaderInfoLog(shader));}return shader;};BABYLON.Engine.prototype.createShaderProgram=function(vertexCode,fragmentCode,defines){var vertexShader=compileShader(this._gl,vertexCode,"vertex",defines);var fragmentShader=compileShader(this._gl,fragmentCode,"fragment",defines);var shaderProgram=this._gl.createProgram();this._gl.attachShader(shaderProgram,vertexShader);this._gl.attachShader(shaderProgram,fragmentShader);this._gl.linkProgram(shaderProgram);var error=this._gl.getProgramInfoLog(shaderProgram);if(error){throw new Error(error);}this._gl.deleteShader(vertexShader);this._gl.deleteShader(fragmentShader);return shaderProgram;};BABYLON.Engine.prototype.getUniforms=function(shaderProgram,uniformsNames){var results=[];for(var index=0;index=0){this._gl.enableVertexAttribArray(effect.getAttribute(index));}}this._currentEffect=effect;};BABYLON.Engine.prototype.setMatrices=function(uniform,matrices){if(!uniform)return;this._gl.uniformMatrix4fv(uniform,false,matrices);};BABYLON.Engine.prototype.setMatrix=function(uniform,matrix){if(!uniform)return;this._gl.uniformMatrix4fv(uniform,false,matrix.toArray());};BABYLON.Engine.prototype.setFloat=function(uniform,value){if(!uniform)return;this._gl.uniform1f(uniform,value);};BABYLON.Engine.prototype.setFloat2=function(uniform,x,y){if(!uniform)return;this._gl.uniform2f(uniform,x,y);};BABYLON.Engine.prototype.setFloat3=function(uniform,x,y,z){if(!uniform)return;this._gl.uniform3f(uniform,x,y,z);};BABYLON.Engine.prototype.setBool=function(uniform,bool){if(!uniform)return;this._gl.uniform1i(uniform,bool);};BABYLON.Engine.prototype.setFloat4=function(uniform,x,y,z,w){if(!uniform)return;this._gl.uniform4f(uniform,x,y,z,w);};BABYLON.Engine.prototype.setColor3=function(uniform,color3){if(!uniform)return;this._gl.uniform3f(uniform,color3.r,color3.g,color3.b);};BABYLON.Engine.prototype.setColor4=function(uniform,color3,alpha){if(!uniform)return;this._gl.uniform4f(uniform,color3.r,color3.g,color3.b,alpha);};BABYLON.Engine.prototype.setState=function(culling){if(this._currentState.culling!==culling){if(culling){this._gl.cullFace(this.cullBackFaces?this._gl.BACK:this._gl.FRONT);this._gl.enable(this._gl.CULL_FACE);}else{this._gl.disable(this._gl.CULL_FACE);}this._currentState.culling=culling;}};BABYLON.Engine.prototype.setDepthBuffer=function(enable){if(enable){this._gl.enable(this._gl.DEPTH_TEST);}else{this._gl.disable(this._gl.DEPTH_TEST);}};BABYLON.Engine.prototype.setDepthWrite=function(enable){this._gl.depthMask(enable);};BABYLON.Engine.prototype.setColorWrite=function(enable){this._gl.colorMask(enable,enable,enable,enable);};BABYLON.Engine.prototype.setAlphaMode=function(mode){switch(mode){case BABYLON.Engine.ALPHA_DISABLE:this.setDepthWrite(true);this._gl.disable(this._gl.BLEND);break;case BABYLON.Engine.ALPHA_COMBINE:this.setDepthWrite(false);this._gl.blendFuncSeparate(this._gl.SRC_ALPHA,this._gl.ONE_MINUS_SRC_ALPHA,this._gl.ZERO,this._gl.ONE);this._gl.enable(this._gl.BLEND);break;case BABYLON.Engine.ALPHA_ADD:this.setDepthWrite(false);this._gl.blendFuncSeparate(this._gl.ONE,this._gl.ONE,this._gl.ZERO,this._gl.ONE);this._gl.enable(this._gl.BLEND);break;}};BABYLON.Engine.prototype.setAlphaTesting=function(enable){this._alphaTest=enable;};BABYLON.Engine.prototype.getAlphaTesting=function(){return this._alphaTest;};BABYLON.Engine.prototype.wipeCaches=function(){this._activeTexturesCache=[];this._currentEffect=null;this._currentState={culling:null};this._cachedVertexBuffers=null;this._cachedVertexBuffers=null;this._cachedEffectForVertexBuffers=null;};var getExponantOfTwo=function(value,max){var count=1;do{count*=2;}while(countmax)count=max;return count;};BABYLON.Engine.prototype.createTexture=function(url,noMipmap,invertY,scene){var texture=this._gl.createTexture();var that=this;var onload=function(img){var potWidth=getExponantOfTwo(img.width,that._caps.maxTextureSize);var potHeight=getExponantOfTwo(img.height,that._caps.maxTextureSize);var isPot=(img.width==potWidth&&img.height==potHeight);if(!isPot){that._workingCanvas.width=potWidth;that._workingCanvas.height=potHeight;that._workingContext.drawImage(img,0,0,img.width,img.height,0,0,potWidth,potHeight);};that._gl.bindTexture(that._gl.TEXTURE_2D,texture);that._gl.pixelStorei(that._gl.UNPACK_FLIP_Y_WEBGL,invertY===undefined?true:invertY);that._gl.texImage2D(that._gl.TEXTURE_2D,0,that._gl.RGBA,that._gl.RGBA,that._gl.UNSIGNED_BYTE,isPot?img:that._workingCanvas);that._gl.texParameteri(that._gl.TEXTURE_2D,that._gl.TEXTURE_MAG_FILTER,that._gl.LINEAR);if(noMipmap){that._gl.texParameteri(that._gl.TEXTURE_2D,that._gl.TEXTURE_MIN_FILTER,that._gl.LINEAR);}else{that._gl.texParameteri(that._gl.TEXTURE_2D,that._gl.TEXTURE_MIN_FILTER,that._gl.LINEAR_MIPMAP_LINEAR);that._gl.generateMipmap(that._gl.TEXTURE_2D);}that._gl.bindTexture(that._gl.TEXTURE_2D,null);that._activeTexturesCache=[];texture._baseWidth=img.width;texture._baseHeight=img.height;texture._width=potWidth;texture._height=potHeight;texture.isReady=true;scene._removePendingData(texture);};var onerror=function(){scene._removePendingData(texture);};scene._addPendingData(texture);BABYLON.Tools.LoadImage(url,onload,onerror,scene.database);texture.url=url;texture.noMipmap=noMipmap;texture.references=1;this._loadedTexturesCache.push(texture);return texture;};BABYLON.Engine.prototype.createDynamicTexture=function(width,height,generateMipMaps){var texture=this._gl.createTexture();width=getExponantOfTwo(width,this._caps.maxTextureSize);height=getExponantOfTwo(height,this._caps.maxTextureSize);this._gl.bindTexture(this._gl.TEXTURE_2D,texture);this._gl.texParameteri(this._gl.TEXTURE_2D,this._gl.TEXTURE_MAG_FILTER,this._gl.LINEAR);if(!generateMipMaps){this._gl.texParameteri(this._gl.TEXTURE_2D,this._gl.TEXTURE_MIN_FILTER,this._gl.LINEAR);}else{this._gl.texParameteri(this._gl.TEXTURE_2D,this._gl.TEXTURE_MIN_FILTER,this._gl.LINEAR_MIPMAP_LINEAR);}this._gl.bindTexture(this._gl.TEXTURE_2D,null);this._activeTexturesCache=[];texture._baseWidth=width;texture._baseHeight=height;texture._width=width;texture._height=height;texture.isReady=false;texture.generateMipMaps=generateMipMaps;texture.references=1;this._loadedTexturesCache.push(texture);return texture;};BABYLON.Engine.prototype.updateDynamicTexture=function(texture,canvas,invertY){this._gl.bindTexture(this._gl.TEXTURE_2D,texture);this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL,invertY);this._gl.texImage2D(this._gl.TEXTURE_2D,0,this._gl.RGBA,this._gl.RGBA,this._gl.UNSIGNED_BYTE,canvas);if(texture.generateMipMaps){this._gl.generateMipmap(this._gl.TEXTURE_2D);}this._gl.bindTexture(this._gl.TEXTURE_2D,null);this._activeTexturesCache=[];texture.isReady=true;};BABYLON.Engine.prototype.updateVideoTexture=function(texture,video){this._gl.bindTexture(this._gl.TEXTURE_2D,texture);this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL,false);if(video.videoWidth!==texture._width||video.videoHeight!==texture._height){if(!texture._workingCanvas){texture._workingCanvas=document.createElement("canvas");texture._workingContext=texture._workingCanvas.getContext("2d");texture._workingCanvas.width=texture._width;texture._workingCanvas.height=texture._height;}texture._workingContext.drawImage(video,0,0,video.videoWidth,video.videoHeight,0,0,texture._width,texture._height);this._gl.texImage2D(this._gl.TEXTURE_2D,0,this._gl.RGBA,this._gl.RGBA,this._gl.UNSIGNED_BYTE,texture._workingCanvas);}else{this._gl.texImage2D(this._gl.TEXTURE_2D,0,this._gl.RGBA,this._gl.RGBA,this._gl.UNSIGNED_BYTE,video);}if(texture.generateMipMaps){this._gl.generateMipmap(this._gl.TEXTURE_2D);}this._gl.bindTexture(this._gl.TEXTURE_2D,null);this._activeTexturesCache=[];texture.isReady=true;};BABYLON.Engine.prototype.createRenderTargetTexture=function(size,options){var generateMipMaps=false;var generateDepthBuffer=true;var samplingMode=BABYLON.Texture.TRILINEAR_SAMPLINGMODE;if(options!==undefined){generateMipMaps=options.generateMipMaps===undefined?options:options.generateMipmaps;generateDepthBuffer=options.generateDepthBuffer===undefined?true:options.generateDepthBuffer;if(options.samplingMode!==undefined){samplingMode=options.samplingMode;}}var gl=this._gl;var texture=gl.createTexture();gl.bindTexture(gl.TEXTURE_2D,texture);var width=size.width||size;var height=size.height||size;var magFilter=gl.NEAREST;var minFilter=gl.NEAREST;if(samplingMode===BABYLON.Texture.BILINEAR_SAMPLINGMODE){magFilter=gl.LINEAR;if(generateMipMaps){minFilter=gl.LINEAR_MIPMAP_NEAREST;}else{minFilter=gl.LINEAR;}}else if(samplingMode===BABYLON.Texture.TRILINEAR_SAMPLINGMODE){magFilter=gl.LINEAR;if(generateMipMaps){minFilter=gl.LINEAR_MIPMAP_LINEAR;}else{minFilter=gl.LINEAR;}}gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,magFilter);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,minFilter);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.CLAMP_TO_EDGE);gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,width,height,0,gl.RGBA,gl.UNSIGNED_BYTE,null);var depthBuffer;if(generateDepthBuffer){depthBuffer=gl.createRenderbuffer();gl.bindRenderbuffer(gl.RENDERBUFFER,depthBuffer);gl.renderbufferStorage(gl.RENDERBUFFER,gl.DEPTH_COMPONENT16,width,height);}var framebuffer=gl.createFramebuffer();gl.bindFramebuffer(gl.FRAMEBUFFER,framebuffer);gl.framebufferTexture2D(gl.FRAMEBUFFER,gl.COLOR_ATTACHMENT0,gl.TEXTURE_2D,texture,0);if(generateDepthBuffer){gl.framebufferRenderbuffer(gl.FRAMEBUFFER,gl.DEPTH_ATTACHMENT,gl.RENDERBUFFER,depthBuffer);}gl.bindTexture(gl.TEXTURE_2D,null);gl.bindRenderbuffer(gl.RENDERBUFFER,null);gl.bindFramebuffer(gl.FRAMEBUFFER,null);texture._framebuffer=framebuffer;if(generateDepthBuffer){texture._depthBuffer=depthBuffer;}texture._width=width;texture._height=height;texture.isReady=true;texture.generateMipMaps=generateMipMaps;texture.references=1;this._activeTexturesCache=[];this._loadedTexturesCache.push(texture);return texture;};var extensions=["_px.jpg","_py.jpg","_pz.jpg","_nx.jpg","_ny.jpg","_nz.jpg"];var cascadeLoad=function(rootUrl,index,loadedImages,scene,onfinish){var img;var onload=function(){loadedImages.push(img);scene._removePendingData(img);if(index!=extensions.length-1){cascadeLoad(rootUrl,index+1,loadedImages,scene,onfinish);}else{onfinish(loadedImages);}};var onerror=function(){scene._removePendingData(img);};img=BABYLON.Tools.LoadImage(rootUrl+extensions[index],onload,onerror,scene.database);scene._addPendingData(img);};BABYLON.Engine.prototype.createCubeTexture=function(rootUrl,scene){var gl=this._gl;var texture=gl.createTexture();texture.isCube=true;texture.url=rootUrl;texture.references=1;this._loadedTexturesCache.push(texture);var that=this;cascadeLoad(rootUrl,0,[],scene,function(imgs){var width=getExponantOfTwo(imgs[0].width,that._caps.maxCubemapTextureSize);var height=width;that._workingCanvas.width=width;that._workingCanvas.height=height;var faces=[gl.TEXTURE_CUBE_MAP_POSITIVE_X,gl.TEXTURE_CUBE_MAP_POSITIVE_Y,gl.TEXTURE_CUBE_MAP_POSITIVE_Z,gl.TEXTURE_CUBE_MAP_NEGATIVE_X,gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,gl.TEXTURE_CUBE_MAP_NEGATIVE_Z];gl.bindTexture(gl.TEXTURE_CUBE_MAP,texture);gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,false);for(var index=0;indexthis.maximumWorld.x)this.maximumWorld.x=v.x;if(v.y>this.maximumWorld.y)this.maximumWorld.y=v.y;if(v.z>this.maximumWorld.z)this.maximumWorld.z=v.z;}this.maximumWorld.addToRef(this.minimumWorld,this.center);this.center.scaleInPlace(0.5);BABYLON.Vector3.FromArrayToRef(world.m,0,this.directions[0]);BABYLON.Vector3.FromArrayToRef(world.m,4,this.directions[1]);BABYLON.Vector3.FromArrayToRef(world.m,8,this.directions[2]);};BABYLON.BoundingBox.prototype.isInFrustrum=function(frustumPlanes){return BABYLON.BoundingBox.IsInFrustrum(this.vectorsWorld,frustumPlanes);};BABYLON.BoundingBox.prototype.intersectsPoint=function(point){if(this.maximumWorld.xpoint.x)return false;if(this.maximumWorld.ypoint.y)return false;if(this.maximumWorld.zpoint.z)return false;return true;};BABYLON.BoundingBox.prototype.intersectsSphere=function(sphere){var vector=BABYLON.Vector3.Clamp(sphere.centerWorld,this.minimumWorld,this.maximumWorld);var num=BABYLON.Vector3.DistanceSquared(sphere.centerWorld,vector);return(num<=(sphere.radiusWorld*sphere.radiusWorld));};BABYLON.BoundingBox.prototype.intersectsMinMax=function(min,max){if(this.maximumWorld.xmax.x)return false;if(this.maximumWorld.ymax.y)return false;if(this.maximumWorld.zmax.z)return false;return true;};BABYLON.BoundingBox.intersects=function(box0,box1){if(box0.maximumWorld.xbox1.maximumWorld.x)return false;if(box0.maximumWorld.ybox1.maximumWorld.y)return false;if(box0.maximumWorld.zbox1.maximumWorld.z)return false;return true;};BABYLON.BoundingBox.IsInFrustrum=function(boundingVectors,frustumPlanes){for(var p=0;p<6;p++){var inCount=8;for(var i=0;i<8;i++){if(frustumPlanes[p].dotCoordinate(boundingVectors[i])<0){--inCount;}else{break;}}if(inCount==0)return false;}return true;};})();var BABYLON=BABYLON||{};(function(){BABYLON.BoundingInfo=function(minimum,maximum){this.boundingBox=new BABYLON.BoundingBox(minimum,maximum);this.boundingSphere=new BABYLON.BoundingSphere(minimum,maximum);};BABYLON.BoundingInfo.prototype._update=function(world,scale){this.boundingBox._update(world);this.boundingSphere._update(world,scale);};var extentsOverlap=function(min0,max0,min1,max1){return!(min0>max1||min1>max0);};var computeBoxExtents=function(axis,box){var p=BABYLON.Vector3.Dot(box.center,axis);var r0=Math.abs(BABYLON.Vector3.Dot(box.directions[0],axis))*box.extends.x;var r1=Math.abs(BABYLON.Vector3.Dot(box.directions[1],axis))*box.extends.y;var r2=Math.abs(BABYLON.Vector3.Dot(box.directions[2],axis))*box.extends.z;var r=r0+r1+r2;return{min:p-r,max:p+r};};var axisOverlap=function(axis,box0,box1){var result0=computeBoxExtents(axis,box0);var result1=computeBoxExtents(axis,box1);return extentsOverlap(result0.min,result0.max,result1.min,result1.max);};BABYLON.BoundingInfo.prototype.isInFrustrum=function(frustumPlanes){if(!this.boundingSphere.isInFrustrum(frustumPlanes))return false;return this.boundingBox.isInFrustrum(frustumPlanes);};BABYLON.BoundingInfo.prototype._checkCollision=function(collider){return collider._canDoCollision(this.boundingSphere.centerWorld,this.boundingSphere.radiusWorld,this.boundingBox.minimumWorld,this.boundingBox.maximumWorld);};BABYLON.BoundingInfo.prototype.intersectsPoint=function(point){if(!this.boundingSphere.centerWorld){return false;}if(!this.boundingSphere.intersectsPoint(point)){return false;}if(!this.boundingBox.intersectsPoint(point)){return false;}return true;};BABYLON.BoundingInfo.prototype.intersects=function(boundingInfo,precise){if(!this.boundingSphere.centerWorld||!boundingInfo.boundingSphere.centerWorld){return false;}if(!BABYLON.BoundingSphere.intersects(this.boundingSphere,boundingInfo.boundingSphere)){return false;}if(!BABYLON.BoundingBox.intersects(this.boundingBox,boundingInfo.boundingBox)){return false;}if(!precise){return true;}var box0=this.boundingBox;var box1=boundingInfo.boundingBox;if(!axisOverlap(box0.directions[0],box0,box1))return false;if(!axisOverlap(box0.directions[1],box0,box1))return false;if(!axisOverlap(box0.directions[2],box0,box1))return false;if(!axisOverlap(box1.directions[0],box0,box1))return false;if(!axisOverlap(box1.directions[1],box0,box1))return false;if(!axisOverlap(box1.directions[2],box0,box1))return false;if(!axisOverlap(BABYLON.Vector3.Cross(box0.directions[0],box1.directions[0]),box0,box1))return false;if(!axisOverlap(BABYLON.Vector3.Cross(box0.directions[0],box1.directions[1]),box0,box1))return false;if(!axisOverlap(BABYLON.Vector3.Cross(box0.directions[0],box1.directions[2]),box0,box1))return false;if(!axisOverlap(BABYLON.Vector3.Cross(box0.directions[1],box1.directions[0]),box0,box1))return false;if(!axisOverlap(BABYLON.Vector3.Cross(box0.directions[1],box1.directions[1]),box0,box1))return false;if(!axisOverlap(BABYLON.Vector3.Cross(box0.directions[1],box1.directions[2]),box0,box1))return false;if(!axisOverlap(BABYLON.Vector3.Cross(box0.directions[2],box1.directions[0]),box0,box1))return false;if(!axisOverlap(BABYLON.Vector3.Cross(box0.directions[2],box1.directions[1]),box0,box1))return false;if(!axisOverlap(BABYLON.Vector3.Cross(box0.directions[2],box1.directions[2]),box0,box1))return false;return true;};})();var BABYLON=BABYLON||{};(function(){BABYLON.Light=function(name,scene){this.name=name;this.id=name;this._childrenFlag=true;this._scene=scene;scene.lights.push(this);this.animations=[];this.excludedMeshes=[];};BABYLON.Light.prototype=Object.create(BABYLON.Node.prototype);BABYLON.Light.prototype.intensity=1.0;BABYLON.Light.prototype.getScene=function(){return this._scene;};BABYLON.Light.prototype.getShadowGenerator=function(){return this._shadowGenerator;};BABYLON.Light.prototype.transferToEffect=function(){};BABYLON.Light.prototype.getWorldMatrix=function(){var worldMatrix=this._getWorldMatrix();if(this.parent&&this.parent.getWorldMatrix){if(!this._parentedWorldMatrix){this._parentedWorldMatrix=BABYLON.Matrix.Identity();}worldMatrix.multiplyToRef(this.parent.getWorldMatrix(),this._parentedWorldMatrix);return this._parentedWorldMatrix;}return worldMatrix;};BABYLON.Light.prototype.dispose=function(){if(this._shadowGenerator){this._shadowGenerator.dispose();this._shadowGenerator=null;}var index=this._scene.lights.indexOf(this);this._scene.lights.splice(index,1);};})();var BABYLON=BABYLON||{};(function(){BABYLON.PointLight=function(name,position,scene){BABYLON.Light.call(this,name,scene);this.position=position;this.diffuse=new BABYLON.Color3(1.0,1.0,1.0);this.specular=new BABYLON.Color3(1.0,1.0,1.0);};BABYLON.PointLight.prototype=Object.create(BABYLON.Light.prototype);BABYLON.PointLight.prototype.transferToEffect=function(effect,positionUniformName){if(this.parent&&this.parent.getWorldMatrix){if(!this._transformedPosition){this._transformedPosition=BABYLON.Vector3.Zero();}BABYLON.Vector3.TransformCoordinatesToRef(this.position,this.parent.getWorldMatrix(),this._transformedPosition);effect.setFloat4(positionUniformName,this._transformedPosition.x,this._transformedPosition.y,this._transformedPosition.z,0);return;}effect.setFloat4(positionUniformName,this.position.x,this.position.y,this.position.z,0);};BABYLON.PointLight.prototype.getShadowGenerator=function(){return null;};BABYLON.PointLight.prototype._getWorldMatrix=function(){if(!this._worldMatrix){this._worldMatrix=BABYLON.Matrix.Identity();}BABYLON.Matrix.TranslationToRef(this.position.x,this.position.y,this.position.z,this._worldMatrix);return this._worldMatrix;};})();var BABYLON=BABYLON||{};(function(){BABYLON.SpotLight=function(name,position,direction,angle,exponent,scene){BABYLON.Light.call(this,name,scene);this.position=position;this.direction=direction;this.angle=angle;this.exponent=exponent;this.diffuse=new BABYLON.Color3(1.0,1.0,1.0);this.specular=new BABYLON.Color3(1.0,1.0,1.0);};BABYLON.SpotLight.prototype=Object.create(BABYLON.Light.prototype);BABYLON.SpotLight.prototype.transferToEffect=function(effect,positionUniformName,directionUniformName){var normalizeDirection;if(this.parent&&this.parent.getWorldMatrix){if(!this._transformedDirection){this._transformedDirection=BABYLON.Vector3.Zero();}if(!this._transformedPosition){this._transformedPosition=BABYLON.Vector3.Zero();}var parentWorldMatrix=this.parent.getWorldMatrix();BABYLON.Vector3.TransformCoordinatesToRef(this.position,parentWorldMatrix,this._transformedPosition);BABYLON.Vector3.TransformNormalToRef(this.direction,parentWorldMatrix,this._transformedDirection);effect.setFloat4(positionUniformName,this._transformedPosition.x,this._transformedPosition.y,this._transformedPosition.z,this.exponent);normalizeDirection=BABYLON.Vector3.Normalize(this._transformedDirection);}else{effect.setFloat4(positionUniformName,this.position.x,this.position.y,this.position.z,this.exponent);normalizeDirection=BABYLON.Vector3.Normalize(this.direction);}effect.setFloat4(directionUniformName,normalizeDirection.x,normalizeDirection.y,normalizeDirection.z,Math.cos(this.angle*0.5));};BABYLON.SpotLight.prototype._getWorldMatrix=function(){if(!this._worldMatrix){this._worldMatrix=BABYLON.Matrix.Identity();}BABYLON.Matrix.TranslationToRef(this.position.x,this.position.y,this.position.z,this._worldMatrix);return this._worldMatrix;};})();var BABYLON=BABYLON||{};(function(){BABYLON.DirectionalLight=function(name,direction,scene){BABYLON.Light.call(this,name,scene);this.position=direction.scale(-1);this.direction=direction;this.diffuse=new BABYLON.Color3(1.0,1.0,1.0);this.specular=new BABYLON.Color3(1.0,1.0,1.0);};BABYLON.DirectionalLight.prototype=Object.create(BABYLON.Light.prototype);BABYLON.DirectionalLight.prototype._computeTransformedPosition=function(){if(this.parent&&this.parent.getWorldMatrix){if(!this._transformedPosition){this._transformedPosition=BABYLON.Vector3.Zero();}BABYLON.Vector3.TransformCoordinatesToRef(this.position,this.parent.getWorldMatrix(),this._transformedPosition);return true;}return false;};BABYLON.DirectionalLight.prototype.transferToEffect=function(effect,directionUniformName){if(this.parent&&this.parent.getWorldMatrix){if(!this._transformedDirection){this._transformedDirection=BABYLON.Vector3.Zero();}BABYLON.Vector3.TransformNormalToRef(this.direction,this.parent.getWorldMatrix(),this._transformedDirection);effect.setFloat4(directionUniformName,this._transformedDirection.x,this._transformedDirection.y,this._transformedDirection.z,1);return;}effect.setFloat4(directionUniformName,this.direction.x,this.direction.y,this.direction.z,1);};BABYLON.DirectionalLight.prototype._getWorldMatrix=function(){if(!this._worldMatrix){this._worldMatrix=BABYLON.Matrix.Identity();}BABYLON.Matrix.TranslationToRef(this.position.x,this.position.y,this.position.z,this._worldMatrix);return this._worldMatrix;};})();var BABYLON=BABYLON||{};(function(){BABYLON.ShadowGenerator=function(mapSize,light){this._light=light;this._scene=light.getScene();light._shadowGenerator=this;this._shadowMap=new BABYLON.RenderTargetTexture(light.name+"_shadowMap",mapSize,this._scene,false);this._shadowMap.wrapU=BABYLON.Texture.CLAMP_ADDRESSMODE;this._shadowMap.wrapV=BABYLON.Texture.CLAMP_ADDRESSMODE;this._shadowMap.renderParticles=false;var that=this;var renderSubMesh=function(subMesh){var mesh=subMesh.getMesh();var world=mesh.getWorldMatrix();var engine=that._scene.getEngine();if(that.isReady(mesh)){engine.enableEffect(that._effect);if(mesh.skeleton&&mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind)&&mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind)){that._effect.setMatrix("world",world);that._effect.setMatrix("viewProjection",that.getTransformMatrix());that._effect.setMatrices("mBones",mesh.skeleton.getTransformMatrices());}else{world.multiplyToRef(that.getTransformMatrix(),that._worldViewProjection);that._effect.setMatrix("worldViewProjection",that._worldViewProjection);}mesh.bindAndDraw(subMesh,that._effect,false);}};this._shadowMap.customRenderFunction=function(opaqueSubMeshes,alphaTestSubMeshes){var index;for(index=0;index=0;};var intersectBoxAASphere=function(boxMin,boxMax,sphereCenter,sphereRadius){if(boxMin.x>sphereCenter.x+sphereRadius)return false;if(sphereCenter.x-sphereRadius>boxMax.x)return false;if(boxMin.y>sphereCenter.y+sphereRadius)return false;if(sphereCenter.y-sphereRadius>boxMax.y)return false;if(boxMin.z>sphereCenter.z+sphereRadius)return false;if(sphereCenter.z-sphereRadius>boxMax.z)return false;return true;};var getLowestRoot=function(a,b,c,maxR){var determinant=b*b-4.0*a*c;var result={root:0,found:false};if(determinant<0)return result;var sqrtD=Math.sqrt(determinant);var r1=(-b-sqrtD)/(2.0*a);var r2=(-b+sqrtD)/(2.0*a);if(r1>r2){var temp=r2;r2=r1;r1=temp;}if(r1>0&&r10&&r2this.velocityWorldLength+max+sphereRadius){return false;}if(!intersectBoxAASphere(vecMin,vecMax,this.basePointWorld,this.velocityWorldLength+max))return false;return true;};BABYLON.Collider.prototype._testTriangle=function(faceIndex,subMesh,p1,p2,p3){var t0;var embeddedInPlane=false;if(!subMesh._trianglePlanes){subMesh._trianglePlanes=[];}if(!subMesh._trianglePlanes[faceIndex]){subMesh._trianglePlanes[faceIndex]=new BABYLON.Plane(0,0,0,0);subMesh._trianglePlanes[faceIndex].copyFromPoints(p1,p2,p3);}var trianglePlane=subMesh._trianglePlanes[faceIndex];if((!subMesh.getMaterial())&&!trianglePlane.isFrontFacingTo(this.normalizedVelocity,0))return;var signedDistToTrianglePlane=trianglePlane.signedDistanceTo(this.basePoint);var normalDotVelocity=BABYLON.Vector3.Dot(trianglePlane.normal,this.velocity);if(normalDotVelocity==0){if(Math.abs(signedDistToTrianglePlane)>=1.0)return;embeddedInPlane=true;t0=0;}else{t0=(-1.0-signedDistToTrianglePlane)/normalDotVelocity;var t1=(1.0-signedDistToTrianglePlane)/normalDotVelocity;if(t0>t1){var temp=t1;t1=t0;t0=temp;}if(t0>1.0||t1<0.0)return;if(t0<0)t0=0;if(t0>1.0)t0=1.0;}this._collisionPoint.copyFromFloats(0,0,0);var found=false;var t=1.0;if(!embeddedInPlane){this.basePoint.subtractToRef(trianglePlane.normal,this._planeIntersectionPoint);this.velocity.scaleToRef(t0,this._tempVector);this._planeIntersectionPoint.addInPlace(this._tempVector);if(this._checkPointInTriangle(this._planeIntersectionPoint,p1,p2,p3,trianglePlane.normal)){found=true;t=t0;this._collisionPoint.copyFrom(this._planeIntersectionPoint);}}if(!found){var velocitySquaredLength=this.velocity.lengthSquared();var a=velocitySquaredLength;this.basePoint.subtractToRef(p1,this._tempVector);var b=2.0*(BABYLON.Vector3.Dot(this.velocity,this._tempVector));var c=this._tempVector.lengthSquared-1.0;var lowestRoot=getLowestRoot(a,b,c,t);if(lowestRoot.found){t=lowestRoot.root;found=true;this._collisionPoint.copyFrom(p1);}this.basePoint.subtractToRef(p2,this._tempVector);b=2.0*(BABYLON.Vector3.Dot(this.velocity,this._tempVector));c=this._tempVector.lengthSquared-1.0;lowestRoot=getLowestRoot(a,b,c,t);if(lowestRoot.found){t=lowestRoot.root;found=true;this._collisionPoint.copyFrom(p2);}this.basePoint.subtractToRef(p3,this._tempVector);b=2.0*(BABYLON.Vector3.Dot(this.velocity,this._tempVector));c=this._tempVector.lengthSquared-1.0;lowestRoot=getLowestRoot(a,b,c,t);if(lowestRoot.found){t=lowestRoot.root;found=true;this._collisionPoint.copyFrom(p3);}p2.subtractToRef(p1,this._edge);p1.subtractToRef(this.basePoint,this._baseToVertex);var edgeSquaredLength=this._edge.lengthSquared();var edgeDotVelocity=BABYLON.Vector3.Dot(this._edge,this.velocity);var edgeDotBaseToVertex=BABYLON.Vector3.Dot(this._edge,this._baseToVertex);a=edgeSquaredLength*(-velocitySquaredLength)+edgeDotVelocity*edgeDotVelocity;b=edgeSquaredLength*(2.0*BABYLON.Vector3.Dot(this.velocity,this._baseToVertex))-2.0*edgeDotVelocity*edgeDotBaseToVertex;c=edgeSquaredLength*(1.0-this._baseToVertex.lengthSquared())+edgeDotBaseToVertex*edgeDotBaseToVertex;lowestRoot=getLowestRoot(a,b,c,t);if(lowestRoot.found){var f=(edgeDotVelocity*lowestRoot.root-edgeDotBaseToVertex)/edgeSquaredLength;if(f>=0.0&&f<=1.0){t=lowestRoot.root;found=true;this._edge.scaleInPlace(f);p1.addToRef(this._edge,this._collisionPoint);}}p3.subtractToRef(p2,this._edge);p2.subtractToRef(this.basePoint,this._baseToVertex);edgeSquaredLength=this._edge.lengthSquared();edgeDotVelocity=BABYLON.Vector3.Dot(this._edge,this.velocity);edgeDotBaseToVertex=BABYLON.Vector3.Dot(this._edge,this._baseToVertex);a=edgeSquaredLength*(-velocitySquaredLength)+edgeDotVelocity*edgeDotVelocity;b=edgeSquaredLength*(2.0*BABYLON.Vector3.Dot(this.velocity,this._baseToVertex))-2.0*edgeDotVelocity*edgeDotBaseToVertex;c=edgeSquaredLength*(1.0-this._baseToVertex.lengthSquared())+edgeDotBaseToVertex*edgeDotBaseToVertex;lowestRoot=getLowestRoot(a,b,c,t);if(lowestRoot.found){var f=(edgeDotVelocity*lowestRoot.root-edgeDotBaseToVertex)/edgeSquaredLength;if(f>=0.0&&f<=1.0){t=lowestRoot.root;found=true;this._edge.scaleInPlace(f);p2.addToRef(this._edge,this._collisionPoint);}}p1.subtractToRef(p3,this._edge);p3.subtractToRef(this.basePoint,this._baseToVertex);edgeSquaredLength=this._edge.lengthSquared();edgeDotVelocity=BABYLON.Vector3.Dot(this._edge,this.velocity);edgeDotBaseToVertex=BABYLON.Vector3.Dot(this._edge,this._baseToVertex);a=edgeSquaredLength*(-velocitySquaredLength)+edgeDotVelocity*edgeDotVelocity;b=edgeSquaredLength*(2.0*BABYLON.Vector3.Dot(this.velocity,this._baseToVertex))-2.0*edgeDotVelocity*edgeDotBaseToVertex;c=edgeSquaredLength*(1.0-this._baseToVertex.lengthSquared())+edgeDotBaseToVertex*edgeDotBaseToVertex;lowestRoot=getLowestRoot(a,b,c,t);if(lowestRoot.found){var f=(edgeDotVelocity*lowestRoot.root-edgeDotBaseToVertex)/edgeSquaredLength;if(f>=0.0&&f<=1.0){t=lowestRoot.root;found=true;this._edge.scaleInPlace(f);p3.addToRef(this._edge,this._collisionPoint);}}}if(found){var distToCollision=t*this.velocity.length();if(!this.collisionFound||distToCollision=0.0){this.rotation.y=(-Math.atan(vDir.z/vDir.x)+Math.PI/2.0);}else{this.rotation.y=(-Math.atan(vDir.z/vDir.x)-Math.PI/2.0);}this.rotation.z=-Math.acos(BABYLON.Vector3.Dot(new BABYLON.Vector3(0,1.0,0),this.upVector));if(isNaN(this.rotation.x))this.rotation.x=0;if(isNaN(this.rotation.y))this.rotation.y=0;if(isNaN(this.rotation.z))this.rotation.z=0;};BABYLON.FreeCamera.prototype.attachControl=function(canvas,noPreventDefault){var previousPosition;var that=this;var engine=this._scene.getEngine();if(this._attachedCanvas){return;}this._attachedCanvas=canvas;if(this._onMouseDown===undefined){this._onMouseDown=function(evt){previousPosition={x:evt.clientX,y:evt.clientY};if(!noPreventDefault){evt.preventDefault();}};this._onMouseUp=function(evt){previousPosition=null;if(!noPreventDefault){evt.preventDefault();}};this._onMouseOut=function(evt){previousPosition=null;that._keys=[];if(!noPreventDefault){evt.preventDefault();}};this._onMouseMove=function(evt){if(!previousPosition&&!engine.isPointerLock){return;}var offsetX;var offsetY;if(!engine.isPointerLock){offsetX=evt.clientX-previousPosition.x;offsetY=evt.clientY-previousPosition.y;}else{offsetX=evt.movementX||evt.mozMovementX||evt.webkitMovementX||evt.msMovementX||0;offsetY=evt.movementY||evt.mozMovementY||evt.webkitMovementY||evt.msMovementY||0;}that.cameraRotation.y+=offsetX/that.angularSensibility;that.cameraRotation.x+=offsetY/that.angularSensibility;previousPosition={x:evt.clientX,y:evt.clientY};if(!noPreventDefault){evt.preventDefault();}};this._onKeyDown=function(evt){if(that.keysUp.indexOf(evt.keyCode)!==-1||that.keysDown.indexOf(evt.keyCode)!==-1||that.keysLeft.indexOf(evt.keyCode)!==-1||that.keysRight.indexOf(evt.keyCode)!==-1){var index=that._keys.indexOf(evt.keyCode);if(index===-1){that._keys.push(evt.keyCode);}if(!noPreventDefault){evt.preventDefault();}}};this._onKeyUp=function(evt){if(that.keysUp.indexOf(evt.keyCode)!==-1||that.keysDown.indexOf(evt.keyCode)!==-1||that.keysLeft.indexOf(evt.keyCode)!==-1||that.keysRight.indexOf(evt.keyCode)!==-1){var index=that._keys.indexOf(evt.keyCode);if(index>=0){that._keys.splice(index,1);}if(!noPreventDefault){evt.preventDefault();}}};this._onLostFocus=function(){that._keys=[];};this._reset=function(){that._keys=[];previousPosition=null;that.cameraDirection=new BABYLON.Vector3(0,0,0);that.cameraRotation=new BABYLON.Vector2(0,0);};}canvas.addEventListener("mousedown",this._onMouseDown,false);canvas.addEventListener("mouseup",this._onMouseUp,false);canvas.addEventListener("mouseout",this._onMouseOut,false);canvas.addEventListener("mousemove",this._onMouseMove,false);window.addEventListener("keydown",this._onKeyDown,false);window.addEventListener("keyup",this._onKeyUp,false);window.addEventListener("blur",this._onLostFocus,false);};BABYLON.FreeCamera.prototype.detachControl=function(canvas){if(this._attachedCanvas!=canvas){return;}canvas.removeEventListener("mousedown",this._onMouseDown);canvas.removeEventListener("mouseup",this._onMouseUp);canvas.removeEventListener("mouseout",this._onMouseOut);canvas.removeEventListener("mousemove",this._onMouseMove);window.removeEventListener("keydown",this._onKeyDown);window.removeEventListener("keyup",this._onKeyUp);window.removeEventListener("blur",this._onLostFocus);this._attachedCanvas=null;if(this._reset){this._reset();}};BABYLON.FreeCamera.prototype._collideWithWorld=function(velocity){this.position.subtractFromFloatsToRef(0,this.ellipsoid.y,0,this._oldPosition);this._collider.radius=this.ellipsoid;this._scene._getNewPosition(this._oldPosition,velocity,this._collider,3,this._newPosition);this._newPosition.subtractToRef(this._oldPosition,this._diffPosition);if(this._diffPosition.length()>BABYLON.Engine.collisionsEpsilon){this.position.addInPlace(this._diffPosition);if(this.onCollide){this.onCollide(this._collider.collidedMesh);}}};BABYLON.FreeCamera.prototype._checkInputs=function(){if(!this._localDirection){this._localDirection=BABYLON.Vector3.Zero();this._transformedDirection=BABYLON.Vector3.Zero();}for(var index=0;index0||Math.abs(this.cameraDirection.y)>0||Math.abs(this.cameraDirection.z)>0;var needToRotate=Math.abs(this.cameraRotation.x)>0||Math.abs(this.cameraRotation.y)>0;if(needToMove){if(this.checkCollisions&&this._scene.collisionsEnabled){this._collideWithWorld(this.cameraDirection);if(this.applyGravity){var oldPosition=this.position;this._collideWithWorld(this._scene.gravity);this._needMoveForGravity=(BABYLON.Vector3.DistanceSquared(oldPosition,this.position)!=0);}}else{this.position.addInPlace(this.cameraDirection);}}if(needToRotate){this.rotation.x+=this.cameraRotation.x;this.rotation.y+=this.cameraRotation.y;if(!this.noRotationConstraint){var limit=(Math.PI/2)*0.95;if(this.rotation.x>limit)this.rotation.x=limit;if(this.rotation.x<-limit)this.rotation.x=-limit;}}if(needToMove){this.cameraDirection.scaleInPlace(this.inertia);}if(needToRotate){this.cameraRotation.scaleInPlace(this.inertia);}};BABYLON.FreeCamera.prototype._getViewMatrix=function(){BABYLON.Vector3.FromFloatsToRef(0,0,1,this._referencePoint);if(!this.lockedTarget){if(this.upVector.x!=0||this.upVector.y!=1.0||this.upVector.z!=0){BABYLON.Matrix.LookAtLHToRef(BABYLON.Vector3.Zero(),this._referencePoint,this.upVector,this._lookAtTemp);BABYLON.Matrix.RotationYawPitchRollToRef(this.rotation.y,this.rotation.x,this.rotation.z,this._cameraRotationMatrix);this._lookAtTemp.multiplyToRef(this._cameraRotationMatrix,this._tempMatrix);this._lookAtTemp.invert();this._tempMatrix.multiplyToRef(this._lookAtTemp,this._cameraRotationMatrix);}else{BABYLON.Matrix.RotationYawPitchRollToRef(this.rotation.y,this.rotation.x,this.rotation.z,this._cameraRotationMatrix);}BABYLON.Vector3.TransformCoordinatesToRef(this._referencePoint,this._cameraRotationMatrix,this._transformedReferencePoint);this.position.addToRef(this._transformedReferencePoint,this._currentTarget);}else{if(this.lockedTarget.position){this._currentTarget.copyFrom(this.lockedTarget.position);}else{this._currentTarget.copyFrom(this.lockedTarget);}}BABYLON.Matrix.LookAtLHToRef(this.position,this._currentTarget,this.upVector,this._viewMatrix);return this._viewMatrix;};})();var BABYLON=BABYLON||{};(function(){BABYLON.TouchCamera=function(name,position,scene){BABYLON.FreeCamera.call(this,name,position,scene);this._offsetX=null;this._offsetY=null;this._pointerCount=0;this._pointerPressed=[];};BABYLON.TouchCamera.prototype=Object.create(BABYLON.FreeCamera.prototype);BABYLON.TouchCamera.prototype.angularSensibility=200000.0;BABYLON.TouchCamera.prototype.moveSensibility=500.0;BABYLON.TouchCamera.prototype.attachControl=function(canvas,noPreventDefault){var previousPosition;var that=this;if(this._attachedCanvas){return;}this._attachedCanvas=canvas;if(this._onPointerDown===undefined){this._onPointerDown=function(evt){if(!noPreventDefault){evt.preventDefault();}that._pointerPressed.push(evt.pointerId);if(that._pointerPressed.length!==1){return;}previousPosition={x:evt.clientX,y:evt.clientY};};this._onPointerUp=function(evt){if(!noPreventDefault){evt.preventDefault();}var index=that._pointerPressed.indexOf(evt.pointerId);if(index===-1){return;}that._pointerPressed.splice(index,1);if(index!=0){return;}previousPosition=null;that._offsetX=null;that._offsetY=null;};this._onPointerMove=function(evt){if(!noPreventDefault){evt.preventDefault();}if(!previousPosition){return;}var index=that._pointerPressed.indexOf(evt.pointerId);if(index!=0){return;}that._offsetX=evt.clientX-previousPosition.x;that._offsetY=-(evt.clientY-previousPosition.y);};this._onLostFocus=function(){that._offsetX=null;that._offsetY=null;};}canvas.addEventListener("pointerdown",this._onPointerDown);canvas.addEventListener("pointerup",this._onPointerUp);canvas.addEventListener("pointerout",this._onPointerUp);canvas.addEventListener("pointermove",this._onPointerMove);window.addEventListener("blur",this._onLostFocus);};BABYLON.TouchCamera.prototype.detachControl=function(canvas){if(this._attachedCanvas!=canvas){return;}canvas.removeEventListener("pointerdown",this._onPointerDown);canvas.removeEventListener("pointerup",this._onPointerUp);canvas.removeEventListener("pointerout",this._onPointerUp);canvas.removeEventListener("pointermove",this._onPointerMove);window.removeEventListener("blur",this._onLostFocus);this._attachedCanvas=null;};BABYLON.TouchCamera.prototype._checkInputs=function(){if(!this._offsetX){return;}this.cameraRotation.y+=this._offsetX/this.angularSensibility;if(this._pointerPressed.length>1){this.cameraRotation.x+=-this._offsetY/this.angularSensibility;}else{var speed=this._computeLocalCameraSpeed();var direction=new BABYLON.Vector3(0,0,speed*this._offsetY/this.moveSensibility);BABYLON.Matrix.RotationYawPitchRollToRef(this.rotation.y,this.rotation.x,0,this._cameraRotationMatrix);this.cameraDirection.addInPlace(BABYLON.Vector3.TransformCoordinates(direction,this._cameraRotationMatrix));}};})();var BABYLON=BABYLON||{};(function(){BABYLON.DeviceOrientationCamera=function(name,position,scene){BABYLON.FreeCamera.call(this,name,position,scene);this._offsetX=null;this._offsetY=null;this._orientationGamma=0;this._orientationBeta=0;this._initialOrientationGamma=0;this._initialOrientationBeta=0;};BABYLON.DeviceOrientationCamera.prototype=Object.create(BABYLON.FreeCamera.prototype);BABYLON.DeviceOrientationCamera.prototype.angularSensibility=10000.0;BABYLON.DeviceOrientationCamera.prototype.moveSensibility=50.0;BABYLON.DeviceOrientationCamera.prototype.attachControl=function(canvas,noPreventDefault){if(this._attachedCanvas){return;}this._attachedCanvas=canvas;var that=this;if(!this._orientationChanged){this._orientationChanged=function(evt){if(!that._initialOrientationGamma){that._initialOrientationGamma=evt.gamma;that._initialOrientationBeta=evt.beta;}that._orientationGamma=evt.gamma;that._orientationBeta=evt.beta;that._offsetY=(that._initialOrientationBeta-that._orientationBeta);that._offsetX=(that._initialOrientationGamma-that._orientationGamma);};}window.addEventListener("deviceorientation",this._orientationChanged);};BABYLON.DeviceOrientationCamera.prototype.detachControl=function(canvas){if(this._attachedCanvas!=canvas){return;}window.removeEventListener("deviceorientation",this._orientationChanged);this._attachedCanvas=null;this._orientationGamma=0;this._orientationBeta=0;this._initialOrientationGamma=0;this._initialOrientationBeta=0;};BABYLON.DeviceOrientationCamera.prototype._checkInputs=function(){if(!this._offsetX){return;}this.cameraRotation.y-=this._offsetX/this.angularSensibility;var speed=this._computeLocalCameraSpeed();var direction=new BABYLON.Vector3(0,0,speed*this._offsetY/this.moveSensibility);BABYLON.Matrix.RotationYawPitchRollToRef(this.rotation.y,this.rotation.x,0,this._cameraRotationMatrix);this.cameraDirection.addInPlace(BABYLON.Vector3.TransformCoordinates(direction,this._cameraRotationMatrix));};})();var BABYLON=BABYLON||{};(function(){var eventPrefix=BABYLON.Tools.GetPointerPrefix();BABYLON.ArcRotateCamera=function(name,alpha,beta,radius,target,scene){BABYLON.Camera.call(this,name,BABYLON.Vector3.Zero(),scene);this.alpha=alpha;this.beta=beta;this.radius=radius;this.target=target;this._keys=[];this.keysUp=[38];this.keysDown=[40];this.keysLeft=[37];this.keysRight=[39];this._viewMatrix=new BABYLON.Matrix();this.getViewMatrix();};BABYLON.ArcRotateCamera.prototype=Object.create(BABYLON.Camera.prototype);BABYLON.ArcRotateCamera.prototype.inertialAlphaOffset=0;BABYLON.ArcRotateCamera.prototype.inertialBetaOffset=0;BABYLON.ArcRotateCamera.prototype.lowerAlphaLimit=null;BABYLON.ArcRotateCamera.prototype.upperAlphaLimit=null;BABYLON.ArcRotateCamera.prototype.lowerBetaLimit=null;BABYLON.ArcRotateCamera.prototype.upperBetaLimit=null;BABYLON.ArcRotateCamera.prototype.lowerRadiusLimit=null;BABYLON.ArcRotateCamera.prototype.upperRadiusLimit=null;BABYLON.ArcRotateCamera.prototype.angularSensibility=1000.0;BABYLON.ArcRotateCamera.prototype.attachControl=function(canvas,noPreventDefault){var previousPosition;var that=this;var pointerId;if(this._attachedCanvas){return;}this._attachedCanvas=canvas;var engine=this._scene.getEngine();if(this._onPointerDown===undefined){this._onPointerDown=function(evt){if(pointerId){return;}pointerId=evt.pointerId;previousPosition={x:evt.clientX,y:evt.clientY};if(!noPreventDefault){evt.preventDefault();}};this._onPointerUp=function(evt){previousPosition=null;pointerId=null;if(!noPreventDefault){evt.preventDefault();}};this._onPointerMove=function(evt){if(!previousPosition){return;}if(pointerId!==evt.pointerId){return;}var offsetX=evt.clientX-previousPosition.x;var offsetY=evt.clientY-previousPosition.y;that.inertialAlphaOffset-=offsetX/that.angularSensibility;that.inertialBetaOffset-=offsetY/that.angularSensibility;previousPosition={x:evt.clientX,y:evt.clientY};if(!noPreventDefault){evt.preventDefault();}};this._onMouseMove=function(evt){if(!engine.isPointerLock){return;}var offsetX=evt.movementX||evt.mozMovementX||evt.webkitMovementX||evt.msMovementX||0;var offsetY=evt.movementY||evt.mozMovementY||evt.webkitMovementY||evt.msMovementY||0;that.inertialAlphaOffset-=offsetX/that.angularSensibility;that.inertialBetaOffset-=offsetY/that.angularSensibility;if(!noPreventDefault){evt.preventDefault();}};this._wheel=function(event){var delta=0;if(event.wheelDelta){delta=event.wheelDelta/120;}else if(event.detail){delta=-event.detail/3;}if(delta)that.radius-=delta;if(event.preventDefault){if(!noPreventDefault){event.preventDefault();}}};this._onKeyDown=function(evt){if(that.keysUp.indexOf(evt.keyCode)!==-1||that.keysDown.indexOf(evt.keyCode)!==-1||that.keysLeft.indexOf(evt.keyCode)!==-1||that.keysRight.indexOf(evt.keyCode)!==-1){var index=that._keys.indexOf(evt.keyCode);if(index===-1){that._keys.push(evt.keyCode);}if(evt.preventDefault){if(!noPreventDefault){evt.preventDefault();}}}};this._onKeyUp=function(evt){if(that.keysUp.indexOf(evt.keyCode)!==-1||that.keysDown.indexOf(evt.keyCode)!==-1||that.keysLeft.indexOf(evt.keyCode)!==-1||that.keysRight.indexOf(evt.keyCode)!==-1){var index=that._keys.indexOf(evt.keyCode);if(index>=0){that._keys.splice(index,1);}if(evt.preventDefault){if(!noPreventDefault){evt.preventDefault();}}}};this._onLostFocus=function(){that._keys=[];pointerId=null;};this._onGestureStart=function(e){if(window.MSGesture===undefined){return;}if(!that._MSGestureHandler){that._MSGestureHandler=new MSGesture();that._MSGestureHandler.target=canvas;}that._MSGestureHandler.addPointer(e.pointerId);};this._onGesture=function(e){that.radius*=e.scale;if(e.preventDefault){if(!noPreventDefault){e.stopPropagation();e.preventDefault();}}};this._reset=function(){that._keys=[];that.inertialAlphaOffset=0;that.inertialBetaOffset=0;previousPosition=null;pointerId=null;};}canvas.addEventListener(eventPrefix+"down",this._onPointerDown,false);canvas.addEventListener(eventPrefix+"up",this._onPointerUp,false);canvas.addEventListener(eventPrefix+"out",this._onPointerUp,false);canvas.addEventListener(eventPrefix+"move",this._onPointerMove,false);canvas.addEventListener("mousemove",this._onMouseMove,false);canvas.addEventListener("MSPointerDown",this._onGestureStart,false);canvas.addEventListener("MSGestureChange",this._onGesture,false);window.addEventListener("keydown",this._onKeyDown,false);window.addEventListener("keyup",this._onKeyUp,false);window.addEventListener('mousewheel',this._wheel,false);window.addEventListener("blur",this._onLostFocus,false);};BABYLON.ArcRotateCamera.prototype.detachControl=function(canvas){if(this._attachedCanvas!=canvas){return;}canvas.removeEventListener(eventPrefix+"down",this._onPointerDown);canvas.removeEventListener(eventPrefix+"up",this._onPointerUp);canvas.removeEventListener(eventPrefix+"out",this._onPointerUp);canvas.removeEventListener(eventPrefix+"move",this._onPointerMove);canvas.removeEventListener("mousemove",this._onMouseMove);canvas.removeEventListener("MSPointerDown",this._onGestureStart);canvas.removeEventListener("MSGestureChange",this._onGesture);window.removeEventListener("keydown",this._onKeyDown);window.removeEventListener("keyup",this._onKeyUp);window.removeEventListener('mousewheel',this._wheel);window.removeEventListener("blur",this._onLostFocus);this._MSGestureHandler=null;this._attachedCanvas=null;if(this._reset){this._reset();}};BABYLON.ArcRotateCamera.prototype._update=function(){for(var index=0;indexthis.upperAlphaLimit){this.alpha=this.upperAlphaLimit;}if(this.lowerBetaLimit&&this.betathis.upperBetaLimit){this.beta=this.upperBetaLimit;}if(this.lowerRadiusLimit&&this.radiusthis.upperRadiusLimit){this.radius=this.upperRadiusLimit;}};BABYLON.ArcRotateCamera.prototype.setPosition=function(position){var radiusv3=position.subtract(this.target.position?this.target.position:this.target);this.radius=radiusv3.length();this.alpha=Math.atan(radiusv3.z/radiusv3.x);this.beta=Math.acos(radiusv3.y/this.radius);};BABYLON.ArcRotateCamera.prototype._getViewMatrix=function(){if(this.beta>Math.PI)this.beta=Math.PI;if(this.beta<=0)this.beta=0.01;var cosa=Math.cos(this.alpha);var sina=Math.sin(this.alpha);var cosb=Math.cos(this.beta);var sinb=Math.sin(this.beta);this.target.addToRef(new BABYLON.Vector3(this.radius*cosa*sinb,this.radius*cosb,this.radius*sina*sinb),this.position);BABYLON.Matrix.LookAtLHToRef(this.position,this.target,this.upVector,this._viewMatrix);return this._viewMatrix;};})();var BABYLON=BABYLON||{};(function(){BABYLON.Scene=function(engine){this._engine=engine;this.autoClear=true;this.clearColor=new BABYLON.Color3(0.2,0.2,0.3);this.ambientColor=new BABYLON.Color3(0,0,0);engine.scenes.push(this);this._totalVertices=0;this._activeVertices=0;this._activeParticles=0;this._lastFrameDuration=0;this._evaluateActiveMeshesDuration=0;this._renderTargetsDuration=0;this._renderDuration=0;this._renderId=0;this._executeWhenReadyTimeoutId=-1;this._toBeDisposed=new BABYLON.Tools.SmartArray(256);this._onReadyCallbacks=[];this._pendingData=[];this._onBeforeRenderCallbacks=[];this.fogMode=BABYLON.Scene.FOGMODE_NONE;this.fogColor=new BABYLON.Color3(0.2,0.2,0.3);this.fogDensity=0.1;this.fogStart=0;this.fogEnd=1000.0;this.lightsEnabled=true;this.lights=[];this.cameras=[];this.activeCamera=null;this.meshes=[];this._activeMeshes=new BABYLON.Tools.SmartArray(256);this._processedMaterials=new BABYLON.Tools.SmartArray(256);this._renderTargets=new BABYLON.Tools.SmartArray(256);this._activeParticleSystems=new BABYLON.Tools.SmartArray(256);this._activeSkeletons=new BABYLON.Tools.SmartArray(32);this._renderingManager=new BABYLON.RenderingManager(this);this.materials=[];this.multiMaterials=[];this.defaultMaterial=new BABYLON.StandardMaterial("default material",this);this.texturesEnabled=true;this.textures=[];this.particlesEnabled=true;this.particleSystems=[];this.spriteManagers=[];this.layers=[];this.skeletons=[];this.lensFlareSystems=[];this.collisionsEnabled=true;this.gravity=new BABYLON.Vector3(0,-9.0,0);this._activeAnimatables=[];this._transformMatrix=BABYLON.Matrix.Zero();this._scaledPosition=BABYLON.Vector3.Zero();this._scaledVelocity=BABYLON.Vector3.Zero();this.postProcessesEnabled=true;this.postProcessManager=new BABYLON.PostProcessManager(this);this.renderTargetsEnabled=true;this.customRenderTargets=[];this.activeCameras=[];};BABYLON.Scene.prototype.getEngine=function(){return this._engine;};BABYLON.Scene.prototype.getTotalVertices=function(){return this._totalVertices;};BABYLON.Scene.prototype.getActiveVertices=function(){return this._activeVertices;};BABYLON.Scene.prototype.getActiveParticles=function(){return this._activeParticles;};BABYLON.Scene.prototype.getLastFrameDuration=function(){return this._lastFrameDuration;};BABYLON.Scene.prototype.getEvaluateActiveMeshesDuration=function(){return this._evaluateActiveMeshesDuration;};BABYLON.Scene.prototype.getRenderTargetsDuration=function(){return this._renderTargetsDuration;};BABYLON.Scene.prototype.getRenderDuration=function(){return this._renderDuration;};BABYLON.Scene.prototype.getParticlesDuration=function(){return this._particlesDuration;};BABYLON.Scene.prototype.getSpritesDuration=function(){return this._spritesDuration;};BABYLON.Scene.prototype.getAnimationRatio=function(){return this._animationRatio;};BABYLON.Scene.prototype.getRenderId=function(){return this._renderId;};BABYLON.Scene.prototype.isReady=function(){if(this._pendingData.length>0){return false;}for(var index=0;index-1){this._onBeforeRenderCallbacks.splice(index,1);}};BABYLON.Scene.prototype._addPendingData=function(data){this._pendingData.push(data);};BABYLON.Scene.prototype._removePendingData=function(data){var index=this._pendingData.indexOf(data);if(index!==-1){this._pendingData.splice(index,1);}};BABYLON.Scene.prototype.getWaitingItemsCount=function(){return this._pendingData.length;};BABYLON.Scene.prototype.executeWhenReady=function(func){this._onReadyCallbacks.push(func);if(this._executeWhenReadyTimeoutId!==-1){return;}var that=this;this._executeWhenReadyTimeoutId=setTimeout(function(){that._checkIsReady();},150);};BABYLON.Scene.prototype._checkIsReady=function(){if(this.isReady()){this._onReadyCallbacks.forEach(function(func){func();});this._onReadyCallbacks=[];this._executeWhenReadyTimeoutId=-1;return;}var that=this;this._executeWhenReadyTimeoutId=setTimeout(function(){that._checkIsReady();},150);};BABYLON.Scene.prototype.beginAnimation=function(target,from,to,loop,speedRatio,onAnimationEnd){if(speedRatio===undefined){speedRatio=1.0;}if(target.animations){this.stopAnimation(target);var animatable=new BABYLON._Animatable(target,from,to,loop,speedRatio,onAnimationEnd);this._activeAnimatables.push(animatable);}if(target.getAnimatables){var animatables=target.getAnimatables();for(var index=0;index=0;index--){if(this.meshes[index].id===id){return this.meshes[index];}}return null;};BABYLON.Scene.prototype.getLastEntryByID=function(id){for(var index=this.meshes.length-1;index>=0;index--){if(this.meshes[index].id===id){return this.meshes[index];}}for(var index=this.cameras.length-1;index>=0;index--){if(this.cameras[index].id===id){return this.cameras[index];}}for(var index=this.lights.length-1;index>=0;index--){if(this.lights[index].id===id){return this.lights[index];}}return null;};BABYLON.Scene.prototype.getMeshByName=function(name){for(var index=0;index=0;index--){if(this.skeletons[index].id===id){return this.skeletons[index];}}return null;};BABYLON.Scene.prototype.getSkeletonById=function(id){for(var index=0;index0&&mesh.isInFrustrum(this._frustumPlanes))){if(mesh._renderId===0){this._activeMeshes.push(mesh);}mesh._renderId=this._renderId;if(mesh.skeleton){this._activeSkeletons.pushNoDuplicate(mesh.skeleton);}var subMeshes=block.subMeshes[meshIndex];for(var subIndex=0;subIndex0&&mesh.isInFrustrum(this._frustumPlanes)){this._activeMeshes.push(mesh);if(mesh.skeleton){this._activeSkeletons.pushNoDuplicate(mesh.skeleton);}for(var subIndex=0;subIndex0){engine.restoreDefaultFramebuffer();}this._renderTargetsDuration=new Date()-beforeRenderTargetDate;this.postProcessManager._prepareFrame();var beforeRenderDate=new Date();if(this.layers.length){engine.setDepthBuffer(false);var layerIndex;var layer;for(layerIndex=0;layerIndex0){var currentRenderId=this._renderId;for(var cameraIndex=0;cameraIndex=maximumRetry){finalPosition.copyFrom(position);return;}collider._initialize(position,velocity,closeDistance);for(var index=0;indexmax.x)max.x=v.x;if(v.y>max.y)max.y=v.y;if(v.z>max.z)max.z=v.z;};var min=new BABYLON.Vector3(Number.MAX_VALUE,Number.MAX_VALUE,Number.MAX_VALUE);var max=new BABYLON.Vector3(-Number.MAX_VALUE,-Number.MAX_VALUE,-Number.MAX_VALUE);for(var index=0;index=pickingInfo.distance)continue;pickingInfo=result;if(fastCheck){break;}}return pickingInfo||new BABYLON.PickingInfo();};BABYLON.Scene.prototype.pick=function(x,y,predicate,fastCheck){var that=this;return this._internalPick(function(world){return that.createPickingRay(x,y,world);},predicate,fastCheck);};BABYLON.Scene.prototype.pickWithRay=function(ray,predicate,fastCheck){var that=this;return this._internalPick(function(world){if(!that._pickWithRayInverseMatrix){that._pickWithRayInverseMatrix=BABYLON.Matrix.Identity();}world.invertToRef(that._pickWithRayInverseMatrix);return BABYLON.Ray.Transform(ray,that._pickWithRayInverseMatrix);},predicate,fastCheck);};BABYLON.Scene.prototype.enablePhysics=function(gravity){if(this._physicsEngine){return true;}if(!BABYLON.PhysicsEngine.IsSupported()){return false;}this._physicsEngine=new BABYLON.PhysicsEngine(gravity);return true;};BABYLON.Scene.prototype.disablePhysicsEngine=function(){if(!this._physicsEngine){return;}this._physicsEngine.dispose();this._physicsEngine=undefined;};BABYLON.Scene.prototype.isPhysicsEnabled=function(){return this._physicsEngine!==undefined;};BABYLON.Scene.prototype.setGravity=function(gravity){if(!this._physicsEngine){return;}this._physicsEngine._setGravity(gravity);};BABYLON.Scene.FOGMODE_NONE=0;BABYLON.Scene.FOGMODE_EXP=1;BABYLON.Scene.FOGMODE_EXP2=2;BABYLON.Scene.FOGMODE_LINEAR=3;})();var BABYLON=BABYLON||{};(function(){BABYLON.VertexBuffer=function(mesh,data,kind,updatable){this._mesh=mesh;this._engine=mesh.getScene().getEngine();this._updatable=updatable;if(updatable){this._buffer=this._engine.createDynamicVertexBuffer(data.length*4);this._engine.updateDynamicVertexBuffer(this._buffer,data);}else{this._buffer=this._engine.createVertexBuffer(data);}this._data=data;this._kind=kind;switch(kind){case BABYLON.VertexBuffer.PositionKind:this._strideSize=3;this._mesh._resetPointsArrayCache();break;case BABYLON.VertexBuffer.NormalKind:this._strideSize=3;break;case BABYLON.VertexBuffer.UVKind:this._strideSize=2;break;case BABYLON.VertexBuffer.UV2Kind:this._strideSize=2;break;case BABYLON.VertexBuffer.ColorKind:this._strideSize=3;break;case BABYLON.VertexBuffer.MatricesIndicesKind:this._strideSize=4;break;case BABYLON.VertexBuffer.MatricesWeightsKind:this._strideSize=4;break;}};BABYLON.VertexBuffer.prototype.isUpdatable=function(){return this._updatable;};BABYLON.VertexBuffer.prototype.getData=function(){return this._data;};BABYLON.VertexBuffer.prototype.getStrideSize=function(){return this._strideSize;};BABYLON.VertexBuffer.prototype.update=function(data){this._engine.updateDynamicVertexBuffer(this._buffer,data);this._data=data;if(this._kind===BABYLON.VertexBuffer.PositionKind){this._mesh._resetPointsArrayCache();}};BABYLON.VertexBuffer.prototype.dispose=function(){this._engine._releaseBuffer(this._buffer);};BABYLON.VertexBuffer.PositionKind="position";BABYLON.VertexBuffer.NormalKind="normal";BABYLON.VertexBuffer.UVKind="uv";BABYLON.VertexBuffer.UV2Kind="uv2";BABYLON.VertexBuffer.ColorKind="color";BABYLON.VertexBuffer.MatricesIndicesKind="matricesIndices";BABYLON.VertexBuffer.MatricesWeightsKind="matricesWeights";})();var BABYLON=BABYLON||{};(function(){BABYLON.Mesh=function(name,scene){this.name=name;this.id=name;this._scene=scene;this._totalVertices=0;this._worldMatrix=BABYLON.Matrix.Identity();scene.meshes.push(this);this.position=new BABYLON.Vector3(0,0,0);this.rotation=new BABYLON.Vector3(0,0,0);this.rotationQuaternion=null;this.scaling=new BABYLON.Vector3(1,1,1);this._pivotMatrix=BABYLON.Matrix.Identity();this._indices=[];this.subMeshes=[];this._renderId=0;this._onBeforeRenderCallbacks=[];this.animations=[];this._positions=null;this._cache={localMatrixUpdated:false,position:BABYLON.Vector3.Zero(),scaling:BABYLON.Vector3.Zero(),rotation:BABYLON.Vector3.Zero(),rotationQuaternion:new BABYLON.Quaternion(0,0,0,0)};this._childrenFlag=false;this._localScaling=BABYLON.Matrix.Zero();this._localRotation=BABYLON.Matrix.Zero();this._localTranslation=BABYLON.Matrix.Zero();this._localBillboard=BABYLON.Matrix.Zero();this._localPivotScaling=BABYLON.Matrix.Zero();this._localPivotScalingRotation=BABYLON.Matrix.Zero();this._localWorld=BABYLON.Matrix.Zero();this._worldMatrix=BABYLON.Matrix.Zero();this._rotateYByPI=BABYLON.Matrix.RotationY(Math.PI);this._collisionsTransformMatrix=BABYLON.Matrix.Zero();this._collisionsScalingMatrix=BABYLON.Matrix.Zero();this._absolutePosition=BABYLON.Vector3.Zero();};BABYLON.Mesh.prototype=Object.create(BABYLON.Node.prototype);BABYLON.Mesh.BILLBOARDMODE_NONE=0;BABYLON.Mesh.BILLBOARDMODE_X=1;BABYLON.Mesh.BILLBOARDMODE_Y=2;BABYLON.Mesh.BILLBOARDMODE_Z=4;BABYLON.Mesh.BILLBOARDMODE_ALL=7;BABYLON.Mesh.prototype.delayLoadState=BABYLON.Engine.DELAYLOADSTATE_NONE;BABYLON.Mesh.prototype.material=null;BABYLON.Mesh.prototype.isVisible=true;BABYLON.Mesh.prototype.isPickable=true;BABYLON.Mesh.prototype.visibility=1.0;BABYLON.Mesh.prototype.billboardMode=BABYLON.Mesh.BILLBOARDMODE_NONE;BABYLON.Mesh.prototype.checkCollisions=false;BABYLON.Mesh.prototype.receiveShadows=false;BABYLON.Mesh.prototype._isDisposed=false;BABYLON.Mesh.prototype.onDispose=null;BABYLON.Mesh.prototype.skeleton=null;BABYLON.Mesh.prototype.renderingGroupId=0;BABYLON.Mesh.prototype.infiniteDistance=false;BABYLON.Mesh.prototype.getBoundingInfo=function(){return this._boundingInfo;};BABYLON.Mesh.prototype.getScene=function(){return this._scene;};BABYLON.Mesh.prototype.getWorldMatrix=function(){if(this._currentRenderId!==this._scene.getRenderId()){this.computeWorldMatrix();}return this._worldMatrix;};BABYLON.Mesh.prototype.getAbsolutePosition=function(){return this._absolutePosition;};BABYLON.Mesh.prototype.getTotalVertices=function(){return this._totalVertices;};BABYLON.Mesh.prototype.getVerticesData=function(kind){return this._vertexBuffers[kind].getData();};BABYLON.Mesh.prototype.isVerticesDataPresent=function(kind){if(!this._vertexBuffers&&this._delayInfo){return this._delayInfo.indexOf(kind)!==-1;}return this._vertexBuffers[kind]!==undefined;};BABYLON.Mesh.prototype.getTotalIndices=function(){return this._indices.length;};BABYLON.Mesh.prototype.getIndices=function(){return this._indices;};BABYLON.Mesh.prototype.getVertexStrideSize=function(){return this._vertexStrideSize;};BABYLON.Mesh.prototype.setPivotMatrix=function(matrix){this._pivotMatrix=matrix;this._cache.pivotMatrixUpdated=true;};BABYLON.Mesh.prototype.getPivotMatrix=function(){return this._localMatrix;};BABYLON.Mesh.prototype.isSynchronized=function(){if(this.billboardMode!==BABYLON.Mesh.BILLBOARDMODE_NONE)return false;if(this._cache.pivotMatrixUpdated){return false;}if(this.infiniteDistance){return false;}if(!this._cache.position.equals(this.position))return false;if(this.rotationQuaternion){if(!this._cache.rotationQuaternion.equals(this.rotationQuaternion))return false;}else{if(!this._cache.rotation.equals(this.rotation))return false;}if(!this._cache.scaling.equals(this.scaling))return false;if(this.parent)return!this.parent._needToSynchonizeChildren();return true;};BABYLON.Mesh.prototype.isReady=function(){return this._isReady;};BABYLON.Mesh.prototype.isAnimated=function(){return this._animationStarted;};BABYLON.Mesh.prototype.isDisposed=function(){return this._isDisposed;};BABYLON.Mesh.prototype.markAsDirty=function(property){if(property==="rotation"){this.rotationQuaternion=null;}this._childrenFlag=true;};BABYLON.Mesh.prototype.refreshBoundingInfo=function(){var data=this.getVerticesData(BABYLON.VertexBuffer.PositionKind);if(!data){return;}var extend=BABYLON.Tools.ExtractMinAndMax(data,0,this._totalVertices);this._boundingInfo=new BABYLON.BoundingInfo(extend.minimum,extend.maximum);for(var index=0;index-1){this._onBeforeRenderCallbacks.splice(index,1);}};BABYLON.Mesh.prototype.render=function(subMesh){if(!this._vertexBuffers||!this._indexBuffer){return;}for(var callbackIndex=0;callbackIndex1&&!subMesh._checkCollision(collider))continue;this._collideForSubMesh(subMesh,transformMatrix,collider);}};BABYLON.Mesh.prototype._checkCollision=function(collider){if(!this._boundingInfo._checkCollision(collider))return;BABYLON.Matrix.ScalingToRef(1.0/collider.radius.x,1.0/collider.radius.y,1.0/collider.radius.z,this._collisionsScalingMatrix);this._worldMatrix.multiplyToRef(this._collisionsScalingMatrix,this._collisionsTransformMatrix);this._processCollisionsForSubModels(collider,this._collisionsTransformMatrix);};BABYLON.Mesh.prototype.intersectsMesh=function(mesh,precise){if(!this._boundingInfo||!mesh._boundingInfo){return false;}return this._boundingInfo.intersects(mesh._boundingInfo,precise);};BABYLON.Mesh.prototype.intersectsPoint=function(point){if(!this._boundingInfo){return false;}return this._boundingInfo.intersectsPoint(point);};BABYLON.Mesh.prototype.intersects=function(ray,fastCheck){var pickingInfo=new BABYLON.PickingInfo();if(!this._boundingInfo||!ray.intersectsSphere(this._boundingInfo.boundingSphere)||!ray.intersectsBox(this._boundingInfo.boundingBox)){return pickingInfo;}this._generatePointsArray();var distance=Number.MAX_VALUE;for(var index=0;index1&&!subMesh.canIntersects(ray))continue;var currentDistance=subMesh.intersects(ray,this._positions,this._indices,fastCheck);if(currentDistance>0){if(fastCheck||currentDistance=0&&distance0){var verticesCount=positions.length/3;for(var firstIndex=verticesCount-2*(totalYRotationSteps+1);(firstIndex+totalYRotationSteps+2)0){if(fastCheck||currentDistance0&&distancemaxVertexIndex)maxVertexIndex=vertexIndex;}return new BABYLON.SubMesh(materialIndex,minVertexIndex,maxVertexIndex-minVertexIndex,startIndex,indexCount,mesh);};})();var BABYLON=BABYLON||{};(function(){BABYLON.BaseTexture=function(url,scene){this._scene=scene;this._scene.textures.push(this);};BABYLON.BaseTexture.prototype.delayLoadState=BABYLON.Engine.DELAYLOADSTATE_NONE;BABYLON.BaseTexture.prototype.hasAlpha=false;BABYLON.BaseTexture.prototype.level=1;BABYLON.BaseTexture.prototype._texture=null;BABYLON.BaseTexture.prototype.onDispose=null;BABYLON.BaseTexture.prototype.getInternalTexture=function(){return this._texture;};BABYLON.BaseTexture.prototype.isReady=function(){if(this.delayLoadState===BABYLON.Engine.DELAYLOADSTATE_NOTLOADED){return true;}if(this._texture){return this._texture.isReady;}return false;};BABYLON.BaseTexture.prototype.getSize=function(){if(this._texture._width){return{width:this._texture._width,height:this._texture._height};}if(this._texture._size){return{width:this._texture._size,height:this._texture._size};}return{width:0,height:0};};BABYLON.BaseTexture.prototype.getBaseSize=function(){if(!this.isReady())return{width:0,height:0};if(this._texture._size){return{width:this._texture._size,height:this._texture._size};}return{width:this._texture._baseWidth,height:this._texture._baseHeight};};BABYLON.BaseTexture.prototype._getFromCache=function(url,noMipmap){var texturesCache=this._scene.getEngine().getLoadedTexturesCache();for(var index=0;index=0){this._scene.textures.splice(index,1);}if(this._texture===undefined){return;}this.releaseInternalTexture();if(this.onDispose){this.onDispose();}};})();var BABYLON=BABYLON||{};(function(){BABYLON.RenderingGroup=function(index,scene){this.index=index;this._scene=scene;this._opaqueSubMeshes=new BABYLON.Tools.SmartArray(256);this._transparentSubMeshes=new BABYLON.Tools.SmartArray(256);this._alphaTestSubMeshes=new BABYLON.Tools.SmartArray(256);};BABYLON.RenderingGroup.prototype.render=function(customRenderFunction,beforeTransparents){if(customRenderFunction){customRenderFunction(this._opaqueSubMeshes,this._alphaTestSubMeshes,this._transparentSubMeshes,beforeTransparents);return true;}if(this._opaqueSubMeshes.length===0&&this._alphaTestSubMeshes.length===0&&this._transparentSubMeshes===0){return false;}var engine=this._scene.getEngine();var subIndex;var submesh;for(subIndex=0;subIndexb._distanceToCamera){return-1;}return 0;});engine.setAlphaMode(BABYLON.Engine.ALPHA_COMBINE);for(subIndex=0;subIndex0||mesh.visibility<1.0){this._transparentSubMeshes.push(subMesh);}}else if(material.needAlphaTesting()){this._alphaTestSubMeshes.push(subMesh);}else{this._opaqueSubMeshes.push(subMesh);}};})();var BABYLON=BABYLON||{};(function(){BABYLON.RenderingManager=function(scene){this._scene=scene;this._renderingGroups=[];};BABYLON.RenderingManager.prototype._renderParticles=function(index,activeMeshes){if(this._scene._activeParticleSystems.length===0){return;}var beforeParticlesDate=new Date();for(var particleIndex=0;particleIndex 1.0 || uv.y < 0. || uv.y > 1.0)\n {\n return 1.0;\n }\n\n float shadow = unpack(texture2D(shadowSampler, uv));\n\n if (depth.z > shadow)\n {\n return 0.;\n }\n return 1.;\n}\n\n// Thanks to http://devmaster.net/\nfloat ChebychevInequality(vec2 moments, float t)\n{\n if (t <= moments.x)\n {\n return 1.0;\n }\n\n float variance = moments.y - (moments.x * moments.x);\n variance = max(variance, 0.);\n\n float d = t - moments.x;\n return variance / (variance + d * d);\n}\n\nfloat computeShadowWithVSM(vec4 vPositionFromLight, sampler2D shadowSampler)\n{\n vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;\n vec2 uv = 0.5 * depth.xy + vec2(0.5, 0.5);\n\n if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0)\n {\n return 1.0;\n }\n\n vec4 texel = texture2D(shadowSampler, uv);\n\n vec2 moments = vec2(unpackHalf(texel.xy), unpackHalf(texel.zw));\n return clamp(1.3 - ChebychevInequality(moments, depth.z), 0., 1.0);\n}\n#endif\n\n// Bump\n#ifdef BUMP\n#extension GL_OES_standard_derivatives : enable\nvarying vec2 vBumpUV;\nuniform vec2 vBumpInfos;\nuniform sampler2D bumpSampler;\n\n// Thanks to http://www.thetenthplanet.de/archives/1180\nmat3 cotangent_frame(vec3 normal, vec3 p, vec2 uv)\n{\n // get edge vectors of the pixel triangle\n vec3 dp1 = dFdx(p);\n vec3 dp2 = dFdy(p);\n vec2 duv1 = dFdx(uv);\n vec2 duv2 = dFdy(uv);\n\n // solve the linear system\n vec3 dp2perp = cross(dp2, normal);\n vec3 dp1perp = cross(normal, dp1);\n vec3 tangent = dp2perp * duv1.x + dp1perp * duv2.x;\n vec3 binormal = dp2perp * duv1.y + dp1perp * duv2.y;\n\n // construct a scale-invariant frame \n float invmax = inversesqrt(max(dot(tangent, tangent), dot(binormal, binormal)));\n return mat3(tangent * invmax, binormal * invmax, normal);\n}\n\nvec3 perturbNormal(vec3 viewDir)\n{\n vec3 map = texture2D(bumpSampler, vBumpUV).xyz * vBumpInfos.y;\n map = map * 255. / 127. - 128. / 127.;\n mat3 TBN = cotangent_frame(vNormalW, -viewDir, vBumpUV);\n return normalize(TBN * map);\n}\n#endif\n\n#ifdef CLIPPLANE\nvarying float fClipDistance;\n#endif\n\n// Fog\n#ifdef FOG\n\n#define FOGMODE_NONE 0.\n#define FOGMODE_EXP 1.\n#define FOGMODE_EXP2 2.\n#define FOGMODE_LINEAR 3.\n#define E 2.71828\n\nuniform vec4 vFogInfos;\nuniform vec3 vFogColor;\nvarying float fFogDistance;\n\nfloat CalcFogFactor()\n{\n float fogCoeff = 1.0;\n float fogStart = vFogInfos.y;\n float fogEnd = vFogInfos.z;\n float fogDensity = vFogInfos.w;\n\n if (FOGMODE_LINEAR == vFogInfos.x)\n {\n fogCoeff = (fogEnd - fFogDistance) / (fogEnd - fogStart);\n }\n else if (FOGMODE_EXP == vFogInfos.x)\n {\n fogCoeff = 1.0 / pow(E, fFogDistance * fogDensity);\n }\n else if (FOGMODE_EXP2 == vFogInfos.x)\n {\n fogCoeff = 1.0 / pow(E, fFogDistance * fFogDistance * fogDensity * fogDensity);\n }\n\n return clamp(fogCoeff, 0.0, 1.0);\n}\n#endif\n\n// Light Computing\nstruct lightingInfo\n{\n vec3 diffuse;\n vec3 specular;\n};\n\nlightingInfo computeLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, vec3 specularColor) {\n lightingInfo result;\n\n vec3 lightVectorW;\n if (lightData.w == 0.)\n {\n lightVectorW = normalize(lightData.xyz - vPositionW);\n }\n else\n {\n lightVectorW = normalize(-lightData.xyz);\n }\n\n // diffuse\n float ndl = max(0., dot(vNormal, lightVectorW));\n\n // Specular\n vec3 angleW = normalize(viewDirectionW + lightVectorW);\n float specComp = max(0., dot(vNormal, angleW));\n specComp = pow(specComp, vSpecularColor.a);\n\n result.diffuse = ndl * diffuseColor;\n result.specular = specComp * specularColor;\n\n return result;\n}\n\nlightingInfo computeSpotLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec4 lightDirection, vec3 diffuseColor, vec3 specularColor) {\n lightingInfo result;\n\n vec3 lightVectorW = normalize(lightData.xyz - vPositionW);\n\n // diffuse\n float cosAngle = max(0., dot(-lightDirection.xyz, lightVectorW));\n float spotAtten = 0.0;\n\n if (cosAngle >= lightDirection.w)\n {\n cosAngle = max(0., pow(cosAngle, lightData.w));\n spotAtten = max(0., (cosAngle - lightDirection.w) / (1. - cosAngle));\n\n // Diffuse\n float ndl = max(0., dot(vNormal, -lightDirection.xyz));\n\n // Specular\n vec3 angleW = normalize(viewDirectionW - lightDirection.xyz);\n float specComp = max(0., dot(vNormal, angleW));\n specComp = pow(specComp, vSpecularColor.a);\n\n result.diffuse = ndl * spotAtten * diffuseColor;\n result.specular = specComp * specularColor * spotAtten;\n\n return result;\n }\n\n result.diffuse = vec3(0.);\n result.specular = vec3(0.);\n\n return result;\n}\n\nlightingInfo computeHemisphericLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, vec3 specularColor, vec3 groundColor) {\n lightingInfo result;\n\n // Diffuse\n float ndl = dot(vNormal, lightData.xyz) * 0.5 + 0.5;\n\n // Specular\n vec3 angleW = normalize(viewDirectionW + lightData.xyz);\n float specComp = max(0., dot(vNormal, angleW));\n specComp = pow(specComp, vSpecularColor.a);\n\n result.diffuse = mix(groundColor, diffuseColor, ndl);\n result.specular = specComp * specularColor;\n\n return result;\n}\n\nvoid main(void) {\n // Clip plane\n#ifdef CLIPPLANE\n if (fClipDistance > 0.0)\n discard;\n#endif\n\n vec3 viewDirectionW = normalize(vEyePosition - vPositionW);\n\n // Base color\n vec4 baseColor = vec4(1., 1., 1., 1.);\n vec3 diffuseColor = vDiffuseColor.rgb;\n\n#ifdef VERTEXCOLOR\n diffuseColor *= vColor;\n#endif\n\n#ifdef DIFFUSE\n baseColor = texture2D(diffuseSampler, vDiffuseUV);\n\n#ifdef ALPHATEST\n if (baseColor.a < 0.4)\n discard;\n#endif\n\n baseColor.rgb *= vDiffuseInfos.y;\n#endif\n\n // Bump\n vec3 normalW = vNormalW;\n\n#ifdef BUMP\n normalW = perturbNormal(viewDirectionW);\n#endif\n\n // Ambient color\n vec3 baseAmbientColor = vec3(1., 1., 1.);\n\n#ifdef AMBIENT\n baseAmbientColor = texture2D(ambientSampler, vAmbientUV).rgb * vAmbientInfos.y;\n#endif\n\n // Lighting\n vec3 diffuseBase = vec3(0., 0., 0.);\n vec3 specularBase = vec3(0., 0., 0.);\n float shadow = 1.;\n\n#ifdef LIGHT0\n#ifdef SPOTLIGHT0\n lightingInfo info = computeSpotLighting(viewDirectionW, normalW, vLightData0, vLightDirection0, vLightDiffuse0, vLightSpecular0);\n#endif\n#ifdef HEMILIGHT0\n lightingInfo info = computeHemisphericLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0, vLightSpecular0, vLightGround0);\n#endif\n#ifdef POINTDIRLIGHT0\n lightingInfo info = computeLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0, vLightSpecular0);\n#endif\n#ifdef SHADOW0\n#ifdef SHADOWVSM0\n shadow = computeShadowWithVSM(vPositionFromLight0, shadowSampler0);\n#else\n shadow = computeShadow(vPositionFromLight0, shadowSampler0);\n#endif\n#else\n shadow = 1.;\n#endif\n diffuseBase += info.diffuse * shadow;\n specularBase += info.specular * shadow;\n#endif\n\n#ifdef LIGHT1\n#ifdef SPOTLIGHT1\n info = computeSpotLighting(viewDirectionW, normalW, vLightData1, vLightDirection1, vLightDiffuse1, vLightSpecular1);\n#endif\n#ifdef HEMILIGHT1\n info = computeHemisphericLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1, vLightSpecular1, vLightGround1);\n#endif\n#ifdef POINTDIRLIGHT1\n info = computeLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1, vLightSpecular1);\n#endif\n#ifdef SHADOW1\n#ifdef SHADOWVSM1\n shadow = computeShadowWithVSM(vPositionFromLight1, shadowSampler1);\n#else\n shadow = computeShadow(vPositionFromLight1, shadowSampler1);\n#endif\n#else\n shadow = 1.;\n#endif\n diffuseBase += info.diffuse * shadow;\n specularBase += info.specular * shadow;\n#endif\n\n#ifdef LIGHT2\n#ifdef SPOTLIGHT2\n info = computeSpotLighting(viewDirectionW, normalW, vLightData2, vLightDirection2, vLightDiffuse2, vLightSpecular2);\n#endif\n#ifdef HEMILIGHT2\n info = computeHemisphericLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2, vLightSpecular2, vLightGround2);\n#endif\n#ifdef POINTDIRLIGHT2\n info = computeLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2, vLightSpecular2);\n#endif\n#ifdef SHADOW2\n#ifdef SHADOWVSM2\n shadow = computeShadowWithVSM(vPositionFromLight2, shadowSampler2);\n#else\n shadow = computeShadow(vPositionFromLight2, shadowSampler2);\n#endif \n#else\n shadow = 1.;\n#endif\n diffuseBase += info.diffuse * shadow;\n specularBase += info.specular * shadow;\n#endif\n\n#ifdef LIGHT3\n#ifdef SPOTLIGHT3\n info = computeSpotLighting(viewDirectionW, normalW, vLightData3, vLightDirection3, vLightDiffuse3, vLightSpecular3);\n#endif\n#ifdef HEMILIGHT3\n info = computeHemisphericLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3, vLightSpecular3, vLightGround3);\n#endif\n#ifdef POINTDIRLIGHT3\n info = computeLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3, vLightSpecular3);\n#endif\n#ifdef SHADOW3\n#ifdef SHADOWVSM3\n shadow = computeShadowWithVSM(vPositionFromLight3, shadowSampler3);\n#else\n shadow = computeShadow(vPositionFromLight3, shadowSampler3);\n#endif \n#else\n shadow = 1.;\n#endif\n diffuseBase += info.diffuse * shadow;\n specularBase += info.specular * shadow;\n#endif\n\n // Reflection\n vec3 reflectionColor = vec3(0., 0., 0.);\n\n#ifdef REFLECTION\n vec3 vReflectionUVW = computeReflectionCoords(vReflectionInfos.x, vec4(vPositionW, 1.0), normalW);\n\n if (vReflectionInfos.z != 0.0)\n {\n reflectionColor = textureCube(reflectionCubeSampler, vReflectionUVW).rgb * vReflectionInfos.y;\n }\n else\n {\n vec2 coords = vReflectionUVW.xy;\n\n if (vReflectionInfos.x == MAP_PROJECTION)\n {\n coords /= vReflectionUVW.z;\n }\n\n coords.y = 1.0 - coords.y;\n\n reflectionColor = texture2D(reflection2DSampler, coords).rgb * vReflectionInfos.y;\n }\n#endif\n\n // Alpha\n float alpha = vDiffuseColor.a;\n\n#ifdef OPACITY\n vec4 opacityMap = texture2D(opacitySampler, vOpacityUV);\n opacityMap.rgb = opacityMap.rgb * vec3(0.3, 0.59, 0.11) * opacityMap.a;\n alpha *= (opacityMap.x + opacityMap.y + opacityMap.z)* vOpacityInfos.y;\n#endif\n\n // Emissive\n vec3 emissiveColor = vEmissiveColor;\n#ifdef EMISSIVE\n emissiveColor += texture2D(emissiveSampler, vEmissiveUV).rgb * vEmissiveInfos.y;\n#endif\n\n // Specular map\n vec3 specularColor = vSpecularColor.rgb;\n#ifdef SPECULAR\n specularColor = texture2D(specularSampler, vSpecularUV).rgb * vSpecularInfos.y;\n#endif\n\n // Composition\n vec3 finalDiffuse = clamp(diffuseBase * diffuseColor + emissiveColor + vAmbientColor, 0.0, 1.0) * baseColor.rgb;\n vec3 finalSpecular = specularBase * specularColor;\n\n vec4 color = vec4(finalDiffuse * baseAmbientColor + finalSpecular + reflectionColor, alpha);\n\n#ifdef FOG\n float fog = CalcFogFactor();\n color.rgb = fog * color.rgb + (1.0 - fog) * vFogColor;\n#endif\n\n gl_FragColor = color;\n}", +defaultVertexShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n// Attributes\nattribute vec3 position;\nattribute vec3 normal;\n#ifdef UV1\nattribute vec2 uv;\n#endif\n#ifdef UV2\nattribute vec2 uv2;\n#endif\n#ifdef VERTEXCOLOR\nattribute vec3 color;\n#endif\n#ifdef BONES\nattribute vec4 matricesIndices;\nattribute vec4 matricesWeights;\n#endif\n\n// Uniforms\nuniform mat4 world;\nuniform mat4 view;\nuniform mat4 viewProjection;\n\n#ifdef DIFFUSE\nvarying vec2 vDiffuseUV;\nuniform mat4 diffuseMatrix;\nuniform vec2 vDiffuseInfos;\n#endif\n\n#ifdef AMBIENT\nvarying vec2 vAmbientUV;\nuniform mat4 ambientMatrix;\nuniform vec2 vAmbientInfos;\n#endif\n\n#ifdef OPACITY\nvarying vec2 vOpacityUV;\nuniform mat4 opacityMatrix;\nuniform vec2 vOpacityInfos;\n#endif\n\n#ifdef EMISSIVE\nvarying vec2 vEmissiveUV;\nuniform vec2 vEmissiveInfos;\nuniform mat4 emissiveMatrix;\n#endif\n\n#ifdef SPECULAR\nvarying vec2 vSpecularUV;\nuniform vec2 vSpecularInfos;\nuniform mat4 specularMatrix;\n#endif\n\n#ifdef BUMP\nvarying vec2 vBumpUV;\nuniform vec2 vBumpInfos;\nuniform mat4 bumpMatrix;\n#endif\n\n#ifdef BONES\nuniform mat4 mBones[BonesPerMesh];\n#endif\n\n// Output\nvarying vec3 vPositionW;\nvarying vec3 vNormalW;\n\n#ifdef VERTEXCOLOR\nvarying vec3 vColor;\n#endif\n\n#ifdef CLIPPLANE\nuniform vec4 vClipPlane;\nvarying float fClipDistance;\n#endif\n\n#ifdef FOG\nvarying float fFogDistance;\n#endif\n\n#ifdef SHADOWS\n#ifdef LIGHT0\nuniform mat4 lightMatrix0;\nvarying vec4 vPositionFromLight0;\n#endif\n#ifdef LIGHT1\nuniform mat4 lightMatrix1;\nvarying vec4 vPositionFromLight1;\n#endif\n#ifdef LIGHT2\nuniform mat4 lightMatrix2;\nvarying vec4 vPositionFromLight2;\n#endif\n#ifdef LIGHT3\nuniform mat4 lightMatrix3;\nvarying vec4 vPositionFromLight3;\n#endif\n#endif\n\n#ifdef REFLECTION\nvarying vec3 vPositionUVW;\n#endif\n\nvoid main(void) {\n mat4 finalWorld;\n\n#ifdef REFLECTION\n vPositionUVW = position;\n#endif \n\n#ifdef BONES\n mat4 m0 = mBones[int(matricesIndices.x)] * matricesWeights.x;\n mat4 m1 = mBones[int(matricesIndices.y)] * matricesWeights.y;\n mat4 m2 = mBones[int(matricesIndices.z)] * matricesWeights.z;\n\n#ifdef BONES4\n mat4 m3 = mBones[int(matricesIndices.w)] * matricesWeights.w;\n finalWorld = world * (m0 + m1 + m2 + m3);\n#else\n finalWorld = world * (m0 + m1 + m2);\n#endif \n\n#else\n finalWorld = world;\n#endif\n gl_Position = viewProjection * finalWorld * vec4(position, 1.0);\n\n vec4 worldPos = finalWorld * vec4(position, 1.0);\n vPositionW = vec3(worldPos);\n vNormalW = normalize(vec3(finalWorld * vec4(normal, 0.0)));\n\n // Texture coordinates\n#ifndef UV1\n vec2 uv = vec2(0., 0.);\n#endif\n#ifndef UV2\n vec2 uv2 = vec2(0., 0.);\n#endif\n\n#ifdef DIFFUSE\n if (vDiffuseInfos.x == 0.)\n {\n vDiffuseUV = vec2(diffuseMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vDiffuseUV = vec2(diffuseMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n#ifdef AMBIENT\n if (vAmbientInfos.x == 0.)\n {\n vAmbientUV = vec2(ambientMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vAmbientUV = vec2(ambientMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n#ifdef OPACITY\n if (vOpacityInfos.x == 0.)\n {\n vOpacityUV = vec2(opacityMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vOpacityUV = vec2(opacityMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n#ifdef EMISSIVE\n if (vEmissiveInfos.x == 0.)\n {\n vEmissiveUV = vec2(emissiveMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vEmissiveUV = vec2(emissiveMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n#ifdef SPECULAR\n if (vSpecularInfos.x == 0.)\n {\n vSpecularUV = vec2(specularMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vSpecularUV = vec2(specularMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n#ifdef BUMP\n if (vBumpInfos.x == 0.)\n {\n vBumpUV = vec2(bumpMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vBumpUV = vec2(bumpMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n // Clip plane\n#ifdef CLIPPLANE\n fClipDistance = dot(worldPos, vClipPlane);\n#endif\n\n // Fog\n#ifdef FOG\n fFogDistance = (view * worldPos).z;\n#endif\n\n // Shadows\n#ifdef SHADOWS\n#ifdef LIGHT0\n vPositionFromLight0 = lightMatrix0 * vec4(position, 1.0);\n#endif\n#ifdef LIGHT1\n vPositionFromLight1 = lightMatrix1 * vec4(position, 1.0);\n#endif\n#ifdef LIGHT2\n vPositionFromLight2 = lightMatrix2 * vec4(position, 1.0);\n#endif\n#ifdef LIGHT3\n vPositionFromLight3 = lightMatrix3 * vec4(position, 1.0);\n#endif\n#endif\n\n // Vertex color\n#ifdef VERTEXCOLOR\n vColor = color;\n#endif\n}", +fxaaPixelShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n#define FXAA_REDUCE_MIN (1.0/128.0)\n#define FXAA_REDUCE_MUL (1.0/8.0)\n#define FXAA_SPAN_MAX 8.0\n\nvarying vec2 vUV;\nuniform sampler2D textureSampler;\nuniform vec2 texelSize;\n\nvoid main(){\n vec2 localTexelSize = texelSize;\n vec3 rgbNW = texture2D(textureSampler, (vUV + vec2(-1.0, -1.0) * localTexelSize)).xyz;\n vec3 rgbNE = texture2D(textureSampler, (vUV + vec2(1.0, -1.0) * localTexelSize)).xyz;\n vec3 rgbSW = texture2D(textureSampler, (vUV + vec2(-1.0, 1.0) * localTexelSize)).xyz;\n vec3 rgbSE = texture2D(textureSampler, (vUV + vec2(1.0, 1.0) * localTexelSize)).xyz;\n vec3 rgbM = texture2D(textureSampler, vUV ).xyz;\n vec3 luma = vec3(0.299, 0.587, 0.114);\n float lumaNW = dot(rgbNW, luma);\n float lumaNE = dot(rgbNE, luma);\n float lumaSW = dot(rgbSW, luma);\n float lumaSE = dot(rgbSE, luma);\n float lumaM = dot(rgbM, luma);\n float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));\n float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));\n\n vec2 dir = vec2(-((lumaNW + lumaNE) - (lumaSW + lumaSE)), ((lumaNW + lumaSW) - (lumaNE + lumaSE)));\n\n float dirReduce = max(\n (lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL),\n FXAA_REDUCE_MIN);\n\n float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce);\n dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX),\n max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),\n dir * rcpDirMin)) * localTexelSize;\n\n vec3 rgbA = 0.5 * (\n texture2D(textureSampler, vUV + dir * (1.0 / 3.0 - 0.5)).xyz +\n texture2D(textureSampler, vUV + dir * (2.0 / 3.0 - 0.5)).xyz);\n\n vec3 rgbB = rgbA * 0.5 + 0.25 * (\n texture2D(textureSampler, vUV + dir * -0.5).xyz +\n texture2D(textureSampler, vUV + dir * 0.5).xyz);\n float lumaB = dot(rgbB, luma);\n if ((lumaB < lumaMin) || (lumaB > lumaMax)) {\n gl_FragColor = vec4(rgbA, 1.0);\n }\n else {\n gl_FragColor = vec4(rgbB, 1.0);\n }\n}", +iedefaultPixelShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n#define MAP_PROJECTION 4.\n\n// Constants\nuniform vec3 vEyePosition;\nuniform vec3 vAmbientColor;\nuniform vec4 vDiffuseColor;\nuniform vec4 vSpecularColor;\nuniform vec3 vEmissiveColor;\n\n// Input\nvarying vec3 vPositionW;\nvarying vec3 vNormalW;\n\n#ifdef VERTEXCOLOR\nvarying vec3 vColor;\n#endif\n\n// Lights\n#ifdef LIGHT0\nuniform vec4 vLightData0;\nuniform vec3 vLightDiffuse0;\nuniform vec3 vLightSpecular0;\n#ifdef SHADOW0\nvarying vec4 vPositionFromLight0;\nuniform sampler2D shadowSampler0;\n#endif\n#ifdef SPOTLIGHT0\nuniform vec4 vLightDirection0;\n#endif\n#ifdef HEMILIGHT0\nuniform vec3 vLightGround0;\n#endif\n#endif\n\n#ifdef LIGHT1\nuniform vec4 vLightData1;\nuniform vec3 vLightDiffuse1;\nuniform vec3 vLightSpecular1;\n#ifdef SHADOW1\nvarying vec4 vPositionFromLight1;\nuniform sampler2D shadowSampler1;\n#endif\n#ifdef SPOTLIGHT1\nuniform vec4 vLightDirection1;\n#endif\n#ifdef HEMILIGHT1\nuniform vec3 vLightGround1;\n#endif\n#endif\n\n#ifdef LIGHT2\nuniform vec4 vLightData2;\nuniform vec3 vLightDiffuse2;\nuniform vec3 vLightSpecular2;\n#ifdef SHADOW2\nvarying vec4 vPositionFromLight2;\nuniform sampler2D shadowSampler2;\n#endif\n#ifdef SPOTLIGHT2\nuniform vec4 vLightDirection2;\n#endif\n#ifdef HEMILIGHT2\nuniform vec3 vLightGround2;\n#endif\n#endif\n\n#ifdef LIGHT3\nuniform vec4 vLightData3;\nuniform vec3 vLightDiffuse3;\nuniform vec3 vLightSpecular3;\n#ifdef SHADOW3\nvarying vec4 vPositionFromLight3;\nuniform sampler2D shadowSampler3;\n#endif\n#ifdef SPOTLIGHT3\nuniform vec4 vLightDirection3;\n#endif\n#ifdef HEMILIGHT3\nuniform vec3 vLightGround3;\n#endif\n#endif\n\n// Samplers\n#ifdef DIFFUSE\nvarying vec2 vDiffuseUV;\nuniform sampler2D diffuseSampler;\nuniform vec2 vDiffuseInfos;\n#endif\n\n#ifdef AMBIENT\nvarying vec2 vAmbientUV;\nuniform sampler2D ambientSampler;\nuniform vec2 vAmbientInfos;\n#endif\n\n#ifdef OPACITY \nvarying vec2 vOpacityUV;\nuniform sampler2D opacitySampler;\nuniform vec2 vOpacityInfos;\n#endif\n\n#ifdef REFLECTION\nvarying vec3 vReflectionUVW;\nuniform samplerCube reflectionCubeSampler;\nuniform sampler2D reflection2DSampler;\nuniform vec3 vReflectionInfos;\n#endif\n\n#ifdef EMISSIVE\nvarying vec2 vEmissiveUV;\nuniform vec2 vEmissiveInfos;\nuniform sampler2D emissiveSampler;\n#endif\n\n#ifdef SPECULAR\nvarying vec2 vSpecularUV;\nuniform vec2 vSpecularInfos;\nuniform sampler2D specularSampler;\n#endif\n\n// Shadows\n#ifdef SHADOWS\n\nfloat unpack(vec4 color)\n{\n const vec4 bitShift = vec4(1. / (255. * 255. * 255.), 1. / (255. * 255.), 1. / 255., 1.);\n return dot(color, bitShift);\n}\n\nfloat unpackHalf(vec2 color)\n{\n return color.x + (color.y / 255.0);\n}\n\nfloat computeShadow(vec4 vPositionFromLight, sampler2D shadowSampler)\n{\n vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;\n vec2 uv = 0.5 * depth.xy + vec2(0.5, 0.5);\n\n if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0)\n {\n return 1.0;\n }\n\n float shadow = unpack(texture2D(shadowSampler, uv));\n\n if (depth.z > shadow)\n {\n return 0.;\n }\n return 1.;\n}\n\n// Thanks to http://devmaster.net/\nfloat ChebychevInequality(vec2 moments, float t)\n{\n if (t <= moments.x)\n {\n return 1.0;\n }\n\n float variance = moments.y - (moments.x * moments.x);\n variance = max(variance, 0.);\n\n float d = t - moments.x;\n return variance / (variance + d * d);\n}\n\nfloat computeShadowWithVSM(vec4 vPositionFromLight, sampler2D shadowSampler)\n{\n vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;\n vec2 uv = 0.5 * depth.xy + vec2(0.5, 0.5);\n\n if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0)\n {\n return 1.0;\n }\n\n vec4 texel = texture2D(shadowSampler, uv);\n\n vec2 moments = vec2(unpackHalf(texel.xy), unpackHalf(texel.zw));\n return clamp(1.3 - ChebychevInequality(moments, depth.z), 0., 1.0);\n}\n#endif\n\n#ifdef CLIPPLANE\nvarying float fClipDistance;\n#endif\n\n// Fog\n#ifdef FOG\n\n#define FOGMODE_NONE 0.\n#define FOGMODE_EXP 1.\n#define FOGMODE_EXP2 2.\n#define FOGMODE_LINEAR 3.\n#define E 2.71828\n\nuniform vec4 vFogInfos;\nuniform vec3 vFogColor;\nvarying float fFogDistance;\n\nfloat CalcFogFactor()\n{\n float fogCoeff = 1.0;\n float fogStart = vFogInfos.y;\n float fogEnd = vFogInfos.z;\n float fogDensity = vFogInfos.w;\n\n if (FOGMODE_LINEAR == vFogInfos.x)\n {\n fogCoeff = (fogEnd - fFogDistance) / (fogEnd - fogStart);\n }\n else if (FOGMODE_EXP == vFogInfos.x)\n {\n fogCoeff = 1.0 / pow(E, fFogDistance * fogDensity);\n }\n else if (FOGMODE_EXP2 == vFogInfos.x)\n {\n fogCoeff = 1.0 / pow(E, fFogDistance * fFogDistance * fogDensity * fogDensity);\n }\n\n return clamp(fogCoeff, 0.0, 1.0);\n}\n#endif\n\n// Light Computing\nmat3 computeLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, vec3 specularColor) {\n mat3 result;\n\n vec3 lightVectorW;\n if (lightData.w == 0.)\n {\n lightVectorW = normalize(lightData.xyz - vPositionW);\n }\n else\n {\n lightVectorW = normalize(-lightData.xyz);\n }\n\n // diffuse\n float ndl = max(0., dot(vNormal, lightVectorW));\n\n // Specular\n vec3 angleW = normalize(viewDirectionW + lightVectorW);\n float specComp = max(0., dot(vNormal, angleW));\n specComp = max(0., pow(specComp, max(1.0, vSpecularColor.a)));\n\n result[0] = ndl * diffuseColor;\n result[1] = specComp * specularColor;\n result[2] = vec3(0.);\n\n return result;\n}\n\nmat3 computeSpotLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec4 lightDirection, vec3 diffuseColor, vec3 specularColor) {\n mat3 result;\n\n vec3 lightVectorW = normalize(lightData.xyz - vPositionW);\n\n // diffuse\n float cosAngle = max(0., dot(-lightDirection.xyz, lightVectorW));\n float spotAtten = 0.0;\n\n if (cosAngle >= lightDirection.w)\n {\n cosAngle = max(0., pow(cosAngle, lightData.w));\n spotAtten = max(0., (cosAngle - lightDirection.w) / (1. - cosAngle));\n\n // Diffuse\n float ndl = max(0., dot(vNormal, -lightDirection.xyz));\n\n // Specular\n vec3 angleW = normalize(viewDirectionW - lightDirection.xyz);\n float specComp = max(0., dot(vNormal, angleW));\n specComp = pow(specComp, vSpecularColor.a);\n\n result[0] = ndl * spotAtten * diffuseColor;\n result[1] = specComp * specularColor * spotAtten;\n result[2] = vec3(0.);\n\n return result;\n }\n\n result[0] = vec3(0.);\n result[1] = vec3(0.);\n result[2] = vec3(0.);\n\n return result;\n}\n\nmat3 computeHemisphericLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, vec3 specularColor, vec3 groundColor) {\n mat3 result;\n\n // Diffuse\n float ndl = dot(vNormal, lightData.xyz) * 0.5 + 0.5;\n\n // Specular\n vec3 angleW = normalize(viewDirectionW + lightData.xyz);\n float specComp = max(0., dot(vNormal, angleW));\n specComp = pow(specComp, vSpecularColor.a);\n\n result[0] = mix(groundColor, diffuseColor, ndl);\n result[1] = specComp * specularColor;\n result[2] = vec3(0.);\n\n return result;\n}\n\nvoid main(void) {\n // Clip plane\n#ifdef CLIPPLANE\n if (fClipDistance > 0.0)\n discard;\n#endif\n\n vec3 viewDirectionW = normalize(vEyePosition - vPositionW);\n\n // Base color\n vec4 baseColor = vec4(1., 1., 1., 1.);\n vec3 diffuseColor = vDiffuseColor.rgb;\n\n#ifdef VERTEXCOLOR\n diffuseColor *= vColor;\n#endif\n\n#ifdef DIFFUSE\n baseColor = texture2D(diffuseSampler, vDiffuseUV);\n\n#ifdef ALPHATEST\n if (baseColor.a < 0.4)\n discard;\n#endif\n\n baseColor.rgb *= vDiffuseInfos.y;\n#endif\n\n // Bump\n vec3 normalW = vNormalW;\n\n // Ambient color\n vec3 baseAmbientColor = vec3(1., 1., 1.);\n\n#ifdef AMBIENT\n baseAmbientColor = texture2D(ambientSampler, vAmbientUV).rgb * vAmbientInfos.y;\n#endif\n\n // Lighting\n vec3 diffuseBase = vec3(0., 0., 0.);\n vec3 specularBase = vec3(0., 0., 0.);\n float shadow = 1.;\n\n#ifdef LIGHT0\n#ifdef SPOTLIGHT0\n mat3 info = computeSpotLighting(viewDirectionW, normalW, vLightData0, vLightDirection0, vLightDiffuse0, vLightSpecular0);\n#endif\n#ifdef HEMILIGHT0\n mat3 info = computeHemisphericLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0, vLightSpecular0, vLightGround0);\n#endif\n#ifdef POINTDIRLIGHT0\n mat3 info = computeLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0, vLightSpecular0);\n#endif\n#ifdef SHADOW0\n#ifdef SHADOWVSM0\n shadow = computeShadowWithVSM(vPositionFromLight0, shadowSampler0);\n#else\n shadow = computeShadow(vPositionFromLight0, shadowSampler0);\n#endif\n#else\n shadow = 1.;\n#endif\n diffuseBase += info[0] * shadow;\n specularBase += info[1] * shadow;\n#endif\n\n#ifdef LIGHT1\n#ifdef SPOTLIGHT1\n info = computeSpotLighting(viewDirectionW, normalW, vLightData1, vLightDirection1, vLightDiffuse1, vLightSpecular1);\n#endif\n#ifdef HEMILIGHT1\n info = computeHemisphericLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1, vLightSpecular1, vLightGround1);\n#endif\n#ifdef POINTDIRLIGHT1\n info = computeLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1, vLightSpecular1);\n#endif\n#ifdef SHADOW1\n#ifdef SHADOWVSM1\n shadow = computeShadowWithVSM(vPositionFromLight1, shadowSampler1);\n#else\n shadow = computeShadow(vPositionFromLight1, shadowSampler1);\n#endif\n#else\n shadow = 1.;\n#endif\n diffuseBase += info[0] * shadow;\n specularBase += info[1] * shadow;\n#endif\n\n#ifdef LIGHT2\n#ifdef SPOTLIGHT2\n info = computeSpotLighting(viewDirectionW, normalW, vLightData2, vLightDirection2, vLightDiffuse2, vLightSpecular2);\n#endif\n#ifdef HEMILIGHT2\n info = computeHemisphericLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2, vLightSpecular2, vLightGround2);\n#endif\n#ifdef POINTDIRLIGHT2\n info = computeLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2, vLightSpecular2);\n#endif\n#ifdef SHADOW2\n#ifdef SHADOWVSM2\n shadow = computeShadowWithVSM(vPositionFromLight2, shadowSampler2);\n#else\n shadow = computeShadow(vPositionFromLight2, shadowSampler2);\n#endif \n#else\n shadow = 1.;\n#endif\n diffuseBase += info[0] * shadow;\n specularBase += info[1] * shadow;\n#endif\n\n#ifdef LIGHT3\n#ifdef SPOTLIGHT3\n info = computeSpotLighting(viewDirectionW, normalW, vLightData3, vLightDirection3, vLightDiffuse3, vLightSpecular3);\n#endif\n#ifdef HEMILIGHT3\n info = computeHemisphericLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3, vLightSpecular3, vLightGround3);\n#endif\n#ifdef POINTDIRLIGHT3\n info = computeLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3, vLightSpecular3);\n#endif\n#ifdef SHADOW3\n#ifdef SHADOWVSM3\n shadow = computeShadowWithVSM(vPositionFromLight3, shadowSampler3);\n#else\n shadow = computeShadow(vPositionFromLight3, shadowSampler3);\n#endif \n#else\n shadow = 1.;\n#endif\n diffuseBase += info[0] * shadow;\n specularBase += info[1] * shadow;\n#endif\n\n // Reflection\n vec3 reflectionColor = vec3(0., 0., 0.);\n\n#ifdef REFLECTION\n if (vReflectionInfos.z != 0.0)\n {\n reflectionColor = textureCube(reflectionCubeSampler, vReflectionUVW).rgb * vReflectionInfos.y;\n }\n else\n {\n vec2 coords = vReflectionUVW.xy;\n\n if (vReflectionInfos.x == MAP_PROJECTION)\n {\n coords /= vReflectionUVW.z;\n }\n\n coords.y = 1.0 - coords.y;\n\n reflectionColor = texture2D(reflection2DSampler, coords).rgb * vReflectionInfos.y;\n }\n#endif\n\n // Alpha\n float alpha = vDiffuseColor.a;\n\n#ifdef OPACITY\n vec4 opacityMap = texture2D(opacitySampler, vOpacityUV);\n opacityMap.rgb = opacityMap.rgb * vec3(0.3, 0.59, 0.11) * opacityMap.a;\n alpha *= (opacityMap.x + opacityMap.y + opacityMap.z)* vOpacityInfos.y;\n#endif\n\n // Emissive\n vec3 emissiveColor = vEmissiveColor;\n#ifdef EMISSIVE\n emissiveColor += texture2D(emissiveSampler, vEmissiveUV).rgb * vEmissiveInfos.y;\n#endif\n\n // Specular map\n vec3 specularColor = vSpecularColor.rgb;\n#ifdef SPECULAR\n specularColor = texture2D(specularSampler, vSpecularUV).rgb * vSpecularInfos.y;\n#endif\n\n // Composition\n vec3 finalDiffuse = clamp(diffuseBase * diffuseColor + emissiveColor + vAmbientColor, 0.0, 1.0) * baseColor.rgb;\n vec3 finalSpecular = specularBase * specularColor;\n\n vec4 color = vec4(finalDiffuse * baseAmbientColor + finalSpecular + reflectionColor, alpha);\n\n#ifdef FOG\n float fog = CalcFogFactor();\n color.rgb = fog * color.rgb + (1.0 - fog) * vFogColor;\n#endif\n\n gl_FragColor = color;\n}", +iedefaultVertexShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n#define MAP_EXPLICIT 0.\n#define MAP_SPHERICAL 1.\n#define MAP_PLANAR 2.\n#define MAP_CUBIC 3.\n#define MAP_PROJECTION 4.\n#define MAP_SKYBOX 5.\n\n// Attributes\nattribute vec3 position;\nattribute vec3 normal;\n#ifdef UV1\nattribute vec2 uv;\n#endif\n#ifdef UV2\nattribute vec2 uv2;\n#endif\n#ifdef VERTEXCOLOR\nattribute vec3 color;\n#endif\n#ifdef BONES\nattribute vec4 matricesIndices;\nattribute vec4 matricesWeights;\n#endif\n\n// Uniforms\nuniform mat4 world;\nuniform mat4 view;\nuniform mat4 viewProjection;\n\n#ifdef DIFFUSE\nvarying vec2 vDiffuseUV;\nuniform mat4 diffuseMatrix;\nuniform vec2 vDiffuseInfos;\n#endif\n\n#ifdef AMBIENT\nvarying vec2 vAmbientUV;\nuniform mat4 ambientMatrix;\nuniform vec2 vAmbientInfos;\n#endif\n\n#ifdef OPACITY\nvarying vec2 vOpacityUV;\nuniform mat4 opacityMatrix;\nuniform vec2 vOpacityInfos;\n#endif\n\n#ifdef REFLECTION\nuniform vec3 vEyePosition;\nvarying vec3 vReflectionUVW;\nuniform vec3 vReflectionInfos;\nuniform mat4 reflectionMatrix;\n#endif\n\n#ifdef EMISSIVE\nvarying vec2 vEmissiveUV;\nuniform vec2 vEmissiveInfos;\nuniform mat4 emissiveMatrix;\n#endif\n\n#ifdef SPECULAR\nvarying vec2 vSpecularUV;\nuniform vec2 vSpecularInfos;\nuniform mat4 specularMatrix;\n#endif\n\n#ifdef BUMP\nvarying vec2 vBumpUV;\nuniform vec2 vBumpInfos;\nuniform mat4 bumpMatrix;\n#endif\n\n#ifdef BONES\nuniform mat4 mBones[BonesPerMesh];\n#endif\n\n// Output\nvarying vec3 vPositionW;\nvarying vec3 vNormalW;\n\n#ifdef VERTEXCOLOR\nvarying vec3 vColor;\n#endif\n\n#ifdef CLIPPLANE\nuniform vec4 vClipPlane;\nvarying float fClipDistance;\n#endif\n\n#ifdef FOG\nvarying float fFogDistance;\n#endif\n\n#ifdef SHADOWS\n#ifdef LIGHT0\nuniform mat4 lightMatrix0;\nvarying vec4 vPositionFromLight0;\n#endif\n#ifdef LIGHT1\nuniform mat4 lightMatrix1;\nvarying vec4 vPositionFromLight1;\n#endif\n#ifdef LIGHT2\nuniform mat4 lightMatrix2;\nvarying vec4 vPositionFromLight2;\n#endif\n#ifdef LIGHT3\nuniform mat4 lightMatrix3;\nvarying vec4 vPositionFromLight3;\n#endif\n#endif\n\n#ifdef REFLECTION\nvec3 computeReflectionCoords(float mode, vec4 worldPos, vec3 worldNormal)\n{\n if (mode == MAP_SPHERICAL)\n {\n vec3 coords = vec3(view * vec4(worldNormal, 0.0));\n\n return vec3(reflectionMatrix * vec4(coords, 1.0));\n }\n else if (mode == MAP_PLANAR)\n {\n vec3 viewDir = worldPos.xyz - vEyePosition;\n vec3 coords = normalize(reflect(viewDir, worldNormal));\n\n return vec3(reflectionMatrix * vec4(coords, 1));\n }\n else if (mode == MAP_CUBIC)\n {\n vec3 viewDir = worldPos.xyz - vEyePosition;\n vec3 coords = reflect(viewDir, worldNormal);\n\n return vec3(reflectionMatrix * vec4(coords, 0));\n }\n else if (mode == MAP_PROJECTION)\n {\n return vec3(reflectionMatrix * (view * worldPos));\n }\n else if (mode == MAP_SKYBOX)\n {\n return position;\n }\n\n return vec3(0, 0, 0);\n}\n#endif\n\nvoid main(void) {\n mat4 finalWorld;\n\n#ifdef BONES\n mat4 m0 = mBones[int(matricesIndices.x)] * matricesWeights.x;\n mat4 m1 = mBones[int(matricesIndices.y)] * matricesWeights.y;\n mat4 m2 = mBones[int(matricesIndices.z)] * matricesWeights.z;\n\n#ifdef BONES4\n mat4 m3 = mBones[int(matricesIndices.w)] * matricesWeights.w;\n finalWorld = world * (m0 + m1 + m2 + m3);\n#else\n finalWorld = world * (m0 + m1 + m2);\n#endif \n\n#else\n finalWorld = world;\n#endif\n\n gl_Position = viewProjection * finalWorld * vec4(position, 1.0);\n\n vec4 worldPos = finalWorld * vec4(position, 1.0);\n vPositionW = vec3(worldPos);\n vNormalW = normalize(vec3(finalWorld * vec4(normal, 0.0)));\n\n // Texture coordinates\n#ifndef UV1\n vec2 uv = vec2(0., 0.);\n#endif\n#ifndef UV2\n vec2 uv2 = vec2(0., 0.);\n#endif\n\n#ifdef DIFFUSE\n if (vDiffuseInfos.x == 0.)\n {\n vDiffuseUV = vec2(diffuseMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vDiffuseUV = vec2(diffuseMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n#ifdef AMBIENT\n if (vAmbientInfos.x == 0.)\n {\n vAmbientUV = vec2(ambientMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vAmbientUV = vec2(ambientMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n#ifdef OPACITY\n if (vOpacityInfos.x == 0.)\n {\n vOpacityUV = vec2(opacityMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vOpacityUV = vec2(opacityMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n#ifdef REFLECTION\n vReflectionUVW = computeReflectionCoords(vReflectionInfos.x, vec4(vPositionW, 1.0), vNormalW);\n#endif\n\n#ifdef EMISSIVE\n if (vEmissiveInfos.x == 0.)\n {\n vEmissiveUV = vec2(emissiveMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vEmissiveUV = vec2(emissiveMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n#ifdef SPECULAR\n if (vSpecularInfos.x == 0.)\n {\n vSpecularUV = vec2(specularMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vSpecularUV = vec2(specularMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n#ifdef BUMP\n if (vBumpInfos.x == 0.)\n {\n vBumpUV = vec2(bumpMatrix * vec4(uv, 1.0, 0.0));\n }\n else\n {\n vBumpUV = vec2(bumpMatrix * vec4(uv2, 1.0, 0.0));\n }\n#endif\n\n // Clip plane\n#ifdef CLIPPLANE\n fClipDistance = dot(worldPos, vClipPlane);\n#endif\n\n // Fog\n#ifdef FOG\n fFogDistance = (view * worldPos).z;\n#endif\n\n // Shadows\n#ifdef SHADOWS\n#ifdef LIGHT0\n vPositionFromLight0 = lightMatrix0 * vec4(position, 1.0);\n#endif\n#ifdef LIGHT1\n vPositionFromLight1 = lightMatrix1 * vec4(position, 1.0);\n#endif\n#ifdef LIGHT2\n vPositionFromLight2 = lightMatrix2 * vec4(position, 1.0);\n#endif\n#ifdef LIGHT3\n vPositionFromLight3 = lightMatrix3 * vec4(position, 1.0);\n#endif\n#endif\n\n // Vertex color\n#ifdef VERTEXCOLOR\n vColor = color;\n#endif\n}", +layerPixelShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n// Samplers\nvarying vec2 vUV;\nuniform sampler2D textureSampler;\n\n// Color\nuniform vec4 color;\n\nvoid main(void) {\n vec4 baseColor = texture2D(textureSampler, vUV);\n\n gl_FragColor = baseColor * color;\n}", +layerVertexShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n// Attributes\nattribute vec2 position;\n\n// Uniforms\nuniform mat4 textureMatrix;\n\n// Output\nvarying vec2 vUV;\n\nconst vec2 madd = vec2(0.5, 0.5);\n\nvoid main(void) { \n\n vUV = vec2(textureMatrix * vec4(position * madd + madd, 1.0, 0.0));\n gl_Position = vec4(position, 0.0, 1.0);\n}", +lensFlarePixelShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n// Samplers\nvarying vec2 vUV;\nuniform sampler2D textureSampler;\n\n// Color\nuniform vec4 color;\n\nvoid main(void) {\n vec4 baseColor = texture2D(textureSampler, vUV);\n\n gl_FragColor = baseColor * color;\n}", +lensFlareVertexShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n// Attributes\nattribute vec2 position;\n\n// Uniforms\nuniform mat4 viewportMatrix;\n\n// Output\nvarying vec2 vUV;\n\nconst vec2 madd = vec2(0.5, 0.5);\n\nvoid main(void) { \n\n vUV = position * madd + madd;\n gl_Position = viewportMatrix * vec4(position, 0.0, 1.0);\n}", +particlesPixelShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n// Samplers\nvarying vec2 vUV;\nvarying vec4 vColor;\nuniform vec4 textureMask;\nuniform sampler2D diffuseSampler;\n\n#ifdef CLIPPLANE\nvarying float fClipDistance;\n#endif\n\nvoid main(void) {\n#ifdef CLIPPLANE\n if (fClipDistance > 0.0)\n discard;\n#endif\n vec4 baseColor = texture2D(diffuseSampler, vUV);\n\n gl_FragColor = (baseColor * textureMask + (vec4(1., 1., 1., 1.) - textureMask)) * vColor;\n}", +particlesVertexShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n// Attributes\nattribute vec3 position;\nattribute vec4 color;\nattribute vec4 options;\n\n// Uniforms\nuniform mat4 view;\nuniform mat4 projection;\n\n// Output\nvarying vec2 vUV;\nvarying vec4 vColor;\n\n#ifdef CLIPPLANE\nuniform vec4 vClipPlane;\nuniform mat4 invView;\nvarying float fClipDistance;\n#endif\n\nvoid main(void) { \n vec3 viewPos = (view * vec4(position, 1.0)).xyz; \n vec3 cornerPos;\n float size = options.y;\n float angle = options.x;\n vec2 offset = options.zw;\n\n cornerPos = vec3(offset.x - 0.5, offset.y - 0.5, 0.) * size;\n\n // Rotate\n vec3 rotatedCorner;\n rotatedCorner.x = cornerPos.x * cos(angle) - cornerPos.y * sin(angle);\n rotatedCorner.y = cornerPos.x * sin(angle) + cornerPos.y * cos(angle);\n rotatedCorner.z = 0.;\n\n // Position\n viewPos += rotatedCorner;\n gl_Position = projection * vec4(viewPos, 1.0); \n \n vColor = color;\n vUV = offset;\n\n // Clip plane\n#ifdef CLIPPLANE\n vec4 worldPos = invView * vec4(viewPos, 1.0);\n fClipDistance = dot(worldPos, vClipPlane);\n#endif\n}", +passPixelShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n// Samplers\nvarying vec2 vUV;\nuniform sampler2D textureSampler;\n\nvoid main(void) \n{\n gl_FragColor = texture2D(textureSampler, vUV);\n}", +postprocessVertexShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n// Attributes\nattribute vec2 position;\n\n// Output\nvarying vec2 vUV;\n\nconst vec2 madd = vec2(0.5, 0.5);\n\nvoid main(void) { \n\n vUV = position * madd + madd;\n gl_Position = vec4(position, 0.0, 1.0);\n}", +refractionPixelShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n// Samplers\nvarying vec2 vUV;\nuniform sampler2D textureSampler;\nuniform sampler2D refractionSampler;\n\n// Parameters\nuniform vec3 baseColor;\nuniform float depth;\nuniform float colorLevel;\n\nvoid main() {\n float ref = 1.0 - texture2D(refractionSampler, vUV).r;\n\n vec2 uv = vUV - vec2(0.5);\n vec2 offset = uv * depth * ref;\n vec3 sourceColor = texture2D(textureSampler, vUV - offset).rgb;\n\n gl_FragColor = vec4(sourceColor + sourceColor * ref * colorLevel, 1.0);\n}", +shadowMapPixelShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\nvec4 pack(float depth)\n{\n const vec4 bitOffset = vec4(255. * 255. * 255., 255. * 255., 255., 1.);\n const vec4 bitMask = vec4(0., 1. / 255., 1. / 255., 1. / 255.);\n \n vec4 comp = fract(depth * bitOffset);\n comp -= comp.xxyz * bitMask;\n \n return comp;\n}\n\n// Thanks to http://devmaster.net/\nvec2 packHalf(float depth) \n{ \n const vec2 bitOffset = vec2(1.0 / 255., 0.);\n vec2 color = vec2(depth, fract(depth * 255.));\n\n return color - (color.yy * bitOffset);\n}\n\n#ifndef VSM\nvarying vec4 vPosition;\n#endif\n\nvoid main(void)\n{\n#ifdef VSM\n float moment1 = gl_FragCoord.z / gl_FragCoord.w;\n float moment2 = moment1 * moment1;\n gl_FragColor = vec4(packHalf(moment1), packHalf(moment2));\n#else\n gl_FragColor = pack(vPosition.z / vPosition.w);\n#endif\n}", +shadowMapVertexShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n// Attribute\nattribute vec3 position;\n#ifdef BONES\nattribute vec4 matricesIndices;\nattribute vec4 matricesWeights;\n#endif\n\n// Uniform\n#ifdef BONES\nuniform mat4 world;\nuniform mat4 mBones[BonesPerMesh];\nuniform mat4 viewProjection;\n#else\nuniform mat4 worldViewProjection;\n#endif\n\n#ifndef VSM\nvarying vec4 vPosition;\n#endif\n\nvoid main(void)\n{\n#ifdef BONES\n mat4 m0 = mBones[int(matricesIndices.x)] * matricesWeights.x;\n mat4 m1 = mBones[int(matricesIndices.y)] * matricesWeights.y;\n mat4 m2 = mBones[int(matricesIndices.z)] * matricesWeights.z;\n mat4 m3 = mBones[int(matricesIndices.w)] * matricesWeights.w;\n mat4 finalWorld = world * (m0 + m1 + m2 + m3);\n gl_Position = viewProjection * finalWorld * vec4(position, 1.0);\n#else\n#ifndef VSM\n vPosition = worldViewProjection * vec4(position, 1.0);\n#endif\n gl_Position = worldViewProjection * vec4(position, 1.0);\n#endif\n}", +spritesPixelShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\nuniform bool alphaTest;\n\nvarying vec4 vColor;\n\n// Samplers\nvarying vec2 vUV;\nuniform sampler2D diffuseSampler;\n\n// Fog\n#ifdef FOG\n\n#define FOGMODE_NONE 0.\n#define FOGMODE_EXP 1.\n#define FOGMODE_EXP2 2.\n#define FOGMODE_LINEAR 3.\n#define E 2.71828\n\nuniform vec4 vFogInfos;\nuniform vec3 vFogColor;\nvarying float fFogDistance;\n\nfloat CalcFogFactor()\n{\n float fogCoeff = 1.0;\n float fogStart = vFogInfos.y;\n float fogEnd = vFogInfos.z;\n float fogDensity = vFogInfos.w;\n\n if (FOGMODE_LINEAR == vFogInfos.x)\n {\n fogCoeff = (fogEnd - fFogDistance) / (fogEnd - fogStart);\n }\n else if (FOGMODE_EXP == vFogInfos.x)\n {\n fogCoeff = 1.0 / pow(E, fFogDistance * fogDensity);\n }\n else if (FOGMODE_EXP2 == vFogInfos.x)\n {\n fogCoeff = 1.0 / pow(E, fFogDistance * fFogDistance * fogDensity * fogDensity);\n }\n\n return min(1., max(0., fogCoeff));\n}\n#endif\n\n\nvoid main(void) {\n vec4 baseColor = texture2D(diffuseSampler, vUV);\n\n if (alphaTest) \n {\n if (baseColor.a < 0.95)\n discard;\n }\n\n baseColor *= vColor;\n\n#ifdef FOG\n float fog = CalcFogFactor();\n baseColor.rgb = fog * baseColor.rgb + (1.0 - fog) * vFogColor;\n#endif\n\n gl_FragColor = baseColor;\n}", +spritesVertexShader:"#ifdef GL_ES\nprecision mediump float;\n#endif\n\n// Attributes\nattribute vec3 position;\nattribute vec4 options;\nattribute vec4 cellInfo;\nattribute vec4 color;\n\n// Uniforms\nuniform vec2 textureInfos;\nuniform mat4 view;\nuniform mat4 projection;\n\n// Output\nvarying vec2 vUV;\nvarying vec4 vColor;\n\n#ifdef FOG\nvarying float fFogDistance;\n#endif\n\nvoid main(void) { \n vec3 viewPos = (view * vec4(position, 1.0)).xyz; \n vec3 cornerPos;\n \n float angle = options.x;\n float size = options.y;\n vec2 offset = options.zw;\n vec2 uvScale = textureInfos.xy;\n\n cornerPos = vec3(offset.x - 0.5, offset.y - 0.5, 0.) * size;\n\n // Rotate\n vec3 rotatedCorner;\n rotatedCorner.x = cornerPos.x * cos(angle) - cornerPos.y * sin(angle);\n rotatedCorner.y = cornerPos.x * sin(angle) + cornerPos.y * cos(angle);\n rotatedCorner.z = 0.;\n\n // Position\n viewPos += rotatedCorner;\n gl_Position = projection * vec4(viewPos, 1.0); \n\n // Color\n vColor = color;\n \n // Texture\n vec2 uvOffset = vec2(abs(offset.x - cellInfo.x), 1.0 - abs(offset.y - cellInfo.y));\n\n vUV = (uvOffset + cellInfo.zw) * uvScale;\n\n // Fog\n#ifdef FOG\n fFogDistance = viewPos.z;\n#endif\n}", +};})();var BABYLON=BABYLON||{};(function(){BABYLON.Material=function(name,scene){this.name=name;this.id=name;this._scene=scene;scene.materials.push(this);};BABYLON.Material.prototype.checkReadyOnEveryCall=true;BABYLON.Material.prototype.checkReadyOnlyOnce=false;BABYLON.Material.prototype.alpha=1.0;BABYLON.Material.prototype.wireframe=false;BABYLON.Material.prototype.backFaceCulling=true;BABYLON.Material.prototype._effect=null;BABYLON.Material.prototype._wasPreviouslyReady=false;BABYLON.Material.prototype.onDispose=null;BABYLON.Material.prototype.isReady=function(mesh){return true;};BABYLON.Material.prototype.getEffect=function(){return this._effect;};BABYLON.Material.prototype.needAlphaBlending=function(){return(this.alpha<1.0);};BABYLON.Material.prototype.needAlphaTesting=function(){return false;};BABYLON.Material.prototype._preBind=function(){var engine=this._scene.getEngine();engine.enableEffect(this._effect);engine.setState(this.backFaceCulling);};BABYLON.Material.prototype.bind=function(world,mesh){};BABYLON.Material.prototype.unbind=function(){};BABYLON.Material.prototype.baseDispose=function(){var index=this._scene.materials.indexOf(this);this._scene.materials.splice(index,1);if(this.onDispose){this.onDispose();}};BABYLON.Material.prototype.dispose=function(){this.baseDispose();};})();var BABYLON=BABYLON||{};(function(){BABYLON.StandardMaterial=function(name,scene){BABYLON.Material.call(this,name,scene);this.diffuseTexture=null;this.ambientTexture=null;this.opacityTexture=null;this.reflectionTexture=null;this.emissiveTexture=null;this.specularTexture=null;this.bumpTexture=null;this.ambientColor=new BABYLON.Color3(0,0,0);this.diffuseColor=new BABYLON.Color3(1,1,1);this.specularColor=new BABYLON.Color3(1,1,1);this.specularPower=64;this.emissiveColor=new BABYLON.Color3(0,0,0);this._cachedDefines=null;this._renderTargets=new BABYLON.Tools.SmartArray(16);this._worldViewProjectionMatrix=BABYLON.Matrix.Zero();this._lightMatrix=BABYLON.Matrix.Zero();this._globalAmbientColor=new BABYLON.Color3(0,0,0);this._baseColor=new BABYLON.Color3();this._scaledDiffuse=new BABYLON.Color3();this._scaledSpecular=new BABYLON.Color3();};BABYLON.StandardMaterial.prototype=Object.create(BABYLON.Material.prototype);BABYLON.StandardMaterial.prototype.needAlphaBlending=function(){return(this.alpha<1.0)||(this.opacityTexture!=null);};BABYLON.StandardMaterial.prototype.needAlphaTesting=function(){return this.diffuseTexture!=null&&this.diffuseTexture.hasAlpha;};BABYLON.StandardMaterial.prototype.isReady=function(mesh){if(this.checkReadyOnlyOnce){if(this._wasPreviouslyReady){return true;}}if(!this.checkReadyOnEveryCall){if(this._renderId===this._scene.getRenderId()){return true;}}var engine=this._scene.getEngine();var defines=[];var optionalDefines=[];if(this._scene.texturesEnabled){if(this.diffuseTexture){if(!this.diffuseTexture.isReady()){return false;}else{defines.push("#define DIFFUSE");}}if(this.ambientTexture){if(!this.ambientTexture.isReady()){return false;}else{defines.push("#define AMBIENT");}}if(this.opacityTexture){if(!this.opacityTexture.isReady()){return false;}else{defines.push("#define OPACITY");}}if(this.reflectionTexture){if(!this.reflectionTexture.isReady()){return false;}else{defines.push("#define REFLECTION");}}if(this.emissiveTexture){if(!this.emissiveTexture.isReady()){return false;}else{defines.push("#define EMISSIVE");}}if(this.specularTexture){if(!this.specularTexture.isReady()){return false;}else{defines.push("#define SPECULAR");optionalDefines.push(defines[defines.length-1]);}}}if(this._scene.getEngine().getCaps().standardDerivatives&&this.bumpTexture){if(!this.bumpTexture.isReady()){return false;}else{defines.push("#define BUMP");optionalDefines.push(defines[defines.length-1]);}}if(BABYLON.clipPlane){defines.push("#define CLIPPLANE");}if(engine.getAlphaTesting()){defines.push("#define ALPHATEST");}if(this._scene.fogMode!==BABYLON.Scene.FOGMODE_NONE){defines.push("#define FOG");optionalDefines.push(defines[defines.length-1]);}var shadowsActivated=false;var lightIndex=0;if(this._scene.lightsEnabled){for(var index=0;index0){optionalDefines.push(defines[defines.length-1]);}var type;if(light instanceof BABYLON.SpotLight){type="#define SPOTLIGHT"+lightIndex;}else if(light instanceof BABYLON.HemisphericLight){type="#define HEMILIGHT"+lightIndex;}else{type="#define POINTDIRLIGHT"+lightIndex;}defines.push(type);if(lightIndex>0){optionalDefines.push(defines[defines.length-1]);}var shadowGenerator=light.getShadowGenerator();if(mesh&&mesh.receiveShadows&&shadowGenerator){defines.push("#define SHADOW"+lightIndex);if(lightIndex>0){optionalDefines.push(defines[defines.length-1]);}if(!shadowsActivated){defines.push("#define SHADOWS");shadowsActivated=true;}if(shadowGenerator.useVarianceShadowMap){defines.push("#define SHADOWVSM"+lightIndex);if(lightIndex>0){optionalDefines.push(defines[defines.length-1]);}}}lightIndex++;if(lightIndex==4)break;}}var attribs=[BABYLON.VertexBuffer.PositionKind,BABYLON.VertexBuffer.NormalKind];if(mesh){if(mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UVKind)){attribs.push(BABYLON.VertexBuffer.UVKind);defines.push("#define UV1");}if(mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UV2Kind)){attribs.push(BABYLON.VertexBuffer.UV2Kind);defines.push("#define UV2");}if(mesh.isVerticesDataPresent(BABYLON.VertexBuffer.ColorKind)){attribs.push(BABYLON.VertexBuffer.ColorKind);defines.push("#define VERTEXCOLOR");}if(mesh.skeleton&&mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind)&&mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind)){attribs.push(BABYLON.VertexBuffer.MatricesIndicesKind);attribs.push(BABYLON.VertexBuffer.MatricesWeightsKind);defines.push("#define BONES");defines.push("#define BonesPerMesh "+mesh.skeleton.bones.length);defines.push("#define BONES4");optionalDefines.push(defines[defines.length-1]);}}var join=defines.join("\n");if(this._cachedDefines!=join){this._cachedDefines=join;var shaderName="default";if(BABYLON.Tools.isIE()){shaderName="iedefault";}this._effect=this._scene.getEngine().createEffect(shaderName,attribs,["world","view","viewProjection","vEyePosition","vLightsType","vAmbientColor","vDiffuseColor","vSpecularColor","vEmissiveColor","vLightData0","vLightDiffuse0","vLightSpecular0","vLightDirection0","vLightGround0","lightMatrix0","vLightData1","vLightDiffuse1","vLightSpecular1","vLightDirection1","vLightGround1","lightMatrix1","vLightData2","vLightDiffuse2","vLightSpecular2","vLightDirection2","vLightGround2","lightMatrix2","vLightData3","vLightDiffuse3","vLightSpecular3","vLightDirection3","vLightGround3","lightMatrix3","vFogInfos","vFogColor","vDiffuseInfos","vAmbientInfos","vOpacityInfos","vReflectionInfos","vEmissiveInfos","vSpecularInfos","vBumpInfos","mBones","vClipPlane","diffuseMatrix","ambientMatrix","opacityMatrix","reflectionMatrix","emissiveMatrix","specularMatrix","bumpMatrix"],["diffuseSampler","ambientSampler","opacitySampler","reflectionCubeSampler","reflection2DSampler","emissiveSampler","specularSampler","bumpSampler","shadowSampler0","shadowSampler1","shadowSampler2","shadowSampler3"],join,optionalDefines);}if(!this._effect.isReady()){return false;}this._renderId=this._scene.getRenderId();this._wasPreviouslyReady=true;return true;};BABYLON.StandardMaterial.prototype.getRenderTargetTextures=function(){this._renderTargets.reset();if(this.reflectionTexture&&this.reflectionTexture.isRenderTarget){this._renderTargets.push(this.reflectionTexture);}return this._renderTargets;};BABYLON.StandardMaterial.prototype.unbind=function(){if(this.reflectionTexture&&this.reflectionTexture.isRenderTarget){this._effect.setTexture("reflection2DSampler",null);}};BABYLON.StandardMaterial.prototype.bind=function(world,mesh){this._baseColor.copyFrom(this.diffuseColor);this._effect.setMatrix("world",world);this._effect.setMatrix("viewProjection",this._scene.getTransformMatrix());if(mesh.skeleton&&mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind)&&mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind)){this._effect.setMatrices("mBones",mesh.skeleton.getTransformMatrices());}if(this.diffuseTexture){this._effect.setTexture("diffuseSampler",this.diffuseTexture);this._effect.setFloat2("vDiffuseInfos",this.diffuseTexture.coordinatesIndex,this.diffuseTexture.level);this._effect.setMatrix("diffuseMatrix",this.diffuseTexture._computeTextureMatrix());this._baseColor.copyFromFloats(1,1,1);}if(this.ambientTexture){this._effect.setTexture("ambientSampler",this.ambientTexture);this._effect.setFloat2("vAmbientInfos",this.ambientTexture.coordinatesIndex,this.ambientTexture.level);this._effect.setMatrix("ambientMatrix",this.ambientTexture._computeTextureMatrix());}if(this.opacityTexture){this._effect.setTexture("opacitySampler",this.opacityTexture);this._effect.setFloat2("vOpacityInfos",this.opacityTexture.coordinatesIndex,this.opacityTexture.level);this._effect.setMatrix("opacityMatrix",this.opacityTexture._computeTextureMatrix());}if(this.reflectionTexture){if(this.reflectionTexture.isCube){this._effect.setTexture("reflectionCubeSampler",this.reflectionTexture);}else{this._effect.setTexture("reflection2DSampler",this.reflectionTexture);}this._effect.setMatrix("reflectionMatrix",this.reflectionTexture._computeReflectionTextureMatrix());this._effect.setFloat3("vReflectionInfos",this.reflectionTexture.coordinatesMode,this.reflectionTexture.level,this.reflectionTexture.isCube?1:0);}if(this.emissiveTexture){this._effect.setTexture("emissiveSampler",this.emissiveTexture);this._effect.setFloat2("vEmissiveInfos",this.emissiveTexture.coordinatesIndex,this.emissiveTexture.level);this._effect.setMatrix("emissiveMatrix",this.emissiveTexture._computeTextureMatrix());}if(this.specularTexture){this._effect.setTexture("specularSampler",this.specularTexture);this._effect.setFloat2("vSpecularInfos",this.specularTexture.coordinatesIndex,this.specularTexture.level);this._effect.setMatrix("specularMatrix",this.specularTexture._computeTextureMatrix());}if(this.bumpTexture&&this._scene.getEngine().getCaps().standardDerivatives){this._effect.setTexture("bumpSampler",this.bumpTexture);this._effect.setFloat2("vBumpInfos",this.bumpTexture.coordinatesIndex,this.bumpTexture.level);this._effect.setMatrix("bumpMatrix",this.bumpTexture._computeTextureMatrix());}this._scene.ambientColor.multiplyToRef(this.ambientColor,this._globalAmbientColor);this._effect.setVector3("vEyePosition",this._scene.activeCamera.position);this._effect.setColor3("vAmbientColor",this._globalAmbientColor);this._effect.setColor4("vDiffuseColor",this._baseColor,this.alpha*mesh.visibility);this._effect.setColor4("vSpecularColor",this.specularColor,this.specularPower);this._effect.setColor3("vEmissiveColor",this.emissiveColor);if(this._scene.lightsEnabled){var lightIndex=0;for(var index=0;index0){results.push(this.diffuseTexture);}if(this.ambientTexture&&this.ambientTexture.animations&&this.ambientTexture.animations.length>0){results.push(this.ambientTexture);}if(this.opacityTexture&&this.opacityTexture.animations&&this.opacityTexture.animations.length>0){results.push(this.opacityTexture);}if(this.reflectionTexture&&this.reflectionTexture.animations&&this.reflectionTexture.animations.length>0){results.push(this.reflectionTexture);}if(this.emissiveTexture&&this.emissiveTexture.animations&&this.emissiveTexture.animations.length>0){results.push(this.emissiveTexture);}if(this.specularTexture&&this.specularTexture.animations&&this.specularTexture.animations.length>0){results.push(this.specularTexture);}if(this.bumpTexture&&this.bumpTexture.animations&&this.bumpTexture.animations.length>0){results.push(this.bumpTexture);}return results;};BABYLON.StandardMaterial.prototype.dispose=function(){if(this.diffuseTexture){this.diffuseTexture.dispose();}if(this.ambientTexture){this.ambientTexture.dispose();}if(this.opacityTexture){this.opacityTexture.dispose();}if(this.reflectionTexture){this.reflectionTexture.dispose();}if(this.emissiveTexture){this.emissiveTexture.dispose();}if(this.specularTexture){this.specularTexture.dispose();}if(this.bumpTexture){this.bumpTexture.dispose();}this.baseDispose();};BABYLON.StandardMaterial.prototype.clone=function(name){var newStandardMaterial=new BABYLON.StandardMaterial(name,this._scene);newStandardMaterial.checkReadyOnEveryCall=this.checkReadyOnEveryCall;newStandardMaterial.alpha=this.alpha;newStandardMaterial.wireframe=this.wireframe;newStandardMaterial.backFaceCulling=this.backFaceCulling;if(this.diffuseTexture&&this.diffuseTexture.clone){newStandardMaterial.diffuseTexture=this.diffuseTexture.clone();}if(this.ambientTexture&&this.ambientTexture.clone){newStandardMaterial.ambientTexture=this.ambientTexture.clone();}if(this.opacityTexture&&this.opacityTexture.clone){newStandardMaterial.opacityTexture=this.opacityTexture.clone();}if(this.reflectionTexture&&this.reflectionTexture.clone){newStandardMaterial.reflectionTexture=this.reflectionTexture.clone();}if(this.emissiveTexture&&this.emissiveTexture.clone){newStandardMaterial.emissiveTexture=this.emissiveTexture.clone();}if(this.specularTexture&&this.specularTexture.clone){newStandardMaterial.specularTexture=this.specularTexture.clone();}if(this.bumpTexture&&this.bumpTexture.clone){newStandardMaterial.bumpTexture=this.bumpTexture.clone();}newStandardMaterial.ambientColor=this.ambientColor.clone();newStandardMaterial.diffuseColor=this.diffuseColor.clone();newStandardMaterial.specularColor=this.specularColor.clone();newStandardMaterial.specularPower=this.specularPower;newStandardMaterial.emissiveColor=this.emissiveColor.clone();return newStandardMaterial;};})();var BABYLON=BABYLON||{};(function(){BABYLON.MultiMaterial=function(name,scene){this.name=name;this.id=name;this._scene=scene;scene.multiMaterials.push(this);this.subMaterials=[];};BABYLON.MultiMaterial.prototype.getSubMaterial=function(index){if(index<0||index>=this.subMaterials.length){return this._scene.defaultMaterial;}return this.subMaterials[index];};BABYLON.MultiMaterial.prototype.isReady=function(mesh){var result=true;for(var index=0;indexversion.data){that.mustUpdateRessources=true;updateInDBCallback();}else{callback(version.data);}}else{that.mustUpdateRessources=true;updateInDBCallback();}};transaction.onabort=function(event){callback(-1);};var getRequest=transaction.objectStore("versions").get(url);getRequest.onsuccess=function(event){version=event.target.result;};getRequest.onerror=function(event){console.log("Error loading version for scene "+url+" from DB.");callback(-1);};}catch(ex){console.log("Error while accessing 'versions' object store (READ OP). Exception: "+ex.message);callback(-1);}}else{console.log("Error: IndexedDB not supported by your browser or BabylonJS Database is not open.");callback(-1);}};BABYLON.Database.prototype._saveVersionIntoDBAsync=function(url,callback){if(this.isSupported&&!this.hasReachedQuota){var that=this;try{var transaction=this.db.transaction(["versions"],"readwrite");transaction.onabort=function(event){try{if(event.srcElement.error.name==="QuotaExceededError"){that.hasReachedQuota=true;}}catch(ex){}callback(-1);};transaction.oncomplete=function(event){callback(that.manifestVersionFound);};var newVersion={};newVersion.sceneUrl=url;newVersion.data=this.manifestVersionFound;var addRequest=transaction.objectStore("versions").put(newVersion);addRequest.onsuccess=function(event){console.log("");};addRequest.onerror=function(event){console.log("Error in DB add version request in BABYLON.Database.");};}catch(ex){console.log("Error while accessing 'versions' object store (WRITE OP). Exception: "+ex.message);callback(-1);}}else{callback(-1);}};BABYLON.Database.prototype.loadSceneFromDB=function(url,sceneLoaded,progressCallBack,errorCallback){var that=this;var completeUrl=BABYLON.Database.ReturnFullUrlLocation(url);var saveAndLoadScene=function(event){that._saveSceneIntoDBAsync(completeUrl,sceneLoaded,progressCallBack);};this._checkVersionFromDB(completeUrl,function(version){if(version!==-1){if(!that.mustUpdateRessources){that._loadSceneFromDBAsync(completeUrl,sceneLoaded,saveAndLoadScene);}else{that._saveSceneIntoDBAsync(completeUrl,sceneLoaded,progressCallBack);}}else{errorCallback();}});};BABYLON.Database.prototype._loadSceneFromDBAsync=function(url,callback,notInDBCallback){if(this.isSupported){var scene;var transaction=this.db.transaction(["scenes"]);transaction.oncomplete=function(event){if(scene){callback(scene.data);}else{notInDBCallback();}};transaction.onabort=function(event){notInDBCallback();};var getRequest=transaction.objectStore("scenes").get(url);getRequest.onsuccess=function(event){scene=event.target.result;};getRequest.onerror=function(event){console.log("Error loading scene "+url+" from DB.");notInDBCallback();};}else{console.log("Error: IndexedDB not supported by your browser or BabylonJS Database is not open.");callback();}};BABYLON.Database.prototype._saveSceneIntoDBAsync=function(url,callback,progressCallback){if(this.isSupported){var xhr=new XMLHttpRequest(),sceneText;var that=this;xhr.open("GET",url,true);xhr.onprogress=progressCallback;xhr.addEventListener("load",function(){if(xhr.status===200){sceneText=xhr.responseText;if(!that.hasReachedQuota){var transaction=that.db.transaction(["scenes"],"readwrite");transaction.onabort=function(event){try{if(event.srcElement.error.name==="QuotaExceededError"){that.hasReachedQuota=true;}}catch(ex){}callback(sceneText);};transaction.oncomplete=function(event){callback(sceneText);};var newScene={};newScene.sceneUrl=url;newScene.data=sceneText;newScene.version=that.manifestVersionFound;try{var addRequest=transaction.objectStore("scenes").put(newScene);addRequest.onsuccess=function(event){console.log("");};addRequest.onerror=function(event){console.log("Error in DB add scene request in BABYLON.Database.");};}catch(ex){callback(sceneText);}}else{callback(sceneText);}}else{callback();}},false);xhr.addEventListener("error",function(event){console.log("error on XHR request.");callback();},false);xhr.send();}else{console.log("Error: IndexedDB not supported by your browser or BabylonJS Database is not open.");callback();}};})();var BABYLON=BABYLON||{};(function(){var loadCubeTexture=function(rootUrl,parsedTexture,scene){var texture=new BABYLON.CubeTexture(rootUrl+parsedTexture.name,scene);texture.name=parsedTexture.name;texture.hasAlpha=parsedTexture.hasAlpha;texture.level=parsedTexture.level;texture.coordinatesMode=parsedTexture.coordinatesMode;return texture;};var loadTexture=function(rootUrl,parsedTexture,scene){if(!parsedTexture.name&&!parsedTexture.isRenderTarget){return null;}if(parsedTexture.isCube){return loadCubeTexture(rootUrl,parsedTexture,scene);}var texture;if(parsedTexture.mirrorPlane){texture=new BABYLON.MirrorTexture(parsedTexture.name,parsedTexture.renderTargetSize,scene);texture._waitingRenderList=parsedTexture.renderList;texture.mirrorPlane=BABYLON.Plane.FromArray(parsedTexture.mirrorPlane);}else if(parsedTexture.isRenderTarget){texture=new BABYLON.RenderTargetTexture(parsedTexture.name,parsedTexture.renderTargetSize,scene);texture._waitingRenderList=parsedTexture.renderList;}else{texture=new BABYLON.Texture(rootUrl+parsedTexture.name,scene);}texture.name=parsedTexture.name;texture.hasAlpha=parsedTexture.hasAlpha;texture.level=parsedTexture.level;texture.coordinatesIndex=parsedTexture.coordinatesIndex;texture.coordinatesMode=parsedTexture.coordinatesMode;texture.uOffset=parsedTexture.uOffset;texture.vOffset=parsedTexture.vOffset;texture.uScale=parsedTexture.uScale;texture.vScale=parsedTexture.vScale;texture.uAng=parsedTexture.uAng;texture.vAng=parsedTexture.vAng;texture.wAng=parsedTexture.wAng;texture.wrapU=parsedTexture.wrapU;texture.wrapV=parsedTexture.wrapV;if(parsedTexture.animations){for(var animationIndex=0;animationIndex-1){parentBone=skeleton.bones[parsedBone.parentBoneIndex];}var bone=new BABYLON.Bone(parsedBone.name,skeleton,parentBone,BABYLON.Matrix.FromArray(parsedBone.matrix));if(parsedBone.animation){bone.animations.push(parseAnimation(parsedBone.animation));}}return skeleton;};var parseMaterial=function(parsedMaterial,scene,rootUrl){var material;material=new BABYLON.StandardMaterial(parsedMaterial.name,scene);material.ambientColor=BABYLON.Color3.FromArray(parsedMaterial.ambient);material.diffuseColor=BABYLON.Color3.FromArray(parsedMaterial.diffuse);material.specularColor=BABYLON.Color3.FromArray(parsedMaterial.specular);material.specularPower=parsedMaterial.specularPower;material.emissiveColor=BABYLON.Color3.FromArray(parsedMaterial.emissive);material.alpha=parsedMaterial.alpha;material.id=parsedMaterial.id;material.backFaceCulling=parsedMaterial.backFaceCulling;if(parsedMaterial.diffuseTexture){material.diffuseTexture=loadTexture(rootUrl,parsedMaterial.diffuseTexture,scene);}if(parsedMaterial.ambientTexture){material.ambientTexture=loadTexture(rootUrl,parsedMaterial.ambientTexture,scene);}if(parsedMaterial.opacityTexture){material.opacityTexture=loadTexture(rootUrl,parsedMaterial.opacityTexture,scene);}if(parsedMaterial.reflectionTexture){material.reflectionTexture=loadTexture(rootUrl,parsedMaterial.reflectionTexture,scene);}if(parsedMaterial.emissiveTexture){material.emissiveTexture=loadTexture(rootUrl,parsedMaterial.emissiveTexture,scene);}if(parsedMaterial.specularTexture){material.specularTexture=loadTexture(rootUrl,parsedMaterial.specularTexture,scene);}if(parsedMaterial.bumpTexture){material.bumpTexture=loadTexture(rootUrl,parsedMaterial.bumpTexture,scene);}return material;};var parseMaterialById=function(id,parsedData,scene,rootUrl){for(var index=0;index-1){mesh.skeleton=scene.getLastSkeletonByID(parsedMesh.skeletonId);}if(parsedMesh.physicsImpostor){if(!scene.isPhysicsEnabled()){scene.enablePhysics();}switch(parsedMesh.physicsImpostor){case 1:mesh.setPhysicsState({impostor:BABYLON.PhysicsEngine.BoxImpostor,mass:parsedMesh.physicsMass,friction:parsedMesh.physicsFriction,restitution:parsedMesh.physicsRestitution});break;case 2:mesh.setPhysicsState({impostor:BABYLON.PhysicsEngine.SphereImpostor,mass:parsedMesh.physicsMass,friction:parsedMesh.physicsFriction,restitution:parsedMesh.physicsRestitution});break;}}if(parsedMesh.animations){for(var animationIndex=0;animationIndex>8);floatIndices.push((matricesIndex&0x00FF0000)>>16);floatIndices.push(matricesIndex>>24);}mesh.setVerticesData(floatIndices,BABYLON.VertexBuffer.MatricesIndicesKind,false);}if(parsedGeometry.matricesWeights){mesh.setVerticesData(parsedGeometry.matricesWeights,BABYLON.VertexBuffer.MatricesWeightsKind,false);}mesh.setIndices(parsedGeometry.indices);}if(parsedGeometry.subMeshes){mesh.subMeshes=[];for(var subIndex=0;subIndex-1&&scene.skeletons){var skeletonAlreadyLoaded=(loadedSkeletonsIds.indexOf(parsedMesh.skeletonId)>-1);if(!skeletonAlreadyLoaded){for(var skeletonIndex=0;skeletonIndex>0;this._vertices[arrayOffset+9]=sprite.cellIndex-offset*rowSize;this._vertices[arrayOffset+10]=offset;this._vertices[arrayOffset+11]=sprite.color.r;this._vertices[arrayOffset+12]=sprite.color.g;this._vertices[arrayOffset+13]=sprite.color.b;this._vertices[arrayOffset+14]=sprite.color.a;};BABYLON.SpriteManager.prototype.render=function(){if(!this._effectBase.isReady()||!this._effectFog.isReady()||!this._spriteTexture||!this._spriteTexture.isReady())return 0;var engine=this._scene.getEngine();var baseSize=this._spriteTexture.getBaseSize();var deltaTime=BABYLON.Tools.GetDeltaTime();var max=Math.min(this._capacity,this.sprites.length);var rowSize=baseSize.width/this.cellSize;var offset=0;for(var index=0;indexthis._delay){this._time=this._time%this._delay;this.cellIndex+=this._direction;if(this.cellIndex==this._toIndex){if(this._loopAnimation){this.cellIndex=this._fromIndex;}else{this._animationStarted=false;if(this.disposeWhenFinishedAnimating){this.dispose();}}}}};BABYLON.Sprite.prototype.dispose=function(){for(var i=0;i0;for(var index=0;index=particle.lifeTime){this._stockParticles.push(this.particles.splice(index,1)[0]);index--;continue;}else{particle.colorStep.scaleToRef(this._scaledUpdateSpeed,this._scaledColorStep);particle.color.addInPlace(this._scaledColorStep);if(particle.color.a<0)particle.color.a=0;particle.direction.scaleToRef(this._scaledUpdateSpeed,this._scaledDirection);particle.position.addInPlace(this._scaledDirection);particle.angle+=particle.angularSpeed*this._scaledUpdateSpeed;this.gravity.scaleToRef(this._scaledUpdateSpeed,this._scaledGravity);particle.direction.addInPlace(this._scaledGravity);}}var worldMatrix;if(this.emitter.position){worldMatrix=this.emitter.getWorldMatrix();}else{worldMatrix=BABYLON.Matrix.Translation(this.emitter.x,this.emitter.y,this.emitter.z);}for(var index=0;index-1){emitCout=this.manualEmitCount;this.manualEmitCount=0;}else{emitCout=this.emitRate;}var newParticles=((emitCout*this._scaledUpdateSpeed)>>0);this._newPartsExcess+=emitCout*this._scaledUpdateSpeed-newParticles;if(this._newPartsExcess>1.0){newParticles+=this._newPartsExcess>>0;this._newPartsExcess-=this._newPartsExcess>>0;}this._alive=false;if(!this._stopped){this._actualFrame+=this._scaledUpdateSpeed;if(this.targetStopDuration&&this._actualFrame>=this.targetStopDuration)this.stop();}else{newParticles=0;}this._update(newParticles);if(this._stopped){if(!this._alive){this._started=false;if(this.disposeOnStop){this._scene._toBeDisposed.push(this);}}}var offset=0;for(var index=0;index0){return highLimitValue.clone?highLimitValue.clone():highLimitValue;}this.currentFrame=currentFrame;for(var key=0;key=currentFrame){var startValue=this._keys[key].value;var endValue=this._keys[key+1].value;var gradient=(currentFrame-this._keys[key].frame)/(this._keys[key+1].frame-this._keys[key].frame);switch(this.dataType){case BABYLON.Animation.ANIMATIONTYPE_FLOAT:switch(loopMode){case BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE:case BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT:return this.floatInterpolateFunction(startValue,endValue,gradient);case BABYLON.Animation.ANIMATIONLOOPMODE_RELATIVE:return offsetValue*repeatCount+this.floatInterpolateFunction(startValue,endValue,gradient);}break;case BABYLON.Animation.ANIMATIONTYPE_QUATERNION:var quaternion=null;switch(loopMode){case BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE:case BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT:quaternion=this.quaternionInterpolateFunction(startValue,endValue,gradient);break;case BABYLON.Animation.ANIMATIONLOOPMODE_RELATIVE:quaternion=this.quaternionInterpolateFunction(startValue,endValue,gradient).add(offsetValue.scale(repeatCount));break;}return quaternion;case BABYLON.Animation.ANIMATIONTYPE_VECTOR3:switch(loopMode){case BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE:case BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT:return this.vector3InterpolateFunction(startValue,endValue,gradient);case BABYLON.Animation.ANIMATIONLOOPMODE_RELATIVE:return this.vector3InterpolateFunction(startValue,endValue,gradient).add(offsetValue.scale(repeatCount));}case BABYLON.Animation.ANIMATIONTYPE_MATRIX:switch(loopMode){case BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE:case BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT:case BABYLON.Animation.ANIMATIONLOOPMODE_RELATIVE:return startValue;}default:break;}break;}}return this._keys[this._keys.length-1].value;};BABYLON.Animation.prototype.animate=function(target,delay,from,to,loop,speedRatio){if(!this.targetPropertyPath||this.targetPropertyPath.length<1){return false;}var returnValue=true;if(this._keys[0].frame!=0){var newKey={frame:0,value:this._keys[0].value};this._keys.splice(0,0,newKey);}if(fromthis._keys[this._keys.length-1].frame){from=this._keys[0].frame;}if(tothis._keys[this._keys.length-1].frame){to=this._keys[this._keys.length-1].frame;}var range=to-from;var ratio=delay*(this.framePerSecond*speedRatio)/1000.0;if(ratio>range&&!loop){offsetValue=0;returnValue=false;}else{var offsetValue=0;var highLimitValue=0;if(this.loopMode!=BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE){var keyOffset=to.toString()+from.toString();if(!this._offsetsCache[keyOffset]){var fromValue=this._interpolate(from,0,BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE);var toValue=this._interpolate(to,0,BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE);switch(this.dataType){case BABYLON.Animation.ANIMATIONTYPE_FLOAT:this._offsetsCache[keyOffset]=toValue-fromValue;break;case BABYLON.Animation.ANIMATIONTYPE_QUATERNION:this._offsetsCache[keyOffset]=toValue.subtract(fromValue);break;case BABYLON.Animation.ANIMATIONTYPE_VECTOR3:this._offsetsCache[keyOffset]=toValue.subtract(fromValue);default:break;}this._highLimitsCache[keyOffset]=toValue;}highLimitValue=this._highLimitsCache[keyOffset];offsetValue=this._offsetsCache[keyOffset];}}var repeatCount=(ratio/range)>>0;var currentFrame=returnValue?from+ratio%range:to;var currentValue=this._interpolate(currentFrame,repeatCount,this.loopMode,offsetValue,highLimitValue);if(this.targetPropertyPath.length>1){var property=target[this.targetPropertyPath[0]];for(var index=1;indexthis._capacity){BABYLON.Octree._CreateBlocks(this._minPoint,this._maxPoint,this.meshes,this._capacity,this);}};BABYLON.OctreeBlock.prototype.addEntries=function(meshes){for(var index=0;index0){this._camera.postProcesses[0].width=-1;}};})();var BABYLON=BABYLON||{};(function(){BABYLON.PostProcessManager=function(scene){this._scene=scene;var vertices=[];vertices.push(1,1);vertices.push(-1,1);vertices.push(-1,-1);vertices.push(1,-1);this._vertexDeclaration=[2];this._vertexStrideSize=2*4;this._vertexBuffer=scene.getEngine().createVertexBuffer(vertices);var indices=[];indices.push(0);indices.push(1);indices.push(2);indices.push(0);indices.push(2);indices.push(3);this._indexBuffer=scene.getEngine().createIndexBuffer(indices);};BABYLON.PostProcessManager.prototype._prepareFrame=function(){var postProcesses=this._scene.activeCamera.postProcesses;if(postProcesses.length===0||!this._scene.postProcessesEnabled){return;}postProcesses[0].activate();};BABYLON.PostProcessManager.prototype._finalizeFrame=function(){var postProcesses=this._scene.activeCamera.postProcesses;if(postProcesses.length===0||!this._scene.postProcessesEnabled){return;}var engine=this._scene.getEngine();for(var index=0;index0){if((this._positionX>globalViewport.x)&&(this._positionXglobalViewport.y)&&(this._positionYdistance;};BABYLON.LensFlareSystem.prototype.render=function(){if(!this._effect.isReady())return false;var engine=this._scene.getEngine();var viewport=this._scene.activeCamera.viewport;var globalViewport=viewport.toGlobal(engine);if(!this.computeEffectivePosition(globalViewport)){return false;}if(!this._isVisible()){return false;}var awayX;var awayY;if(this._positionXglobalViewport.x+globalViewport.width-this.borderLimit){awayX=this._positionX-globalViewport.x-globalViewport.width+this.borderLimit;}else{awayX=0;}if(this._positionYglobalViewport.y+globalViewport.height-this.borderLimit){awayY=this._positionY-globalViewport.y-globalViewport.height+this.borderLimit;}else{awayY=0;}var away=(awayX>awayY)?awayX:awayY;if(away>this.borderLimit){away=this.borderLimit;}var intensity=1.0-(away/this.borderLimit);if(intensity<0){return false;}if(intensity>1.0){intensity=1.0;}var centerX=globalViewport.x+globalViewport.width/2;var centerY=globalViewport.y+globalViewport.height/2;var distX=centerX-this._positionX;var distY=centerY-this._positionY;engine.enableEffect(this._effect);engine.setState(false);engine.setDepthBuffer(false);engine.setAlphaMode(BABYLON.Engine.ALPHA_ADD);engine.bindBuffers(this._vertexBuffer,this._indexBuffer,this._vertexDeclaration,this._vertexStrideSize,this._effect);for(var index=0;index0){that.textureLoadingCallback(remaining);}}that.currentScene.render();}};function drag(e){e.stopPropagation();e.preventDefault();};function drop(eventDrop){eventDrop.stopPropagation();eventDrop.preventDefault();that.loadFiles(eventDrop);};BABYLON.FilesInput.prototype.loadFiles=function(event){if(that.startingProcessingFilesCallback)that.startingProcessingFilesCallback();var sceneFileToLoad;var filesToLoad;BABYLON.FilesTextures={};if(event&&event.dataTransfer&&event.dataTransfer.files){filesToLoad=event.dataTransfer.files;}if(event&&event.target&&event.target.files){filesToLoad=event.target.files;}if(filesToLoad&&filesToLoad.length>0){for(var i=0;i1.0){delta=1.0;}this._world.step(delta);for(var index=0;index 180) + console.log(numVecs+" created"); + */ +}; + +/** + * @method cross + * @memberof CANNON.Vec3 + * @brief Vector cross product + * @param CANNON.Vec3 v + * @param CANNON.Vec3 target Optional. Target to save in. + * @return CANNON.Vec3 + */ +CANNON.Vec3.prototype.cross = function(v,target){ + var vx=v.x, vy=v.y, vz=v.z, x=this.x, y=this.y, z=this.z; + target = target || new CANNON.Vec3(); + + target.x = (y * vz) - (z * vy); + target.y = (z * vx) - (x * vz); + target.z = (x * vy) - (y * vx); + + return target; +}; + +/** + * @method set + * @memberof CANNON.Vec3 + * @brief Set the vectors' 3 elements + * @param float x + * @param float y + * @param float z + * @return CANNON.Vec3 + */ +CANNON.Vec3.prototype.set = function(x,y,z){ + this.x = x; + this.y = y; + this.z = z; + return this; +}; + +/** + * @method vadd + * @memberof CANNON.Vec3 + * @brief Vector addition + * @param CANNON.Vec3 v + * @param CANNON.Vec3 target Optional. + * @return CANNON.Vec3 + */ +CANNON.Vec3.prototype.vadd = function(v,target){ + if(target){ + target.x = v.x + this.x; + target.y = v.y + this.y; + target.z = v.z + this.z; + } else { + return new CANNON.Vec3(this.x + v.x, + this.y + v.y, + this.z + v.z); + } +}; + +/** + * @method vsub + * @memberof CANNON.Vec3 + * @brief Vector subtraction + * @param CANNON.Vec3 v + * @param CANNON.Vec3 target Optional. Target to save in. + * @return CANNON.Vec3 + */ +CANNON.Vec3.prototype.vsub = function(v,target){ + if(target){ + target.x = this.x - v.x; + target.y = this.y - v.y; + target.z = this.z - v.z; + } else { + return new CANNON.Vec3(this.x-v.x, + this.y-v.y, + this.z-v.z); + } +}; + +/** + * @method crossmat + * @memberof CANNON.Vec3 + * @brief Get the cross product matrix a_cross from a vector, such that a x b = a_cross * b = c + * @see http://www8.cs.umu.se/kurser/TDBD24/VT06/lectures/Lecture6.pdf + * @return CANNON.Mat3 + */ +CANNON.Vec3.prototype.crossmat = function(){ + return new CANNON.Mat3([ 0, -this.z, this.y, + this.z, 0, -this.x, + -this.y, this.x, 0]); +}; + +/** + * @method normalize + * @memberof CANNON.Vec3 + * @brief Normalize the vector. Note that this changes the values in the vector. + * @return float Returns the norm of the vector + */ +CANNON.Vec3.prototype.normalize = function(){ + var x=this.x, y=this.y, z=this.z; + var n = Math.sqrt(x*x + y*y + z*z); + if(n>0.0){ + var invN = 1/n; + this.x *= invN; + this.y *= invN; + this.z *= invN; + } else { + // Make something up + this.x = 0; + this.y = 0; + this.z = 0; + } + return n; +}; + +/** + * @method unit + * @memberof CANNON.Vec3 + * @brief Get the version of this vector that is of length 1. + * @param CANNON.Vec3 target Optional target to save in + * @return CANNON.Vec3 Returns the unit vector + */ +CANNON.Vec3.prototype.unit = function(target){ + target = target || new CANNON.Vec3(); + var x=this.x, y=this.y, z=this.z; + var ninv = Math.sqrt(x*x + y*y + z*z); + if(ninv>0.0){ + ninv = 1.0/ninv; + target.x = x * ninv; + target.y = y * ninv; + target.z = z * ninv; + } else { + target.x = 1; + target.y = 0; + target.z = 0; + } + return target; +}; + +/** + * @method norm + * @memberof CANNON.Vec3 + * @brief Get the 2-norm (length) of the vector + * @return float + */ +CANNON.Vec3.prototype.norm = function(){ + var x=this.x, y=this.y, z=this.z; + return Math.sqrt(x*x + y*y + z*z); +}; + +/** + * @method norm2 + * @memberof CANNON.Vec3 + * @brief Get the squared length of the vector + * @return float + */ +CANNON.Vec3.prototype.norm2 = function(){ + return this.dot(this); +}; + +CANNON.Vec3.prototype.distanceTo = function(p){ + var x=this.x, y=this.y, z=this.z; + var px=p.x, py=p.y, pz=p.z; + return Math.sqrt((px-x)*(px-x)+ + (py-y)*(py-y)+ + (pz-z)*(pz-z)); +}; + +/** + * @method mult + * @memberof CANNON.Vec3 + * @brief Multiply the vector with a scalar + * @param float scalar + * @param CANNON.Vec3 target + * @return CANNON.Vec3 + */ +CANNON.Vec3.prototype.mult = function(scalar,target){ + target = target || new CANNON.Vec3(); + var x = this.x, + y = this.y, + z = this.z; + target.x = scalar * x; + target.y = scalar * y; + target.z = scalar * z; + return target; +}; + +/** + * @method dot + * @memberof CANNON.Vec3 + * @brief Calculate dot product + * @param CANNON.Vec3 v + * @return float + */ +CANNON.Vec3.prototype.dot = function(v){ + return this.x * v.x + this.y * v.y + this.z * v.z; +}; + +/** + * @method isZero + * @memberof CANNON.Vec3 + * @return bool + */ +CANNON.Vec3.prototype.isZero = function(){ + return this.x===0 && this.y===0 && this.z===0; +}; + +/** + * @method negate + * @memberof CANNON.Vec3 + * @brief Make the vector point in the opposite direction. + * @param CANNON.Vec3 target Optional target to save in + * @return CANNON.Vec3 + */ +CANNON.Vec3.prototype.negate = function(target){ + target = target || new CANNON.Vec3(); + target.x = -this.x; + target.y = -this.y; + target.z = -this.z; + return target; +}; + +/** + * @method tangents + * @memberof CANNON.Vec3 + * @brief Compute two artificial tangents to the vector + * @param CANNON.Vec3 t1 Vector object to save the first tangent in + * @param CANNON.Vec3 t2 Vector object to save the second tangent in + */ +var Vec3_tangents_n = new CANNON.Vec3(); +var Vec3_tangents_randVec = new CANNON.Vec3(); +CANNON.Vec3.prototype.tangents = function(t1,t2){ + var norm = this.norm(); + if(norm>0.0){ + var n = Vec3_tangents_n; + var inorm = 1/norm; + n.set(this.x*inorm,this.y*inorm,this.z*inorm); + var randVec = Vec3_tangents_randVec; + if(Math.abs(n.x) < 0.9){ + randVec.set(1,0,0); + n.cross(randVec,t1); + } else { + randVec.set(0,1,0); + n.cross(randVec,t1); + } + n.cross(t1,t2); + } else { + // The normal length is zero, make something up + t1.set(1,0,0).normalize(); + t2.set(0,1,0).normalize(); + } +}; + +/** + * @method toString + * @memberof CANNON.Vec3 + * @brief Converts to a more readable format + * @return string + */ +CANNON.Vec3.prototype.toString = function(){ + return this.x+","+this.y+","+this.z; +}; + +/** + * @method copy + * @memberof CANNON.Vec3 + * @brief Copy the vector. + * @param CANNON.Vec3 target + * @return CANNON.Vec3 + */ +CANNON.Vec3.prototype.copy = function(target){ + target = target || new CANNON.Vec3(); + target.x = this.x; + target.y = this.y; + target.z = this.z; + return target; +}; + + +/** + * @method lerp + * @memberof CANNON.Vec3 + * @brief Do a linear interpolation between two vectors + * @param CANNON.Vec3 v + * @param float t A number between 0 and 1. 0 will make this function return u, and 1 will make it return v. Numbers in between will generate a vector in between them. + * @param CANNON.Vec3 target + */ +CANNON.Vec3.prototype.lerp = function(v,t,target){ + var x=this.x, y=this.y, z=this.z; + target.x = x + (v.x-x)*t; + target.y = y + (v.y-y)*t; + target.z = z + (v.z-z)*t; +}; + +/** + * @method almostEquals + * @memberof CANNON.Vec3 + * @brief Check if a vector equals is almost equal to another one. + * @param CANNON.Vec3 v + * @param float precision + * @return bool + */ +CANNON.Vec3.prototype.almostEquals = function(v,precision){ + if(precision===undefined){ + precision = 1e-6; + } + if( Math.abs(this.x-v.x)>precision || + Math.abs(this.y-v.y)>precision || + Math.abs(this.z-v.z)>precision){ + return false; + } + return true; +}; + +/** + * @method almostZero + * @brief Check if a vector is almost zero + * @param float precision + * @memberof CANNON.Vec3 + */ +CANNON.Vec3.prototype.almostZero = function(precision){ + if(precision===undefined){ + precision = 1e-6; + } + if( Math.abs(this.x)>precision || + Math.abs(this.y)>precision || + Math.abs(this.z)>precision){ + return false; + } + return true; +}; + + +/** + * @class CANNON.Quaternion + * @brief A Quaternion describes a rotation in 3D space. + * @description The Quaternion is mathematically defined as Q = x*i + y*j + z*k + w, where (i,j,k) are imaginary basis vectors. (x,y,z) can be seen as a vector related to the axis of rotation, while the real multiplier, w, is related to the amount of rotation. + * @param float x Multiplier of the imaginary basis vector i. + * @param float y Multiplier of the imaginary basis vector j. + * @param float z Multiplier of the imaginary basis vector k. + * @param float w Multiplier of the real part. + * @see http://en.wikipedia.org/wiki/Quaternion + */ +CANNON.Quaternion = function(x,y,z,w){ + /** + * @property float x + * @memberof CANNON.Quaternion + */ + this.x = x!==undefined ? x : 0; + /** + * @property float y + * @memberof CANNON.Quaternion + */ + this.y = y!==undefined ? y : 0; + /** + * @property float z + * @memberof CANNON.Quaternion + */ + this.z = z!==undefined ? z : 0; + /** + * @property float w + * @memberof CANNON.Quaternion + * @brief The multiplier of the real quaternion basis vector. + */ + this.w = w!==undefined ? w : 1; +}; + +/** + * @method set + * @memberof CANNON.Quaternion + * @brief Set the value of the quaternion. + * @param float x + * @param float y + * @param float z + * @param float w + */ +CANNON.Quaternion.prototype.set = function(x,y,z,w){ + this.x = x; + this.y = y; + this.z = z; + this.w = w; +}; + +/** + * @method toString + * @memberof CANNON.Quaternion + * @brief Convert to a readable format + * @return string + */ +CANNON.Quaternion.prototype.toString = function(){ + return this.x+","+this.y+","+this.z+","+this.w; +}; + +/** + * @method setFromAxisAngle + * @memberof CANNON.Quaternion + * @brief Set the quaternion components given an axis and an angle. + * @param CANNON.Vec3 axis + * @param float angle in radians + */ +CANNON.Quaternion.prototype.setFromAxisAngle = function(axis,angle){ + var s = Math.sin(angle*0.5); + this.x = axis.x * s; + this.y = axis.y * s; + this.z = axis.z * s; + this.w = Math.cos(angle*0.5); +}; + +// saves axis to targetAxis and returns +CANNON.Quaternion.prototype.toAxisAngle = function(targetAxis){ + targetAxis = targetAxis || new CANNON.Vec3(); + this.normalize(); // if w>1 acos and sqrt will produce errors, this cant happen if quaternion is normalised + var angle = 2 * Math.acos(this.w); + var s = Math.sqrt(1-this.w*this.w); // assuming quaternion normalised then w is less than 1, so term always positive. + if (s < 0.001) { // test to avoid divide by zero, s is always positive due to sqrt + // if s close to zero then direction of axis not important + targetAxis.x = this.x; // if it is important that axis is normalised then replace with x=1; y=z=0; + targetAxis.y = this.y; + targetAxis.z = this.z; + } else { + targetAxis.x = this.x / s; // normalise axis + targetAxis.y = this.y / s; + targetAxis.z = this.z / s; + } + return [targetAxis,angle]; +}; + +/** + * @method setFromVectors + * @memberof CANNON.Quaternion + * @brief Set the quaternion value given two vectors. The resulting rotation will be the needed rotation to rotate u to v. + * @param CANNON.Vec3 u + * @param CANNON.Vec3 v + */ +CANNON.Quaternion.prototype.setFromVectors = function(u,v){ + var a = u.cross(v); + this.x = a.x; + this.y = a.y; + this.z = a.z; + this.w = Math.sqrt(Math.pow(u.norm(),2) * Math.pow(v.norm(),2)) + u.dot(v); + this.normalize(); +}; + +/** + * @method mult + * @memberof CANNON.Quaternion + * @brief Quaternion multiplication + * @param CANNON.Quaternion q + * @param CANNON.Quaternion target Optional. + * @return CANNON.Quaternion + */ +var Quaternion_mult_va = new CANNON.Vec3(); +var Quaternion_mult_vb = new CANNON.Vec3(); +var Quaternion_mult_vaxvb = new CANNON.Vec3(); +CANNON.Quaternion.prototype.mult = function(q,target){ + target = target || new CANNON.Quaternion(); + var w = this.w, + va = Quaternion_mult_va, + vb = Quaternion_mult_vb, + vaxvb = Quaternion_mult_vaxvb; + + va.set(this.x,this.y,this.z); + vb.set(q.x,q.y,q.z); + target.w = w*q.w - va.dot(vb); + va.cross(vb,vaxvb); + + target.x = w * vb.x + q.w*va.x + vaxvb.x; + target.y = w * vb.y + q.w*va.y + vaxvb.y; + target.z = w * vb.z + q.w*va.z + vaxvb.z; + + return target; +}; + +/** + * @method inverse + * @memberof CANNON.Quaternion + * @brief Get the inverse quaternion rotation. + * @param CANNON.Quaternion target + * @return CANNON.Quaternion + */ +CANNON.Quaternion.prototype.inverse = function(target){ + var x = this.x, y = this.y, z = this.z, w = this.w; + target = target || new CANNON.Quaternion(); + + this.conjugate(target); + var inorm2 = 1/(x*x + y*y + z*z + w*w); + target.x *= inorm2; + target.y *= inorm2; + target.z *= inorm2; + target.w *= inorm2; + + return target; +}; + +/** + * @method conjugate + * @memberof CANNON.Quaternion + * @brief Get the quaternion conjugate + * @param CANNON.Quaternion target + * @return CANNON.Quaternion + */ +CANNON.Quaternion.prototype.conjugate = function(target){ + target = target || new CANNON.Quaternion(); + + target.x = -this.x; + target.y = -this.y; + target.z = -this.z; + target.w = this.w; + + return target; +}; + +/** + * @method normalize + * @memberof CANNON.Quaternion + * @brief Normalize the quaternion. Note that this changes the values of the quaternion. + */ +CANNON.Quaternion.prototype.normalize = function(){ + var l = Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w); + if ( l === 0 ) { + this.x = 0; + this.y = 0; + this.z = 0; + this.w = 0; + } else { + l = 1 / l; + this.x *= l; + this.y *= l; + this.z *= l; + this.w *= l; + } +}; + +/** + * @method normalizeFast + * @memberof CANNON.Quaternion + * @brief Approximation of quaternion normalization. Works best when quat is already almost-normalized. + * @see http://jsperf.com/fast-quaternion-normalization + * @author unphased, https://github.com/unphased + */ +CANNON.Quaternion.prototype.normalizeFast = function () { + var f = (3.0-(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w))/2.0; + if ( f === 0 ) { + this.x = 0; + this.y = 0; + this.z = 0; + this.w = 0; + } else { + this.x *= f; + this.y *= f; + this.z *= f; + this.w *= f; + } +}; + +/** + * @method vmult + * @memberof CANNON.Quaternion + * @brief Multiply the quaternion by a vector + * @param CANNON.Vec3 v + * @param CANNON.Vec3 target Optional + * @return CANNON.Vec3 + */ +CANNON.Quaternion.prototype.vmult = function(v,target){ + target = target || new CANNON.Vec3(); + if(this.w===0.0){ + target.x = v.x; + target.y = v.y; + target.z = v.z; + } else { + + var x = v.x, + y = v.y, + z = v.z; + + var qx = this.x, + qy = this.y, + qz = this.z, + qw = this.w; + + // q*v + var ix = qw * x + qy * z - qz * y, + iy = qw * y + qz * x - qx * z, + iz = qw * z + qx * y - qy * x, + iw = -qx * x - qy * y - qz * z; + + target.x = ix * qw + iw * -qx + iy * -qz - iz * -qy; + target.y = iy * qw + iw * -qy + iz * -qx - ix * -qz; + target.z = iz * qw + iw * -qz + ix * -qy - iy * -qx; + } + + return target; +}; + +/** + * @method copy + * @memberof CANNON.Quaternion + * @param CANNON.Quaternion target + */ +CANNON.Quaternion.prototype.copy = function(target){ + target.x = this.x; + target.y = this.y; + target.z = this.z; + target.w = this.w; +}; + +/** + * @method toEuler + * @memberof CANNON.Quaternion + * @brief Convert the quaternion to euler angle representation. Order: YZX, as this page describes: http://www.euclideanspace.com/maths/standards/index.htm + * @param CANNON.Vec3 target + * @param string order Three-character string e.g. "YZX", which also is default. + */ +CANNON.Quaternion.prototype.toEuler = function(target,order){ + order = order || "YZX"; + + var heading, attitude, bank; + var x = this.x, y = this.y, z = this.z, w = this.w; + + switch(order){ + case "YZX": + var test = x*y + z*w; + if (test > 0.499) { // singularity at north pole + heading = 2 * Math.atan2(x,w); + attitude = Math.PI/2; + bank = 0; + } + if (test < -0.499) { // singularity at south pole + heading = -2 * Math.atan2(x,w); + attitude = - Math.PI/2; + bank = 0; + } + if(isNaN(heading)){ + var sqx = x*x; + var sqy = y*y; + var sqz = z*z; + heading = Math.atan2(2*y*w - 2*x*z , 1 - 2*sqy - 2*sqz); // Heading + attitude = Math.asin(2*test); // attitude + bank = Math.atan2(2*x*w - 2*y*z , 1 - 2*sqx - 2*sqz); // bank + } + break; + default: + throw new Error("Euler order "+order+" not supported yet."); + } + + target.y = heading; + target.z = attitude; + target.x = bank; +}; + +/** + * @class CANNON.EventTarget + * @see https://github.com/mrdoob/eventtarget.js/ + */ +CANNON.EventTarget = function () { + var listeners = {}; + this.addEventListener = function ( type, listener ) { + if ( listeners[ type ] === undefined ) { + listeners[ type ] = []; + } + if ( listeners[ type ].indexOf( listener ) === - 1 ) { + listeners[ type ].push( listener ); + } + }; + this.dispatchEvent = function ( event ) { + for ( var listener in listeners[ event.type ] ) { + listeners[ event.type ][ listener ]( event ); + } + }; + this.removeEventListener = function ( type, listener ) { + var index = listeners[ type ].indexOf( listener ); + if ( index !== - 1 ) { + listeners[ type ].splice( index, 1 ); + } + }; +}; + +/** + * @class CANNON.ObjectPool + * @brief For pooling objects that can be reused. + */ +CANNON.ObjectPool = function(){ + this.objects = []; + this.type = Object; +}; + +CANNON.ObjectPool.prototype.release = function(){ + var Nargs = arguments.length; + for(var i=0; i!==Nargs; i++){ + this.objects.push(arguments[i]); + } +}; + +CANNON.ObjectPool.prototype.get = function(){ + if(this.objects.length===0){ + return this.constructObject(); + } else { + return this.objects.pop(); + } +}; + +CANNON.ObjectPool.prototype.constructObject = function(){ + throw new Error("constructObject() not implemented in this ObjectPool subclass yet!"); +}; + +/** + * @class CANNON.Vec3Pool + */ +CANNON.Vec3Pool = function(){ + CANNON.ObjectPool.call(this); + this.type = CANNON.Vec3; +}; +CANNON.Vec3Pool.prototype = new CANNON.ObjectPool(); + +CANNON.Vec3Pool.prototype.constructObject = function(){ + return new CANNON.Vec3(); +}; + +/** + * @class CANNON.Shape + * @author schteppe + * @brief Base class for shapes + * @todo Should have a mechanism for caching bounding sphere radius instead of calculating it each time + */ +CANNON.Shape = function(){ + + /** + * @property int type + * @memberof CANNON.Shape + * @brief The type of this shape. Must be set to an int > 0 by subclasses. + * @see CANNON.Shape.types + */ + this.type = 0; + + this.aabbmin = new CANNON.Vec3(); + this.aabbmax = new CANNON.Vec3(); + + this.boundingSphereRadius = 0; + this.boundingSphereRadiusNeedsUpdate = true; +}; +CANNON.Shape.prototype.constructor = CANNON.Shape; + +/** + * @method computeBoundingSphereRadius + * @memberof CANNON.Shape + * @brief Computes the bounding sphere radius. The result is stored in the property .boundingSphereRadius + * @return float + */ +CANNON.Shape.prototype.computeBoundingSphereRadius = function(){ + throw "computeBoundingSphereRadius() not implemented for shape type "+this.type; +}; + +/** + * @method getBoundingSphereRadius + * @memberof CANNON.Shape + * @brief Returns the bounding sphere radius. The result is stored in the property .boundingSphereRadius + * @return float + */ +CANNON.Shape.prototype.getBoundingSphereRadius = function(){ + if (this.boundingSphereRadiusNeedsUpdate) { + this.computeBoundingSphereRadius(); + } + return this.boundingSphereRadius; +}; + +/** + * @method volume + * @memberof CANNON.Shape + * @brief Get the volume of this shape + * @return float + */ +CANNON.Shape.prototype.volume = function(){ + throw "volume() not implemented for shape type "+this.type; +}; + +/** + * @method calculateLocalInertia + * @memberof CANNON.Shape + * @brief Calculates the inertia in the local frame for this shape. + * @return CANNON.Vec3 + * @see http://en.wikipedia.org/wiki/List_of_moments_of_inertia + */ +CANNON.Shape.prototype.calculateLocalInertia = function(mass,target){ + throw "calculateLocalInertia() not implemented for shape type "+this.type; +}; + +/** + * @method calculateTransformedInertia + * @memberof CANNON.Shape + * @brief Calculates inertia in a specified frame for this shape. + * @return CANNON.Vec3 + */ +var Shape_calculateTransformedInertia_localInertia = new CANNON.Vec3(); +var Shape_calculateTransformedInertia_worldInertia = new CANNON.Vec3(); +CANNON.Shape.prototype.calculateTransformedInertia = function(mass,quat,target){ + target = target || new CANNON.Vec3(); + + // Compute inertia in the world frame + //quat.normalize(); + var localInertia = Shape_calculateTransformedInertia_localInertia; + var worldInertia = Shape_calculateTransformedInertia_worldInertia; + this.calculateLocalInertia(mass,localInertia); + + // @todo Is this rotation OK? Check! + quat.vmult(localInertia,worldInertia); + target.x = Math.abs(worldInertia.x); + target.y = Math.abs(worldInertia.y); + target.z = Math.abs(worldInertia.z); + return target; +}; + +// Calculates the local aabb and sets the result to .aabbmax and .aabbmin +CANNON.Shape.calculateLocalAABB = function(){ + throw new Error(".calculateLocalAABB is not implemented for this Shape yet!"); +}; + +/** + * @property Object types + * @memberof CANNON.Shape + * @brief The available shape types. + */ +CANNON.Shape.types = { + SPHERE:1, + PLANE:2, + BOX:4, + COMPOUND:8, + CONVEXPOLYHEDRON:16 +}; + + + +/** + * @class CANNON.Body + * @brief Base class for all body types. + * @param string type + * @extends CANNON.EventTarget + * @event collide The body object dispatches a "collide" event whenever it collides with another body. Event parameters are "with" (the body it collides with) and "contact" (the contact equation that is generated). + */ +CANNON.Body = function(type){ + + CANNON.EventTarget.apply(this); + + this.type = type; + + /** + * @property CANNON.World world + * @memberof CANNON.Body + * @brief Reference to the world the body is living in + */ + this.world = null; + + /** + * @property function preStep + * @memberof CANNON.Body + * @brief Callback function that is used BEFORE stepping the system. Use it to apply forces, for example. Inside the function, "this" will refer to this CANNON.Body object. + * @todo dispatch an event from the World instead + */ + this.preStep = null; + + /** + * @property function postStep + * @memberof CANNON.Body + * @brief Callback function that is used AFTER stepping the system. Inside the function, "this" will refer to this CANNON.Body object. + * @todo dispatch an event from the World instead + */ + this.postStep = null; + + this.vlambda = new CANNON.Vec3(); + + this.collisionFilterGroup = 1; + this.collisionFilterMask = 1; +}; + +/* + * @brief A dynamic body is fully simulated. Can be moved manually by the user, but normally they move according to forces. A dynamic body can collide with all body types. A dynamic body always has finite, non-zero mass. + */ +CANNON.Body.DYNAMIC = 1; + +/* + * @brief A static body does not move during simulation and behaves as if it has infinite mass. Static bodies can be moved manually by setting the position of the body. The velocity of a static body is always zero. Static bodies do not collide with other static or kinematic bodies. + */ +CANNON.Body.STATIC = 2; + +/* + * A kinematic body moves under simulation according to its velocity. They do not respond to forces. They can be moved manually, but normally a kinematic body is moved by setting its velocity. A kinematic body behaves as if it has infinite mass. Kinematic bodies do not collide with other static or kinematic bodies. + */ +CANNON.Body.KINEMATIC = 4; + +/** + * @class CANNON.Particle + * @brief A body consisting of one point mass. Does not have orientation. + * @param float mass + * @param CANNON.Material material + */ +CANNON.Particle = function(mass,material){ + + // Check input + if(typeof(mass)!=="number"){ + throw new Error("Argument 1 (mass) must be a number."); + } + if(typeof(material)!=="undefined" && !(material instanceof(CANNON.Material))){ + throw new Error("Argument 3 (material) must be an instance of CANNON.Material."); + } + + CANNON.Body.call(this,"particle"); + + /** + * @property CANNON.Vec3 position + * @memberof CANNON.Particle + */ + this.position = new CANNON.Vec3(); + + /** + * @property CANNON.Vec3 initPosition + * @memberof CANNON.Particle + * @brief Initial position of the body + */ + this.initPosition = new CANNON.Vec3(); + + /** + * @property CANNON.Vec3 velocity + * @memberof CANNON.Particle + */ + this.velocity = new CANNON.Vec3(); + + /** + * @property CANNON.Vec3 initVelocity + * @memberof CANNON.Particle + */ + this.initVelocity = new CANNON.Vec3(); + + /** + * @property CANNON.Vec3 force + * @memberof CANNON.Particle + * @brief Linear force on the body + */ + this.force = new CANNON.Vec3(); + + /** + * @property float mass + * @memberof CANNON.Particle + */ + this.mass = mass; + + /** + * @property float invMass + * @memberof CANNON.Particle + */ + this.invMass = mass>0 ? 1.0/mass : 0; + + /** + * @property CANNON.Material material + * @memberof CANNON.Particle + */ + this.material = material; + + /** + * @property float linearDamping + * @memberof CANNON.Particle + */ + this.linearDamping = 0.01; // Perhaps default should be zero here? + + /** + * @property int motionstate + * @memberof CANNON.Particle + * @brief One of the states CANNON.Body.DYNAMIC, CANNON.Body.STATIC and CANNON.Body.KINEMATIC + */ + this.motionstate = (mass <= 0.0 ? CANNON.Body.STATIC : CANNON.Body.DYNAMIC); + + /** + * @property bool allowSleep + * @memberof CANNON.Particle + * @brief If true, the body will automatically fall to sleep. + */ + this.allowSleep = true; + + // 0:awake, 1:sleepy, 2:sleeping + this.sleepState = 0; + + /** + * @property float sleepSpeedLimit + * @memberof CANNON.Particle + * @brief If the speed (the norm of the velocity) is smaller than this value, the body is considered sleepy. + */ + this.sleepSpeedLimit = 0.1; + + /** + * @property float sleepTimeLimit + * @memberof CANNON.Particle + * @brief If the body has been sleepy for this sleepTimeLimit seconds, it is considered sleeping. + */ + this.sleepTimeLimit = 1; + + this.timeLastSleepy = 0; + +}; + +CANNON.Particle.prototype = new CANNON.Body(); +CANNON.Particle.prototype.constructor = CANNON.Particle; + +/** +* @method isAwake +* @memberof CANNON.Particle +* @return bool +*/ +CANNON.Particle.prototype.isAwake = function(){ + return this.sleepState === 0; +}; + +/** +* @method isSleepy +* @memberof CANNON.Particle +* @return bool +*/ +CANNON.Particle.prototype.isSleepy = function(){ + return this.sleepState === 1; +}; + +/** +* @method isSleeping +* @memberof CANNON.Particle +* @return bool +*/ +CANNON.Particle.prototype.isSleeping = function(){ + return this.sleepState === 2; +}; + +/** +* @method wakeUp +* @memberof CANNON.Particle +* @brief Wake the body up. +*/ +CANNON.Particle.prototype.wakeUp = function(){ + var s = this.sleepState; + this.sleepState = 0; + if(s === 2){ + this.dispatchEvent({type:"wakeup"}); + } +}; + +/** +* @method sleep +* @memberof CANNON.Particle +* @brief Force body sleep +*/ +CANNON.Particle.prototype.sleep = function(){ + this.sleepState = 2; +}; + +/** +* @method sleepTick +* @memberof CANNON.Particle +* @param float time The world time in seconds +* @brief Called every timestep to update internal sleep timer and change sleep state if needed. +*/ +CANNON.Particle.prototype.sleepTick = function(time){ + if(this.allowSleep){ + var sleepState = this.sleepState; + var speedSquared = this.velocity.norm2(); + var speedLimitSquared = Math.pow(this.sleepSpeedLimit,2); + if(sleepState===0 && speedSquared < speedLimitSquared){ + this.sleepState = 1; // Sleepy + this.timeLastSleepy = time; + this.dispatchEvent({type:"sleepy"}); + } else if(sleepState===1 && speedSquared > speedLimitSquared){ + this.wakeUp(); // Wake up + } else if(sleepState===1 && (time - this.timeLastSleepy ) > this.sleepTimeLimit){ + this.sleepState = 2; // Sleeping + this.dispatchEvent({type:"sleep"}); + } + } +}; + + +/** + * @class CANNON.RigidBody + * @brief Rigid body base class + * @param float mass + * @param CANNON.Shape shape + * @param CANNON.Material material + */ +CANNON.RigidBody = function(mass,shape,material){ + + // Check input + if(typeof(mass)!=="number"){ + throw new Error("Argument 1 (mass) must be a number."); + } + if(typeof(material)!=="undefined" && !(material instanceof(CANNON.Material))){ + throw new Error("Argument 3 (material) must be an instance of CANNON.Material."); + } + + CANNON.Particle.call(this,mass,material); + + var that = this; + + /** + * @property CANNON.Vec3 tau + * @memberof CANNON.RigidBody + * @brief Rotational force on the body, around center of mass + */ + this.tau = new CANNON.Vec3(); + + /** + * @property CANNON.Quaternion quaternion + * @memberof CANNON.RigidBody + * @brief Orientation of the body + */ + this.quaternion = new CANNON.Quaternion(); + + /** + * @property CANNON.Quaternion initQuaternion + * @memberof CANNON.RigidBody + */ + this.initQuaternion = new CANNON.Quaternion(); + + /** + * @property CANNON.Vec3 angularVelocity + * @memberof CANNON.RigidBody + */ + this.angularVelocity = new CANNON.Vec3(); + + /** + * @property CANNON.Vec3 initAngularVelocity + * @memberof CANNON.RigidBody + */ + this.initAngularVelocity = new CANNON.Vec3(); + + /** + * @property CANNON.Shape shape + * @memberof CANNON.RigidBody + */ + this.shape = shape; + + /** + * @property CANNON.Vec3 inertia + * @memberof CANNON.RigidBody + */ + this.inertia = new CANNON.Vec3(); + shape.calculateLocalInertia(mass,this.inertia); + + this.inertiaWorld = new CANNON.Vec3(); + this.inertia.copy(this.inertiaWorld); + this.inertiaWorldAutoUpdate = false; + + /** + * @property CANNON.Vec3 intInertia + * @memberof CANNON.RigidBody + */ + this.invInertia = new CANNON.Vec3(this.inertia.x>0 ? 1.0/this.inertia.x : 0, + this.inertia.y>0 ? 1.0/this.inertia.y : 0, + this.inertia.z>0 ? 1.0/this.inertia.z : 0); + this.invInertiaWorld = new CANNON.Vec3(); + this.invInertia.copy(this.invInertiaWorld); + this.invInertiaWorldAutoUpdate = false; + + /** + * @property float angularDamping + * @memberof CANNON.RigidBody + */ + this.angularDamping = 0.01; // Perhaps default should be zero here? + + /** + * @property CANNON.Vec3 aabbmin + * @memberof CANNON.RigidBody + */ + this.aabbmin = new CANNON.Vec3(); + + /** + * @property CANNON.Vec3 aabbmax + * @memberof CANNON.RigidBody + */ + this.aabbmax = new CANNON.Vec3(); + + /** + * @property bool aabbNeedsUpdate + * @memberof CANNON.RigidBody + * @brief Indicates if the AABB needs to be updated before use. + */ + this.aabbNeedsUpdate = true; + + this.wlambda = new CANNON.Vec3(); +}; + +CANNON.RigidBody.prototype = new CANNON.Particle(0); +CANNON.RigidBody.prototype.constructor = CANNON.RigidBody; + +CANNON.RigidBody.prototype.computeAABB = function(){ + this.shape.calculateWorldAABB(this.position, + this.quaternion, + this.aabbmin, + this.aabbmax); + this.aabbNeedsUpdate = false; +}; + +/** + * Apply force to a world point. This could for example be a point on the RigidBody surface. Applying force this way will add to Body.force and Body.tau. + * @param CANNON.Vec3 force The amount of force to add. + * @param CANNON.Vec3 worldPoint A world point to apply the force on. + */ +var RigidBody_applyForce_r = new CANNON.Vec3(); +var RigidBody_applyForce_rotForce = new CANNON.Vec3(); +CANNON.RigidBody.prototype.applyForce = function(force,worldPoint){ + // Compute point position relative to the body center + var r = RigidBody_applyForce_r; + worldPoint.vsub(this.position,r); + + // Compute produced rotational force + var rotForce = RigidBody_applyForce_rotForce; + r.cross(force,rotForce); + + // Add linear force + this.force.vadd(force,this.force); + + // Add rotational force + this.tau.vadd(rotForce,this.tau); +}; + +/** + * Apply impulse to a world point. This could for example be a point on the RigidBody surface. An impulse is a force added to a body during a short period of time (impulse = force * time). Impulses will be added to Body.velocity and Body.angularVelocity. + * @param CANNON.Vec3 impulse The amount of impulse to add. + * @param CANNON.Vec3 worldPoint A world point to apply the force on. + */ +var RigidBody_applyImpulse_r = new CANNON.Vec3(); +var RigidBody_applyImpulse_velo = new CANNON.Vec3(); +var RigidBody_applyImpulse_rotVelo = new CANNON.Vec3(); +CANNON.RigidBody.prototype.applyImpulse = function(impulse,worldPoint){ + // Compute point position relative to the body center + var r = RigidBody_applyImpulse_r; + worldPoint.vsub(this.position,r); + + // Compute produced central impulse velocity + var velo = RigidBody_applyImpulse_velo; + impulse.copy(velo); + velo.mult(this.invMass,velo); + + // Add linear impulse + this.velocity.vadd(velo, this.velocity); + + // Compute produced rotational impulse velocity + var rotVelo = RigidBody_applyImpulse_rotVelo; + r.cross(impulse,rotVelo); + rotVelo.x *= this.invInertia.x; + rotVelo.y *= this.invInertia.y; + rotVelo.z *= this.invInertia.z; + + // Add rotational Impulse + this.angularVelocity.vadd(rotVelo, this.angularVelocity); +}; + + +/** + * @brief Spherical rigid body + * @class CANNON.Sphere + * @extends CANNON.Shape + * @param float radius + * @author schteppe / http://github.com/schteppe + */ +CANNON.Sphere = function(radius){ + CANNON.Shape.call(this); + + /** + * @property float radius + * @memberof CANNON.Sphere + */ + this.radius = radius!==undefined ? Number(radius) : 1.0; + this.type = CANNON.Shape.types.SPHERE; +}; +CANNON.Sphere.prototype = new CANNON.Shape(); +CANNON.Sphere.prototype.constructor = CANNON.Sphere; + +CANNON.Sphere.prototype.calculateLocalInertia = function(mass,target){ + target = target || new CANNON.Vec3(); + var I = 2.0*mass*this.radius*this.radius/5.0; + target.x = I; + target.y = I; + target.z = I; + return target; +}; + +CANNON.Sphere.prototype.volume = function(){ + return 4.0 * Math.PI * this.radius / 3.0; +}; + +CANNON.Sphere.prototype.computeBoundingSphereRadius = function(){ + this.boundingSphereRadiusNeedsUpdate = false; + this.boundingSphereRadius = this.radius; +}; + +CANNON.Sphere.prototype.calculateWorldAABB = function(pos,quat,min,max){ + var r = this.radius; + var axes = ['x','y','z']; + for(var i=0; i this.particles.length) + this.neighbors.pop(); + } +}; + +/** + * Get neighbors within smoothing volume, save in the array neighbors + * @param CANNON.Body particle + * @param Array neighbors + */ +var SPHSystem_getNeighbors_dist = new CANNON.Vec3(); +CANNON.SPHSystem.prototype.getNeighbors = function(particle,neighbors){ + var N = this.particles.length, + id = particle.id, + R2 = this.smoothingRadius * this.smoothingRadius, + dist = SPHSystem_getNeighbors_dist; + for(var i=0; i!==N; i++){ + var p = this.particles[i]; + p.position.vsub(particle.position,dist); + if(id!==p.id && dist.norm2() < R2){ + neighbors.push(p); + } + } +}; + +// Temp vectors for calculation +var SPHSystem_update_dist = new CANNON.Vec3(), + SPHSystem_update_a_pressure = new CANNON.Vec3(), + SPHSystem_update_a_visc = new CANNON.Vec3(), + SPHSystem_update_gradW = new CANNON.Vec3(), + SPHSystem_update_r_vec = new CANNON.Vec3(), + SPHSystem_update_u = new CANNON.Vec3(); // Relative velocity +CANNON.SPHSystem.prototype.update = function(){ + var N = this.particles.length, + dist = SPHSystem_update_dist, + cs = this.speedOfSound, + eps = this.eps; + + for(var i=0; i!==N; i++){ + var p = this.particles[i]; // Current particle + var neighbors = this.neighbors[i]; + + // Get neighbors + neighbors.length = 0; + this.getNeighbors(p,neighbors); + neighbors.push(this.particles[i]); // Add current too + var numNeighbors = neighbors.length; + + // Accumulate density for the particle + var sum = 0.0; + for(var j=0; j!==numNeighbors; j++){ + + //printf("Current particle has position %f %f %f\n",objects[id].pos.x(),objects[id].pos.y(),objects[id].pos.z()); + p.position.vsub(neighbors[j].position, dist); + var len = dist.norm(); + + var weight = this.w(len); + sum += neighbors[j].mass * weight; + } + + // Save + this.densities[i] = sum; + this.pressures[i] = cs * cs * (this.densities[i] - this.density); + } + + // Add forces + + // Sum to these accelerations + var a_pressure= SPHSystem_update_a_pressure; + var a_visc = SPHSystem_update_a_visc; + var gradW = SPHSystem_update_gradW; + var r_vec = SPHSystem_update_r_vec; + var u = SPHSystem_update_u; + + for(var i=0; i!==N; i++){ + + var particle = this.particles[i]; + + a_pressure.set(0,0,0); + a_visc.set(0,0,0); + + // Init vars + var Pij; + var nabla; + var Vij; + + // Sum up for all other neighbors + var neighbors = this.neighbors[i]; + var numNeighbors = neighbors.length; + + //printf("Neighbors: "); + for(var j=0; j!==numNeighbors; j++){ + + var neighbor = neighbors[j]; + //printf("%d ",nj); + + // Get r once for all.. + particle.position.vsub(neighbor.position,r_vec); + var r = r_vec.norm(); + + // Pressure contribution + Pij = -neighbor.mass * (this.pressures[i] / (this.densities[i]*this.densities[i] + eps) + this.pressures[j] / (this.densities[j]*this.densities[j] + eps)); + this.gradw(r_vec, gradW); + // Add to pressure acceleration + gradW.mult(Pij , gradW) + a_pressure.vadd(gradW, a_pressure); + + // Viscosity contribution + neighbor.velocity.vsub(particle.velocity, u); + u.mult( 1.0 / (0.0001+this.densities[i] * this.densities[j]) * this.viscosity * neighbor.mass , u ); + nabla = this.nablaw(r); + u.mult(nabla,u); + // Add to viscosity acceleration + a_visc.vadd( u, a_visc ); + } + + // Calculate force + a_visc.mult(particle.mass, a_visc); + a_pressure.mult(particle.mass, a_pressure); + + // Add force to particles + particle.force.vadd(a_visc, particle.force); + particle.force.vadd(a_pressure, particle.force); + } +}; + +// Calculate the weight using the W(r) weightfunction +CANNON.SPHSystem.prototype.w = function(r){ + // 315 + var h = this.smoothingRadius; + return 315.0/(64.0*Math.PI*Math.pow(h,9)) * Math.pow(h*h-r*r,3); +}; + +// calculate gradient of the weight function +CANNON.SPHSystem.prototype.gradw = function(rVec,resultVec){ + var r = rVec.norm(), + h = this.smoothingRadius; + rVec.mult(945.0/(32.0*Math.PI*Math.pow(h,9)) * Math.pow((h*h-r*r),2) , resultVec); +}; + +// Calculate nabla(W) +CANNON.SPHSystem.prototype.nablaw = function(r){ + var h = this.smoothingRadius; + var nabla = 945.0/(32.0*Math.PI*Math.pow(h,9)) * (h*h-r*r)*(7*r*r - 3*h*h); + return nabla; +}; + + +/** + * @class CANNON.Box + * @brief A 3d box shape. + * @param CANNON.Vec3 halfExtents + * @author schteppe + * @extends CANNON.Shape + */ +CANNON.Box = function(halfExtents){ + CANNON.Shape.call(this); + + /** + * @property CANNON.Vec3 halfExtents + * @memberof CANNON.Box + */ + this.halfExtents = halfExtents; + this.type = CANNON.Shape.types.BOX; + + /** + * @property CANNON.ConvexPolyhedron convexPolyhedronRepresentation + * @brief Used by the contact generator to make contacts with other convex polyhedra for example + * @memberof CANNON.Box + */ + this.convexPolyhedronRepresentation = null; + + this.updateConvexPolyhedronRepresentation(); +}; +CANNON.Box.prototype = new CANNON.Shape(); +CANNON.Box.prototype.constructor = CANNON.Box; + +/** + * @method updateConvexPolyhedronRepresentation + * @memberof CANNON.Box + * @brief Updates the local convex polyhedron representation used for some collisions. + */ +CANNON.Box.prototype.updateConvexPolyhedronRepresentation = function(){ + var sx = this.halfExtents.x; + var sy = this.halfExtents.y; + var sz = this.halfExtents.z; + var V = CANNON.Vec3; + + function createBoxPolyhedron(size){ + size = size || 1; + var vertices = [new CANNON.Vec3(-size,-size,-size), + new CANNON.Vec3( size,-size,-size), + new CANNON.Vec3( size, size,-size), + new CANNON.Vec3(-size, size,-size), + new CANNON.Vec3(-size,-size, size), + new CANNON.Vec3( size,-size, size), + new CANNON.Vec3( size, size, size), + new CANNON.Vec3(-size, size, size)]; + var faces =[[3,2,1,0], // -z + [4,5,6,7], // +z + [5,4,1,0], // -y + [2,3,6,7], // +y + [0,4,7,3 /*0,3,4,7*/ ], // -x + [1,2,5,6], // +x + ]; + var faceNormals = [new CANNON.Vec3( 0, 0,-1), + new CANNON.Vec3( 0, 0, 1), + new CANNON.Vec3( 0,-1, 0), + new CANNON.Vec3( 0, 1, 0), + new CANNON.Vec3(-1, 0, 0), + new CANNON.Vec3( 1, 0, 0)]; + var boxShape = new CANNON.ConvexPolyhedron(vertices, + faces, + faceNormals); + return boxShape; + } + + var h = new CANNON.ConvexPolyhedron([new V(-sx,-sy,-sz), + new V( sx,-sy,-sz), + new V( sx, sy,-sz), + new V(-sx, sy,-sz), + new V(-sx,-sy, sz), + new V( sx,-sy, sz), + new V( sx, sy, sz), + new V(-sx, sy, sz)], + [[3,2,1,0], // -z + [4,5,6,7], // +z + [5,4,1,0], // -y + [2,3,6,7], // +y + [0,4,7,3], // -x + [1,2,5,6], // +x + ], + [new V( 0, 0,-1), + new V( 0, 0, 1), + new V( 0,-1, 0), + new V( 0, 1, 0), + new V(-1, 0, 0), + new V( 1, 0, 0)]); + this.convexPolyhedronRepresentation = h; +}; + +CANNON.Box.prototype.calculateLocalInertia = function(mass,target){ + target = target || new CANNON.Vec3(); + var e = this.halfExtents; + target.x = 1.0 / 12.0 * mass * ( 2*e.y*2*e.y + 2*e.z*2*e.z ); + target.y = 1.0 / 12.0 * mass * ( 2*e.x*2*e.x + 2*e.z*2*e.z ); + target.z = 1.0 / 12.0 * mass * ( 2*e.y*2*e.y + 2*e.x*2*e.x ); + return target; +}; + +/** + * @method getSideNormals + * @memberof CANNON.Box + * @brief Get the box 6 side normals + * @param bool includeNegative If true, this function returns 6 vectors. If false, it only returns 3 (but you get 6 by reversing those 3) + * @param CANNON.Quaternion quat Orientation to apply to the normal vectors. If not provided, the vectors will be in respect to the local frame. + * @return array + */ +CANNON.Box.prototype.getSideNormals = function(sixTargetVectors,quat){ + var sides = sixTargetVectors; + var ex = this.halfExtents; + sides[0].set( ex.x, 0, 0); + sides[1].set( 0, ex.y, 0); + sides[2].set( 0, 0, ex.z); + sides[3].set( -ex.x, 0, 0); + sides[4].set( 0, -ex.y, 0); + sides[5].set( 0, 0, -ex.z); + + if(quat!==undefined){ + for(var i=0; i!==sides.length; i++){ + quat.vmult(sides[i],sides[i]); + } + } + + return sides; +}; + +CANNON.Box.prototype.volume = function(){ + return 8.0 * this.halfExtents.x * this.halfExtents.y * this.halfExtents.z; +}; + +CANNON.Box.prototype.computeBoundingSphereRadius = function(){ + this.boundingSphereRadius = this.halfExtents.norm(); + this.boundingSphereRadiusNeedsUpdate = false; +}; + +var worldCornerTempPos = new CANNON.Vec3(); +var worldCornerTempNeg = new CANNON.Vec3(); +CANNON.Box.prototype.forEachWorldCorner = function(pos,quat,callback){ + + var e = this.halfExtents; + var corners = [[ e.x, e.y, e.z], + [ -e.x, e.y, e.z], + [ -e.x, -e.y, e.z], + [ -e.x, -e.y, -e.z], + [ e.x, -e.y, -e.z], + [ e.x, e.y, -e.z], + [ -e.x, e.y, -e.z], + [ e.x, -e.y, e.z]]; + for(var i=0; i max.x){ + max.x = x; + } + if(y > max.y){ + max.y = y; + } + if(z > max.z){ + max.z = z; + } + + if(x < min.x){ + min.x = x; + } + if(y < min.y){ + min.y = y; + } + if(z < min.z){ + min.z = z; + } + }); +}; + +/** + * @class CANNON.Plane + * @extends CANNON.Shape + * @param CANNON.Vec3 normal + * @brief A plane, facing in the Z direction. + * @description A plane, facing in the Z direction. The plane has its surface at z=0 and everything below z=0 is assumed to be solid plane. To make the plane face in some other direction than z, you must put it inside a RigidBody and rotate that body. See the demos. + * @author schteppe + */ +CANNON.Plane = function(){ + CANNON.Shape.call(this); + this.type = CANNON.Shape.types.PLANE; + + // World oriented normal + this.worldNormal = new CANNON.Vec3(); + this.worldNormalNeedsUpdate = true; +}; +CANNON.Plane.prototype = new CANNON.Shape(); +CANNON.Plane.prototype.constructor = CANNON.Plane; + +CANNON.Plane.prototype.computeWorldNormal = function(quat){ + var n = this.worldNormal; + n.set(0,0,1); + quat.vmult(n,n); + this.worldNormalNeedsUpdate = false; +}; + +CANNON.Plane.prototype.calculateLocalInertia = function(mass,target){ + target = target || new CANNON.Vec3(); + return target; +}; + +CANNON.Plane.prototype.volume = function(){ + return Infinity; // The plane is infinite... +}; + +var tempNormal = new CANNON.Vec3(); +CANNON.Plane.prototype.calculateWorldAABB = function(pos,quat,min,max){ + // The plane AABB is infinite, except if the normal is pointing along any axis + tempNormal.set(0,0,1); // Default plane normal is z + quat.vmult(tempNormal,tempNormal); + min.set(-Infinity,-Infinity,-Infinity); + max.set(Infinity,Infinity,Infinity); + + if(tempNormal.x === 1){ max.x = pos.x; } + if(tempNormal.y === 1){ max.y = pos.y; } + if(tempNormal.z === 1){ max.z = pos.z; } + + if(tempNormal.x === -1){ min.x = pos.x; } + if(tempNormal.y === -1){ min.y = pos.y; } + if(tempNormal.z === -1){ min.z = pos.z; } + +}; + + +/** + * @class CANNON.Compound + * @extends CANNON.Shape + * @brief A shape made of several other shapes. + * @author schteppe + */ +CANNON.Compound = function(){ + CANNON.Shape.call(this); + this.type = CANNON.Shape.types.COMPOUND; + this.childShapes = []; + this.childOffsets = []; + this.childOrientations = []; +}; +CANNON.Compound.prototype = new CANNON.Shape(); +CANNON.Compound.prototype.constructor = CANNON.Compound; + +/** + * @method addChild + * @memberof CANNON.Compound + * @brief Add a child shape. + * @param CANNON.Shape shape + * @param CANNON.Vec3 offset + * @param CANNON.Quaternion orientation + */ +CANNON.Compound.prototype.addChild = function(shape,offset,orientation){ + offset = offset || new CANNON.Vec3(); + orientation = orientation || new CANNON.Quaternion(); + this.childShapes.push(shape); + this.childOffsets.push(offset); + this.childOrientations.push(orientation); +}; + +CANNON.Compound.prototype.volume = function(){ + var r = 0.0; + var Nchildren = this.childShapes.length; + for(var i=0; i!==Nchildren; i++){ + r += this.childShapes[i].volume(); + } + return r; +}; + +var Compound_calculateLocalInertia_mr2 = new CANNON.Vec3(); +var Compound_calculateLocalInertia_childInertia = new CANNON.Vec3(); +CANNON.Compound.prototype.calculateLocalInertia = function(mass,target){ + target = target || new CANNON.Vec3(); + + // Calculate the total volume, we will spread out this objects' mass on the sub shapes + var V = this.volume(); + var childInertia = Compound_calculateLocalInertia_childInertia; + for(var i=0, Nchildren=this.childShapes.length; i!==Nchildren; i++){ + // Get child information + var b = this.childShapes[i]; + var o = this.childOffsets[i]; + var q = this.childOrientations[i]; + var m = b.volume() / V * mass; + + // Get the child inertia, transformed relative to local frame + //var inertia = b.calculateTransformedInertia(m,q); + b.calculateLocalInertia(m,childInertia); // Todo transform! + //console.log(childInertia,m,b.volume(),V); + + // Add its inertia using the parallel axis theorem, i.e. + // I += I_child; + // I += m_child * r^2 + + target.vadd(childInertia,target); + var mr2 = Compound_calculateLocalInertia_mr2; + mr2.set(m*o.x*o.x, + m*o.y*o.y, + m*o.z*o.z); + target.vadd(mr2,target); + } + + return target; +}; + +CANNON.Compound.prototype.computeBoundingSphereRadius = function(){ + var r = 0.0; + for(var i = 0; i max.x){ + max.x = aabbmaxTemp.x; + } + if(aabbmaxTemp.y > max.y){ + max.y = aabbmaxTemp.y; + } + if(aabbmaxTemp.z > max.z){ + max.z = aabbmaxTemp.z; + } + } +}; + +/** + * @class CANNON.ConvexPolyhedron + * @extends CANNON.Shape + * @brief A set of points in space describing a convex shape. + * @author qiao / https://github.com/qiao (original author, see https://github.com/qiao/three.js/commit/85026f0c769e4000148a67d45a9e9b9c5108836f) + * @author schteppe / https://github.com/schteppe + * @see http://www.altdevblogaday.com/2011/05/13/contact-generation-between-3d-convex-meshes/ + * @see http://bullet.googlecode.com/svn/trunk/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp + * @todo move the clipping functions to ContactGenerator? + * @param array points An array of CANNON.Vec3's + * @param array faces + * @param array normals + */ +CANNON.ConvexPolyhedron = function( points , faces , normals ) { + var that = this; + CANNON.Shape.call( this ); + this.type = CANNON.Shape.types.CONVEXPOLYHEDRON; + + /* + * @brief Get face normal given 3 vertices + * @param CANNON.Vec3 va + * @param CANNON.Vec3 vb + * @param CANNON.Vec3 vc + * @param CANNON.Vec3 target + * @todo unit test? + */ + var cb = new CANNON.Vec3(); + var ab = new CANNON.Vec3(); + function normal( va, vb, vc, target ) { + vb.vsub(va,ab); + vc.vsub(vb,cb); + cb.cross(ab,target); + if ( !target.isZero() ) { + target.normalize(); + } + } + + /** + * @property array vertices + * @memberof CANNON.ConvexPolyhedron + * @brief Array of CANNON.Vec3 + */ + this.vertices = points||[]; + + this.worldVertices = []; // World transformed version of .vertices + this.worldVerticesNeedsUpdate = true; + + /** + * @property array faces + * @memberof CANNON.ConvexPolyhedron + * @brief Array of integer arrays, indicating which vertices each face consists of + * @todo Needed? + */ + this.faces = faces||[]; + + /** + * @property array faceNormals + * @memberof CANNON.ConvexPolyhedron + * @brief Array of CANNON.Vec3 + * @todo Needed? + */ + this.faceNormals = [];//normals||[]; + /* + for(var i=0; imax){ + max = val; + } + if(min===null || valmax){ + // Inconsistent - swap + var temp = min; + min = max; + max = temp; + } + // Output + maxmin[0] = max; + maxmin[1] = min; + } + + /** + * @method testSepAxis + * @memberof CANNON.ConvexPolyhedron + * @brief Test separating axis against two hulls. Both hulls are projected onto the axis and the overlap size is returned if there is one. + * @param CANNON.Vec3 axis + * @param CANNON.ConvexPolyhedron hullB + * @param CANNON.Vec3 posA + * @param CANNON.Quaternion quatA + * @param CANNON.Vec3 posB + * @param CANNON.Quaternion quatB + * @return float The overlap depth, or FALSE if no penetration. + */ + this.testSepAxis = function(axis, hullB, posA, quatA, posB, quatB){ + var maxminA=[], maxminB=[], hullA=this; + project(hullA, axis, posA, quatA, maxminA); + project(hullB, axis, posB, quatB, maxminB); + var maxA = maxminA[0]; + var minA = maxminA[1]; + var maxB = maxminB[0]; + var minB = maxminB[1]; + if(maxA0.0){ + target.negate(target); + } + return true; + }; + + /** + * @method clipAgainstHull + * @memberof CANNON.ConvexPolyhedron + * @brief Clip this hull against another hull + * @param CANNON.Vec3 posA + * @param CANNON.Quaternion quatA + * @param CANNON.ConvexPolyhedron hullB + * @param CANNON.Vec3 posB + * @param CANNON.Quaternion quatB + * @param CANNON.Vec3 separatingNormal + * @param float minDist Clamp distance + * @param float maxDist + * @param array result The an array of contact point objects, see clipFaceAgainstHull + * @see http://bullet.googlecode.com/svn/trunk/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp + */ + var WorldNormal = new CANNON.Vec3(); + this.clipAgainstHull = function(posA,quatA,hullB,posB,quatB,separatingNormal,minDist,maxDist,result){ + if(!(posA instanceof CANNON.Vec3)){ + throw new Error("posA must be Vec3"); + } + if(!(quatA instanceof CANNON.Quaternion)){ + throw new Error("quatA must be Quaternion"); + } + var hullA = this; + var curMaxDist = maxDist; + var closestFaceB = -1; + var dmax = -Infinity; + for(var face=0; face < hullB.faces.length; face++){ + hullB.faceNormals[face].copy(WorldNormal); + quatB.vmult(WorldNormal,WorldNormal); + //posB.vadd(WorldNormal,WorldNormal); + var d = WorldNormal.dot(separatingNormal); + if (d > dmax){ + dmax = d; + closestFaceB = face; + } + } + var worldVertsB1 = []; + var polyB = hullB.faces[closestFaceB]; + var numVertices = polyB.length; + for(var e0=0; e0=0){ + this.clipFaceAgainstHull(separatingNormal, + posA, + quatA, + worldVertsB1, + minDist, + maxDist, + result); + } + }; + + /** + * @method clipFaceAgainstHull + * @memberof CANNON.ConvexPolyhedron + * @brief Clip a face against a hull. + * @param CANNON.Vec3 separatingNormal + * @param CANNON.Vec3 posA + * @param CANNON.Quaternion quatA + * @param Array worldVertsB1 An array of CANNON.Vec3 with vertices in the world frame. + * @param float minDist Distance clamping + * @param float maxDist + * @param Array result Array to store resulting contact points in. Will be objects with properties: point, depth, normal. These are represented in world coordinates. + */ + var faceANormalWS = new CANNON.Vec3(); + var edge0 = new CANNON.Vec3(); + var WorldEdge0 = new CANNON.Vec3(); + var worldPlaneAnormal1 = new CANNON.Vec3(); + var planeNormalWS1 = new CANNON.Vec3(); + var worldA1 = new CANNON.Vec3(); + var localPlaneNormal = new CANNON.Vec3(); + var planeNormalWS = new CANNON.Vec3(); + this.clipFaceAgainstHull = function(separatingNormal, posA, quatA, worldVertsB1, minDist, maxDist,result){ + if(!(separatingNormal instanceof CANNON.Vec3)){ + throw new Error("sep normal must be vector"); + } + if(!(worldVertsB1 instanceof Array)){ + throw new Error("world verts must be array"); + } + minDist = Number(minDist); + maxDist = Number(maxDist); + var hullA = this; + var worldVertsB2 = []; + var pVtxIn = worldVertsB1; + var pVtxOut = worldVertsB2; + // Find the face with normal closest to the separating axis + var closestFaceA = -1; + var dmin = Infinity; + for(var face=0; face= 0, so output intersection + var newv = new CANNON.Vec3(); + firstVertex.lerp(lastVertex, + n_dot_first / (n_dot_first - n_dot_last), + newv); + outVertices.push(newv); + } + } else { + if(n_dot_last<0){ + // Start >= 0, end < 0 so output intersection and end + var newv = new CANNON.Vec3(); + firstVertex.lerp(lastVertex, + n_dot_first / (n_dot_first - n_dot_last), + newv); + outVertices.push(newv); + outVertices.push(lastVertex); + } + } + firstVertex = lastVertex; + n_dot_first = n_dot_last; + } + return outVertices; + }; + + var that = this; + function normalOfFace(i,target){ + var f = that.faces[i]; + var va = that.vertices[f[0]]; + var vb = that.vertices[f[1]]; + var vc = that.vertices[f[2]]; + return normal(va,vb,vc,target); + } + + function planeConstant(face_i,target){ + var f = that.faces[face_i]; + var n = that.faceNormals[face_i]; + var v = that.vertices[f[0]]; + var c = -n.dot(v); + return c; + } + + + function printFace(i){ + var f = that.faces[i], s = ""; + for(var j=0; j aabbmax.x){ + aabbmax.x = v.x; + } + if (v.y < aabbmin.y){ + aabbmin.y = v.y; + } else if(v.y > aabbmax.y){ + aabbmax.y = v.y; + } + if (v.z < aabbmin.z){ + aabbmin.z = v.z; + } else if(v.z > aabbmax.z){ + aabbmax.z = v.z; + } + } + }; + + //this.computeAABB(); +}; + +CANNON.ConvexPolyhedron.prototype = new CANNON.Shape(); +CANNON.ConvexPolyhedron.prototype.constructor = CANNON.ConvexPolyhedron; + +// Updates .worldVertices and sets .worldVerticesNeedsUpdate to false. +CANNON.ConvexPolyhedron.prototype.computeWorldVertices = function(position,quat){ + var N = this.vertices.length; + while(this.worldVertices.length < N){ + this.worldVertices.push( new CANNON.Vec3() ); + } + + var verts = this.vertices, + worldVerts = this.worldVertices; + for(var i=0; i!==N; i++){ + quat.vmult( verts[i] , worldVerts[i] ); + position.vadd( worldVerts[i] , worldVerts[i] ); + } + + this.worldVerticesNeedsUpdate = false; +}; + +// Updates .worldVertices and sets .worldVerticesNeedsUpdate to false. +CANNON.ConvexPolyhedron.prototype.computeWorldFaceNormals = function(quat){ + var N = this.faceNormals.length; + while(this.worldFaceNormals.length < N){ + this.worldFaceNormals.push( new CANNON.Vec3() ); + } + + var normals = this.faceNormals, + worldNormals = this.worldFaceNormals; + for(var i=0; i!==N; i++){ + quat.vmult( normals[i] , worldNormals[i] ); + } + + this.worldFaceNormalsNeedsUpdate = false; +}; + +CANNON.ConvexPolyhedron.prototype.computeBoundingSphereRadius = function(){ + // Assume points are distributed with local (0,0,0) as center + var max2 = 0; + var verts = this.vertices; + for(var i=0, N=verts.length; i!==N; i++) { + var norm2 = verts[i].norm2(); + if(norm2 > max2){ + max2 = norm2; + } + } + this.boundingSphereRadius = Math.sqrt(max2); + this.boundingSphereRadiusNeedsUpdate = false; +}; + +var tempWorldVertex = new CANNON.Vec3(); +CANNON.ConvexPolyhedron.prototype.calculateWorldAABB = function(pos,quat,min,max){ + var n = this.vertices.length, verts = this.vertices; + var minx,miny,minz,maxx,maxy,maxz; + for(var i=0; i maxx || maxx===undefined){ + maxx = v.x; + } + + if (v.y < miny || miny===undefined){ + miny = v.y; + } else if(v.y > maxy || maxy===undefined){ + maxy = v.y; + } + + if (v.z < minz || minz===undefined){ + minz = v.z; + } else if(v.z > maxz || maxz===undefined){ + maxz = v.z; + } + } + min.set(minx,miny,minz); + max.set(maxx,maxy,maxz); +}; + +// Just approximate volume! +CANNON.ConvexPolyhedron.prototype.volume = function(){ + if(this.boundingSphereRadiusNeedsUpdate){ + this.computeBoundingSphereRadius(); + } + return 4.0 * Math.PI * this.boundingSphereRadius / 3.0; +}; + +// Get an average of all the vertices +CANNON.ConvexPolyhedron.prototype.getAveragePointLocal = function(target){ + target = target || new CANNON.Vec3(); + var n = this.vertices.length, + verts = this.vertices; + for(var i=0; i0) || (r1>0 && r2<0)){ + return false; // Encountered some other sign. Exit. + } else { + } + } + + // If we got here, all dot products were of the same sign. + return positiveResult ? 1 : -1; +}; + + +function pointInConvex(p){ +} + +/** + * @class CANNON.Cylinder + * @extends CANNON.ConvexPolyhedron + * @author schteppe / https://github.com/schteppe + * @param float radiusTop + * @param float radiusBottom + * @param float height + * @param int numSegments The number of segments to build the cylinder out of + */ +CANNON.Cylinder = function( radiusTop, radiusBottom, height , numSegments ) { + var N = numSegments, + verts = [], + normals = [], + faces = [], + bottomface = [], + topface = [], + cos = Math.cos, + sin = Math.sin; + + // First bottom point + verts.push(new CANNON.Vec3(radiusBottom*cos(0), + radiusBottom*sin(0), + -height*0.5)); + bottomface.push(0); + + // First top point + verts.push(new CANNON.Vec3(radiusTop*cos(0), + radiusTop*sin(0), + height*0.5)); + topface.push(1); + + for(var i=0; i shape.getBoundingSphereRadius() ) { + return intersects; + } + + // Checking faces + var dot, scalar, faces = shape.faces, vertices = shape.vertices, normals = shape.faceNormals; + + + for (var fi = 0; fi < faces.length; fi++ ) { + + var face = faces[ fi ]; + var faceNormal = normals[ fi ]; + var q = quat; + var x = position; + + // determine if ray intersects the plane of the face + // note: this works regardless of the direction of the face normal + + // Get plane point in world coordinates... + vertices[face[0]].copy(vector); + q.vmult(vector,vector); + vector.vadd(x,vector); + + // ...but make it relative to the ray origin. We'll fix this later. + vector.vsub(this.origin,vector); + + // Get plane normal + q.vmult(faceNormal,normal); + + // If this dot product is negative, we have something interesting + dot = this.direction.dot(normal); + + // bail if ray and plane are parallel + if ( Math.abs( dot ) < precision ){ + continue; + } + + // calc distance to plane + scalar = normal.dot( vector ) / dot; + + // if negative distance, then plane is behind ray + if ( scalar < 0 ){ + continue; + } + + if ( dot < 0 ) { + + // Intersection point is origin + direction * scalar + this.direction.mult(scalar,intersectPoint); + intersectPoint.vadd(this.origin,intersectPoint); + + // a is the point we compare points b and c with. + vertices[ face[0] ].copy(a); + q.vmult(a,a); + x.vadd(a,a); + + for(var i=1; i= 0 ) && ( v >= 0 ) && ( u + v < 1 ); + } +}; +CANNON.Ray.prototype.constructor = CANNON.Ray; + + +/** + * @class CANNON.Broadphase + * @author schteppe + * @brief Base class for broadphase implementations + */ +CANNON.Broadphase = function(){ + /** + * @property CANNON.World world + * @brief The world to search for collisions in. + * @memberof CANNON.Broadphase + */ + this.world = null; + + /** + * If set to true, the broadphase uses bounding boxes for intersection test, else it uses bounding spheres. + * @property bool useBoundingBoxes + * @memberof CANNON.Broadphase + */ + this.useBoundingBoxes = false; +}; +CANNON.Broadphase.prototype.constructor = CANNON.BroadPhase; + +/** + * @method collisionPairs + * @memberof CANNON.Broadphase + * @brief Get the collision pairs from the world + * @param CANNON.World world The world to search in + * @param Array p1 Empty array to be filled with body objects + * @param Array p2 Empty array to be filled with body objects + * @return array An array with two subarrays of body indices + */ +CANNON.Broadphase.prototype.collisionPairs = function(world,p1,p2){ + throw new Error("collisionPairs not implemented for this BroadPhase class!"); +}; + +/** + * @method needBroadphaseCollision + * @memberof CANNON.Broadphase + * @brief Check if a body pair needs to be intersection tested at all. + * @param CANNON.Body bodyA + * @param CANNON.Body bodyB + * @return bool + */ +var Broadphase_needBroadphaseCollision_STATIC_OR_KINEMATIC = CANNON.Body.STATIC | CANNON.Body.KINEMATIC; +CANNON.Broadphase.prototype.needBroadphaseCollision = function(bodyA,bodyB){ + + // Check collision filter masks + if( (bodyA.collisionFilterGroup & bodyB.collisionFilterMask)===0 || (bodyB.collisionFilterGroup & bodyA.collisionFilterMask)===0){ + return false; + } + + // Check motionstate + if(((bodyA.motionstate & Broadphase_needBroadphaseCollision_STATIC_OR_KINEMATIC)!==0 || bodyA.isSleeping()) && + ((bodyB.motionstate & Broadphase_needBroadphaseCollision_STATIC_OR_KINEMATIC)!==0 || bodyB.isSleeping())) { + // Both bodies are static, kinematic or sleeping. Skip. + return false; + } + + // Two particles don't collide + if(!bodyA.shape && !bodyB.shape){ + return false; + } + + // Two planes don't collide + if(bodyA.shape instanceof CANNON.Plane && bodyB.shape instanceof CANNON.Plane){ + return false; + } + + return true; +}; + +/** + * @method intersectionTest + * @memberof CANNON.Broadphase + * @brief Check if a body pair needs to be intersection tested at all. + * @param CANNON.Body bodyA + * @param CANNON.Body bodyB + * @return bool + */ +CANNON.Broadphase.prototype.intersectionTest = function(bi,bj,pairs1,pairs2){ + if(this.useBoundingBoxes){ + this.doBoundingBoxBroadphase(bi,bj,pairs1,pairs2); + } else { + this.doBoundingSphereBroadphase(bi,bj,pairs1,pairs2); + } +}; + +/** + * @method doBoundingSphereBroadphase + * @memberof CANNON.Broadphase + * @brief Check if the bounding spheres of two bodies are intersecting. + * @param CANNON.Body bi + * @param CANNON.Body bj + * @param Array pairs1 bi is appended to this array if intersection + * @param Array pairs2 bj is appended to this array if intersection + */ +var Broadphase_collisionPairs_r = new CANNON.Vec3(), // Temp objects + Broadphase_collisionPairs_normal = new CANNON.Vec3(), + Broadphase_collisionPairs_quat = new CANNON.Quaternion(), + Broadphase_collisionPairs_relpos = new CANNON.Vec3(); +CANNON.Broadphase.prototype.doBoundingSphereBroadphase = function(bi,bj,pairs1,pairs2){ + + // Local fast access + var types = CANNON.Shape.types, + BOX_SPHERE_COMPOUND_CONVEX = types.SPHERE | types.BOX | types.COMPOUND | types.CONVEXPOLYHEDRON, + PLANE = types.PLANE, + STATIC_OR_KINEMATIC = CANNON.Body.STATIC | CANNON.Body.KINEMATIC; + + // Temp vecs + var r = Broadphase_collisionPairs_r, + normal = Broadphase_collisionPairs_normal, + quat = Broadphase_collisionPairs_quat, + relpos = Broadphase_collisionPairs_relpos; + + var bishape = bi.shape, bjshape = bj.shape; + if(bishape && bjshape){ + var ti = bishape.type, tj = bjshape.type; + + // --- Box / sphere / compound / convexpolyhedron collision --- + if((ti & BOX_SPHERE_COMPOUND_CONVEX) && (tj & BOX_SPHERE_COMPOUND_CONVEX)){ + // Rel. position + bj.position.vsub(bi.position,r); + + // Update bounding spheres if needed + if(bishape.boundingSphereRadiusNeedsUpdate){ + bishape.computeBoundingSphereRadius(); + } + if(bjshape.boundingSphereRadiusNeedsUpdate){ + bjshape.computeBoundingSphereRadius(); + } + + var boundingRadiusSum = bishape.boundingSphereRadius + bjshape.boundingSphereRadius; + if(r.norm2() < boundingRadiusSum*boundingRadiusSum){ + pairs1.push(bi); + pairs2.push(bj); + } + + // --- Sphere/box/compound/convexpoly versus plane --- + } else if((ti & BOX_SPHERE_COMPOUND_CONVEX) && (tj & types.PLANE) || (tj & BOX_SPHERE_COMPOUND_CONVEX) && (ti & types.PLANE)){ + var planeBody = (ti===PLANE) ? bi : bj, // Plane + otherBody = (ti!==PLANE) ? bi : bj; // Other + + var otherShape = otherBody.shape; + var planeShape = planeBody.shape; + + // Rel. position + otherBody.position.vsub(planeBody.position,r); + + if(planeShape.worldNormalNeedsUpdate){ + planeShape.computeWorldNormal(planeBody.quaternion); + } + + normal = planeShape.worldNormal; + + if(otherShape.boundingSphereRadiusNeedsUpdate){ + otherShape.computeBoundingSphereRadius(); + } + + var q = r.dot(normal) - otherShape.boundingSphereRadius; + if(q < 0.0){ + pairs1.push(bi); + pairs2.push(bj); + } + } + } else { + // Particle without shape + if(!bishape && !bjshape){ + // No collisions between 2 particles + } else { + var particle = bishape ? bj : bi; + var other = bishape ? bi : bj; + var otherShape = other.shape; + var type = otherShape.type; + + if(type & BOX_SPHERE_COMPOUND_CONVEX){ + if(type === types.SPHERE){ // particle-sphere + particle.position.vsub(other.position,relpos); + if(otherShape.radius*otherShape.radius >= relpos.norm2()){ + pairs1.push(particle); + pairs2.push(other); + } + } else if(type===types.CONVEXPOLYHEDRON || type===types.BOX || type===types.COMPOUND){ + + if(otherShape.boundingSphereRadiusNeedsUpdate){ + otherShape.computeBoundingSphereRadius(); + } + var R = otherShape.boundingSphereRadius; + particle.position.vsub(other.position,relpos); + if(R*R >= relpos.norm2()){ + pairs1.push(particle); + pairs2.push(other); + } + } + } else if(type === types.PLANE){ + // particle/plane + var plane = other; + normal.set(0,0,1); + plane.quaternion.vmult(normal,normal); + particle.position.vsub(plane.position,relpos); + if(normal.dot(relpos)<=0.0){ + pairs1.push(particle); + pairs2.push(other); + } + } + } + } +}; + +/** + * @method doBoundingBoxBroadphase + * @memberof CANNON.Broadphase + * @brief Check if the bounding boxes of two bodies are intersecting. + * @param CANNON.Body bi + * @param CANNON.Body bj + * @param Array pairs1 + * @param Array pairs2 + */ +CANNON.Broadphase.prototype.doBoundingBoxBroadphase = function(bi,bj,pairs1,pairs2){ + var bishape = bi.shape, + bjshape = bj.shape; + + if(bi.aabbNeedsUpdate){ + bi.computeAABB(); + } + if(bj.aabbNeedsUpdate){ + bj.computeAABB(); + } + + if(bishape && bjshape){ + // Check AABB / AABB + if( !( bi.aabbmax.x < bj.aabbmin.x || + bi.aabbmax.y < bj.aabbmin.y || + bi.aabbmax.z < bj.aabbmin.z || + bi.aabbmin.x > bj.aabbmax.x || + bi.aabbmin.y > bj.aabbmax.y || + bi.aabbmin.z > bj.aabbmax.z ) ){ + pairs1.push(bi); + pairs2.push(bj); + } + } else { + // Particle without shape + if(!bishape && !bjshape){ + // No collisions between 2 particles + } else { + // particle vs AABB + var p = !bishape ? bi : bj; + var other = !bishape ? bj : bi; + + if(other.shape instanceof CANNON.Plane){ + //console.log(p.position.z+"<"+other.aabbmin.z+" = ",p.position.z < other.aabbmin.z); + } + + if( !( p.position.x < other.aabbmin.x || + p.position.y < other.aabbmin.y || + p.position.z < other.aabbmin.z || + p.position.x > other.aabbmax.x || + p.position.y > other.aabbmax.y || + p.position.z > other.aabbmax.z ) ){ + pairs1.push(bi); + pairs2.push(bj); + } + } + } +}; + +/** + * @method makePairsUnique + * @memberof CANNON.Broadphase + * @brief Removes duplicate pairs from the pair arrays. + * @param Array pairs1 + * @param Array pairs2 + */ +var Broadphase_makePairsUnique_temp = {}, + Broadphase_makePairsUnique_p1 = [], + Broadphase_makePairsUnique_p2 = []; +CANNON.Broadphase.prototype.makePairsUnique = function(pairs1,pairs2){ + var t = Broadphase_makePairsUnique_temp, + p1 = Broadphase_makePairsUnique_p1, + p2 = Broadphase_makePairsUnique_p2, + N = pairs1.length; + + for(var i=0; i!==N; i++){ + p1[i] = pairs1[i]; + p2[i] = pairs2[i]; + } + + pairs1.length = 0; + pairs2.length = 0; + + for(var i=0; i!==N; i++){ + var id1 = p1[i].id, + id2 = p2[i].id; + var idx = id1 < id2 ? id1+","+id2 : id2+","+id1; + t[idx] = i; + } + + for(var idx in t){ + var i = t[idx]; + pairs1.push(p1[i]); + pairs2.push(p2[i]); + delete t[idx]; + } +}; + + +/** + * @class CANNON.NaiveBroadphase + * @brief Naive broadphase implementation, used in lack of better ones. + * @description The naive broadphase looks at all possible pairs without restriction, therefore it has complexity N^2 (which is bad) + * @extends CANNON.Broadphase + */ +CANNON.NaiveBroadphase = function(){ + CANNON.Broadphase.apply(this); +}; +CANNON.NaiveBroadphase.prototype = new CANNON.Broadphase(); +CANNON.NaiveBroadphase.prototype.constructor = CANNON.NaiveBroadphase; + +/** + * @method collisionPairs + * @memberof CANNON.NaiveBroadphase + * @brief Get all the collision pairs in the physics world + * @param CANNON.World world + * @param Array pairs1 + * @param Array pairs2 + */ +CANNON.NaiveBroadphase.prototype.collisionPairs = function(world,pairs1,pairs2){ + var bodies = world.bodies, + n = bodies.length, + i,j,bi,bj; + + // Naive N^2 ftw! + for(i=0; i!==n; i++){ + for(j=0; j!==i; j++){ + + bi = bodies[i]; + bj = bodies[j]; + + if(!this.needBroadphaseCollision(bi,bj)){ + continue; + } + + this.intersectionTest(bi,bj,pairs1,pairs2); + } + } +}; + + +/** + * @class CANNON.GridBroadphase + * @brief Axis aligned uniform grid broadphase. + * @extends CANNON.Broadphase + * @todo Needs support for more than just planes and spheres. + * @param CANNON.Vec3 aabbMin + * @param CANNON.Vec3 aabbMax + * @param int nx Number of boxes along x + * @param int ny Number of boxes along y + * @param int nz Number of boxes along z + */ +CANNON.GridBroadphase = function(aabbMin,aabbMax,nx,ny,nz){ + CANNON.Broadphase.apply(this); + this.nx = nx || 10; + this.ny = ny || 10; + this.nz = nz || 10; + this.aabbMin = aabbMin || new CANNON.Vec3(100,100,100); + this.aabbMax = aabbMax || new CANNON.Vec3(-100,-100,-100); + this.bins = []; +}; +CANNON.GridBroadphase.prototype = new CANNON.Broadphase(); +CANNON.GridBroadphase.prototype.constructor = CANNON.GridBroadphase; + +/** + * @method collisionPairs + * @memberof CANNON.GridBroadphase + * @brief Get all the collision pairs in the physics world + * @param CANNON.World world + * @param Array pairs1 + * @param Array pairs2 + */ +var GridBroadphase_collisionPairs_d = new CANNON.Vec3(); +var GridBroadphase_collisionPairs_binPos = new CANNON.Vec3(); +CANNON.GridBroadphase.prototype.collisionPairs = function(world,pairs1,pairs2){ + var N = world.numObjects(), + bodies = world.bodies; + + var max = this.aabbMax, + min = this.aabbMin, + nx = this.nx, + ny = this.ny, + nz = this.nz; + + var xmax = max.x, + ymax = max.y, + zmax = max.z, + xmin = min.x, + ymin = min.y, + zmin = min.z; + + var xmult = nx / (xmax-xmin), + ymult = ny / (ymax-ymin), + zmult = nz / (zmax-zmin); + + var binsizeX = (xmax - xmin) / nx, + binsizeY = (ymax - ymin) / ny, + binsizeZ = (zmax - zmin) / nz; + + var types = CANNON.Shape.types; + var SPHERE = types.SPHERE, + PLANE = types.PLANE, + BOX = types.BOX, + COMPOUND = types.COMPOUND, + CONVEXPOLYHEDRON = types.CONVEXPOLYHEDRON; + + var bins=this.bins, + Nbins=nx*ny*nz; + + // Reset bins + for(var i=bins.length-1; i!==Nbins; i++){ + bins.push([]); + } + for(var i=0; i!==Nbins; i++){ + bins[i].length = 0; + } + + var floor = Math.floor; + + // Put all bodies into the bins + for(var i=0; i!==N; i++){ + var bi = bodies[i]; + var si = bi.shape; + + switch(si.type){ + case SPHERE: + // Put in bin + // check if overlap with other bins + var x = bi.position.x, + y = bi.position.y, + z = bi.position.z; + var r = si.radius; + + var xi1 = floor(xmult * (x-r - xmin)), + yi1 = floor(ymult * (y-r - ymin)), + zi1 = floor(zmult * (z-r - zmin)), + xi2 = floor(xmult * (x+r - xmin)), + yi2 = floor(ymult * (y+r - ymin)), + zi2 = floor(zmult * (z+r - zmin)); + + for(var j=xi1; j!==xi2+1; j++){ + for(var k=yi1; k!==yi2+1; k++){ + for(var l=zi1; l!==zi2+1; l++){ + var xi = j, + yi = k, + zi = l; + var idx = xi * ( ny - 1 ) * ( nz - 1 ) + yi * ( nz - 1 ) + zi; + if(idx >= 0 && idx < Nbins){ + bins[ idx ].push( bi ); + } + } + } + } + break; + + case PLANE: + // Put in all bins for now + // @todo put only in bins that are actually intersecting the plane + var d = GridBroadphase_collisionPairs_d; + var binPos = GridBroadphase_collisionPairs_binPos; + var binRadiusSquared = (binsizeX*binsizeX + binsizeY*binsizeY + binsizeZ*binsizeZ) * 0.25; + + var planeNormal = si.worldNormal; + if(si.worldNormalNeedsUpdate){ + si.computeWorldNormal(bi.quaternion); + } + + for(var j=0; j!==nx; j++){ + for(var k=0; k!==ny; k++){ + for(var l=0; l!==nz; l++){ + var xi = j, + yi = k, + zi = l; + + binPos.set(xi*binsizeX+xmin, yi*binsizeY+ymin, zi*binsizeZ+zmin); + binPos.vsub(bi.position, d); + + if(d.dot(planeNormal) < binRadiusSquared){ + var idx = xi * ( ny - 1 ) * ( nz - 1 ) + yi * ( nz - 1 ) + zi; + bins[ idx ].push( bi ); + } + } + } + } + break; + + default: + console.warn("Shape "+si.type+" not supported in GridBroadphase!"); + break; + } + } + + // Check each bin + for(var i=0; i!==Nbins; i++){ + var bin = bins[i]; + + // Do N^2 broadphase inside + for(var j=0, NbodiesInBin=bin.length; j!==NbodiesInBin; j++){ + var bi = bin[j]; + + for(var k=0; k!==j; k++){ + var bj = bin[k]; + if(this.needBroadphaseCollision(bi,bj)){ + this.intersectionTest(bi,bj,pairs1,pairs2); + } + } + } + } + + this.makePairsUnique(pairs1,pairs2); +}; + + +/** + * @class CANNON.Solver + * @brief Constraint equation solver base class. + * @author schteppe / https://github.com/schteppe + */ +CANNON.Solver = function(){ + // All equations to be solved + this.equations = []; +}; + +// Should be implemented in subclasses! +CANNON.Solver.prototype.solve = function(dt,world){ + // Should return the number of iterations done! + return 0; +}; + +CANNON.Solver.prototype.addEquation = function(eq){ + this.equations.push(eq); +}; + +CANNON.Solver.prototype.removeEquation = function(eq){ + var eqs = this.equations; + var i = eqs.indexOf(eq); + if(i !== -1){ + eqs.splice(i,1); + } +}; + +CANNON.Solver.prototype.removeAllEquations = function(){ + this.equations.length = 0; +}; + + + +/** + * @class CANNON.Solver + * @brief Constraint equation Gauss-Seidel solver. + * @todo The spook parameters should be specified for each constraint, not globally. + * @author schteppe / https://github.com/schteppe + * @see https://www8.cs.umu.se/kurser/5DV058/VT09/lectures/spooknotes.pdf + * @extends CANNON.Solver + */ +CANNON.GSSolver = function(){ + CANNON.Solver.call(this); + + /** + * @property int iterations + * @brief The number of solver iterations determines quality of the constraints in the world. The more iterations, the more correct simulation. More iterations need more computations though. If you have a large gravity force in your world, you will need more iterations. + * @todo write more about solver and iterations in the wiki + * @memberof CANNON.GSSolver + */ + this.iterations = 10; + + /** + * When tolerance is reached, the system is assumed to be converged. + * @property float tolerance + */ + this.tolerance = 0; +}; +CANNON.GSSolver.prototype = new CANNON.Solver(); + +var GSSolver_solve_lambda = []; // Just temporary number holders that we want to reuse each solve. +var GSSolver_solve_invCs = []; +var GSSolver_solve_Bs = []; +CANNON.GSSolver.prototype.solve = function(dt,world){ + var d = this.d, + ks = this.k, + iter = 0, + maxIter = this.iterations, + tolSquared = this.tolerance*this.tolerance, + a = this.a, + b = this.b, + equations = this.equations, + Neq = equations.length, + bodies = world.bodies, + Nbodies = bodies.length, + h = dt, + q, B, invC, deltalambda, deltalambdaTot, GWlambda, lambdaj; + + // Things that does not change during iteration can be computed once + var invCs = GSSolver_solve_invCs, + Bs = GSSolver_solve_Bs, + lambda = GSSolver_solve_lambda; + invCs.length = 0; + Bs.length = 0; + lambda.length = 0; + for(var i=0; i!==Neq; i++){ + var c = equations[i]; + if(c.spookParamsNeedsUpdate){ + c.updateSpookParams(h); + c.spookParamsNeedsUpdate = false; + } + lambda[i] = 0.0; + Bs[i] = c.computeB(h); + invCs[i] = 1.0 / c.computeC(); + } + + + if(Neq !== 0){ + + // Reset vlambda + for(var i=0; i!==Nbodies; i++){ + var b=bodies[i], + vlambda=b.vlambda, + wlambda=b.wlambda; + vlambda.set(0,0,0); + if(wlambda){ + wlambda.set(0,0,0); + } + } + + // Iterate over equations + for(iter=0; iter!==maxIter; iter++){ + + // Accumulate the total error for each iteration. + deltalambdaTot = 0.0; + + for(var j=0; j!==Neq; j++){ + + var c = equations[j]; + + // Compute iteration + B = Bs[j]; + invC = invCs[j]; + lambdaj = lambda[j]; + GWlambda = c.computeGWlambda(); + deltalambda = invC * ( B - GWlambda - c.eps * lambdaj ); + + // Clamp if we are not within the min/max interval + if(lambdaj + deltalambda < c.minForce){ + deltalambda = c.minForce - lambdaj; + } else if(lambdaj + deltalambda > c.maxForce){ + deltalambda = c.maxForce - lambdaj; + } + lambda[j] += deltalambda; + + deltalambdaTot += deltalambda > 0.0 ? deltalambda : -deltalambda; // abs(deltalambda) + + c.addToWlambda(deltalambda); + } + + // If the total error is small enough - stop iterate + if(deltalambdaTot*deltalambdaTot < tolSquared){ + break; + } + } + + // Add result to velocity + for(var i=0; i!==Nbodies; i++){ + var b=bodies[i], + v=b.velocity, + w=b.angularVelocity; + v.vadd(b.vlambda, v); + if(w){ + w.vadd(b.wlambda, w); + } + } + } + + return iter; +}; + + +CANNON.SplitSolver = function(subsolver){ + CANNON.Solver.call(this); + this.subsolver = subsolver; +}; +CANNON.SplitSolver.prototype = new CANNON.Solver(); + +// Returns the number of subsystems +var SplitSolver_solve_nodes = []; // All allocated node objects +var SplitSolver_solve_eqs = []; // Temp array +var SplitSolver_solve_bds = []; // Temp array +var SplitSolver_solve_dummyWorld = {bodies:null}; // Temp object +CANNON.SplitSolver.prototype.solve = function(dt,world){ + var nodes=SplitSolver_solve_nodes, + bodies=world.bodies, + equations=this.equations, + Neq=equations.length, + Nbodies=bodies.length, + subsolver=this.subsolver; + // Create needed nodes, reuse if possible + for(var i=nodes.length; i!==Nbodies; i++){ + nodes.push({ body:bodies[i], children:[], eqs:[], visited:false }); + } + + // Reset node values + for(var i=0; i!==Nbodies; i++){ + var node = nodes[i]; + node.body = bodies[i]; + node.children.length = 0; + node.eqs.length = 0; + node.visited = false; + } + for(var k=0; k!==Neq; k++){ + var eq=equations[k], + i=bodies.indexOf(eq.bi), + j=bodies.indexOf(eq.bj), + ni=nodes[i], + nj=nodes[j]; + ni.children.push(nj); + ni.eqs.push(eq); + nj.children.push(ni); + nj.eqs.push(eq); + } + + var STATIC = CANNON.Body.STATIC; + function getUnvisitedNode(nodes){ + var Nnodes = nodes.length; + for(var i=0; i!==Nnodes; i++){ + var node = nodes[i]; + if(!node.visited && !(node.body.motionstate & STATIC)){ + return node; + } + } + return false; + } + + function bfs(root,visitFunc){ + var queue = []; + queue.push(root); + root.visited = true; + visitFunc(root); + while(queue.length) { + var node = queue.pop(); + // Loop over unvisited child nodes + var child; + while((child = getUnvisitedNode(node.children))) { + child.visited = true; + visitFunc(child); + queue.push(child); + } + } + } + + var child, n=0, eqs=SplitSolver_solve_eqs, bds=SplitSolver_solve_bds; + function visitFunc(node){ + bds.push(node.body); + var Neqs = node.eqs.length; + for(var i=0; i!==Neqs; i++){ + var eq = node.eqs[i]; + if(eqs.indexOf(eq) === -1){ + eqs.push(eq); + } + } + } + var dummyWorld = SplitSolver_solve_dummyWorld; + while((child = getUnvisitedNode(nodes))){ + eqs.length = 0; + bds.length = 0; + bfs(child,visitFunc); + + var Neqs = eqs.length; + for(var i=0; i!==Neqs; i++){ + subsolver.addEquation(eqs[i]); + } + + dummyWorld.bodies = bds; + var iter = subsolver.solve(dt,dummyWorld); + subsolver.removeAllEquations(); + n++; + } + + return n; +}; + + +/** + * @class CANNON.Material + * @brief Defines a physics material. + * @param string name + * @author schteppe + */ +CANNON.Material = function(name){ + /** + * @property string name + * @memberof CANNON.Material + */ + this.name = name; + this.id = -1; +}; + + + +/** + * @class CANNON.ContactMaterial + * @brief Defines what happens when two materials meet. + * @param CANNON.Material m1 + * @param CANNON.Material m2 + * @param float friction + * @param float restitution + * @todo Contact solving parameters here too? + */ +CANNON.ContactMaterial = function(m1, m2, friction, restitution){ + + /// Contact material index in the world, -1 until added to the world + this.id = -1; + + /// The two materials participating in the contact + this.materials = [m1,m2]; + + /// Kinetic friction + this.friction = friction!==undefined ? Number(friction) : 0.3; + + /// Restitution + this.restitution = restitution !== undefined ? Number(restitution) : 0.3; + + // Parameters to pass to the constraint when it is created + this.contactEquationStiffness = 1e7; + this.contactEquationRegularizationTime = 3; + this.frictionEquationStiffness = 1e7; + this.frictionEquationRegularizationTime = 3; +}; + + + +/** + * @class CANNON.World + * @brief The physics world + */ +CANNON.World = function(){ + + CANNON.EventTarget.apply(this); + + /** + * @property bool allowSleep + * @brief Makes bodies go to sleep when they've been inactive + * @memberof CANNON.World + */ + this.allowSleep = false; + + /** + * @property Array contacts + * @brief All the current contacts (instances of CANNON.ContactEquation) in the world. + * @memberof CANNON.World + */ + this.contacts = []; + this.frictionEquations = []; + + /** + * @property int quatNormalizeSkip + * @brief How often to normalize quaternions. Set to 0 for every step, 1 for every second etc.. A larger value increases performance. If bodies tend to explode, set to a smaller value (zero to be sure nothing can go wrong). + * @memberof CANNON.World + */ + this.quatNormalizeSkip = 0; + + /** + * @property bool quatNormalizeFast + * @brief Set to true to use fast quaternion normalization. It is often enough accurate to use. If bodies tend to explode, set to false. + * @memberof CANNON.World + * @see CANNON.Quaternion.normalizeFast + * @see CANNON.Quaternion.normalize + */ + this.quatNormalizeFast = false; + + /** + * @property float time + * @brief The wall-clock time since simulation start + * @memberof CANNON.World + */ + this.time = 0.0; + + /** + * @property int stepnumber + * @brief Number of timesteps taken since start + * @memberof CANNON.World + */ + this.stepnumber = 0; + + /// Default and last timestep sizes + this.default_dt = 1/60; + this.last_dt = this.default_dt; + + this.nextId = 0; + /** + * @property CANNON.Vec3 gravity + * @memberof CANNON.World + */ + this.gravity = new CANNON.Vec3(); + + /** + * @property CANNON.Broadphase broadphase + * @memberof CANNON.World + */ + this.broadphase = null; + + /** + * @property Array bodies + * @memberof CANNON.World + */ + this.bodies = []; + + var th = this; + + /** + * @property CANNON.Solver solver + * @memberof CANNON.World + */ + this.solver = new CANNON.GSSolver(); + + /** + * @property Array constraints + * @memberof CANNON.World + */ + this.constraints = []; + + /** + * @property CANNON.ContactGenerator contactgen + * @memberof CANNON.World + */ + this.contactgen = new CANNON.ContactGenerator(); + + /** @property Collision "matrix", size (Nbodies * (Nbodies.length + 1))/2 + * @brief It's actually a triangular-shaped array of whether two bodies are touching this step, for reference next step + * @memberof CANNON.World + */ + this.collisionMatrix = []; + /** @property Collision "matrix", size (Nbodies * (Nbodies.length + 1))/2 + * @brief collisionMatrix from the previous step + * @memberof CANNON.World + */ + this.collisionMatrixPrevious = []; + + /** + * @property Array materials + * @memberof CANNON.World + */ + this.materials = []; // References to all added materials + + /** + * @property Array contactmaterials + * @memberof CANNON.World + */ + this.contactmaterials = []; // All added contact materials + + this.mats2cmat = []; // Hash: (mat1_id, mat2_id) => contactmat_id + + this.defaultMaterial = new CANNON.Material("default"); + + /** + * @property CANNON.ContactMaterial defaultContactMaterial + * @brief This contact material is used if no suitable contactmaterial is found for a contact. + * @memberof CANNON.World + */ + this.defaultContactMaterial = new CANNON.ContactMaterial(this.defaultMaterial,this.defaultMaterial,0.3,0.0); + + /** + * @property bool doProfiling + * @memberof CANNON.World + */ + this.doProfiling = false; + + /** + * @property Object profile + * @memberof CANNON.World + */ + this.profile = { + solve:0, + makeContactConstraints:0, + broadphase:0, + integrate:0, + nearphase:0, + }; + + /** + * @property Array subystems + * @memberof CANNON.World + */ + this.subsystems = []; +}; + +/** + * @method getContactMaterial + * @memberof CANNON.World + * @brief Get the contact material between materials m1 and m2 + * @param CANNON.Material m1 + * @param CANNON.Material m2 + * @return CANNON.Contactmaterial The contact material if it was found. + */ +CANNON.World.prototype.getContactMaterial = function(m1,m2){ + if((m1 instanceof CANNON.Material) && (m2 instanceof CANNON.Material)){ + + var i = m1.id; + var j = m2.id; + + if(i i){ + var temp = j; + j = i; + i = temp; + } + // Reuse i for the index + i = (i*(i + 1)>>1) + j-1; + return (typeof(current)==="undefined" || current) ? this.collisionMatrix[i] : this.collisionMatrixPrevious[i]; +}; + +CANNON.World.prototype.collisionMatrixSet = function(i,j,value,current){ + if(j > i){ + var temp = j; + j = i; + i = temp; + } + // Reuse i for the index + i = (i*(i + 1)>>1) + j-1; + if (typeof(current)==="undefined" || current) { + this.collisionMatrix[i] = value; + } + else { + this.collisionMatrixPrevious[i] = value; + } +}; + +// transfer old contact state data to T-1 +CANNON.World.prototype.collisionMatrixTick = function(){ + var temp = this.collisionMatrixPrevious; + this.collisionMatrixPrevious = this.collisionMatrix; + this.collisionMatrix = temp; + for (var i=0,l=this.collisionMatrix.length;i!==l;i++) { + this.collisionMatrix[i]=0; + } +}; + +/** + * @method add + * @memberof CANNON.World + * @brief Add a rigid body to the simulation. + * @param CANNON.Body body + * @todo If the simulation has not yet started, why recrete and copy arrays for each body? Accumulate in dynamic arrays in this case. + * @todo Adding an array of bodies should be possible. This would save some loops too + */ +CANNON.World.prototype.add = function(body){ + body.id = this.id(); + body.index = this.bodies.length; + this.bodies.push(body); + body.world = this; + body.position.copy(body.initPosition); + body.velocity.copy(body.initVelocity); + body.timeLastSleepy = this.time; + if(body instanceof CANNON.RigidBody){ + body.angularVelocity.copy(body.initAngularVelocity); + body.quaternion.copy(body.initQuaternion); + } + + var n = this.numObjects(); + this.collisionMatrix.length = n*(n-1)>>1; +}; + +/** + * @method addConstraint + * @memberof CANNON.World + * @brief Add a constraint to the simulation. + * @param CANNON.Constraint c + */ +CANNON.World.prototype.addConstraint = function(c){ + this.constraints.push(c); + c.id = this.id(); +}; + +/** + * @method removeConstraint + * @memberof CANNON.World + * @brief Removes a constraint + * @param CANNON.Constraint c + */ +CANNON.World.prototype.removeConstraint = function(c){ + var idx = this.constraints.indexOf(c); + if(idx!==-1){ + this.constraints.splice(idx,1); + } +}; + +/** + * @method id + * @memberof CANNON.World + * @brief Generate a new unique integer identifyer + * @return int + */ +CANNON.World.prototype.id = function(){ + return this.nextId++; +}; + +/** + * @method remove + * @memberof CANNON.World + * @brief Remove a rigid body from the simulation. + * @param CANNON.Body body + */ +CANNON.World.prototype.remove = function(body){ + body.world = null; + var n = this.numObjects()-1; + var bodies = this.bodies; + bodies.splice(body.index, 1); + for(var i=body.index; i>1; +}; + +/** + * @method addMaterial + * @memberof CANNON.World + * @brief Adds a material to the World. A material can only be added once, it's added more times then nothing will happen. + * @param CANNON.Material m + */ +CANNON.World.prototype.addMaterial = function(m){ + if(m.id === -1){ + var n = this.materials.length; + this.materials.push(m); + m.id = this.materials.length-1; + + // Increase size of collision matrix to (n+1)*(n+1)=n*n+2*n+1 elements, it was n*n last. + for(var i=0; i!==2*n+1; i++){ + this.mats2cmat.push(-1); + } + } +}; + +/** + * @method addContactMaterial + * @memberof CANNON.World + * @brief Adds a contact material to the World + * @param CANNON.ContactMaterial cmat + */ +CANNON.World.prototype.addContactMaterial = function(cmat) { + + // Add materials if they aren't already added + this.addMaterial(cmat.materials[0]); + this.addMaterial(cmat.materials[1]); + + // Save (material1,material2) -> (contact material) reference for easy access later + // Make sure i>j, ie upper right matrix + var i,j; + if(cmat.materials[0].id > cmat.materials[1].id){ + i = cmat.materials[0].id; + j = cmat.materials[1].id; + } else { + j = cmat.materials[0].id; + i = cmat.materials[1].id; + } + + // Add contact material + this.contactmaterials.push(cmat); + cmat.id = this.contactmaterials.length-1; + + // Add current contact material to the material table + this.mats2cmat[i+this.materials.length*j] = cmat.id; // index of the contact material +}; + +CANNON.World.prototype._now = function(){ + if(window.performance.webkitNow){ + return window.performance.webkitNow(); + } else { + return Date.now(); + } +}; + +/** + * @method step + * @memberof CANNON.World + * @brief Step the simulation + * @param float dt + */ +var World_step_postStepEvent = {type:"postStep"}, // Reusable event objects to save memory + World_step_preStepEvent = {type:"preStep"}, + World_step_collideEvent = {type:"collide", "with":null, contact:null }, + World_step_oldContacts = [], // Pools for unused objects + World_step_frictionEquationPool = [], + World_step_p1 = [], // Reusable arrays for collision pairs + World_step_p2 = [], + World_step_gvec = new CANNON.Vec3(), // Temporary vectors and quats + World_step_vi = new CANNON.Vec3(), + World_step_vj = new CANNON.Vec3(), + World_step_wi = new CANNON.Vec3(), + World_step_wj = new CANNON.Vec3(), + World_step_t1 = new CANNON.Vec3(), + World_step_t2 = new CANNON.Vec3(), + World_step_rixn = new CANNON.Vec3(), + World_step_rjxn = new CANNON.Vec3(), + World_step_step_q = new CANNON.Quaternion(), + World_step_step_w = new CANNON.Quaternion(), + World_step_step_wq = new CANNON.Quaternion(); +CANNON.World.prototype.step = function(dt){ + var world = this, + that = this, + contacts = this.contacts, + p1 = World_step_p1, + p2 = World_step_p2, + N = this.numObjects(), + bodies = this.bodies, + solver = this.solver, + gravity = this.gravity, + doProfiling = this.doProfiling, + profile = this.profile, + DYNAMIC = CANNON.Body.DYNAMIC, + now = this._now, + profilingStart, + constraints = this.constraints, + FrictionEquation = CANNON.FrictionEquation, + frictionEquationPool = World_step_frictionEquationPool, + gnorm = gravity.norm(), + gx = gravity.x, + gy = gravity.y, + gz = gravity.z, + i=0; + + + if(doProfiling){ + profilingStart = now(); + } + + if(dt===undefined){ + dt = this.last_dt || this.default_dt; + } + + // Add gravity to all objects + for(i=0; i!==N; i++){ + var bi = bodies[i]; + if(bi.motionstate & DYNAMIC){ // Only for dynamic bodies + var f = bi.force, m = bi.mass; + f.x += m*gx; + f.y += m*gy; + f.z += m*gz; + } + } + + // Update subsystems + for(var i=0, Nsubsystems=this.subsystems.length; i!==Nsubsystems; i++){ + this.subsystems[i].update(); + } + + // 1. Collision detection + if(doProfiling){ profilingStart = now(); } + p1.length = 0; // Clean up pair arrays from last step + p2.length = 0; + this.broadphase.collisionPairs(this,p1,p2); + if(doProfiling){ profile.broadphase = now() - profilingStart; } + + this.collisionMatrixTick(); + + // Generate contacts + if(doProfiling){ profilingStart = now(); } + var oldcontacts = World_step_oldContacts; + var NoldContacts = contacts.length; + + for(i=0; i!==NoldContacts; i++){ + oldcontacts.push(contacts[i]); + } + contacts.length = 0; + + this.contactgen.getContacts(p1,p2, + this, + contacts, + oldcontacts // To be reused + ); + if(doProfiling){ + profile.nearphase = now() - profilingStart; + } + + // Loop over all collisions + if(doProfiling){ + profilingStart = now(); + } + var ncontacts = contacts.length; + + // Transfer FrictionEquation from current list to the pool for reuse + var NoldFrictionEquations = this.frictionEquations.length; + for(i=0; i!==NoldFrictionEquations; i++){ + frictionEquationPool.push(this.frictionEquations[i]); + } + this.frictionEquations.length = 0; + + for(var k=0; k!==ncontacts; k++){ + + // Current contact + var c = contacts[k]; + + // Get current collision indeces + var bi=c.bi, bj=c.bj; + + // Resolve indeces + var i = bodies.indexOf(bi), j = bodies.indexOf(bj); + + // Get collision properties + var cm = this.getContactMaterial(bi.material,bj.material) || this.defaultContactMaterial; + var mu = cm.friction; + var e = cm.restitution; + + // g = ( xj + rj - xi - ri ) .dot ( ni ) + var gvec = World_step_gvec; + gvec.set(bj.position.x + c.rj.x - bi.position.x - c.ri.x, + bj.position.y + c.rj.y - bi.position.y - c.ri.y, + bj.position.z + c.rj.z - bi.position.z - c.ri.z); + var g = gvec.dot(c.ni); // Gap, negative if penetration + + // Action if penetration + if(g<0.0){ + c.restitution = cm.restitution; + c.penetration = g; + c.stiffness = cm.contactEquationStiffness; + c.regularizationTime = cm.contactEquationRegularizationTime; + + solver.addEquation(c); + + // Add friction constraint equation + if(mu > 0){ + + // Create 2 tangent equations + var mug = mu*gnorm; + var reducedMass = (bi.invMass + bj.invMass); + if(reducedMass > 0){ + reducedMass = 1/reducedMass; + } + var pool = frictionEquationPool; + var c1 = pool.length ? pool.pop() : new FrictionEquation(bi,bj,mug*reducedMass); + var c2 = pool.length ? pool.pop() : new FrictionEquation(bi,bj,mug*reducedMass); + this.frictionEquations.push(c1); + this.frictionEquations.push(c2); + + c1.bi = c2.bi = bi; + c1.bj = c2.bj = bj; + c1.minForce = c2.minForce = -mug*reducedMass; + c1.maxForce = c2.maxForce = mug*reducedMass; + + // Copy over the relative vectors + c.ri.copy(c1.ri); + c.rj.copy(c1.rj); + c.ri.copy(c2.ri); + c.rj.copy(c2.rj); + + // Construct tangents + c.ni.tangents(c1.t,c2.t); + + // Add equations to solver + solver.addEquation(c1); + solver.addEquation(c2); + } + + // Now we know that i and j are in contact. Set collision matrix state + this.collisionMatrixSet(i,j,1,true); + + if(this.collisionMatrixGet(i,j,true)!==this.collisionMatrixGet(i,j,false)){ + // First contact! + // We reuse the collideEvent object, otherwise we will end up creating new objects for each new contact, even if there's no event listener attached. + World_step_collideEvent.with = bj; + World_step_collideEvent.contact = c; + bi.dispatchEvent(World_step_collideEvent); + + World_step_collideEvent.with = bi; + bj.dispatchEvent(World_step_collideEvent); + + bi.wakeUp(); + bj.wakeUp(); + } + } + } + if(doProfiling){ + profile.makeContactConstraints = now() - profilingStart; + } + + if(doProfiling){ + profilingStart = now(); + } + + // Add user-added constraints + var Nconstraints = constraints.length; + for(i=0; i!==Nconstraints; i++){ + var c = constraints[i]; + c.update(); + for(var j=0, Neq=c.equations.length; j!==Neq; j++){ + var eq = c.equations[j]; + solver.addEquation(eq); + } + } + + // Solve the constrained system + solver.solve(dt,this); + + if(doProfiling){ + profile.solve = now() - profilingStart; + } + + // Remove all contacts from solver + solver.removeAllEquations(); + + // Apply damping, see http://code.google.com/p/bullet/issues/detail?id=74 for details + var pow = Math.pow; + for(i=0; i!==N; i++){ + var bi = bodies[i]; + if(bi.motionstate & DYNAMIC){ // Only for dynamic bodies + var ld = pow(1.0 - bi.linearDamping,dt); + var v = bi.velocity; + v.mult(ld,v); + var av = bi.angularVelocity; + if(av){ + var ad = pow(1.0 - bi.angularDamping,dt); + av.mult(ad,av); + } + } + } + + this.dispatchEvent(World_step_postStepEvent); + + // Invoke pre-step callbacks + for(i=0; i!==N; i++){ + var bi = bodies[i]; + if(bi.preStep){ + bi.preStep.call(bi); + } + } + + // Leap frog + // vnew = v + h*f/m + // xnew = x + h*vnew + if(doProfiling){ + profilingStart = now(); + } + var q = World_step_step_q; + var w = World_step_step_w; + var wq = World_step_step_wq; + var stepnumber = this.stepnumber; + var DYNAMIC_OR_KINEMATIC = CANNON.Body.DYNAMIC | CANNON.Body.KINEMATIC; + var quatNormalize = stepnumber % (this.quatNormalizeSkip+1) === 0; + var quatNormalizeFast = this.quatNormalizeFast; + var half_dt = dt * 0.5; + var PLANE = CANNON.Shape.types.PLANE, + CONVEX = CANNON.Shape.types.CONVEXPOLYHEDRON; + + for(i=0; i!==N; i++){ + var b = bodies[i], + s = b.shape, + force = b.force, + tau = b.tau; + if((b.motionstate & DYNAMIC_OR_KINEMATIC)){ // Only for dynamic + var velo = b.velocity, + angularVelo = b.angularVelocity, + pos = b.position, + quat = b.quaternion, + invMass = b.invMass, + invInertia = b.invInertia; + velo.x += force.x * invMass * dt; + velo.y += force.y * invMass * dt; + velo.z += force.z * invMass * dt; + + if(b.angularVelocity){ + angularVelo.x += tau.x * invInertia.x * dt; + angularVelo.y += tau.y * invInertia.y * dt; + angularVelo.z += tau.z * invInertia.z * dt; + } + + // Use new velocity - leap frog + if(!b.isSleeping()){ + pos.x += velo.x * dt; + pos.y += velo.y * dt; + pos.z += velo.z * dt; + + if(b.angularVelocity){ + w.set(angularVelo.x, angularVelo.y, angularVelo.z, 0); + w.mult(quat,wq); + quat.x += half_dt * wq.x; + quat.y += half_dt * wq.y; + quat.z += half_dt * wq.z; + quat.w += half_dt * wq.w; + if(quatNormalize){ + if(quatNormalizeFast){ + quat.normalizeFast(); + } else { + quat.normalize(); + } + } + } + + if(b.aabbmin){ + b.aabbNeedsUpdate = true; + } + } + + if(s){ + switch(s.type){ + case PLANE: + s.worldNormalNeedsUpdate = true; + break; + case CONVEX: + s.worldFaceNormalsNeedsUpdate = true; + s.worldVerticesNeedsUpdate = true; + break; + } + } + } + b.force.set(0,0,0); + if(b.tau){ + b.tau.set(0,0,0); + } + } + + if(doProfiling){ + profile.integrate = now() - profilingStart; + } + + // Update world time + this.time += dt; + this.stepnumber += 1; + + this.dispatchEvent(World_step_postStepEvent); + + // Invoke post-step callbacks + for(i=0; i!==N; i++){ + var bi = bodies[i]; + var postStep = bi.postStep; + if(postStep){ + postStep.call(bi); + } + } + + // Update world inertias + // @todo should swap autoUpdate mechanism for .xxxNeedsUpdate + for(i=0; i!==N; i++){ + var b = bodies[i]; + if(b.inertiaWorldAutoUpdate){ + b.quaternion.vmult(b.inertia,b.inertiaWorld); + } + if(b.invInertiaWorldAutoUpdate){ + b.quaternion.vmult(b.invInertia,b.invInertiaWorld); + } + } + + // Sleeping update + if(this.allowSleep){ + for(i=0; i!==N; i++){ + bodies[i].sleepTick(this.time); + } + } +}; + + +/** + * @class CANNON.ContactGenerator + * @brief Helper class for the World. Generates ContactEquations. + * @todo Sphere-ConvexPolyhedron contacts + * @todo Contact reduction + */ +CANNON.ContactGenerator = function(){ + + /** + * @property bool contactReduction + * @memberof CANNON.ContactGenerator + * @brief Turns on or off contact reduction. Can be handy to turn off when debugging new collision types. + */ + this.contactReduction = false; + + // Contact point objects that can be reused + var contactPointPool = []; + + var v3pool = new CANNON.Vec3Pool(); + + /* + * Make a contact object. + * @return object + * @todo reuse old contact point objects + */ + function makeResult(bi,bj){ + if(contactPointPool.length){ + var c = contactPointPool.pop(); + c.bi = bi; + c.bj = bj; + return c; + } else { + return new CANNON.ContactEquation(bi,bj); + } + } + + /* + * Swaps the body references in the contact + * @param object r + */ + function swapResult(r){ + var temp; + temp = r.ri; + r.ri = r.rj; + r.rj = temp; + r.ni.negate(r.ni); + temp = r.bi; + r.bi = r.bj; + r.bj = temp; + } + + function sphereSphere(result,si,sj,xi,xj,qi,qj,bi,bj){ + // We will have only one contact in this case + var r = makeResult(bi,bj); + + // Contact normal + bj.position.vsub(xi, r.ni); + r.ni.normalize(); + + // Contact point locations + r.ni.copy(r.ri); + r.ni.copy(r.rj); + r.ri.mult(si.radius, r.ri); + r.rj.mult(-sj.radius, r.rj); + result.push(r); + } + + var point_on_plane_to_sphere = new CANNON.Vec3(); + var plane_to_sphere_ortho = new CANNON.Vec3(); + function spherePlane(result,si,sj,xi,xj,qi,qj,bi,bj){ + // We will have one contact in this case + var r = makeResult(bi,bj); + + // Contact normal + r.ni.set(0,0,1); + qj.vmult(r.ni,r.ni); + r.ni.negate(r.ni); // body i is the sphere, flip normal + r.ni.normalize(); + + // Vector from sphere center to contact point + r.ni.mult(si.radius,r.ri); + + // Project down sphere on plane + xi.vsub(xj,point_on_plane_to_sphere); + r.ni.mult(r.ni.dot(point_on_plane_to_sphere),plane_to_sphere_ortho); + point_on_plane_to_sphere.vsub(plane_to_sphere_ortho,r.rj); // The sphere position projected to plane + if(plane_to_sphere_ortho.norm2() <= si.radius*si.radius){ + result.push(r); + } + } + + // See http://bulletphysics.com/Bullet/BulletFull/SphereTriangleDetector_8cpp_source.html + var pointInPolygon_edge = new CANNON.Vec3(); + var pointInPolygon_edge_x_normal = new CANNON.Vec3(); + var pointInPolygon_vtp = new CANNON.Vec3(); + function pointInPolygon(verts, normal, p){ + var positiveResult = null; + var N = verts.length; + for(var i=0; i!==N; i++){ + var v = verts[i]; + + // Get edge to the next vertex + var edge = pointInPolygon_edge; + verts[(i+1) % (N)].vsub(v,edge); + + // Get cross product between polygon normal and the edge + var edge_x_normal = pointInPolygon_edge_x_normal; + //var edge_x_normal = new CANNON.Vec3(); + edge.cross(normal,edge_x_normal); + + // Get vector between point and current vertex + var vertex_to_p = pointInPolygon_vtp; + p.vsub(v,vertex_to_p); + + // This dot product determines which side of the edge the point is + var r = edge_x_normal.dot(vertex_to_p); + + // If all such dot products have same sign, we are inside the polygon. + if(positiveResult===null || (r>0 && positiveResult===true) || (r<=0 && positiveResult===false)){ + if(positiveResult===null){ + positiveResult = r>0; + } + continue; + } else { + return false; // Encountered some other sign. Exit. + } + } + + // If we got here, all dot products were of the same sign. + return true; + } + + var box_to_sphere = new CANNON.Vec3(); + var sphereBox_ns = new CANNON.Vec3(); + var sphereBox_ns1 = new CANNON.Vec3(); + var sphereBox_ns2 = new CANNON.Vec3(); + var sphereBox_sides = [new CANNON.Vec3(),new CANNON.Vec3(),new CANNON.Vec3(),new CANNON.Vec3(),new CANNON.Vec3(),new CANNON.Vec3()]; + var sphereBox_sphere_to_corner = new CANNON.Vec3(); + var sphereBox_side_ns = new CANNON.Vec3(); + var sphereBox_side_ns1 = new CANNON.Vec3(); + var sphereBox_side_ns2 = new CANNON.Vec3(); + function sphereBox(result,si,sj,xi,xj,qi,qj,bi,bj){ + // we refer to the box as body j + var sides = sphereBox_sides; + xi.vsub(xj,box_to_sphere); + sj.getSideNormals(sides,qj); + var R = si.radius; + var penetrating_sides = []; + + // Check side (plane) intersections + var found = false; + + // Store the resulting side penetration info + var side_ns = sphereBox_side_ns; + var side_ns1 = sphereBox_side_ns1; + var side_ns2 = sphereBox_side_ns2; + var side_h = null; + var side_penetrations = 0; + var side_dot1 = 0; + var side_dot2 = 0; + var side_distance = null; + for(var idx=0,nsides=sides.length; idx!==nsides && found===false; idx++){ + // Get the plane side normal (ns) + var ns = sphereBox_ns; + sides[idx].copy(ns); + + var h = ns.norm(); + ns.normalize(); + + // The normal/distance dot product tells which side of the plane we are + var dot = box_to_sphere.dot(ns); + + if(dot0){ + // Intersects plane. Now check the other two dimensions + var ns1 = sphereBox_ns1; + var ns2 = sphereBox_ns2; + sides[(idx+1)%3].copy(ns1); + sides[(idx+2)%3].copy(ns2); + var h1 = ns1.norm(); + var h2 = ns2.norm(); + ns1.normalize(); + ns2.normalize(); + var dot1 = box_to_sphere.dot(ns1); + var dot2 = box_to_sphere.dot(ns2); + if(dot1

    -h1 && dot2

    -h2){ + var dist = Math.abs(dot-h-R); + if(side_distance===null || dist < side_distance){ + side_distance = dist; + side_dot1 = dot1; + side_dot2 = dot2; + side_h = h; + ns.copy(side_ns); + ns1.copy(side_ns1); + ns2.copy(side_ns2); + side_penetrations++; + } + } + } + } + if(side_penetrations){ + found = true; + var r = makeResult(bi,bj); + side_ns.mult(-R,r.ri); // Sphere r + side_ns.copy(r.ni); + r.ni.negate(r.ni); // Normal should be out of sphere + side_ns.mult(side_h,side_ns); + side_ns1.mult(side_dot1,side_ns1); + side_ns.vadd(side_ns1,side_ns); + side_ns2.mult(side_dot2,side_ns2); + side_ns.vadd(side_ns2,r.rj); + result.push(r); + } + + // Check corners + var rj = v3pool.get(); + var sphere_to_corner = sphereBox_sphere_to_corner; + for(var j=0; j!==2 && !found; j++){ + for(var k=0; k!==2 && !found; k++){ + for(var l=0; l!==2 && !found; l++){ + rj.set(0,0,0); + if(j){ + rj.vadd(sides[0],rj); + } else { + rj.vsub(sides[0],rj); + } + if(k){ + rj.vadd(sides[1],rj); + } else { + rj.vsub(sides[1],rj); + } + if(l){ + rj.vadd(sides[2],rj); + } else { + rj.vsub(sides[2],rj); + } + + // World position of corner + xj.vadd(rj,sphere_to_corner); + sphere_to_corner.vsub(xi,sphere_to_corner); + + if(sphere_to_corner.norm2() < R*R){ + found = true; + var r = makeResult(bi,bj); + sphere_to_corner.copy(r.ri); + r.ri.normalize(); + r.ri.copy(r.ni); + r.ri.mult(R,r.ri); + rj.copy(r.rj); + result.push(r); + } + } + } + } + v3pool.release(rj); + rj = null; + + // Check edges + var edgeTangent = v3pool.get(); + var edgeCenter = v3pool.get(); + var r = v3pool.get(); // r = edge center to sphere center + var orthogonal = v3pool.get(); + var dist = v3pool.get(); + var Nsides = sides.length; + for(var j=0; j!==Nsides && !found; j++){ + for(var k=0; k!==Nsides && !found; k++){ + if(j%3 !== k%3){ + // Get edge tangent + sides[k].cross(sides[j],edgeTangent); + edgeTangent.normalize(); + sides[j].vadd(sides[k], edgeCenter); + xi.copy(r); + r.vsub(edgeCenter,r); + r.vsub(xj,r); + var orthonorm = r.dot(edgeTangent); // distance from edge center to sphere center in the tangent direction + edgeTangent.mult(orthonorm,orthogonal); // Vector from edge center to sphere center in the tangent direction + + // Find the third side orthogonal to this one + var l = 0; + while(l===j%3 || l===k%3){ + l++; + } + + // vec from edge center to sphere projected to the plane orthogonal to the edge tangent + xi.copy(dist); + dist.vsub(orthogonal,dist); + dist.vsub(edgeCenter,dist); + dist.vsub(xj,dist); + + // Distances in tangent direction and distance in the plane orthogonal to it + var tdist = Math.abs(orthonorm); + var ndist = dist.norm(); + + if(tdist < sides[l].norm() && ndist0){ + // Intersects plane. Now check if the sphere is inside the face polygon + var faceVerts = []; // Face vertices, in world coords + for(var j=0, Nverts=face.length; j!==Nverts; j++){ + var worldVertex = v3pool.get(); + qj.vmult(verts[face[j]], worldVertex); + xj.vadd(worldVertex,worldVertex); + faceVerts.push(worldVertex); + } + + if(pointInPolygon(faceVerts,worldNormal,xi)){ // Is the sphere center in the face polygon? + found = true; + var r = makeResult(bi,bj); + worldNormal.mult(-R,r.ri); // Sphere r + worldNormal.negate(r.ni); // Normal should be out of sphere + + var penetrationVec2 = v3pool.get(); + worldNormal.mult(-penetration,penetrationVec2); + var penetrationSpherePoint = v3pool.get(); + worldNormal.mult(-R,penetrationSpherePoint); + + //xi.vsub(xj).vadd(penetrationSpherePoint).vadd(penetrationVec2 , r.rj); + xi.vsub(xj,r.rj); + r.rj.vadd(penetrationSpherePoint,r.rj); + r.rj.vadd(penetrationVec2 , r.rj); + + v3pool.release(penetrationVec2); + v3pool.release(penetrationSpherePoint); + + result.push(r); + + // Release world vertices + for(var j=0, Nfaceverts=faceVerts.length; j!==Nfaceverts; j++){ + v3pool.release(faceVerts[j]); + } + + return; // We only expect *one* face contact + } else { + // Edge? + for(var j=0; j!==face.length; j++){ + + // Get two world transformed vertices + var v1 = v3pool.get(); + var v2 = v3pool.get(); + qj.vmult(verts[face[(j+1)%face.length]], v1); + qj.vmult(verts[face[(j+2)%face.length]], v2); + xj.vadd(v1, v1); + xj.vadd(v2, v2); + + // Construct edge vector + var edge = sphereConvex_edge; + v2.vsub(v1,edge); + + // Construct the same vector, but normalized + var edgeUnit = sphereConvex_edgeUnit; + edge.unit(edgeUnit); + + // p is xi projected onto the edge + var p = v3pool.get(); + var v1_to_xi = v3pool.get(); + xi.vsub(v1, v1_to_xi); + var dot = v1_to_xi.dot(edgeUnit); + edgeUnit.mult(dot, p); + p.vadd(v1, p); + + // Compute a vector from p to the center of the sphere + var xi_to_p = v3pool.get(); + p.vsub(xi, xi_to_p); + + // Collision if the edge-sphere distance is less than the radius + // AND if p is in between v1 and v2 + if(dot > 0 && dot*dot sj.type){ + var temp; + temp=sj; + sj=si; + si=temp; + + temp=xj; + xj=xi; + xi=temp; + + temp=qj; + qj=qi; + qi=temp; + + temp=bj; + bj=bi; + bi=temp; + + swapped = true; + } + } else { + // Particle! + if(si && !sj){ + var temp; + temp=sj; + sj=si; + si=temp; + + temp=xj; + xj=xi; + xi=temp; + + temp=qj; + qj=qi; + qi=temp; + + temp=bj; + bj=bi; + bi=temp; + + swapped = true; + } + } + + if(si && sj){ + if(si.type === SPHERE){ + + switch(sj.type){ + case SPHERE: // sphere-sphere + sphereSphere(result,si,sj,xi,xj,qi,qj,bi,bj); + break; + case PLANE: // sphere-plane + spherePlane(result,si,sj,xi,xj,qi,qj,bi,bj); + break; + case BOX: // sphere-box + sphereBox(result,si,sj,xi,xj,qi,qj,bi,bj); + break; + case COMPOUND: // sphere-compound + recurseCompound(result,si,sj,xi,xj,qi,qj,bi,bj); + break; + case CONVEXPOLYHEDRON: // sphere-convexpolyhedron + sphereConvex(result,si,sj,xi,xj,qi,qj,bi,bj); + break; + default: + console.warn("Collision between CANNON.Shape.types.SPHERE and "+sj.type+" not implemented yet."); + break; + } + + } else if(si.type === types.PLANE){ + + switch(sj.type){ + case types.PLANE: // plane-plane + throw new Error("Plane-plane collision... wait, you did WHAT?"); + case types.BOX: // plane-box + planeBox(result,si,sj,xi,xj,qi,qj,bi,bj); + break; + case types.COMPOUND: // plane-compound + recurseCompound(result,si,sj,xi,xj,qi,qj,bi,bj); + break; + case types.CONVEXPOLYHEDRON: // plane-convex polyhedron + planeConvex(result,si,sj,xi,xj,qi,qj,bi,bj); + break; + default: + console.warn("Collision between CANNON.Shape.types.PLANE and "+sj.type+" not implemented yet."); + break; + } + + } else if(si.type===types.BOX){ + + switch(sj.type){ + case types.BOX: // box-box + // Do convex/convex instead + nearPhase(result,si.convexPolyhedronRepresentation,sj.convexPolyhedronRepresentation,xi,xj,qi,qj,bi,bj); + break; + case types.COMPOUND: // box-compound + recurseCompound(result,si,sj,xi,xj,qi,qj,bi,bj); + break; + case types.CONVEXPOLYHEDRON: // box-convexpolyhedron + // Do convex/convex instead + nearPhase(result,si.convexPolyhedronRepresentation,sj,xi,xj,qi,qj,bi,bj); + break; + default: + console.warn("Collision between CANNON.Shape.types.BOX and "+sj.type+" not implemented yet."); + break; + } + + } else if(si.type===types.COMPOUND){ + + switch(sj.type){ + case types.COMPOUND: // compound-compound + recurseCompound(result,si,sj,xi,xj,qi,qj,bi,bj); + break; + case types.CONVEXPOLYHEDRON: // compound-convex polyhedron + // Must swap + var r = []; + recurseCompound(r,sj,si,xj,xi,qj,qi,bj,bi); + for(var ri=0; ri!==r.length; ri++){ + swapResult(r[ri]); + result.push(r[ri]); + } + break; + default: + console.warn("Collision between CANNON.Shape.types.COMPOUND and "+sj.type+" not implemented yet."); + break; + } + + } else if(si.type===types.CONVEXPOLYHEDRON){ + + switch(sj.type){ + case types.CONVEXPOLYHEDRON: // convex polyhedron - convex polyhedron + convexConvex(result,si,sj,xi,xj,qi,qj,bi,bj); + break; + default: + console.warn("Collision between CANNON.Shape.types.CONVEXPOLYHEDRON and "+sj.type+" not implemented yet."); + break; + } + + } + + } else { + + // Particle! + switch(sj.type){ + case types.PLANE: // Particle vs plane + particlePlane(result,si,sj,xi,xj,qi,qj,bi,bj); + break; + case types.SPHERE: // Particle vs sphere + particleSphere(result,si,sj,xi,xj,qi,qj,bi,bj); + break; + case types.BOX: // Particle vs box + particleConvex(result,si,sj.convexPolyhedronRepresentation,xi,xj,qi,qj,bi,bj); + break; + case types.CONVEXPOLYHEDRON: // particle-convex + particleConvex(result,si,sj,xi,xj,qi,qj,bi,bj); + break; + case types.COMPOUND: // particle-compound + recurseCompound(result,si,sj,xi,xj,qi,qj,bi,bj); + break; + default: + console.warn("Collision between CANNON.Particle and "+sj.type+" not implemented yet."); + break; + } + } + + // Swap back if we swapped bodies in the beginning + for(var i=0, Nresults=result.length; swapped && i!==Nresults; i++){ + swapResult(result[i]); + } + } + + /** + * @method reduceContacts + * @memberof CANNON.ContactGenerator + * @brief Removes unnecessary members of an array of CANNON.ContactPoint. + */ + this.reduceContacts = function(contacts){ + + }; + + /** + * @method getContacts + * @memberof CANNON.ContactGenerator + * @param array p1 Array of body indices + * @param array p2 Array of body indices + * @param CANNON.World world + * @param array result Array to store generated contacts + * @param array oldcontacts Optional. Array of reusable contact objects + */ + this.getContacts = function(p1,p2,world,result,oldcontacts){ + // Save old contact objects + contactPointPool = oldcontacts; + + for(var k=0, N=p1.length; k!==N; k++){ + // Get current collision indeces + var bi = p1[k], + bj = p2[k]; + + // Get contacts + nearPhase( result, + bi.shape, + bj.shape, + bi.position, + bj.position, + bi.quaternion, + bj.quaternion, + bi, + bj + ); + } + }; +}; + +/** + * @class CANNON.Equation + * @brief Equation base class + * @author schteppe + * @param CANNON.Body bi + * @param CANNON.Body bj + * @param float minForce Minimum (read: negative max) force to be applied by the constraint. + * @param float maxForce Maximum (read: positive max) force to be applied by the constraint. + */ +CANNON.Equation = function(bi,bj,minForce,maxForce){ + this.id = -1; + + /** + * @property float minForce + * @memberof CANNON.Equation + */ + this.minForce = typeof(minForce)==="undefined" ? -1e6 : minForce; + + /** + * @property float maxForce + * @memberof CANNON.Equation + */ + this.maxForce = typeof(maxForce)==="undefined" ? 1e6 : maxForce; + + /** + * @property CANNON.Body bi + * @memberof CANNON.Equation + */ + this.bi = bi; + + /** + * @property CANNON.Body bj + * @memberof CANNON.Equation + */ + this.bj = bj; + + /** + * @property float stiffness + * @brief Corresponds to spring stiffness. Makes constraints stiffer, but harder to solve. + * @memberof CANNON.Equation + */ + this.stiffness = 1e7; + + /** + * @property float regularizationTime + * @brief Similar to damping. Represents the number of timesteps needed to stabilize the constraint. + * @memberof CANNON.Equation + */ + this.regularizationTime = 5; + + /** + * @property float a + * @brief SPOOK parameter + * @memberof CANNON.Equation + */ + this.a = 0.0; + + /** + * @property float b + * @brief SPOOK parameter + * @memberof CANNON.Equation + */ + this.b = 0.0; + + /** + * @property float eps + * @brief SPOOK parameter + * @memberof CANNON.Equation + */ + this.eps = 0.0; + + /** + * @property bool spookParamsNeedsUpdate + * @brief Set to true if you just changed stiffness or regularization. The parameters a,b,eps will be recalculated by the solver before solve. + * @memberof CANNON.Equation + */ + this.spookParamsNeedsUpdate = true; +}; +CANNON.Equation.prototype.constructor = CANNON.Equation; + +/** + * @method updateSpookParams + * @brief Recalculates a,b,eps. + * @memberof CANNON.Equation + */ +CANNON.Equation.prototype.updateSpookParams = function(h){ + var d = this.regularizationTime, + k = this.stiffness; + this.a = 4.0 / (h * (1 + 4 * d)); + this.b = (4.0 * d) / (1 + 4 * d); + this.eps = 4.0 / (h * h * k * (1 + 4 * d)); +}; + + +/** + * @class CANNON.ContactEquation + * @brief Contact/non-penetration constraint equation + * @author schteppe + * @param CANNON.Body bj + * @param CANNON.Body bi + * @extends CANNON.Equation + */ +CANNON.ContactEquation = function(bi,bj){ + CANNON.Equation.call(this,bi,bj,0,1e6); + + /** + * @property float restitution + * @memberof CANNON.ContactEquation + */ + this.restitution = 0.0; // "bounciness": u1 = -e*u0 + + /** + * @property CANNON.Vec3 ri + * @memberof CANNON.ContactEquation + * @brief World-oriented vector that goes from the center of bi to the contact point in bi. + */ + this.ri = new CANNON.Vec3(); + + /** + * @property CANNON.Vec3 rj + * @memberof CANNON.ContactEquation + */ + this.rj = new CANNON.Vec3(); + + this.penetrationVec = new CANNON.Vec3(); + + this.ni = new CANNON.Vec3(); + this.rixn = new CANNON.Vec3(); + this.rjxn = new CANNON.Vec3(); + + this.invIi = new CANNON.Mat3(); + this.invIj = new CANNON.Mat3(); + + // Cache + this.biInvInertiaTimesRixn = new CANNON.Vec3(); + this.bjInvInertiaTimesRjxn = new CANNON.Vec3(); +}; + +CANNON.ContactEquation.prototype = new CANNON.Equation(); +CANNON.ContactEquation.prototype.constructor = CANNON.ContactEquation; + +/** + * @method reset + * @memberof CANNON.ContactEquation + * @brief To be run before object reuse + */ +CANNON.ContactEquation.prototype.reset = function(){ + this.invInertiaTimesRxnNeedsUpdate = true; +}; + +var ContactEquation_computeB_temp1 = new CANNON.Vec3(); // Temp vectors +var ContactEquation_computeB_temp2 = new CANNON.Vec3(); +var ContactEquation_computeB_zero = new CANNON.Vec3(); +CANNON.ContactEquation.prototype.computeB = function(h){ + var a = this.a, + b = this.b; + var bi = this.bi; + var bj = this.bj; + var ri = this.ri; + var rj = this.rj; + var rixn = this.rixn; + var rjxn = this.rjxn; + + var zero = ContactEquation_computeB_zero; + + var vi = bi.velocity; + var wi = bi.angularVelocity ? bi.angularVelocity : zero; + var fi = bi.force; + var taui = bi.tau ? bi.tau : zero; + + var vj = bj.velocity; + var wj = bj.angularVelocity ? bj.angularVelocity : zero; + var fj = bj.force; + var tauj = bj.tau ? bj.tau : zero; + + var penetrationVec = this.penetrationVec; + var invMassi = bi.invMass; + var invMassj = bj.invMass; + + var invIi = this.invIi; + var invIj = this.invIj; + + if(bi.invInertia){ + invIi.setTrace(bi.invInertia); + } else { + invIi.identity(); // ok? + } + if(bj.invInertia){ + invIj.setTrace(bj.invInertia); + } else { + invIj.identity(); // ok? + } + + var n = this.ni; + + // Caluclate cross products + ri.cross(n,rixn); + rj.cross(n,rjxn); + + // Calculate q = xj+rj -(xi+ri) i.e. the penetration vector + var penetrationVec = this.penetrationVec; + penetrationVec.set(0,0,0); + penetrationVec.vadd(bj.position,penetrationVec); + penetrationVec.vadd(rj,penetrationVec); + penetrationVec.vsub(bi.position,penetrationVec); + penetrationVec.vsub(ri,penetrationVec); + + var Gq = n.dot(penetrationVec);//-Math.abs(this.penetration); + + var invIi_vmult_taui = ContactEquation_computeB_temp1; + var invIj_vmult_tauj = ContactEquation_computeB_temp2; + invIi.vmult(taui,invIi_vmult_taui); + invIj.vmult(tauj,invIj_vmult_tauj); + + // Compute iteration + var ePlusOne = this.restitution+1; + var GW = ePlusOne*vj.dot(n) - ePlusOne*vi.dot(n) + wj.dot(rjxn) - wi.dot(rixn); + var GiMf = fj.dot(n)*invMassj - fi.dot(n)*invMassi + rjxn.dot(invIj_vmult_tauj) - rixn.dot(invIi_vmult_taui); + + var B = - Gq * a - GW * b - h*GiMf; + + return B; +}; + +// Compute C = GMG+eps in the SPOOK equation +var computeC_temp1 = new CANNON.Vec3(); +var computeC_temp2 = new CANNON.Vec3(); +CANNON.ContactEquation.prototype.computeC = function(){ + var bi = this.bi; + var bj = this.bj; + var rixn = this.rixn; + var rjxn = this.rjxn; + var invMassi = bi.invMass; + var invMassj = bj.invMass; + + var C = invMassi + invMassj + this.eps; + + var invIi = this.invIi; + var invIj = this.invIj; + + /* + if(bi.invInertia){ + invIi.setTrace(bi.invInertia); + } else { + invIi.identity(); // ok? + } + if(bj.invInertia){ + invIj.setTrace(bj.invInertia); + } else { + invIj.identity(); // ok? + } + */ + + // Compute rxn * I * rxn for each body + invIi.vmult(rixn, this.biInvInertiaTimesRixn); + invIj.vmult(rjxn, this.bjInvInertiaTimesRjxn); + + /* + invIi.vmult(rixn,computeC_temp1); + invIj.vmult(rjxn,computeC_temp2); + + C += computeC_temp1.dot(rixn); + C += computeC_temp2.dot(rjxn); + */ + C += this.biInvInertiaTimesRixn.dot(rixn); + C += this.bjInvInertiaTimesRjxn.dot(rjxn); + + return C; +}; + +var computeGWlambda_ulambda = new CANNON.Vec3(); +CANNON.ContactEquation.prototype.computeGWlambda = function(){ + var bi = this.bi; + var bj = this.bj; + var ulambda = computeGWlambda_ulambda; + + var GWlambda = 0.0; + + bj.vlambda.vsub(bi.vlambda, ulambda); + GWlambda += ulambda.dot(this.ni); + + // Angular + if(bi.wlambda){ + GWlambda -= bi.wlambda.dot(this.rixn); + } + if(bj.wlambda){ + GWlambda += bj.wlambda.dot(this.rjxn); + } + + return GWlambda; +}; + +var ContactEquation_addToWlambda_temp1 = new CANNON.Vec3(); +var ContactEquation_addToWlambda_temp2 = new CANNON.Vec3(); +CANNON.ContactEquation.prototype.addToWlambda = function(deltalambda){ + var bi = this.bi, + bj = this.bj, + rixn = this.rixn, + rjxn = this.rjxn, + invMassi = bi.invMass, + invMassj = bj.invMass, + n = this.ni, + temp1 = ContactEquation_addToWlambda_temp1, + temp2 = ContactEquation_addToWlambda_temp2; + + + // Add to linear velocity + n.mult(invMassi * deltalambda, temp2); + bi.vlambda.vsub(temp2,bi.vlambda); + n.mult(invMassj * deltalambda, temp2); + bj.vlambda.vadd(temp2,bj.vlambda); + + // Add to angular velocity + if(bi.wlambda !== undefined){ + this.biInvInertiaTimesRixn.mult(deltalambda,temp1); + + bi.wlambda.vsub(temp1,bi.wlambda); + } + if(bj.wlambda !== undefined){ + this.bjInvInertiaTimesRjxn.mult(deltalambda,temp1); + bj.wlambda.vadd(temp1,bj.wlambda); + } +}; + + +/** + * @class CANNON.FrictionEquation + * @brief Constrains the slipping in a contact along a tangent + * @author schteppe + * @param CANNON.Body bi + * @param CANNON.Body bj + * @param float slipForce should be +-F_friction = +-mu * F_normal = +-mu * m * g + * @extends CANNON.Equation + */ +CANNON.FrictionEquation = function(bi,bj,slipForce){ + CANNON.Equation.call(this,bi,bj,-slipForce,slipForce); + this.ri = new CANNON.Vec3(); + this.rj = new CANNON.Vec3(); + this.t = new CANNON.Vec3(); // tangent + + + // The following is just cache + this.rixt = new CANNON.Vec3(); + this.rjxt = new CANNON.Vec3(); + this.wixri = new CANNON.Vec3(); + this.wjxrj = new CANNON.Vec3(); + + this.invIi = new CANNON.Mat3(); + this.invIj = new CANNON.Mat3(); + + this.relVel = new CANNON.Vec3(); + this.relForce = new CANNON.Vec3(); + + this.biInvInertiaTimesRixt = new CANNON.Vec3(); + this.bjInvInertiaTimesRjxt = new CANNON.Vec3(); +}; + +CANNON.FrictionEquation.prototype = new CANNON.Equation(); +CANNON.FrictionEquation.prototype.constructor = CANNON.FrictionEquation; + +var FrictionEquation_computeB_temp1 = new CANNON.Vec3(); +var FrictionEquation_computeB_temp2 = new CANNON.Vec3(); +var FrictionEquation_computeB_zero = new CANNON.Vec3(); +CANNON.FrictionEquation.prototype.computeB = function(h){ + var a = this.a, + b = this.b, + bi = this.bi, + bj = this.bj, + ri = this.ri, + rj = this.rj, + rixt = this.rixt, + rjxt = this.rjxt, + wixri = this.wixri, + wjxrj = this.wjxrj, + zero = FrictionEquation_computeB_zero; + + var vi = bi.velocity, + wi = bi.angularVelocity ? bi.angularVelocity : zero, + fi = bi.force, + taui = bi.tau ? bi.tau : zero, + + vj = bj.velocity, + wj = bj.angularVelocity ? bj.angularVelocity : zero, + fj = bj.force, + tauj = bj.tau ? bj.tau : zero, + + relVel = this.relVel, + relForce = this.relForce, + invMassi = bi.invMass, + invMassj = bj.invMass, + + invIi = this.invIi, + invIj = this.invIj, + + t = this.t, + + invIi_vmult_taui = FrictionEquation_computeB_temp1, + invIj_vmult_tauj = FrictionEquation_computeB_temp2; + + if(bi.invInertia){ + invIi.setTrace(bi.invInertia); + } + if(bj.invInertia){ + invIj.setTrace(bj.invInertia); + } + + + // Caluclate cross products + ri.cross(t,rixt); + rj.cross(t,rjxt); + + wi.cross(ri,wixri); + wj.cross(rj,wjxrj); + + invIi.vmult(taui,invIi_vmult_taui); + invIj.vmult(tauj,invIj_vmult_tauj); + + var Gq = 0; // we do only want to constrain motion + var GW = vj.dot(t) - vi.dot(t) + wjxrj.dot(t) - wixri.dot(t); // eq. 40 + var GiMf = fj.dot(t)*invMassj - fi.dot(t)*invMassi + rjxt.dot(invIj_vmult_tauj) - rixt.dot(invIi_vmult_taui); + + var B = - Gq * a - GW * b - h*GiMf; + + return B; +}; + +// Compute C = G * Minv * G + eps +//var FEcomputeC_temp1 = new CANNON.Vec3(); +//var FEcomputeC_temp2 = new CANNON.Vec3(); +CANNON.FrictionEquation.prototype.computeC = function(){ + var bi = this.bi, + bj = this.bj, + rixt = this.rixt, + rjxt = this.rjxt, + invMassi = bi.invMass, + invMassj = bj.invMass, + C = invMassi + invMassj + this.eps, + invIi = this.invIi, + invIj = this.invIj; + + /* + if(bi.invInertia){ + invIi.setTrace(bi.invInertia); + } + if(bj.invInertia){ + invIj.setTrace(bj.invInertia); + } + */ + + // Compute rxt * I * rxt for each body + /* + invIi.vmult(rixt,FEcomputeC_temp1); + invIj.vmult(rjxt,FEcomputeC_temp2); + C += FEcomputeC_temp1.dot(rixt); + C += FEcomputeC_temp2.dot(rjxt); + */ + invIi.vmult(rixt,this.biInvInertiaTimesRixt); + invIj.vmult(rjxt,this.bjInvInertiaTimesRjxt); + C += this.biInvInertiaTimesRixt.dot(rixt); + C += this.bjInvInertiaTimesRjxt.dot(rjxt); + + return C; +}; + +var FrictionEquation_computeGWlambda_ulambda = new CANNON.Vec3(); +CANNON.FrictionEquation.prototype.computeGWlambda = function(){ + + // Correct at all ??? + + var bi = this.bi; + var bj = this.bj; + + var GWlambda = 0.0; + var ulambda = FrictionEquation_computeGWlambda_ulambda; + bj.vlambda.vsub(bi.vlambda,ulambda); + GWlambda += ulambda.dot(this.t); + + // Angular + if(bi.wlambda){ + GWlambda -= bi.wlambda.dot(this.rixt); + } + if(bj.wlambda){ + GWlambda += bj.wlambda.dot(this.rjxt); + } + + return GWlambda; +}; + +var FrictionEquation_addToWlambda_tmp = new CANNON.Vec3(); +CANNON.FrictionEquation.prototype.addToWlambda = function(deltalambda){ + var bi = this.bi, + bj = this.bj, + rixt = this.rixt, + rjxt = this.rjxt, + invMassi = bi.invMass, + invMassj = bj.invMass, + t = this.t, + tmp = FrictionEquation_addToWlambda_tmp, + wi = bi.wlambda, + wj = bj.wlambda; + + // Add to linear velocity + t.mult(invMassi * deltalambda, tmp); + bi.vlambda.vsub(tmp,bi.vlambda); + + t.mult(invMassj * deltalambda, tmp); + bj.vlambda.vadd(tmp,bj.vlambda); + + // Add to angular velocity + if(wi){ + /* + var I = this.invIi; + I.vmult(rixt,tmp); + tmp.mult(deltalambda,tmp); + */ + this.biInvInertiaTimesRixt.mult(deltalambda,tmp); + wi.vsub(tmp,wi); + } + if(wj){ + /* + var I = this.invIj; + I.vmult(rjxt,tmp); + tmp.mult(deltalambda,tmp); + */ + this.bjInvInertiaTimesRjxt.mult(deltalambda,tmp); + wj.vadd(tmp,wj); + } +}; + +/** + * @class CANNON.RotationalEquation + * @brief Rotational constraint. Works to keep the local vectors orthogonal to each other. + * @author schteppe + * @param CANNON.RigidBody bj + * @param CANNON.Vec3 localVectorInBodyA + * @param CANNON.RigidBody bi + * @param CANNON.Vec3 localVectorInBodyB + * @extends CANNON.Equation + */ +CANNON.RotationalEquation = function(bodyA, bodyB){ + CANNON.Equation.call(this,bodyA,bodyB,-1e6,1e6); + this.ni = new CANNON.Vec3(); // World oriented localVectorInBodyA + this.nj = new CANNON.Vec3(); // ...and B + + this.nixnj = new CANNON.Vec3(); + this.njxni = new CANNON.Vec3(); + + this.invIi = new CANNON.Mat3(); + this.invIj = new CANNON.Mat3(); + + this.relVel = new CANNON.Vec3(); + this.relForce = new CANNON.Vec3(); +}; + +CANNON.RotationalEquation.prototype = new CANNON.Equation(); +CANNON.RotationalEquation.prototype.constructor = CANNON.RotationalEquation; + +CANNON.RotationalEquation.prototype.computeB = function(h){ + var a = this.a, + b = this.b; + var bi = this.bi; + var bj = this.bj; + + var ni = this.ni; + var nj = this.nj; + + var nixnj = this.nixnj; + var njxni = this.njxni; + + var vi = bi.velocity; + var wi = bi.angularVelocity ? bi.angularVelocity : new CANNON.Vec3(); + var fi = bi.force; + var taui = bi.tau ? bi.tau : new CANNON.Vec3(); + + var vj = bj.velocity; + var wj = bj.angularVelocity ? bj.angularVelocity : new CANNON.Vec3(); + var fj = bj.force; + var tauj = bj.tau ? bj.tau : new CANNON.Vec3(); + + var invMassi = bi.invMass; + var invMassj = bj.invMass; + + var invIi = this.invIi; + var invIj = this.invIj; + + if(bi.invInertia){ + invIi.setTrace(bi.invInertia); + } else { + invIi.identity(); // ok? + } + if(bj.invInertia) { + invIj.setTrace(bj.invInertia); + } else { + invIj.identity(); // ok? + } + + // Caluclate cross products + ni.cross(nj,nixnj); + nj.cross(ni,njxni); + + // g = ni * nj + // gdot = (nj x ni) * wi + (ni x nj) * wj + // G = [0 njxni 0 nixnj] + // W = [vi wi vj wj] + var Gq = -ni.dot(nj); + var GW = njxni.dot(wi) + nixnj.dot(wj); + var GiMf = 0;//njxni.dot(invIi.vmult(taui)) + nixnj.dot(invIj.vmult(tauj)); + + var B = - Gq * a - GW * b - h*GiMf; + + return B; +}; + +// Compute C = GMG+eps +CANNON.RotationalEquation.prototype.computeC = function(){ + var bi = this.bi; + var bj = this.bj; + var nixnj = this.nixnj; + var njxni = this.njxni; + var invMassi = bi.invMass; + var invMassj = bj.invMass; + + var C = /*invMassi + invMassj +*/ this.eps; + + var invIi = this.invIi; + var invIj = this.invIj; + + if(bi.invInertia){ + invIi.setTrace(bi.invInertia); + } else { + invIi.identity(); // ok? + } + if(bj.invInertia){ + invIj.setTrace(bj.invInertia); + } else { + invIj.identity(); // ok? + } + + C += invIi.vmult(njxni).dot(njxni); + C += invIj.vmult(nixnj).dot(nixnj); + + return C; +}; + +var computeGWlambda_ulambda = new CANNON.Vec3(); +CANNON.RotationalEquation.prototype.computeGWlambda = function(){ + var bi = this.bi; + var bj = this.bj; + var ulambda = computeGWlambda_ulambda; + + var GWlambda = 0.0; + //bj.vlambda.vsub(bi.vlambda, ulambda); + //GWlambda += ulambda.dot(this.ni); + + // Angular + if(bi.wlambda){ + GWlambda += bi.wlambda.dot(this.njxni); + } + if(bj.wlambda){ + GWlambda += bj.wlambda.dot(this.nixnj); + } + + //console.log("GWlambda:",GWlambda); + + return GWlambda; +}; + +CANNON.RotationalEquation.prototype.addToWlambda = function(deltalambda){ + var bi = this.bi; + var bj = this.bj; + var nixnj = this.nixnj; + var njxni = this.njxni; + var invMassi = bi.invMass; + var invMassj = bj.invMass; + + // Add to linear velocity + //bi.vlambda.vsub(n.mult(invMassi * deltalambda),bi.vlambda); + //bj.vlambda.vadd(n.mult(invMassj * deltalambda),bj.vlambda); + + // Add to angular velocity + if(bi.wlambda){ + var I = this.invIi; + bi.wlambda.vsub(I.vmult(nixnj).mult(deltalambda),bi.wlambda); + } + if(bj.wlambda){ + var I = this.invIj; + bj.wlambda.vadd(I.vmult(nixnj).mult(deltalambda),bj.wlambda); + } +}; + + +/** + * @class CANNON.Constraint + * @brief Constraint base class + * @author schteppe + * @param CANNON.Body bodyA + * @param CANNON.Body bodyB + */ +CANNON.Constraint = function(bodyA,bodyB){ + + /** + * @property Array equations + * @memberOf CANNON.Constraint + * @brief Equations to be solved in this constraint + */ + this.equations = []; + + /** + * @property CANNON.Body bodyA + * @memberOf CANNON.Constraint + */ + this.bodyA = bodyA; + + /** + * @property CANNON.Body bodyB + * @memberOf CANNON.Constraint + */ + this.bodyB = bodyB; +}; + +/** + * @method update + * @memberOf CANNON.Constraint + */ +CANNON.Constraint.prototype.update = function(){ + throw new Error("method update() not implmemented in this Constraint subclass!"); +}; + +/** + * @class CANNON.DistanceConstraint + * @brief Constrains two bodies to be at a constant distance from each other. + * @author schteppe + * @param CANNON.Body bodyA + * @param CANNON.Body bodyB + * @param float distance + * @param float maxForce + */ +CANNON.DistanceConstraint = function(bodyA,bodyB,distance,maxForce){ + CANNON.Constraint.call(this,bodyA,bodyB); + + if(typeof(maxForce)==="undefined" ) { + maxForce = 1e6; + } + + // Equations to be fed to the solver + var eqs = this.equations = [ + new CANNON.ContactEquation(bodyA,bodyB), // Just in the normal direction + ]; + + var normal = eqs[0]; + + normal.minForce = -maxForce; + normal.maxForce = maxForce; + + // Update + this.update = function(){ + bodyB.position.vsub(bodyA.position,normal.ni); + normal.ni.normalize(); + /*bodyA.quaternion.vmult(pivotA,normal.ri); + bodyB.quaternion.vmult(pivotB,normal.rj);*/ + normal.ni.mult( distance*0.5,normal.ri); + normal.ni.mult( -distance*0.5,normal.rj); + }; +}; +CANNON.DistanceConstraint.prototype = new CANNON.Constraint(); + + +/** + * @class CANNON.RotationalMotorEquation + * @brief Rotational motor constraint. Works to keep the relative angular velocity of the bodies to a given value + * @author schteppe + * @param CANNON.RigidBody bodyA + * @param CANNON.RigidBody bodyB + * @extends CANNON.Equation + */ +CANNON.RotationalMotorEquation = function(bodyA, bodyB, maxForce){ + maxForce = maxForce || 1e6; + CANNON.Equation.call(this,bodyA,bodyB,-maxForce,maxForce); + this.axisA = new CANNON.Vec3(); // World oriented rotational axis + this.axisB = new CANNON.Vec3(); // World oriented rotational axis + + this.invIi = new CANNON.Mat3(); + this.invIj = new CANNON.Mat3(); + this.targetVelocity = 0; +}; + +CANNON.RotationalMotorEquation.prototype = new CANNON.Equation(); +CANNON.RotationalMotorEquation.prototype.constructor = CANNON.RotationalMotorEquation; + +CANNON.RotationalMotorEquation.prototype.computeB = function(h){ + var a = this.a, + b = this.b; + var bi = this.bi; + var bj = this.bj; + + var axisA = this.axisA; + var axisB = this.axisB; + + var vi = bi.velocity; + var wi = bi.angularVelocity ? bi.angularVelocity : new CANNON.Vec3(); + var fi = bi.force; + var taui = bi.tau ? bi.tau : new CANNON.Vec3(); + + var vj = bj.velocity; + var wj = bj.angularVelocity ? bj.angularVelocity : new CANNON.Vec3(); + var fj = bj.force; + var tauj = bj.tau ? bj.tau : new CANNON.Vec3(); + + var invMassi = bi.invMass; + var invMassj = bj.invMass; + + var invIi = this.invIi; + var invIj = this.invIj; + + if(bi.invInertia){ + invIi.setTrace(bi.invInertia); + } else { + invIi.identity(); // ok? + } + if(bj.invInertia){ + invIj.setTrace(bj.invInertia); + } else { + invIj.identity(); // ok? + } + + // g = 0 + // gdot = axisA * wi - axisB * wj + // G = [0 axisA 0 -axisB] + // W = [vi wi vj wj] + var Gq = 0; + var GW = axisA.dot(wi) + axisB.dot(wj) + this.targetVelocity; + var GiMf = 0;//axis.dot(invIi.vmult(taui)) + axis.dot(invIj.vmult(tauj)); + + var B = - Gq * a - GW * b - h*GiMf; + + return B; +}; + +// Compute C = GMG+eps +CANNON.RotationalMotorEquation.prototype.computeC = function(){ + var bi = this.bi; + var bj = this.bj; + var axisA = this.axisA; + var axisB = this.axisB; + var invMassi = bi.invMass; + var invMassj = bj.invMass; + + var C = this.eps; + + var invIi = this.invIi; + var invIj = this.invIj; + + if(bi.invInertia){ + invIi.setTrace(bi.invInertia); + } else { + invIi.identity(); // ok? + } + if(bj.invInertia){ + invIj.setTrace(bj.invInertia); + } else { + invIj.identity(); // ok? + } + + C += invIi.vmult(axisA).dot(axisB); + C += invIj.vmult(axisB).dot(axisB); + + return C; +}; + +var computeGWlambda_ulambda = new CANNON.Vec3(); +CANNON.RotationalMotorEquation.prototype.computeGWlambda = function(){ + var bi = this.bi; + var bj = this.bj; + var ulambda = computeGWlambda_ulambda; + var axisA = this.axisA; + var axisB = this.axisB; + + var GWlambda = 0.0; + //bj.vlambda.vsub(bi.vlambda, ulambda); + //GWlambda += ulambda.dot(this.ni); + + // Angular + if(bi.wlambda){ + GWlambda += bi.wlambda.dot(axisA); + } + if(bj.wlambda){ + GWlambda += bj.wlambda.dot(axisB); + } + + //console.log("GWlambda:",GWlambda); + + return GWlambda; +}; + +CANNON.RotationalMotorEquation.prototype.addToWlambda = function(deltalambda){ + var bi = this.bi; + var bj = this.bj; + var axisA = this.axisA; + var axisB = this.axisB; + var invMassi = bi.invMass; + var invMassj = bj.invMass; + + // Add to linear velocity + //bi.vlambda.vsub(n.mult(invMassi * deltalambda),bi.vlambda); + //bj.vlambda.vadd(n.mult(invMassj * deltalambda),bj.vlambda); + + // Add to angular velocity + if(bi.wlambda){ + var I = this.invIi; + bi.wlambda.vsub(I.vmult(axisA).mult(deltalambda),bi.wlambda); + } + if(bj.wlambda){ + var I = this.invIj; + bj.wlambda.vadd(I.vmult(axisB).mult(deltalambda),bj.wlambda); + } +}; + + +/** + * @class CANNON.HingeConstraint + * @brief Hinge constraint. Tries to keep the local body axes equal. + * @author schteppe + * @param CANNON.RigidBody bodyA + * @param CANNON.Vec3 pivotA A point defined locally in bodyA. This defines the offset of axisA. + * @param CANNON.Vec3 axisA an axis that bodyA can rotate around. + * @param CANNON.RigidBody bodyB + * @param CANNON.Vec3 pivotB + * @param CANNON.Vec3 axisB + * @param float maxForce + */ +CANNON.HingeConstraint = function(bodyA, pivotA, axisA, bodyB, pivotB, axisB, maxForce){ + CANNON.Constraint.call(this,bodyA,bodyB); + + maxForce = maxForce || 1e6; + var that = this; + // Equations to be fed to the solver + var eqs = this.equations = [ + new CANNON.RotationalEquation(bodyA,bodyB), // rotational1 + new CANNON.RotationalEquation(bodyA,bodyB), // rotational2 + new CANNON.ContactEquation(bodyA,bodyB), // p2pNormal + new CANNON.ContactEquation(bodyA,bodyB), // p2pTangent1 + new CANNON.ContactEquation(bodyA,bodyB), // p2pTangent2 + ]; + + this.getRotationalEquation1 = function(){ return eqs[0]; }; + this.getRotationalEquation2 = function(){ return eqs[1]; }; + this.getPointToPointEquation1 = function(){ return eqs[2]; }; + this.getPointToPointEquation2 = function(){ return eqs[3]; }; + this.getPointToPointEquation3 = function(){ return eqs[4]; }; + + var r1 = this.getRotationalEquation1(); + var r2 = this.getRotationalEquation2(); + var normal = this.getPointToPointEquation1(); + var t1 = this.getPointToPointEquation2(); + var t2 = this.getPointToPointEquation3(); + var motor; // not activated by default + + t1.minForce = t2.minForce = normal.minForce = -maxForce; + t1.maxForce = t2.maxForce = normal.maxForce = maxForce; + + var unitPivotA = pivotA.unit(); + var unitPivotB = pivotB.unit(); + + var axisA_x_pivotA = new CANNON.Vec3(); + var axisA_x_axisA_x_pivotA = new CANNON.Vec3(); + var axisB_x_pivotB = new CANNON.Vec3(); + axisA.cross(unitPivotA,axisA_x_pivotA); + axisA.cross(axisA_x_pivotA,axisA_x_axisA_x_pivotA); + axisB.cross(unitPivotB,axisB_x_pivotB); + + axisA_x_pivotA.normalize(); + axisB_x_pivotB.normalize(); + + // Motor stuff + var motorEnabled = false; + this.motorTargetVelocity = 0; + this.motorMinForce = -maxForce; + this.motorMaxForce = maxForce; + this.enableMotor = function(){ + if(!motorEnabled){ + motor = new CANNON.RotationalMotorEquation(bodyA,bodyB,maxForce); + eqs.push(motor); + motorEnabled = true; + } + }; + this.disableMotor = function(){ + if(motorEnabled){ + motorEnabled = false; + motor = null; + eqs.pop(); + } + }; + + // Update + this.update = function(){ + // Update world positions of pivots + /* + bodyB.position.vsub(bodyA.position,normal.ni); + normal.ni.normalize(); + */ + normal.ni.set(1,0,0); + t1.ni.set(0,1,0); + t2.ni.set(0,0,1); + bodyA.quaternion.vmult(pivotA,normal.ri); + bodyB.quaternion.vmult(pivotB,normal.rj); + + //normal.ni.tangents(t1.ni,t2.ni); + normal.ri.copy(t1.ri); + normal.rj.copy(t1.rj); + normal.ri.copy(t2.ri); + normal.rj.copy(t2.rj); + + // update rotational constraints + bodyA.quaternion.vmult(axisA_x_pivotA, r1.ni); + bodyB.quaternion.vmult(axisB, r1.nj); + bodyA.quaternion.vmult(axisA_x_axisA_x_pivotA, r2.ni); + bodyB.quaternion.vmult(axisB, r2.nj); + + if(motorEnabled){ + bodyA.quaternion.vmult(axisA,motor.axisA); + bodyB.quaternion.vmult(axisB,motor.axisB); + motor.targetVelocity = that.motorTargetVelocity; + motor.maxForce = that.motorMaxForce; + motor.minForce = that.motorMinForce; + } + }; +}; +CANNON.HingeConstraint.prototype = new CANNON.Constraint(); + +/** + * @class CANNON.PointToPointConstraint + * @brief Connects two bodies at given offset points + * @author schteppe + * @param CANNON.Body bodyA + * @param CANNON.Vec3 pivotA The point relative to the center of mass of bodyA which bodyA is constrained to. + * @param CANNON.Body bodyB Body that will be constrained in a similar way to the same point as bodyA. We will therefore get sort of a link between bodyA and bodyB. If not specified, bodyA will be constrained to a static point. + * @param CANNON.Vec3 pivotB See pivotA. + * @param float maxForce The maximum force that should be applied to constrain the bodies. + * @extends CANNON.Constraint + */ +CANNON.PointToPointConstraint = function(bodyA,pivotA,bodyB,pivotB,maxForce){ + CANNON.Constraint.call(this,bodyA,bodyB); + + // Equations to be fed to the solver + var eqs = this.equations = [ + new CANNON.ContactEquation(bodyA,bodyB), // Normal + new CANNON.ContactEquation(bodyA,bodyB), // Tangent2 + new CANNON.ContactEquation(bodyA,bodyB), // Tangent2 + ]; + + var normal = eqs[0]; + var t1 = eqs[1]; + var t2 = eqs[2]; + + t1.minForce = t2.minForce = normal.minForce = -maxForce; + t1.maxForce = t2.maxForce = normal.maxForce = maxForce; + + // Update + this.update = function(){ + bodyB.position.vsub(bodyA.position,normal.ni); + normal.ni.normalize(); + bodyA.quaternion.vmult(pivotA,normal.ri); + bodyB.quaternion.vmult(pivotB,normal.rj); + + normal.ni.tangents(t1.ni,t2.ni); + normal.ri.copy(t1.ri); + normal.rj.copy(t1.rj); + normal.ri.copy(t2.ri); + normal.rj.copy(t2.rj); + }; +}; +CANNON.PointToPointConstraint.prototype = new CANNON.Constraint(); + + +if (typeof module !== 'undefined') { + // export for node + module.exports = CANNON; +} else { + // assign to window + this.CANNON = CANNON; +} + +}).apply(this); \ No newline at end of file diff --git a/readme.md b/readme.md index c56384a1692..881180cfee9 100644 --- a/readme.md +++ b/readme.md @@ -18,6 +18,7 @@ Online [sandbox](http://www.babylonjs.com/sandbox) where you can test your .baby ## Features - Complete scene graph with lights, cameras, materials and meshes - Collisions engine +- Physics engine (thanks to cannon.js) - Scene picking - Antialiasing - Animations engine diff --git a/what's new.md b/what's new.md index 46a6cf5a080..3a339cc617f 100644 --- a/what's new.md +++ b/what's new.md @@ -1,5 +1,14 @@ Changes list ============ +- 1.8.0: + - **Major updates** + - Support for [physics engine](https://github.com/BabylonJS/Babylon.js/wiki/How-to-use-lens-flares) thanks to cannon.js ([deltakosh](http://www.github.com/deltakosh)) + - New [sandbox tool](http://www.babylonjs.com/sandbox/) ([davrous](http://www.github.com/davrous)) + - **Updates** + - New ```animation.currentFrame``` property to get current animation frame ([deltakosh](http://www.github.com/deltakosh)) + - New ```animation.floatInterpolateFunction``` property to define custom float interpolation function ([deltakosh](http://www.github.com/deltakosh)) + - New ```animation.vector3InterpolateFunction``` property to define custom vector3 interpolation function ([deltakosh](http://www.github.com/deltakosh)) + - New ```animation.quaternionInterpolateFunction``` property to define custom quaternion interpolation function ([deltakosh](http://www.github.com/deltakosh)) - 1.7.3: - **Updates** - Support for "file://" moniker ([davrous](https://github.com/davrous)) @@ -13,7 +22,7 @@ - Support for [lens flares](https://github.com/BabylonJS/Babylon.js/wiki/How-to-use-lens-flares) ([deltakosh](http://www.github.com/deltakosh)) - Support for [multi-views](https://github.com/BabylonJS/Babylon.js/wiki/How-to-use-multi-views) ([deltakosh](http://www.github.com/deltakosh)) - **Updates** - - New ```light.excludedMeshes``` property to exclude specific meshes from light coputation ([deltakosh](http://www.github.com/deltakosh)) + - New ```light.excludedMeshes``` property to exclude specific meshes from light computation ([deltakosh](http://www.github.com/deltakosh)) - New ```texture.anisotropicFilteringLevel``` property to define the anisotropic level of a texture ([deltakosh](http://www.github.com/deltakosh)) - New ```mesh.infiniteDistance``` property to make a mesh static from the point of view of the camera ([deltakosh](http://www.github.com/deltakosh)) - New ```scene.customRenderTargets``` property to add our own renderTargetTexture ([deltakosh](http://www.github.com/deltakosh))