Browse Source

Pre-update for babylon.js 1.10

Deltakosh 11 years ago
parent
commit
c8e0784fd1

+ 3 - 2
Babylon/Cameras/babylon.arcRotateCamera.js

@@ -39,6 +39,7 @@ var BABYLON = BABYLON || {};
     BABYLON.ArcRotateCamera.prototype.lowerRadiusLimit = null;
     BABYLON.ArcRotateCamera.prototype.upperRadiusLimit = null;
     BABYLON.ArcRotateCamera.prototype.angularSensibility = 1000.0;
+    BABYLON.ArcRotateCamera.prototype.wheelPrecision = 3.0;
 
     BABYLON.ArcRotateCamera.prototype._getTargetPosition = function () {
         return this.target.position || this.target;
@@ -158,9 +159,9 @@ var BABYLON = BABYLON || {};
             this._wheel = function (event) {
                 var delta = 0;
                 if (event.wheelDelta) {
-                    delta = event.wheelDelta / 120;
+                    delta = event.wheelDelta / (that.wheelPrecision * 40);
                 } else if (event.detail) {
-                    delta = -event.detail / 3;
+                    delta = -event.detail / that.wheelPrecision;
                 }
 
                 if (delta)

+ 134 - 0
Babylon/Cameras/babylon.oculusCamera.js

@@ -0,0 +1,134 @@
+"use strict";
+
+var BABYLON = BABYLON || {};
+
+(function () {
+    BABYLON.OculusController = function () {
+        this._currentOrientation = { yaw: 0, pitch: 0, roll: 0 };
+        this._deviceOrientationHandler = this.onOrientationEvent.bind(this);
+        window.addEventListener("deviceorientation", this._deviceOrientationHandler);
+    };
+
+    BABYLON.OculusController.prototype.onOrientationEvent = function (ev) {
+        var yaw = ev.alpha / 180 * Math.PI;
+        if(!this._referenceYaw){
+            this._referenceYaw= yaw;
+        }
+        this._currentOrientation.yaw = yaw - this._referenceYaw;
+        this._currentOrientation.pitch = ev.beta / 180 * Math.PI;
+        this._currentOrientation.roll = ev.gamma / 180 * Math.PI;
+    };
+    BABYLON.OculusController.prototype.dispose = function () {
+        window.removeEventListener("deviceorientation", this._deviceOrientationHandler);
+    };
+
+    BABYLON.OculusController.prototype.getCurrentOrientation = function () {
+        return this._currentOrientation;
+    };
+
+    BABYLON.OculusController.CameraSettings_OculusRiftDevKit2013_Metric = {
+        HResolution: 1280,
+        VResolution: 800,
+        HScreenSize: 0.149759993,
+        VScreenSize: 0.0935999975,
+        VScreenCenter: 0.0467999987,
+        EyeToScreenDistance: 0.0410000011,
+        LensSeparationDistance: 0.0635000020,
+        InterpupillaryDistance: 0.0640000030,
+        DistortionK: [1.0, 0.219999999, 0.239999995, 0.0],
+        ChromaAbCorrection: [0.995999992, -0.00400000019, 1.01400006, 0.0],
+        PostProcessScaleFactor: 1.714605507808412,
+        LensCenterOffset: 0.151976421
+    };
+
+    BABYLON.OculusOrientedCamera = function (name, position, scene, controller, isLeftEye, ovrSettings, neutralOrientation) {
+        BABYLON.Camera.call(this, name, position, scene);
+        this._controller = controller;
+        this._referenceDirection = new BABYLON.Vector3(0, 0, 1);
+        this._referenceUp = new BABYLON.Vector3(0, 1, 0);
+        this._actualDirection = new BABYLON.Vector3(1, 0, 0);
+        this._actualUp = new BABYLON.Vector3(0, 1, 0);
+        this._currentTargetPoint = new BABYLON.Vector3(0, 0, 0);
+        this._currentOculusOrientation = { yaw: 0.0, pitch: 0.0, roll: 0.0 };
+        this._currentViewMatrix = new BABYLON.Matrix();
+        this._currentOculusOrientationMatrix = new BABYLON.Matrix();
+        this._tempMatrix = new BABYLON.Matrix();
+        neutralOrientation = neutralOrientation || { yaw: 0.0, pitch: 0.0, roll: 0.0 };
+        this._neutralOrientation = neutralOrientation;
+        if (isLeftEye) {
+            this.viewport = new BABYLON.Viewport(0, 0, 0.5, 1.0);
+        } else {
+            this.viewport = new BABYLON.Viewport(0.5, 0, 0.5, 1.0);
+        }
+
+        this._aspectRatioAspectRatio = ovrSettings.HResolution / (2 * ovrSettings.VResolution);
+        this._aspectRatioFov = (2 * Math.atan((ovrSettings.PostProcessScaleFactor * ovrSettings.VScreenSize) / (2 * ovrSettings.EyeToScreenDistance))) ;
+        var hMeters = (ovrSettings.HScreenSize / 4) - (ovrSettings.LensSeparationDistance / 2);
+        var h = (4 * hMeters) / ovrSettings.HScreenSize;
+        this._hMatrix = BABYLON.Matrix.Translation(isLeftEye ? h : -h, 0, 0);
+
+        this._projectionMatrix = new BABYLON.Matrix();
+        this._preViewMatrix = BABYLON.Matrix.Translation(isLeftEye ? .5 * ovrSettings.InterpupillaryDistance : -.5 * ovrSettings.InterpupillaryDistance, 0, 0);
+        new BABYLON.oculusDistortionCorrectionPostProcess("Oculus Distortion", this, !isLeftEye, ovrSettings);
+    };
+    BABYLON.OculusOrientedCamera.buildOculusStereoCamera = function (scene, name, canvas, minZ, maxZ, position, neutralOrientation, useFXAA, controller, ovrSettings) {
+        position = position || new BABYLON.Vector2(0, 0);
+        neutralOrientation = neutralOrientation || { yaw: 0.0, pitch: 0.0, roll: 0.0 };
+        controller = controller || new BABYLON.OculusController();
+        ovrSettings = ovrSettings || BABYLON.OculusController.CameraSettings_OculusRiftDevKit2013_Metric;
+
+        var leftCamera = new BABYLON.OculusOrientedCamera(name + "_left", position, scene, controller, true, ovrSettings, neutralOrientation);
+        leftCamera.minZ = minZ;
+        leftCamera.maxZ = maxZ;
+        if (useFXAA) {
+            new BABYLON.FxaaPostProcess("fxaa_left", 1.0, leftCamera);
+        }
+
+        var rightCamera = new BABYLON.OculusOrientedCamera(name + "_right", position, scene, controller, false, ovrSettings, neutralOrientation);
+        rightCamera.minZ = minZ;
+        rightCamera.maxZ = maxZ;
+        if (useFXAA) {
+            new BABYLON.FxaaPostProcess("fxaa_right", 1.0, rightCamera);
+        }
+        scene.activeCameras = [];
+        scene.activeCameras.push(leftCamera);
+        scene.activeCameras.push(rightCamera);
+        leftCamera.attachControl(canvas);
+        rightCamera.attachControl(canvas);
+    };
+    BABYLON.OculusOrientedCamera.prototype = Object.create(BABYLON.Camera.prototype);
+
+    BABYLON.OculusOrientedCamera.prototype.getViewMatrix = function () {
+
+        BABYLON.Matrix.RotationYawPitchRollToRef(
+            this._currentOculusOrientation.yaw + this._neutralOrientation.yaw,
+            this._currentOculusOrientation.pitch + this._neutralOrientation.pitch,
+            -this._currentOculusOrientation.roll + this._neutralOrientation.roll
+            , this._currentOculusOrientationMatrix);
+
+        BABYLON.Vector3.TransformCoordinatesToRef(this._referenceDirection, this._currentOculusOrientationMatrix, this._actualDirection);
+        BABYLON.Vector3.TransformCoordinatesToRef(this._referenceUp, this._currentOculusOrientationMatrix, this._actualUp);
+        
+        BABYLON.Vector3.FromFloatsToRef(this.position.x + this._actualDirection.x, this.position.y + this._actualDirection.y, this.position.z + this._actualDirection.z, this._currentTargetPoint);
+        BABYLON.Matrix.LookAtLHToRef(this.position, this._currentTargetPoint, this._actualUp, this._tempMatrix);
+        this._tempMatrix.multiplyToRef(this._preViewMatrix, this._currentViewMatrix);
+        return this._currentViewMatrix;
+    };
+
+    BABYLON.OculusOrientedCamera.prototype._update = function () {
+        if (!this._referenceOculusOrientation) {
+            this._referenceOculusOrientation = { yaw: this._controller._currentOrientation.yaw, pitch: this._controller._currentOrientation.pitch, roll: this._controller._currentOrientation.roll };
+        }
+        else {
+            this._currentOculusOrientation.yaw = this._controller._currentOrientation.yaw - this._referenceOculusOrientation.yaw;
+            this._currentOculusOrientation.pitch = this._controller._currentOrientation.pitch - this._referenceOculusOrientation.pitch;
+            this._currentOculusOrientation.roll = this._controller._currentOrientation.roll - this._referenceOculusOrientation.roll;
+        }
+    };
+
+    BABYLON.OculusOrientedCamera.prototype.getProjectionMatrix = function (force) {
+        BABYLON.Matrix.PerspectiveFovLHToRef(this._aspectRatioFov, this._aspectRatioAspectRatio, this.minZ, this.maxZ, this._tempMatrix);
+        this._tempMatrix.multiplyToRef(this._hMatrix, this._projectionMatrix);
+        return this._projectionMatrix;
+    };
+})();

+ 36 - 0
Babylon/Cameras/babylon.virtualJoysticksCamera.js

@@ -0,0 +1,36 @@
+var BABYLON = BABYLON || {};
+
+(function () {
+    BABYLON.VirtualJoysticksCamera = function (name, position, scene) {
+        BABYLON.FreeCamera.call(this, name, position, scene);
+        this.leftjoystick = new BABYLON.VirtualJoystick(true);
+        this.leftjoystick.setAxisForUD("Z");
+        this.leftjoystick.setAxisForLR("X");
+        this.leftjoystick.setJoystickSensibility(0.15);
+        this.rightjoystick = new BABYLON.VirtualJoystick(false);
+        this.rightjoystick.setAxisForUD("X");
+        this.rightjoystick.setAxisForLR("Y");
+        this.rightjoystick.reverseUpDown = true;
+        this.rightjoystick.setJoystickSensibility(0.05);
+        this.rightjoystick.setJoystickColor("yellow");
+    };
+
+    // We're mainly based on the logic defined into the FreeCamera code
+    BABYLON.VirtualJoysticksCamera.prototype = Object.create(BABYLON.FreeCamera.prototype);
+    BABYLON.VirtualJoysticksCamera.prototype._checkInputs = function () {
+        var cameraTransform = BABYLON.Matrix.RotationYawPitchRoll(this.rotation.y, this.rotation.x, 0);
+        var deltaTransform = BABYLON.Vector3.TransformCoordinates(this.leftjoystick.deltaPosition, cameraTransform);
+        this.cameraDirection = this.cameraDirection.add(deltaTransform);
+        this.cameraRotation = this.cameraRotation.add(this.rightjoystick.deltaPosition);
+        if (!this.leftjoystick.pressed) {
+            this.leftjoystick.deltaPosition = this.leftjoystick.deltaPosition.scale(0.9);
+        }
+        if (!this.rightjoystick.pressed) {
+            this.rightjoystick.deltaPosition = this.rightjoystick.deltaPosition.scale(0.9);
+        }
+    };
+
+    BABYLON.VirtualJoysticksCamera.prototype.dispose = function () {
+        this.leftjoystick.releaseCanvas();
+    };
+})();

+ 1 - 1
Babylon/Loading/babylon.sceneLoader.js

@@ -55,7 +55,7 @@ var BABYLON = BABYLON || {};
 
         Load: function (rootUrl, sceneFilename, engine, onsuccess, progressCallBack, onerror) {
 
-            var plugin = this._getPluginForFilename(sceneFilename);
+            var plugin = this._getPluginForFilename(sceneFilename.name || sceneFilename);
             var database;
 
             var loadSceneFromData = function (data) {

+ 1 - 1
Babylon/Physics/babylon.physicsEngine.js

@@ -267,7 +267,7 @@ var BABYLON = BABYLON || {};
 
     // Statics
     BABYLON.PhysicsEngine.IsSupported = function () {
-        return CANNON !== undefined;
+        return window.CANNON !== undefined;
     };
 
     BABYLON.PhysicsEngine.NoImpostor = 0;

+ 32 - 0
Babylon/PostProcess/babylon.oculusDistortionCorrectionPostProcess.js

@@ -0,0 +1,32 @@
+"use strict";
+
+var BABYLON = BABYLON || {};
+
+(function () {
+    BABYLON.oculusDistortionCorrectionPostProcess = function (name, camera, isRightEye, cameraSettings) {
+        BABYLON.PostProcess.call(this, name, "oculusDistortionCorrection", [
+			'LensCenter',
+		    'Scale',
+		    'ScaleIn',
+		    'HmdWarpParam'
+        ], null, cameraSettings.PostProcessScaleFactor, camera, BABYLON.Texture.BILINEAR_SAMPLINGMODE, null, null);
+        this._isRightEye = isRightEye;
+        this._distortionFactors = cameraSettings.DistortionK;
+        this._postProcessScaleFactor = cameraSettings.PostProcessScaleFactor;
+        this._lensCenterOffset = cameraSettings.LensCenterOffset;
+    };
+
+    BABYLON.oculusDistortionCorrectionPostProcess.prototype = Object.create(BABYLON.PostProcess.prototype);
+    BABYLON.oculusDistortionCorrectionPostProcess.prototype.onSizeChanged = function () {
+        this.aspectRatio = this.width * .5 / this.height;
+        this._scaleIn = new BABYLON.Vector2(2, 2 / this.aspectRatio);
+        this._scaleFactor = new BABYLON.Vector2(.5 * (1/this._postProcessScaleFactor), .5 * (1/this._postProcessScaleFactor) * this.aspectRatio);
+        this._lensCenter = new BABYLON.Vector2(this._isRightEye ? 0.5 - this._lensCenterOffset * 0.5 : 0.5 + this._lensCenterOffset * 0.5, 0.5);
+    };
+    BABYLON.oculusDistortionCorrectionPostProcess.prototype.onApply = function (effect) {
+        effect.setFloat2("LensCenter", this._lensCenter.x, this._lensCenter.y);
+        effect.setFloat2("Scale", this._scaleFactor.x, this._scaleFactor.y);
+        effect.setFloat2("ScaleIn", this._scaleIn.x, this._scaleIn.y);
+        effect.setFloat4("HmdWarpParam", this._distortionFactors[0], this._distortionFactors[1], this._distortionFactors[2], this._distortionFactors[3]);
+    };
+})();

+ 31 - 0
Babylon/Shaders/oculusDistortionCorrection.fragment.fx

@@ -0,0 +1,31 @@
+#ifdef GL_ES
+precision mediump float;
+#endif
+
+// Samplers
+varying vec2 vUV;
+uniform sampler2D textureSampler;
+uniform vec2 LensCenter;
+uniform vec2 Scale;
+uniform vec2 ScaleIn;
+uniform vec4 HmdWarpParam;
+
+vec2 HmdWarp(vec2 in01) {
+
+	vec2 theta = (in01 - LensCenter) * ScaleIn; // Scales to [-1, 1]
+	float rSq = theta.x * theta.x + theta.y * theta.y;
+	vec2 rvector = theta * (HmdWarpParam.x + HmdWarpParam.y * rSq + HmdWarpParam.z * rSq * rSq + HmdWarpParam.w * rSq * rSq * rSq);
+	return LensCenter + Scale * rvector;
+}
+
+
+
+void main(void)
+{
+	vec2 tc = HmdWarp(vUV);
+	if (tc.x <0.0 || tc.x>1.0 || tc.y<0.0 || tc.y>1.0)
+		gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+	else{
+		gl_FragColor = vec4(texture2D(textureSampler, tc).rgb, 1.0);
+	}
+}

+ 142 - 0
Babylon/Tools/babylon.tools.dds.js

@@ -0,0 +1,142 @@
+"use strict";
+
+var BABYLON = BABYLON || {};
+
+(function () {
+    BABYLON.Tools = BABYLON.Tools|| {};
+
+    // Based on demo done by Brandon Jones - http://media.tojicode.com/webgl-samples/dds.html
+    // All values and structures referenced from:
+    // http://msdn.microsoft.com/en-us/library/bb943991.aspx/
+    var DDS_MAGIC = 0x20534444;
+
+    var DDSD_CAPS = 0x1,
+        DDSD_HEIGHT = 0x2,
+        DDSD_WIDTH = 0x4,
+        DDSD_PITCH = 0x8,
+        DDSD_PIXELFORMAT = 0x1000,
+        DDSD_MIPMAPCOUNT = 0x20000,
+        DDSD_LINEARSIZE = 0x80000,
+        DDSD_DEPTH = 0x800000;
+
+    var DDSCAPS_COMPLEX = 0x8,
+        DDSCAPS_MIPMAP = 0x400000,
+        DDSCAPS_TEXTURE = 0x1000;
+
+    var DDSCAPS2_CUBEMAP = 0x200,
+        DDSCAPS2_CUBEMAP_POSITIVEX = 0x400,
+        DDSCAPS2_CUBEMAP_NEGATIVEX = 0x800,
+        DDSCAPS2_CUBEMAP_POSITIVEY = 0x1000,
+        DDSCAPS2_CUBEMAP_NEGATIVEY = 0x2000,
+        DDSCAPS2_CUBEMAP_POSITIVEZ = 0x4000,
+        DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x8000,
+        DDSCAPS2_VOLUME = 0x200000;
+
+    var DDPF_ALPHAPIXELS = 0x1,
+        DDPF_ALPHA = 0x2,
+        DDPF_FOURCC = 0x4,
+        DDPF_RGB = 0x40,
+        DDPF_YUV = 0x200,
+        DDPF_LUMINANCE = 0x20000;
+
+    function FourCCToInt32(value) {
+        return value.charCodeAt(0) +
+            (value.charCodeAt(1) << 8) +
+            (value.charCodeAt(2) << 16) +
+            (value.charCodeAt(3) << 24);
+    }
+
+    function Int32ToFourCC(value) {
+        return String.fromCharCode(
+            value & 0xff,
+            (value >> 8) & 0xff,
+            (value >> 16) & 0xff,
+            (value >> 24) & 0xff
+        );
+    }
+
+    var FOURCC_DXT1 = FourCCToInt32("DXT1");
+    var FOURCC_DXT5 = FourCCToInt32("DXT5");
+
+    var headerLengthInt = 31; // The header length in 32 bit ints
+
+    // Offsets into the header array
+    var off_magic = 0;
+
+    var off_size = 1;
+    var off_flags = 2;
+    var off_height = 3;
+    var off_width = 4;
+
+    var off_mipmapCount = 7;
+
+    var off_pfFlags = 20;
+    var off_pfFourCC = 21;
+
+
+    BABYLON.Tools.GetDDSInfo = function (arrayBuffer) {
+        var header = new Int32Array(arrayBuffer, 0, headerLengthInt);
+
+        var mipmapCount = 1;
+        if (header[off_flags] & DDSD_MIPMAPCOUNT) {
+            mipmapCount = Math.max(1, header[off_mipmapCount]);
+        }
+
+        return {
+            width: header[off_width],
+            height: header[off_height],
+            mipmapCount: mipmapCount
+        };
+    };
+
+    BABYLON.Tools.UploadDDSLevels = function (gl, ext, arrayBuffer, loadMipmaps) {
+        var header = new Int32Array(arrayBuffer, 0, headerLengthInt),
+            fourCC, blockBytes, internalFormat,
+            width, height, dataLength, dataOffset,
+            byteArray, mipmapCount, i;
+
+        if (header[off_magic] != DDS_MAGIC) {
+            console.error("Invalid magic number in DDS header");
+            return;
+        }
+
+        if (!header[off_pfFlags] & DDPF_FOURCC) {
+            console.error("Unsupported format, must contain a FourCC code");
+            return;
+        }
+
+        fourCC = header[off_pfFourCC];
+        switch (fourCC) {
+            case FOURCC_DXT1:
+                blockBytes = 8;
+                internalFormat = ext.COMPRESSED_RGBA_S3TC_DXT1_EXT;
+                break;
+            case FOURCC_DXT5:
+                blockBytes = 16;
+                internalFormat = ext.COMPRESSED_RGBA_S3TC_DXT5_EXT;
+                break;
+            default:
+                console.error("Unsupported FourCC code:", Int32ToFourCC(fourCC));
+                return;
+        }
+
+        mipmapCount = 1;
+        if (header[off_flags] & DDSD_MIPMAPCOUNT && loadMipmaps !== false) {
+            mipmapCount = Math.max(1, header[off_mipmapCount]);
+        }
+
+        width = header[off_width];
+        height = header[off_height];
+        dataOffset = header[off_size] + 4;
+
+        for (i = 0; i < mipmapCount; ++i) {
+            dataLength = Math.max(4, width) / 4 * Math.max(4, height) / 4 * blockBytes;
+            byteArray = new Uint8Array(arrayBuffer, dataOffset, dataLength);
+            gl.compressedTexImage2D(gl.TEXTURE_2D, i, internalFormat, width, height, 0, byteArray);
+            dataOffset += dataLength;
+            width *= 0.5;
+            height *= 0.5;
+        }
+    };
+
+})();

+ 7 - 3
Babylon/Tools/babylon.tools.js

@@ -3,7 +3,7 @@
 var BABYLON = BABYLON || {};
 
 (function () {
-    BABYLON.Tools = {};
+    BABYLON.Tools = BABYLON.Tools || {};
 
     BABYLON.Tools.GetFilename = function (path) {
         var index = path.lastIndexOf("/");
@@ -215,18 +215,22 @@ var BABYLON = BABYLON || {};
         return img;
     };
 
-    BABYLON.Tools.LoadFile = function (url, callback, progressCallBack, database) {
+    BABYLON.Tools.LoadFile = function (url, callback, progressCallBack, database, useArrayBuffer) {
         var noIndexedDB = function () {
             var request = new XMLHttpRequest();
             var loadUrl = BABYLON.Tools.BaseUrl + url;
             request.open('GET', loadUrl, true);
+            
+            if (useArrayBuffer) {
+                request.responseType = "arraybuffer";
+            }
 
             request.onprogress = progressCallBack;
 
             request.onreadystatechange = function () {
                 if (request.readyState == 4) {
                     if (request.status == 200) {
-                        callback(request.responseText);
+                        callback(!useArrayBuffer ? request.responseText : request.response);
                     } else { // Failed
                         throw new Error(request.status, "Unable to load " + loadUrl);
                     }

+ 340 - 0
Babylon/Tools/babylon.virtualJoystick.js

@@ -0,0 +1,340 @@
+/// <reference path="../../babylon.js" />
+
+// Mainly based on these 2 articles : 
+// Creating an universal virtual touch joystick working for all Touch models thanks to Hand.JS : http://blogs.msdn.com/b/davrous/archive/2013/02/22/creating-an-universal-virtual-touch-joystick-working-for-all-touch-models-thanks-to-hand-js.aspx
+// & on Seb Lee-Delisle original work: http://seb.ly/2011/04/multi-touch-game-controller-in-javascripthtml5-for-ipad/ 
+
+"use strict";
+
+// shim layer with setTimeout fallback
+window.requestAnimationFrame = (function () {
+    return window.requestAnimationFrame ||
+          window.webkitRequestAnimationFrame ||
+          window.mozRequestAnimationFrame ||
+          function (callback) {
+              window.setTimeout(callback, 1000 / 60);
+          };
+})();
+
+(function (BABYLON) {
+    var VirtualJoystick = (function () {
+        var vjCanvas, vjCanvasContext, vjCanvasWidth, vjCanvasHeight, halfWidth, halfHeight;
+        var globalJoystickIndex = 0;
+
+        function VirtualJoystick(leftJoystick) {
+            if (leftJoystick) {
+                this._leftJoystick = true;
+            }
+            else {
+                this._leftJoystick = false;
+            }
+
+            this.joystickIndex = globalJoystickIndex;
+            globalJoystickIndex++;
+
+            // By default left & right arrow keys are moving the X
+            // and up & down keys are moving the Y
+            this._axisTargetedByLeftAndRight = "X";
+            this._axisTargetedByUpAndDown = "Y";
+
+            this.reverseLeftRight = false;
+            this.reverseUpDown = false;
+
+            // collections of pointers
+            this._touches = new BABYLON.VirtualJoystick.Collection();
+            this.deltaPosition = BABYLON.Vector3.Zero();
+
+            this._joystickSensibility = 25;
+            this._inversedSensibility = 1 / (this._joystickSensibility / 1000);
+            this._rotationSpeed = 25;
+            this._inverseRotationSpeed = 1 / (this._rotationSpeed / 1000);
+            this._rotateOnAxisRelativeToMesh = false;
+
+            var that = this;
+
+            // injecting a canvas element on top of the canvas 3D game
+            if (!vjCanvas) {
+                window.addEventListener("resize", function () {
+                    vjCanvasWidth = window.innerWidth;
+                    vjCanvasHeight = window.innerHeight;
+                    vjCanvas.width = vjCanvasWidth;
+                    vjCanvas.height = vjCanvasHeight;
+                    halfWidth = vjCanvasWidth / 2;
+                    halfHeight = vjCanvasHeight / 2;
+                }, false);
+                vjCanvas = document.createElement("canvas");
+                vjCanvasWidth = window.innerWidth;
+                vjCanvasHeight = window.innerHeight;
+                vjCanvas.width = window.innerWidth;
+                vjCanvas.height = window.innerHeight;
+                vjCanvas.style.width = "100%";
+                vjCanvas.style.height = "100%";
+                vjCanvas.style.position = "absolute";
+                vjCanvas.style.backgroundColor = "transparent";
+                vjCanvas.style.top = "0px";
+                vjCanvas.style.left = "0px";
+                vjCanvas.style.zIndex = 10;
+                vjCanvas.style.msTouchAction = "none";
+                vjCanvasContext = vjCanvas.getContext('2d');
+                vjCanvasContext.strokeStyle = "#ffffff";
+                vjCanvasContext.lineWidth = 2;
+                document.body.appendChild(vjCanvas);
+            }
+            halfWidth = vjCanvas.width / 2;
+            halfHeight = vjCanvas.height / 2;
+            this.pressed = false;
+            // default joystick color
+            this._joystickColor = "cyan";
+
+            this.joystickPointerID = -1;
+            // current joystick position
+            this.joystickPointerPos = new BABYLON.Vector2(0, 0);
+            // origin joystick position
+            this.joystickPointerStartPos = new BABYLON.Vector2(0, 0);
+            this.deltaJoystickVector = new BABYLON.Vector2(0, 0);
+
+            vjCanvas.addEventListener('pointerdown', function (evt) {
+                that.onPointerDown(evt);
+            }, false);
+            vjCanvas.addEventListener('pointermove', function (evt) {
+                that.onPointerMove(evt);
+            }, false);
+            vjCanvas.addEventListener('pointerup', function (evt) {
+                that.onPointerUp(evt);
+            }, false);
+            vjCanvas.addEventListener('pointerout', function (evt) {
+                that.onPointerUp(evt);
+            }, false);
+            vjCanvas.addEventListener("contextmenu", function (e) {
+                e.preventDefault();    // Disables system menu
+            }, false);
+            requestAnimationFrame(function () {
+                that.drawVirtualJoystick();
+            });
+        }
+
+        VirtualJoystick.prototype.setJoystickSensibility = function (newJoystickSensibility) {
+            this._joystickSensibility = newJoystickSensibility;
+            this._inversedSensibility = 1 / (this._joystickSensibility / 1000);
+        };
+
+        VirtualJoystick.prototype.onPointerDown = function (e) {
+            e.preventDefault();
+            var newPointer = { identifier: e.pointerId, x: e.clientX, y: e.clientY, type: this.givePointerType(e) };
+            var positionOnScreenCondition;
+            if (this._leftJoystick === true) {
+                positionOnScreenCondition = (e.clientX < halfWidth);
+            }
+            else {
+                positionOnScreenCondition = (e.clientX > halfWidth);
+            }
+
+            if (positionOnScreenCondition && this.joystickPointerID < 0) {
+                // First contact will be dedicated to the virtual joystick
+                this.joystickPointerID = e.pointerId;
+                this.joystickPointerStartPos.x = e.clientX;
+                this.joystickPointerStartPos.y = e.clientY;
+                this.joystickPointerPos = this.joystickPointerStartPos.clone();
+                this.deltaJoystickVector.x = 0;
+                this.deltaJoystickVector.y = 0;
+                this.pressed = true;
+                this._touches.add(e.pointerId, newPointer);
+            }
+            else {
+                // You can only trigger the action buttons with a joystick declared
+                if (globalJoystickIndex < 2 && this._action) {
+                    this._action();
+                    this._touches.add(e.pointerId, newPointer);
+                }
+            }
+        };
+
+        VirtualJoystick.prototype.onPointerMove = function (e) {
+            // If the current pointer is the one associated to the joystick (first touch contact)
+            if (this.joystickPointerID == e.pointerId) {
+                this.joystickPointerPos.x = e.clientX;
+                this.joystickPointerPos.y = e.clientY;
+                this.deltaJoystickVector = this.joystickPointerPos.clone();
+                this.deltaJoystickVector = this.deltaJoystickVector.subtract(this.joystickPointerStartPos);
+
+                var directionLeftRight = this.reverseLeftRight ? -1 : 1;
+                var deltaJoystickX = directionLeftRight * this.deltaJoystickVector.x / this._inversedSensibility;
+                switch (this._axisTargetedByLeftAndRight) {
+                    case "X":
+                        this.deltaPosition.x = Math.min(1, Math.max(-1, deltaJoystickX));
+                        break;
+                    case "Y":
+                        this.deltaPosition.y = Math.min(1, Math.max(-1, deltaJoystickX));
+                        break;
+                    case "Z":
+                        this.deltaPosition.z = Math.min(1, Math.max(-1, deltaJoystickX));
+                        break;
+                }
+                var directionUpDown = this.reverseUpDown ? 1 : -1;
+                var deltaJoystickY = directionUpDown * this.deltaJoystickVector.y / this._inversedSensibility;
+                switch (this._axisTargetedByUpAndDown) {
+                    case "X":
+                        this.deltaPosition.x = Math.min(1, Math.max(-1, deltaJoystickY));
+                        break;
+                    case "Y":
+                        this.deltaPosition.y = Math.min(1, Math.max(-1, deltaJoystickY));
+                        break;
+                    case "Z":
+                        this.deltaPosition.z = Math.min(1, Math.max(-1, deltaJoystickY));
+                        break;
+                }
+            }
+            else {
+                if (this._touches.item(e.pointerId)) {
+                    this._touches.item(e.pointerId).x = e.clientX;
+                    this._touches.item(e.pointerId).y = e.clientY;
+                }
+            }
+        };
+
+        VirtualJoystick.prototype.onPointerUp = function (e) {
+            if (this.joystickPointerID == e.pointerId) {
+                this.joystickPointerID = -1;
+                this.pressed = false;
+            }
+            this.deltaJoystickVector.x = 0;
+            this.deltaJoystickVector.y = 0;
+
+            this._touches.remove(e.pointerId);
+        };
+
+        VirtualJoystick.prototype.setJoystickColor = function (newColor) {
+            this._joystickColor = newColor;
+        };
+
+        VirtualJoystick.prototype.setActionOnTouch = function (action) {
+            this._action = action;
+        };
+
+        // Define which axis you'd like to control for left & right 
+        VirtualJoystick.prototype.setAxisForLR = function (axisLetter) {
+            switch (axisLetter) {
+                case "X":
+                case "Y":
+                case "Z":
+                    this._axisTargetedByLeftAndRight = axisLetter;
+                    break;
+                default:
+                    this._axisTargetedByLeftAndRight = "X";
+                    break;
+            }
+        };
+
+        // Define which axis you'd like to control for up & down 
+        VirtualJoystick.prototype.setAxisForUD = function (axisLetter) {
+            switch (axisLetter) {
+                case "X":
+                case "Y":
+                case "Z":
+                    this._axisTargetedByUpAndDown = axisLetter;
+                    break;
+                default:
+                    this._axisTargetedByUpAndDown = "Y";
+                    break;
+            }
+        };
+
+        VirtualJoystick.prototype.drawVirtualJoystick = function () {
+            var that = this;
+
+            if (that._leftJoystick) {
+                vjCanvasContext.clearRect(0, 0, vjCanvasWidth / 2, vjCanvasHeight);
+            }
+            else {
+                vjCanvasContext.clearRect(vjCanvasWidth / 2, 0, vjCanvasWidth, vjCanvasHeight);
+            }
+            this._touches.forEach(function (touch) {
+                if (touch.identifier === that.joystickPointerID) {
+                    vjCanvasContext.beginPath();
+                    vjCanvasContext.strokeStyle = that._joystickColor;
+                    vjCanvasContext.lineWidth = 6;
+                    vjCanvasContext.arc(that.joystickPointerStartPos.x, that.joystickPointerStartPos.y, 40, 0, Math.PI * 2, true);
+                    vjCanvasContext.stroke();
+                    vjCanvasContext.beginPath();
+                    vjCanvasContext.strokeStyle = that._joystickColor;
+                    vjCanvasContext.lineWidth = 2;
+                    vjCanvasContext.arc(that.joystickPointerStartPos.x, that.joystickPointerStartPos.y, 60, 0, Math.PI * 2, true);
+                    vjCanvasContext.stroke();
+                    vjCanvasContext.beginPath();
+                    vjCanvasContext.strokeStyle = that._joystickColor;
+                    vjCanvasContext.arc(that.joystickPointerPos.x, that.joystickPointerPos.y, 40, 0, Math.PI * 2, true);
+                    vjCanvasContext.stroke();
+                }
+                else {
+                    vjCanvasContext.beginPath();
+                    vjCanvasContext.fillStyle = "white";
+                    vjCanvasContext.beginPath();
+                    vjCanvasContext.strokeStyle = "red";
+                    vjCanvasContext.lineWidth = "6";
+                    vjCanvasContext.arc(touch.x, touch.y, 40, 0, Math.PI * 2, true);
+                    vjCanvasContext.stroke();
+                };
+            });
+            requestAnimationFrame(function () {
+                that.drawVirtualJoystick();
+            });
+        };
+
+        VirtualJoystick.prototype.givePointerType = function (event) {
+            switch (event.pointerType) {
+                case event.POINTER_TYPE_MOUSE:
+                    return "MOUSE";
+                    break;
+                case event.POINTER_TYPE_PEN:
+                    return "PEN";
+                    break;
+                case event.POINTER_TYPE_TOUCH:
+                    return "TOUCH";
+                    break;
+            }
+        };
+
+        VirtualJoystick.prototype.releaseCanvas = function () {
+            if (vjCanvas) {
+                document.body.removeChild(vjCanvas);
+            };
+        };
+
+        return VirtualJoystick;
+    })();
+    BABYLON.VirtualJoystick = VirtualJoystick;
+
+    var Collection = (function () {
+        function Collection() {
+            this.count = 0;
+            this.collection = {};
+        };
+        Collection.prototype.add = function (key, item) {
+            if (this.collection[key] != undefined) {
+                return undefined;
+            }
+            this.collection[key] = item;
+            return ++this.count;
+        };
+        Collection.prototype.remove = function (key) {
+            if (this.collection[key] == undefined) {
+                return undefined;
+            }
+            delete this.collection[key];
+            return --this.count;
+        };
+        Collection.prototype.item = function (key) {
+            return this.collection[key];
+        };
+        Collection.prototype.forEach = function (block) {
+            var key;
+            for (key in this.collection) {
+                if (this.collection.hasOwnProperty(key)) {
+                    block(this.collection[key]);
+                }
+            }
+        };
+        return Collection;
+    })();
+    BABYLON.VirtualJoystick.Collection = Collection;
+})(BABYLON || (BABYLON = {}));

+ 64 - 39
Babylon/babylon.engine.js

@@ -41,6 +41,7 @@ var BABYLON = BABYLON || {};
 
         // Extensions
         this._caps.standardDerivatives = (this._gl.getExtension('OES_standard_derivatives') !== null);
+        this._caps.s3tc = this._gl.getExtension('WEBGL_compressed_texture_s3tc') ;
         this._caps.textureFloat = (this._gl.getExtension('OES_texture_float') !== null);        
         this._caps.textureAnisotropicFilterExtension = this._gl.getExtension('EXT_texture_filter_anisotropic') || this._gl.getExtension('WEBKIT_EXT_texture_filter_anisotropic') || this._gl.getExtension('MOZ_EXT_texture_filter_anisotropic');
         this._caps.maxAnisotropy = this._caps.textureAnisotropicFilterExtension ? this._gl.getParameter(this._caps.textureAnisotropicFilterExtension.MAX_TEXTURE_MAX_ANISOTROPY_EXT) : 0;
@@ -603,56 +604,80 @@ var BABYLON = BABYLON || {};
         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;
+    var prepareWebGLTexture = function (texture, scene, width, height, invertY, noMipmap, processFunction) {
+        var engine = scene.getEngine();
+        var potWidth = getExponantOfTwo(width, engine._caps.maxTextureSize);
+        var potHeight = getExponantOfTwo(height, engine._caps.maxTextureSize);
 
-                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);
+        engine._gl.bindTexture(engine._gl.TEXTURE_2D, texture);
+        engine._gl.pixelStorei(engine._gl.UNPACK_FLIP_Y_WEBGL, invertY === undefined ? true : invertY);
 
-            that._activeTexturesCache = [];
-            texture._baseWidth = img.width;
-            texture._baseHeight = img.height;
-            texture._width = potWidth;
-            texture._height = potHeight;
-            texture.isReady = true;
-            scene._removePendingData(texture);
-        };
+        processFunction(potWidth, potHeight);
 
-        var onerror = function () {
-            scene._removePendingData(texture);
-        };
+        engine._gl.texParameteri(engine._gl.TEXTURE_2D, engine._gl.TEXTURE_MAG_FILTER, engine._gl.LINEAR);
 
-        scene._addPendingData(texture);
-        BABYLON.Tools.LoadImage(url, onload, onerror, scene.database);
+        if (noMipmap) {
+            engine._gl.texParameteri(engine._gl.TEXTURE_2D, engine._gl.TEXTURE_MIN_FILTER, engine._gl.LINEAR);
+        } else {
+            engine._gl.texParameteri(engine._gl.TEXTURE_2D, engine._gl.TEXTURE_MIN_FILTER, engine._gl.LINEAR_MIPMAP_LINEAR);
+            engine._gl.generateMipmap(engine._gl.TEXTURE_2D);
+        }
+        engine._gl.bindTexture(engine._gl.TEXTURE_2D, null);
 
+        engine._activeTexturesCache = [];
+        texture._baseWidth = width;
+        texture._baseHeight = height;
+        texture._width = potWidth;
+        texture._height = potHeight;
+        texture.isReady = true;
+        scene._removePendingData(texture);
+    };
+
+    BABYLON.Engine.prototype.createTexture = function (url, noMipmap, invertY, scene) {
+        var texture = this._gl.createTexture();
+        var that = this;
+        var isDDS = this.getCaps().s3tc && (url.substr(url.length - 4, 4).toLowerCase() === ".dds");
+
+        scene._addPendingData(texture);
         texture.url = url;
         texture.noMipmap = noMipmap;
         texture.references = 1;
         this._loadedTexturesCache.push(texture);
 
+        if (isDDS) {
+            BABYLON.Tools.LoadFile(url, function (data) {
+                var info = BABYLON.Tools.GetDDSInfo(data);
+
+                var loadMipmap = info.mipmapCount > 1 && !noMipmap;
+
+                prepareWebGLTexture(texture, scene, info.width, info.height, invertY, !loadMipmap, function (potWidth, potHeight) {
+                    BABYLON.Tools.UploadDDSLevels(that._gl, that.getCaps().s3tc, data, loadMipmap);
+                });
+            }, null, scene.database, true);
+        } else {
+            var onload = function(img) {
+                prepareWebGLTexture(texture, scene, img.width, img.height, invertY, noMipmap, function (potWidth, potHeight) {
+                    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.texImage2D(that._gl.TEXTURE_2D, 0, that._gl.RGBA, that._gl.RGBA, that._gl.UNSIGNED_BYTE, isPot ? img : that._workingCanvas);
+
+                });
+            };
+
+            var onerror = function() {
+                scene._removePendingData(texture);
+            };
+
+            BABYLON.Tools.LoadImage(url, onload, onerror, scene.database);
+        }
+
         return texture;
     };
 

+ 4 - 0
Tools/BuildOurOwnBabylonJS/BuildOurOwnBabylonJS/babylonJS.xml

@@ -1,5 +1,9 @@
 <?xml version="1.0" encoding="utf-8" ?>
 <files xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="babylonJS.xsd">
+  <script src="Babylon/PostProcess/babylon.oculusDistortionCorrectionPostProcess.js"></script>
+  <script src="Babylon/Tools/babylon.virtualJoystick.js"></script>
+  <script src="Babylon/Cameras/babylon.oculusCamera.js"></script>
+  <script src="Babylon/Cameras/babylon.virtualJoysticksCamera.js"></script>
   <script src="Babylon/Mesh/babylon.csg.js"></script>
   <script src="Babylon/Tools/babylon.sceneSerializer.js"></script>
   <script src="Babylon/Physics/babylon.physicsEngine.js"></script>