Explorar o código

Add hdr cube texture support (moving from mat lib to core)

David Catuhe %!s(int64=9) %!d(string=hai) anos
pai
achega
67de58db6c
Modificáronse 36 ficheiros con 4581 adicións e 3186 borrados
  1. 5 1
      Tools/Gulp/config.json
  2. 19 19
      dist/preview release/babylon.core.js
  3. 2386 2255
      dist/preview release/babylon.d.ts
  4. 27 26
      dist/preview release/babylon.js
  5. 676 10
      dist/preview release/babylon.max.js
  6. 26 25
      dist/preview release/babylon.noworker.js
  7. 1 0
      dist/preview release/what's new.md
  8. 1 7
      materialsLibrary/config.json
  9. 2 2
      materialsLibrary/dist/babylon.fireMaterial.js
  10. 1 1
      materialsLibrary/dist/babylon.fireMaterial.min.js
  11. 1 1
      materialsLibrary/dist/babylon.normalMaterial.js
  12. 1 1
      materialsLibrary/dist/babylon.normalMaterial.min.js
  13. 0 608
      materialsLibrary/dist/babylon.pbrMaterial.js
  14. 2 2
      materialsLibrary/dist/babylon.pbrMaterial.min.js
  15. 1 1
      materialsLibrary/dist/babylon.simpleMaterial.js
  16. 1 1
      materialsLibrary/dist/babylon.simpleMaterial.min.js
  17. 1 1
      materialsLibrary/dist/babylon.terrainMaterial.js
  18. 1 1
      materialsLibrary/dist/babylon.terrainMaterial.min.js
  19. 0 104
      materialsLibrary/dist/dts/babylon.pbrMaterial.d.ts
  20. 0 48
      materialsLibrary/materials/pbr/babylon.sphericalharmonics.ts
  21. 0 43
      materialsLibrary/materials/pbr/babylon.sphericalpolynomial.ts
  22. 676 10
      materialsLibrary/test/refs/babylon.max.js
  23. 5 1
      src/Culling/babylon.boundingBox.js
  24. 1 1
      src/Culling/babylon.boundingBox.ts
  25. 118 0
      src/Materials/Textures/babylon.hdrCubeTexture.js
  26. 0 2
      materialsLibrary/materials/pbr/babylon.hdrcubetexture.ts
  27. 75 0
      src/Math/babylon.math.js
  28. 81 0
      src/Math/babylon.math.ts
  29. 69 8
      src/Particles/babylon.solidParticleSystem.js
  30. 1 1
      src/Particles/babylon.solidParticleSystem.ts
  31. 106 0
      src/Tools/HDR/babylon.tools.cubemapToSphericalPolynomial.js
  32. 0 2
      materialsLibrary/materials/pbr/babylon.tools.cubemaptosphericalpolynomial.ts
  33. 170 0
      src/Tools/HDR/babylon.tools.hdr.js
  34. 0 2
      materialsLibrary/materials/pbr/babylon.tools.hdr.ts
  35. 127 0
      src/Tools/HDR/babylon.tools.panoramaToCubemap.js
  36. 0 2
      materialsLibrary/materials/pbr/babylon.tools.panoramatocubemap.ts

+ 5 - 1
Tools/Gulp/config.json

@@ -172,7 +172,11 @@
       "../../src/PostProcess/babylon.tonemapPostProcess.js",
       "../../src/Probes/babylon.reflectionProbe.js",
       "../../src/Particles/babylon.solidParticle.js",
-      "../../src/Particles/babylon.solidParticleSystem.js"
+      "../../src/Particles/babylon.solidParticleSystem.js",
+      "../../src/tools/hdr/babylon.tools.cubemaptosphericalpolynomial.js",
+      "../../src/tools/hdr/babylon.tools.panoramatocubemap.js",
+      "../../src/tools/hdr/babylon.tools.hdr.js",
+      "../../src/materials/textures/babylon.hdrcubetexture.js"
     ]
   }
 }

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 19 - 19
dist/preview release/babylon.core.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 2386 - 2255
dist/preview release/babylon.d.ts


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 27 - 26
dist/preview release/babylon.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 676 - 10
dist/preview release/babylon.max.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 26 - 25
dist/preview release/babylon.noworker.js


+ 1 - 0
dist/preview release/what's new.md

@@ -1,6 +1,7 @@
 - 2.4.0:
   - **Major updates**
     - New refraction channel for Standard material (including fresnel support). Refraction texture can be provided by a reflection probe or a refraction texture. [See demo here](http://www.babylonjs.com/Demos/refraction/) ([deltakosh](https://github.com/deltakosh))
+    - Added support for HDR cubemaps ([sebavan](https://github.com/sebavan))
   - **Updates**
     - New OnPickTrigger support for spritesManager ([deltakosh](https://github.com/deltakosh))
     - New SPS method `digest()` ([jerome](https://github.com/jbousquie))    

+ 1 - 7
materialsLibrary/config.json

@@ -10,13 +10,7 @@
       "output": "babylon.gradientMaterial.js"
     },
     {
-      "file": ["materials/pbr/babylon.pbrMaterial.ts",
-        "materials/pbr/babylon.sphericalharmonics.ts",
-        "materials/pbr/babylon.sphericalpolynomial.ts", 
-        "materials/pbr/babylon.tools.panoramatocubemap.ts",
-        "materials/pbr/babylon.tools.cubemaptosphericalpolynomial.ts",
-        "materials/pbr/babylon.tools.hdr.ts",
-        "materials/pbr/babylon.hdrcubetexture.ts"],
+      "file": "materials/pbr/babylon.pbrMaterial.ts",
       "shaderFiles": [
         "materials/pbr/pbr.vertex.fx",
         "materials/pbr/pbr.fragment.fx",

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 2 - 2
materialsLibrary/dist/babylon.fireMaterial.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1 - 1
materialsLibrary/dist/babylon.fireMaterial.min.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1 - 1
materialsLibrary/dist/babylon.normalMaterial.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1 - 1
materialsLibrary/dist/babylon.normalMaterial.min.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 608
materialsLibrary/dist/babylon.pbrMaterial.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 2 - 2
materialsLibrary/dist/babylon.pbrMaterial.min.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1 - 1
materialsLibrary/dist/babylon.simpleMaterial.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1 - 1
materialsLibrary/dist/babylon.simpleMaterial.min.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1 - 1
materialsLibrary/dist/babylon.terrainMaterial.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1 - 1
materialsLibrary/dist/babylon.terrainMaterial.min.js


+ 0 - 104
materialsLibrary/dist/dts/babylon.pbrMaterial.d.ts

@@ -88,107 +88,3 @@ declare module BABYLON {
         static Parse(source: any, scene: Scene, rootUrl: string): PBRMaterial;
     }
 }
-
-/// <reference path="../../../dist/preview release/babylon.d.ts" />
-declare module BABYLON {
-    class SphericalHarmonics {
-        L00: Vector3;
-        L1_1: Vector3;
-        L10: Vector3;
-        L11: Vector3;
-        L2_2: Vector3;
-        L2_1: Vector3;
-        L20: Vector3;
-        L21: Vector3;
-        L22: Vector3;
-        addLight(direction: Vector3, color: Color3, deltaSolidAngle: number): void;
-        scale(scale: number): void;
-    }
-}
-
-/// <reference path="../../../dist/preview release/babylon.d.ts" />
-declare module BABYLON {
-    class SphericalPolynomial {
-        x: Vector3;
-        y: Vector3;
-        z: Vector3;
-        xx: Vector3;
-        yy: Vector3;
-        zz: Vector3;
-        xy: Vector3;
-        yz: Vector3;
-        zx: Vector3;
-        addAmbient(color: Color3): void;
-        static getSphericalPolynomialFromHarmonics(harmonics: SphericalHarmonics): SphericalPolynomial;
-    }
-}
-
-/// <reference path="../../../dist/preview release/babylon.d.ts" />
-declare module BABYLON.Internals {
-    interface CubeMapInfo {
-        front: Float32Array;
-        back: Float32Array;
-        left: Float32Array;
-        right: Float32Array;
-        up: Float32Array;
-        down: Float32Array;
-        size: number;
-    }
-    class PanoramaToCubeMapTools {
-        private static FACE_FRONT;
-        private static FACE_BACK;
-        private static FACE_LEFT;
-        private static FACE_RIGHT;
-        private static FACE_UP;
-        private static FACE_DOWN;
-        static ConvertPanoramaToCubemap(float32Array: Float32Array, inputWidth: number, inputHeight: number, size: number): CubeMapInfo;
-        private static CreateCubemapTexture(texSize, faceData, float32Array, inputWidth, inputHeight);
-        private static CalcProjectionSpherical(vDir, float32Array, inputWidth, inputHeight);
-    }
-}
-
-/// <reference path="../../../dist/preview release/babylon.d.ts" />
-declare module BABYLON.Internals {
-    class CubeMapToSphericalPolynomialTools {
-        private static FileFaces;
-        static ConvertCubeMapToSphericalPolynomial(cubeInfo: CubeMapInfo): SphericalPolynomial;
-    }
-}
-
-/// <reference path="../../../dist/preview release/babylon.d.ts" />
-declare module BABYLON.Internals {
-    interface HDRInfo {
-        height: number;
-        width: number;
-        dataPosition: number;
-    }
-    class HDRTools {
-        private static Ldexp(mantissa, exponent);
-        private static Rgbe2float(float32array, red, green, blue, exponent, index);
-        private static readStringLine(uint8array, startIndex);
-        static RGBE_ReadHeader(uint8array: Uint8Array): HDRInfo;
-        static GetCubeMapTextureData(buffer: ArrayBuffer, size: number): CubeMapInfo;
-        static RGBE_ReadPixels(uint8array: Uint8Array, hdrInfo: HDRInfo): Float32Array;
-        private static RGBE_ReadPixels_RLE(uint8array, hdrInfo);
-    }
-}
-
-/// <reference path="../../../dist/preview release/babylon.d.ts" />
-declare module BABYLON {
-    class HDRCubeTexture extends BaseTexture {
-        url: string;
-        coordinatesMode: number;
-        private _noMipmap;
-        private _extensions;
-        private _textureMatrix;
-        private _size;
-        sphericalPolynomial: SphericalPolynomial;
-        constructor(url: string, scene: Scene, size: number, noMipmap?: boolean);
-        private loadTexture();
-        clone(): HDRCubeTexture;
-        delayLoad(): void;
-        getReflectionTextureMatrix(): Matrix;
-        static Parse(parsedTexture: any, scene: Scene, rootUrl: string): HDRCubeTexture;
-        serialize(): any;
-    }
-}

+ 0 - 48
materialsLibrary/materials/pbr/babylon.sphericalharmonics.ts

@@ -1,48 +0,0 @@
-/// <reference path="../../../dist/preview release/babylon.d.ts"/>
-
-module BABYLON {
-
-    export class SphericalHarmonics {
-        public L00: Vector3 = Vector3.Zero();
-        public L1_1: Vector3 = Vector3.Zero();
-        public L10: Vector3 = Vector3.Zero();
-        public L11: Vector3 = Vector3.Zero();
-        public L2_2: Vector3 = Vector3.Zero();
-        public L2_1: Vector3 = Vector3.Zero();
-        public L20: Vector3 = Vector3.Zero();
-        public L21: Vector3 = Vector3.Zero();
-        public L22: Vector3 = Vector3.Zero();
-
-        public addLight(direction: Vector3, color: Color3, deltaSolidAngle: number) : void
-        {
-            var colorVector = new Vector3(color.r, color.g, color.b);
-            var c = colorVector.scale(deltaSolidAngle);
-
-            this.L00 = this.L00.add(c.scale(0.282095));
-
-            this.L1_1 = this.L1_1.add(c.scale(0.488603 * direction.y));
-            this.L10 = this.L10.add(c.scale(0.488603 * direction.z));
-            this.L11 = this.L11.add(c.scale(0.488603 * direction.x));
-
-            this.L2_2 = this.L2_2.add(c.scale(1.092548  * direction.x * direction.y));
-            this.L2_1 = this.L2_1.add(c.scale(1.092548 * direction.y * direction.z));
-            this.L21 = this.L21.add(c.scale(1.092548 * direction.x * direction.z));
-
-            this.L20 = this.L20.add(c.scale(0.315392 * (3.0 * direction.z * direction.z - 1.0)));
-            this.L22 = this.L22.add(c.scale(0.546274 * (direction.x * direction.x - direction.y * direction.y)));
-        }
-
-        public scale(scale: number): void
-        {
-            this.L00 = this.L00.scale(scale);
-            this.L1_1 = this.L1_1.scale(scale);
-            this.L10 = this.L10.scale(scale);
-            this.L11 = this.L11.scale(scale);
-            this.L2_2 = this.L2_2.scale(scale);
-            this.L2_1 = this.L2_1.scale(scale);
-            this.L20 = this.L20.scale(scale);
-            this.L21 = this.L21.scale(scale);
-            this.L22 = this.L22.scale(scale);
-        }
-    }
-}

+ 0 - 43
materialsLibrary/materials/pbr/babylon.sphericalpolynomial.ts

@@ -1,43 +0,0 @@
-/// <reference path="../../../dist/preview release/babylon.d.ts"/>
-
-module BABYLON {
-
-    export class SphericalPolynomial {
-        public x: Vector3 = Vector3.Zero();
-        public y: Vector3 = Vector3.Zero();
-        public z: Vector3 = Vector3.Zero();
-        public xx: Vector3 = Vector3.Zero();
-        public yy: Vector3 = Vector3.Zero();
-        public zz: Vector3 = Vector3.Zero();
-        public xy: Vector3 = Vector3.Zero();
-        public yz: Vector3 = Vector3.Zero();
-        public zx: Vector3 = Vector3.Zero();
-
-        public addAmbient(color: Color3): void
-        {
-            var colorVector = new Vector3(color.r, color.g, color.b);
-            this.xx = this.xx.add(colorVector);
-            this.yy = this.yy.add(colorVector);
-            this.zz = this.zz.add(colorVector);
-        }
-
-        public static getSphericalPolynomialFromHarmonics(harmonics: SphericalHarmonics): SphericalPolynomial 
-        {
-            var result = new SphericalPolynomial();
-
-            result.x = harmonics.L11.scale(1.02333);
-            result.y = harmonics.L1_1.scale(1.02333);
-            result.z = harmonics.L10.scale(1.02333);
-
-            result.xx = harmonics.L00.scale(0.886277).subtract(harmonics.L20.scale(0.247708)).add(harmonics.L22.scale(0.429043));
-            result.yy = harmonics.L00.scale(0.886277).subtract(harmonics.L20.scale(0.247708)).subtract(harmonics.L22.scale(0.429043));
-            result.zz = harmonics.L00.scale(0.886277).add(harmonics.L20.scale(0.495417));
-
-            result.yz = harmonics.L2_1.scale(0.858086);
-            result.zx = harmonics.L21.scale(0.858086);
-            result.xy = harmonics.L2_2.scale(0.858086);
-
-            return result;
-        }
-    }
-}

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 676 - 10
materialsLibrary/test/refs/babylon.max.js


+ 5 - 1
src/Culling/babylon.boundingBox.js

@@ -6,7 +6,7 @@ var BABYLON;
             this.maximum = maximum;
             this.vectors = new Array();
             this.vectorsWorld = new Array();
-            // Bounding vectors            
+            // Bounding vectors
             this.vectors.push(this.minimum.clone());
             this.vectors.push(this.maximum.clone());
             this.vectors.push(this.minimum.clone());
@@ -37,6 +37,10 @@ var BABYLON;
         BoundingBox.prototype.getWorldMatrix = function () {
             return this._worldMatrix;
         };
+        BoundingBox.prototype.setWorldMatrix = function (matrix) {
+            this._worldMatrix.copyFrom(matrix);
+            return this;
+        };
         BoundingBox.prototype._update = function (world) {
             BABYLON.Vector3.FromFloatsToRef(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE, this.minimumWorld);
             BABYLON.Vector3.FromFloatsToRef(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE, this.maximumWorld);

+ 1 - 1
src/Culling/babylon.boundingBox.ts

@@ -180,4 +180,4 @@
             return true;
         }
     }
-}
+}

+ 118 - 0
src/Materials/Textures/babylon.hdrCubeTexture.js

@@ -0,0 +1,118 @@
+var __extends = (this && this.__extends) || function (d, b) {
+    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
+    function __() { this.constructor = d; }
+    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+};
+var BABYLON;
+(function (BABYLON) {
+    var HDRCubeTexture = (function (_super) {
+        __extends(HDRCubeTexture, _super);
+        function HDRCubeTexture(url, scene, size, noMipmap) {
+            _super.call(this, scene);
+            this.coordinatesMode = BABYLON.Texture.CUBIC_MODE;
+            this.sphericalPolynomial = null;
+            this.name = url;
+            this.url = url;
+            this._noMipmap = noMipmap;
+            this.hasAlpha = false;
+            this._size = size;
+            if (!url) {
+                return;
+            }
+            this._texture = this._getFromCache(url, noMipmap);
+            if (!this._texture) {
+                if (!scene.useDelayedTextureLoading) {
+                    this.loadTexture();
+                }
+                else {
+                    this.delayLoadState = BABYLON.Engine.DELAYLOADSTATE_NOTLOADED;
+                }
+            }
+            this.isCube = true;
+            this._textureMatrix = BABYLON.Matrix.Identity();
+        }
+        HDRCubeTexture.prototype.loadTexture = function () {
+            var _this = this;
+            var callback = function (buffer) {
+                var data = BABYLON.Internals.HDRTools.GetCubeMapTextureData(buffer, _this._size);
+                _this.sphericalPolynomial = BABYLON.Internals.CubeMapToSphericalPolynomialTools.ConvertCubeMapToSphericalPolynomial(data);
+                var mapping = [
+                    "left",
+                    "down",
+                    "front",
+                    "right",
+                    "up",
+                    "back"
+                ];
+                var results = [];
+                for (var j = 0; j < 6; j++) {
+                    var dataFace = data[mapping[j]];
+                    // TODO. Support Int Textures...
+                    //                     // 3 channels of 1 bytes per pixel in bytes.
+                    //                     var byteBuffer = new ArrayBuffer(this._size * this._size * 3);
+                    //                     var byteArray = new Uint8Array(byteBuffer);
+                    // 
+                    //                     /* now convert data from buffer into bytes */
+                    //                     for(var i = 0; i < this._size * this._size; i++) {
+                    //                         byteArray[(i * 3) + 0] = dataFace[(i * 3) + 0] * 255;
+                    //                         byteArray[(i * 3) + 1] = dataFace[(i * 3) + 1] * 255;
+                    //                         byteArray[(i * 3) + 2] = dataFace[(i * 3) + 2] * 255;
+                    //                     }
+                    results.push(dataFace);
+                }
+                return results;
+            };
+            this._texture = this.getScene().getEngine().createRawCubeTexture(this.url, this.getScene(), this._size, BABYLON.Engine.TEXTUREFORMAT_RGB, BABYLON.Engine.TEXTURETYPE_FLOAT, this._noMipmap, callback);
+        };
+        HDRCubeTexture.prototype.clone = function () {
+            var newTexture = new HDRCubeTexture(this.url, this.getScene(), this._size, this._noMipmap);
+            // Base texture
+            newTexture.level = this.level;
+            newTexture.wrapU = this.wrapU;
+            newTexture.wrapV = this.wrapV;
+            newTexture.coordinatesIndex = this.coordinatesIndex;
+            newTexture.coordinatesMode = this.coordinatesMode;
+            return newTexture;
+        };
+        // Methods
+        HDRCubeTexture.prototype.delayLoad = function () {
+            if (this.delayLoadState !== BABYLON.Engine.DELAYLOADSTATE_NOTLOADED) {
+                return;
+            }
+            this.delayLoadState = BABYLON.Engine.DELAYLOADSTATE_LOADED;
+            this._texture = this._getFromCache(this.url, this._noMipmap);
+            if (!this._texture) {
+                this.loadTexture();
+            }
+        };
+        HDRCubeTexture.prototype.getReflectionTextureMatrix = function () {
+            return this._textureMatrix;
+        };
+        HDRCubeTexture.Parse = function (parsedTexture, scene, rootUrl) {
+            var texture = null;
+            if (parsedTexture.name && !parsedTexture.isRenderTarget) {
+                texture = new BABYLON.HDRCubeTexture(rootUrl + parsedTexture.name, scene, parsedTexture.size);
+                texture.name = parsedTexture.name;
+                texture.hasAlpha = parsedTexture.hasAlpha;
+                texture.level = parsedTexture.level;
+                texture.coordinatesMode = parsedTexture.coordinatesMode;
+            }
+            return texture;
+        };
+        HDRCubeTexture.prototype.serialize = function () {
+            if (!this.name) {
+                return null;
+            }
+            var serializationObject = {};
+            serializationObject.name = this.name;
+            serializationObject.hasAlpha = this.hasAlpha;
+            serializationObject.isCube = true;
+            serializationObject.level = this.level;
+            serializationObject.size = this._size;
+            serializationObject.coordinatesMode = this.coordinatesMode;
+            return serializationObject;
+        };
+        return HDRCubeTexture;
+    })(BABYLON.BaseTexture);
+    BABYLON.HDRCubeTexture = HDRCubeTexture;
+})(BABYLON || (BABYLON = {}));

+ 0 - 2
materialsLibrary/materials/pbr/babylon.hdrcubetexture.ts

@@ -1,5 +1,3 @@
-/// <reference path="../../../dist/preview release/babylon.d.ts"/>
-
 module BABYLON {
     export class HDRCubeTexture extends BaseTexture {
         public url: string;

+ 75 - 0
src/Math/babylon.math.js

@@ -2916,6 +2916,81 @@ var BABYLON;
         return Curve3;
     })();
     BABYLON.Curve3 = Curve3;
+    // SphericalHarmonics
+    var SphericalHarmonics = (function () {
+        function SphericalHarmonics() {
+            this.L00 = Vector3.Zero();
+            this.L1_1 = Vector3.Zero();
+            this.L10 = Vector3.Zero();
+            this.L11 = Vector3.Zero();
+            this.L2_2 = Vector3.Zero();
+            this.L2_1 = Vector3.Zero();
+            this.L20 = Vector3.Zero();
+            this.L21 = Vector3.Zero();
+            this.L22 = Vector3.Zero();
+        }
+        SphericalHarmonics.prototype.addLight = function (direction, color, deltaSolidAngle) {
+            var colorVector = new Vector3(color.r, color.g, color.b);
+            var c = colorVector.scale(deltaSolidAngle);
+            this.L00 = this.L00.add(c.scale(0.282095));
+            this.L1_1 = this.L1_1.add(c.scale(0.488603 * direction.y));
+            this.L10 = this.L10.add(c.scale(0.488603 * direction.z));
+            this.L11 = this.L11.add(c.scale(0.488603 * direction.x));
+            this.L2_2 = this.L2_2.add(c.scale(1.092548 * direction.x * direction.y));
+            this.L2_1 = this.L2_1.add(c.scale(1.092548 * direction.y * direction.z));
+            this.L21 = this.L21.add(c.scale(1.092548 * direction.x * direction.z));
+            this.L20 = this.L20.add(c.scale(0.315392 * (3.0 * direction.z * direction.z - 1.0)));
+            this.L22 = this.L22.add(c.scale(0.546274 * (direction.x * direction.x - direction.y * direction.y)));
+        };
+        SphericalHarmonics.prototype.scale = function (scale) {
+            this.L00 = this.L00.scale(scale);
+            this.L1_1 = this.L1_1.scale(scale);
+            this.L10 = this.L10.scale(scale);
+            this.L11 = this.L11.scale(scale);
+            this.L2_2 = this.L2_2.scale(scale);
+            this.L2_1 = this.L2_1.scale(scale);
+            this.L20 = this.L20.scale(scale);
+            this.L21 = this.L21.scale(scale);
+            this.L22 = this.L22.scale(scale);
+        };
+        return SphericalHarmonics;
+    })();
+    BABYLON.SphericalHarmonics = SphericalHarmonics;
+    // SphericalPolynomial
+    var SphericalPolynomial = (function () {
+        function SphericalPolynomial() {
+            this.x = Vector3.Zero();
+            this.y = Vector3.Zero();
+            this.z = Vector3.Zero();
+            this.xx = Vector3.Zero();
+            this.yy = Vector3.Zero();
+            this.zz = Vector3.Zero();
+            this.xy = Vector3.Zero();
+            this.yz = Vector3.Zero();
+            this.zx = Vector3.Zero();
+        }
+        SphericalPolynomial.prototype.addAmbient = function (color) {
+            var colorVector = new Vector3(color.r, color.g, color.b);
+            this.xx = this.xx.add(colorVector);
+            this.yy = this.yy.add(colorVector);
+            this.zz = this.zz.add(colorVector);
+        };
+        SphericalPolynomial.getSphericalPolynomialFromHarmonics = function (harmonics) {
+            var result = new SphericalPolynomial();
+            result.x = harmonics.L11.scale(1.02333);
+            result.y = harmonics.L1_1.scale(1.02333);
+            result.z = harmonics.L10.scale(1.02333);
+            result.xx = harmonics.L00.scale(0.886277).subtract(harmonics.L20.scale(0.247708)).add(harmonics.L22.scale(0.429043));
+            result.yy = harmonics.L00.scale(0.886277).subtract(harmonics.L20.scale(0.247708)).subtract(harmonics.L22.scale(0.429043));
+            result.zz = harmonics.L00.scale(0.886277).add(harmonics.L20.scale(0.495417));
+            result.yz = harmonics.L2_1.scale(0.858086);
+            result.zx = harmonics.L21.scale(0.858086);
+            result.xy = harmonics.L2_2.scale(0.858086);
+            return result;
+        };
+        return SphericalPolynomial;
+    })();
+    BABYLON.SphericalPolynomial = SphericalPolynomial;
     // Vertex formats
     var PositionNormalVertex = (function () {
         function PositionNormalVertex(position, normal) {

+ 81 - 0
src/Math/babylon.math.ts

@@ -3596,6 +3596,87 @@
         }
     }
 
+    // SphericalHarmonics
+    export class SphericalHarmonics {
+        public L00: Vector3 = Vector3.Zero();
+        public L1_1: Vector3 = Vector3.Zero();
+        public L10: Vector3 = Vector3.Zero();
+        public L11: Vector3 = Vector3.Zero();
+        public L2_2: Vector3 = Vector3.Zero();
+        public L2_1: Vector3 = Vector3.Zero();
+        public L20: Vector3 = Vector3.Zero();
+        public L21: Vector3 = Vector3.Zero();
+        public L22: Vector3 = Vector3.Zero();
+
+        public addLight(direction: Vector3, color: Color3, deltaSolidAngle: number): void {
+            var colorVector = new Vector3(color.r, color.g, color.b);
+            var c = colorVector.scale(deltaSolidAngle);
+
+            this.L00 = this.L00.add(c.scale(0.282095));
+
+            this.L1_1 = this.L1_1.add(c.scale(0.488603 * direction.y));
+            this.L10 = this.L10.add(c.scale(0.488603 * direction.z));
+            this.L11 = this.L11.add(c.scale(0.488603 * direction.x));
+
+            this.L2_2 = this.L2_2.add(c.scale(1.092548 * direction.x * direction.y));
+            this.L2_1 = this.L2_1.add(c.scale(1.092548 * direction.y * direction.z));
+            this.L21 = this.L21.add(c.scale(1.092548 * direction.x * direction.z));
+
+            this.L20 = this.L20.add(c.scale(0.315392 * (3.0 * direction.z * direction.z - 1.0)));
+            this.L22 = this.L22.add(c.scale(0.546274 * (direction.x * direction.x - direction.y * direction.y)));
+        }
+
+        public scale(scale: number): void {
+            this.L00 = this.L00.scale(scale);
+            this.L1_1 = this.L1_1.scale(scale);
+            this.L10 = this.L10.scale(scale);
+            this.L11 = this.L11.scale(scale);
+            this.L2_2 = this.L2_2.scale(scale);
+            this.L2_1 = this.L2_1.scale(scale);
+            this.L20 = this.L20.scale(scale);
+            this.L21 = this.L21.scale(scale);
+            this.L22 = this.L22.scale(scale);
+        }
+    }
+
+    // SphericalPolynomial
+    export class SphericalPolynomial {
+        public x: Vector3 = Vector3.Zero();
+        public y: Vector3 = Vector3.Zero();
+        public z: Vector3 = Vector3.Zero();
+        public xx: Vector3 = Vector3.Zero();
+        public yy: Vector3 = Vector3.Zero();
+        public zz: Vector3 = Vector3.Zero();
+        public xy: Vector3 = Vector3.Zero();
+        public yz: Vector3 = Vector3.Zero();
+        public zx: Vector3 = Vector3.Zero();
+
+        public addAmbient(color: Color3): void {
+            var colorVector = new Vector3(color.r, color.g, color.b);
+            this.xx = this.xx.add(colorVector);
+            this.yy = this.yy.add(colorVector);
+            this.zz = this.zz.add(colorVector);
+        }
+
+        public static getSphericalPolynomialFromHarmonics(harmonics: SphericalHarmonics): SphericalPolynomial {
+            var result = new SphericalPolynomial();
+
+            result.x = harmonics.L11.scale(1.02333);
+            result.y = harmonics.L1_1.scale(1.02333);
+            result.z = harmonics.L10.scale(1.02333);
+
+            result.xx = harmonics.L00.scale(0.886277).subtract(harmonics.L20.scale(0.247708)).add(harmonics.L22.scale(0.429043));
+            result.yy = harmonics.L00.scale(0.886277).subtract(harmonics.L20.scale(0.247708)).subtract(harmonics.L22.scale(0.429043));
+            result.zz = harmonics.L00.scale(0.886277).add(harmonics.L20.scale(0.495417));
+
+            result.yz = harmonics.L2_1.scale(0.858086);
+            result.zx = harmonics.L21.scale(0.858086);
+            result.xy = harmonics.L2_2.scale(0.858086);
+
+            return result;
+        }
+    }
+
     // Vertex formats
     export class PositionNormalVertex {
         constructor(public position: Vector3 = Vector3.Zero(), public normal: Vector3 = Vector3.Up()) {

+ 69 - 8
src/Particles/babylon.solidParticleSystem.js

@@ -7,15 +7,32 @@ var BABYLON;
         /**
         * Creates a SPS (Solid Particle System) object.
         * @param name the SPS name, this will be the underlying mesh name
-        * @param updatable (default true) if the SPS must be updatable or immutable
-        * @param isPickable (default false) if the solid particles must be pickable
+        * @param scene the scene in which the SPS is added
+        * @param options "updatable" (default true) : if the SPS must be updatable or immutable, "isPickable" (default false) : if the solid particles must be pickable
         */
         function SolidParticleSystem(name, scene, options) {
             // public members
+            /**
+            *  The SPS array of Solid Particle objects. Just access each particle as with any classic array.
+            *  Example : var p = SPS.particles[i];
+            */
             this.particles = new Array();
+            /**
+            * The SPS total number of particles. Read only. Use SPS.counter instead if you need to set your own value.
+            */
             this.nbParticles = 0;
+            /**
+            * If the particles must ever face the camera (default false). Useful for planar particles.
+            */
             this.billboard = false;
+            /**
+            * This a counter ofr your own usage. It's not set by any SPS functions.
+            */
             this.counter = 0;
+            /**
+            * This empty object is intended to store some SPS specific or temporary values in order to lower the Garbage Collector activity.
+            * Please read : http://doc.babylonjs.com/tutorials/Solid_Particle_System#garbage-collector-concerns
+            */
             this.vars = {};
             this._positions = new Array();
             this._indices = new Array();
@@ -34,6 +51,7 @@ var BABYLON;
             this._computeParticleTexture = true;
             this._computeParticleRotation = true;
             this._computeParticleVertex = false;
+            this._computeBoundingBox = false;
             this._cam_axisZ = BABYLON.Vector3.Zero();
             this._cam_axisY = BABYLON.Vector3.Zero();
             this._cam_axisX = BABYLON.Vector3.Zero();
@@ -60,6 +78,9 @@ var BABYLON;
             this._sinYaw = 0.0;
             this._cosYaw = 0.0;
             this._w = 0.0;
+            this._minimum = BABYLON.Tmp.Vector3[0];
+            this._maximum = BABYLON.Tmp.Vector3[1];
+            this._vertexWorld = BABYLON.Tmp.Vector3[2];
             this.name = name;
             this._scene = scene;
             this._camera = scene.activeCamera;
@@ -305,8 +326,7 @@ var BABYLON;
         * Please read the doc : http://doc.babylonjs.com/tutorials/Solid_Particle_System#create-an-immutable-sps
         * @param mesh any Mesh object that will be used as a model for the solid particles.
         * @param nb the number of particles to be created from this model
-        * @param positionFunction an optional javascript function to called for each particle on SPS creation
-        * @param vertexFunction an optional javascript function to called for each vertex of each particle on SPS creation
+        * @param options positionFunction is an optional javascript function to called for each particle on SPS creation. vertexFunction an optional javascript function to called for each vertex of each particle on SPS creation
         */
         SolidParticleSystem.prototype.addShape = function (mesh, nb, options) {
             var meshPos = mesh.getVerticesData(BABYLON.VertexBuffer.PositionKind);
@@ -438,6 +458,10 @@ var BABYLON;
             var colorIndex = 0;
             var uvidx = 0;
             var uvIndex = 0;
+            if (this._computeBoundingBox) {
+                BABYLON.Vector3.FromFloatsToRef(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE, this._minimum);
+                BABYLON.Vector3.FromFloatsToRef(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE, this._maximum);
+            }
             // particle loop
             end = (end > this.nbParticles - 1) ? this.nbParticles - 1 : end;
             for (var p = start; p <= end; p++) {
@@ -487,6 +511,26 @@ var BABYLON;
                     this._positions32[idx] = this._particle.position.x + this._cam_axisX.x * this._rotated.x + this._cam_axisY.x * this._rotated.y + this._cam_axisZ.x * this._rotated.z;
                     this._positions32[idx + 1] = this._particle.position.y + this._cam_axisX.y * this._rotated.x + this._cam_axisY.y * this._rotated.y + this._cam_axisZ.y * this._rotated.z;
                     this._positions32[idx + 2] = this._particle.position.z + this._cam_axisX.z * this._rotated.x + this._cam_axisY.z * this._rotated.y + this._cam_axisZ.z * this._rotated.z;
+                    if (this._computeBoundingBox) {
+                        if (this._positions32[idx] < this._minimum.x) {
+                            this._minimum.x = this._positions32[idx];
+                        }
+                        if (this._positions32[idx] > this._maximum.x) {
+                            this._maximum.x = this._positions32[idx];
+                        }
+                        if (this._positions32[idx + 1] < this._minimum.y) {
+                            this._minimum.y = this._positions32[idx + 1];
+                        }
+                        if (this._positions32[idx + 1] > this._maximum.y) {
+                            this._maximum.y = this._positions32[idx + 1];
+                        }
+                        if (this._positions32[idx + 2] < this._minimum.z) {
+                            this._minimum.z = this._positions32[idx + 2];
+                        }
+                        if (this._positions32[idx + 2] > this._maximum.z) {
+                            this._maximum.z = this._positions32[idx + 2];
+                        }
+                    }
                     // normals : if the particles can't be morphed then just rotate the normals
                     if (!this._computeParticleVertex && !this.billboard) {
                         this._normal.x = this._fixedNormal32[idx];
@@ -534,6 +578,10 @@ var BABYLON;
                     this.mesh.updateVerticesData(BABYLON.VertexBuffer.NormalKind, this._normals32, false, false);
                 }
             }
+            if (this._computeBoundingBox) {
+                this.mesh._boundingInfo = new BABYLON.BoundingInfo(this._minimum, this._maximum);
+                this.mesh._boundingInfo.boundingBox.setWorldMatrix(this.mesh._worldMatrix);
+            }
             this.afterUpdateParticles(start, end, update);
         };
         SolidParticleSystem.prototype._quaternionRotationYPR = function () {
@@ -650,7 +698,7 @@ var BABYLON;
             },
             // Optimizer setters
             /**
-            * Tells to setParticle() to compute the particle rotations or not.
+            * Tells to setParticles() to compute the particle rotations or not.
             * Default value : true. The SPS is faster when it's set to false.
             * Note : the particle rotations aren't stored values, so setting computeParticleRotation to false will prevents the particle to rotate.
             */
@@ -665,7 +713,7 @@ var BABYLON;
                 return this._computeParticleColor;
             },
             /**
-            * Tells to setParticle() to compute the particle colors or not.
+            * Tells to setParticles() to compute the particle colors or not.
             * Default value : true. The SPS is faster when it's set to false.
             * Note : the particle colors are stored values, so setting computeParticleColor to false will keep yet the last colors set.
             */
@@ -680,7 +728,7 @@ var BABYLON;
                 return this._computeParticleTexture;
             },
             /**
-            * Tells to setParticle() to compute the particle textures or not.
+            * Tells to setParticles() to compute the particle textures or not.
             * Default value : true. The SPS is faster when it's set to false.
             * Note : the particle textures are stored values, so setting computeParticleTexture to false will keep yet the last colors set.
             */
@@ -695,7 +743,7 @@ var BABYLON;
                 return this._computeParticleVertex;
             },
             /**
-            * Tells to setParticle() to call the vertex function for each vertex of each particle, or not.
+            * Tells to setParticles() to call the vertex function for each vertex of each particle, or not.
             * Default value : false. The SPS is faster when it's set to false.
             * Note : the particle custom vertex positions aren't stored values.
             */
@@ -705,6 +753,19 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        Object.defineProperty(SolidParticleSystem.prototype, "computeBoundingBox", {
+            get: function () {
+                return this._computeBoundingBox;
+            },
+            /**
+            * Tells to setParticles() to compute or not the mesh bounding box when computing the particle positions.
+            */
+            set: function (val) {
+                this._computeBoundingBox = val;
+            },
+            enumerable: true,
+            configurable: true
+        });
         // =======================================================================
         // Particle behavior logic
         // these following methods may be overwritten by the user to fit his needs

+ 1 - 1
src/Particles/babylon.solidParticleSystem.ts

@@ -909,4 +909,4 @@ module BABYLON {
         public afterUpdateParticles(start?: number, stop?: number, update?: boolean): void {
         }
     }
-}
+}

+ 106 - 0
src/Tools/HDR/babylon.tools.cubemapToSphericalPolynomial.js

@@ -0,0 +1,106 @@
+var BABYLON;
+(function (BABYLON) {
+    var Internals;
+    (function (Internals) {
+        var FileFaceOrientation = (function () {
+            function FileFaceOrientation(name, worldAxisForNormal, worldAxisForFileX, worldAxisForFileY) {
+                this.name = name;
+                this.worldAxisForNormal = worldAxisForNormal;
+                this.worldAxisForFileX = worldAxisForFileX;
+                this.worldAxisForFileY = worldAxisForFileY;
+            }
+            return FileFaceOrientation;
+        })();
+        ;
+        var CubeMapToSphericalPolynomialTools = (function () {
+            function CubeMapToSphericalPolynomialTools() {
+            }
+            CubeMapToSphericalPolynomialTools.ConvertCubeMapToSphericalPolynomial = function (cubeInfo) {
+                var sphericalHarmonics = new BABYLON.SphericalHarmonics();
+                var totalSolidAngle = 0.0;
+                // The (u,v) range is [-1,+1], so the distance between each texel is 2/Size.
+                var du = 2.0 / cubeInfo.size;
+                var dv = du;
+                // The (u,v) of the first texel is half a texel from the corner (-1,-1).
+                var minUV = du * 0.5 - 1.0;
+                for (var faceIndex = 0; faceIndex < 6; faceIndex++) {
+                    var fileFace = this.FileFaces[faceIndex];
+                    var dataArray = cubeInfo[fileFace.name];
+                    var v = minUV;
+                    // TODO: we could perform the summation directly into a SphericalPolynomial (SP), which is more efficient than SphericalHarmonic (SH).
+                    // This is possible because during the summation we do not need the SH-specific properties, e.g. orthogonality.
+                    // Because SP is still linear, so summation is fine in that basis.
+                    for (var y = 0; y < cubeInfo.size; y++) {
+                        var u = minUV;
+                        for (var x = 0; x < cubeInfo.size; x++) {
+                            // World direction (not normalised)
+                            var worldDirection = fileFace.worldAxisForFileX.scale(u).add(fileFace.worldAxisForFileY.scale(v)).add(fileFace.worldAxisForNormal);
+                            worldDirection.normalize();
+                            var deltaSolidAngle = Math.pow(1.0 + u * u + v * v, -3.0 / 2.0);
+                            if (1) {
+                                var r = dataArray[(y * cubeInfo.size * 3) + (x * 3) + 0];
+                                var g = dataArray[(y * cubeInfo.size * 3) + (x * 3) + 1];
+                                var b = dataArray[(y * cubeInfo.size * 3) + (x * 3) + 2];
+                                var color = new BABYLON.Color3(r, g, b);
+                                sphericalHarmonics.addLight(worldDirection, color, deltaSolidAngle);
+                            }
+                            else {
+                                if (faceIndex == 0) {
+                                    dataArray[(y * cubeInfo.size * 3) + (x * 3) + 0] = 1;
+                                    dataArray[(y * cubeInfo.size * 3) + (x * 3) + 1] = 0;
+                                    dataArray[(y * cubeInfo.size * 3) + (x * 3) + 2] = 0;
+                                }
+                                else if (faceIndex == 1) {
+                                    dataArray[(y * cubeInfo.size * 3) + (x * 3) + 0] = 0;
+                                    dataArray[(y * cubeInfo.size * 3) + (x * 3) + 1] = 1;
+                                    dataArray[(y * cubeInfo.size * 3) + (x * 3) + 2] = 0;
+                                }
+                                else if (faceIndex == 2) {
+                                    dataArray[(y * cubeInfo.size * 3) + (x * 3) + 0] = 0;
+                                    dataArray[(y * cubeInfo.size * 3) + (x * 3) + 1] = 0;
+                                    dataArray[(y * cubeInfo.size * 3) + (x * 3) + 2] = 1;
+                                }
+                                else if (faceIndex == 3) {
+                                    dataArray[(y * cubeInfo.size * 3) + (x * 3) + 0] = 1;
+                                    dataArray[(y * cubeInfo.size * 3) + (x * 3) + 1] = 1;
+                                    dataArray[(y * cubeInfo.size * 3) + (x * 3) + 2] = 0;
+                                }
+                                else if (faceIndex == 4) {
+                                    dataArray[(y * cubeInfo.size * 3) + (x * 3) + 0] = 1;
+                                    dataArray[(y * cubeInfo.size * 3) + (x * 3) + 1] = 0;
+                                    dataArray[(y * cubeInfo.size * 3) + (x * 3) + 2] = 1;
+                                }
+                                else if (faceIndex == 5) {
+                                    dataArray[(y * cubeInfo.size * 3) + (x * 3) + 0] = 0;
+                                    dataArray[(y * cubeInfo.size * 3) + (x * 3) + 1] = 1;
+                                    dataArray[(y * cubeInfo.size * 3) + (x * 3) + 2] = 1;
+                                }
+                                var color = new BABYLON.Color3(dataArray[(y * cubeInfo.size * 3) + (x * 3) + 0], dataArray[(y * cubeInfo.size * 3) + (x * 3) + 1], dataArray[(y * cubeInfo.size * 3) + (x * 3) + 2]);
+                                sphericalHarmonics.addLight(worldDirection, color, deltaSolidAngle);
+                            }
+                            totalSolidAngle += deltaSolidAngle;
+                            u += du;
+                        }
+                        v += dv;
+                    }
+                }
+                var correctSolidAngle = 4.0 * Math.PI; // Solid angle for entire sphere is 4*pi
+                var correction = correctSolidAngle / totalSolidAngle;
+                sphericalHarmonics.scale(correction);
+                // Additionally scale by pi -- audit needed
+                sphericalHarmonics.scale(1.0 / Math.PI);
+                return BABYLON.SphericalPolynomial.getSphericalPolynomialFromHarmonics(sphericalHarmonics);
+            };
+            CubeMapToSphericalPolynomialTools.FileFaces = [
+                new FileFaceOrientation("left", new BABYLON.Vector3(1, 0, 0), new BABYLON.Vector3(0, 0, -1), new BABYLON.Vector3(0, -1, 0)),
+                new FileFaceOrientation("right", new BABYLON.Vector3(-1, 0, 0), new BABYLON.Vector3(0, 0, 1), new BABYLON.Vector3(0, -1, 0)),
+                new FileFaceOrientation("down", new BABYLON.Vector3(0, 1, 0), new BABYLON.Vector3(1, 0, 0), new BABYLON.Vector3(0, 0, 1)),
+                new FileFaceOrientation("up", new BABYLON.Vector3(0, -1, 0), new BABYLON.Vector3(1, 0, 0), new BABYLON.Vector3(0, 0, -1)),
+                new FileFaceOrientation("front", new BABYLON.Vector3(0, 0, 1), new BABYLON.Vector3(1, 0, 0), new BABYLON.Vector3(0, -1, 0)),
+                new FileFaceOrientation("back", new BABYLON.Vector3(0, 0, -1), new BABYLON.Vector3(-1, 0, 0), new BABYLON.Vector3(0, -1, 0)) // -Z bottom
+            ];
+            return CubeMapToSphericalPolynomialTools;
+        })();
+        Internals.CubeMapToSphericalPolynomialTools = CubeMapToSphericalPolynomialTools;
+    })(Internals = BABYLON.Internals || (BABYLON.Internals = {}));
+})(BABYLON || (BABYLON = {}));

+ 0 - 2
materialsLibrary/materials/pbr/babylon.tools.cubemaptosphericalpolynomial.ts

@@ -1,5 +1,3 @@
-/// <reference path="../../../dist/preview release/babylon.d.ts"/>
-
 module BABYLON.Internals {
 
     class FileFaceOrientation

+ 170 - 0
src/Tools/HDR/babylon.tools.hdr.js

@@ -0,0 +1,170 @@
+var BABYLON;
+(function (BABYLON) {
+    var Internals;
+    (function (Internals) {
+        ;
+        var HDRTools = (function () {
+            function HDRTools() {
+            }
+            HDRTools.Ldexp = function (mantissa, exponent) {
+                if (exponent > 1023) {
+                    return mantissa * Math.pow(2, 1023) * Math.pow(2, exponent - 1023);
+                }
+                if (exponent < -1074) {
+                    return mantissa * Math.pow(2, -1074) * Math.pow(2, exponent + 1074);
+                }
+                return mantissa * Math.pow(2, exponent);
+            };
+            HDRTools.Rgbe2float = function (float32array, red, green, blue, exponent, index) {
+                if (exponent > 0) {
+                    exponent = this.Ldexp(1.0, exponent - (128 + 8));
+                    float32array[index + 0] = red * exponent;
+                    float32array[index + 1] = green * exponent;
+                    float32array[index + 2] = blue * exponent;
+                }
+                else {
+                    float32array[index + 0] = 0;
+                    float32array[index + 1] = 0;
+                    float32array[index + 2] = 0;
+                }
+            };
+            HDRTools.readStringLine = function (uint8array, startIndex) {
+                var line = "";
+                var character = "";
+                for (var i = startIndex; i < uint8array.length - startIndex; i++) {
+                    character = String.fromCharCode(uint8array[i]);
+                    if (character == "\n") {
+                        break;
+                    }
+                    line += character;
+                }
+                return line;
+            };
+            /* minimal header reading.  modify if you want to parse more information */
+            HDRTools.RGBE_ReadHeader = function (uint8array) {
+                var height = 0;
+                var width = 0;
+                var line = this.readStringLine(uint8array, 0);
+                if (line[0] != '#' || line[1] != '?') {
+                    throw "Bad HDR Format.";
+                }
+                var endOfHeader = false;
+                var findFormat = false;
+                var lineIndex = 0;
+                do {
+                    lineIndex += (line.length + 1);
+                    line = this.readStringLine(uint8array, lineIndex);
+                    if (line == "FORMAT=32-bit_rle_rgbe") {
+                        findFormat = true;
+                    }
+                    else if (line.length == 0) {
+                        endOfHeader = true;
+                    }
+                } while (!endOfHeader);
+                if (!findFormat) {
+                    throw "HDR Bad header format, unsupported FORMAT";
+                }
+                lineIndex += (line.length + 1);
+                line = this.readStringLine(uint8array, lineIndex);
+                var sizeRegexp = /^\-Y (.*) \+X (.*)$/g;
+                var match = sizeRegexp.exec(line);
+                // TODO. Support +Y and -X if needed.
+                if (match.length < 3) {
+                    throw "HDR Bad header format, no size";
+                }
+                width = parseInt(match[2]);
+                height = parseInt(match[1]);
+                if (width < 8 || width > 0x7fff) {
+                    throw "HDR Bad header format, unsupported size";
+                }
+                lineIndex += (line.length + 1);
+                return {
+                    height: height,
+                    width: width,
+                    dataPosition: lineIndex
+                };
+            };
+            HDRTools.GetCubeMapTextureData = function (buffer, size) {
+                var uint8array = new Uint8Array(buffer);
+                var hdrInfo = this.RGBE_ReadHeader(uint8array);
+                var data = this.RGBE_ReadPixels_RLE(uint8array, hdrInfo);
+                var cubeMapData = Internals.PanoramaToCubeMapTools.ConvertPanoramaToCubemap(data, hdrInfo.width, hdrInfo.height, size);
+                return cubeMapData;
+            };
+            HDRTools.RGBE_ReadPixels = function (uint8array, hdrInfo) {
+                // Keep for multi format supports.
+                return this.RGBE_ReadPixels_RLE(uint8array, hdrInfo);
+            };
+            HDRTools.RGBE_ReadPixels_RLE = function (uint8array, hdrInfo) {
+                var num_scanlines = hdrInfo.height;
+                var scanline_width = hdrInfo.width;
+                var a, b, c, d, count;
+                var dataIndex = hdrInfo.dataPosition;
+                var index = 0, endIndex = 0, i = 0;
+                var scanLineArrayBuffer = new ArrayBuffer(scanline_width * 4); // four channel R G B E
+                var scanLineArray = new Uint8Array(scanLineArrayBuffer);
+                // 3 channels of 4 bytes per pixel in float.
+                var resultBuffer = new ArrayBuffer(hdrInfo.width * hdrInfo.height * 4 * 3);
+                var resultArray = new Float32Array(resultBuffer);
+                // read in each successive scanline
+                while (num_scanlines > 0) {
+                    a = uint8array[dataIndex++];
+                    b = uint8array[dataIndex++];
+                    c = uint8array[dataIndex++];
+                    d = uint8array[dataIndex++];
+                    if (a != 2 || b != 2 || (c & 0x80)) {
+                        // this file is not run length encoded
+                        throw "HDR Bad header format, not RLE";
+                    }
+                    if (((c << 8) | d) != scanline_width) {
+                        throw "HDR Bad header format, wrong scan line width";
+                    }
+                    index = 0;
+                    // read each of the four channels for the scanline into the buffer
+                    for (i = 0; i < 4; i++) {
+                        endIndex = (i + 1) * scanline_width;
+                        while (index < endIndex) {
+                            a = uint8array[dataIndex++];
+                            b = uint8array[dataIndex++];
+                            if (a > 128) {
+                                // a run of the same value
+                                count = a - 128;
+                                if ((count == 0) || (count > endIndex - index)) {
+                                    throw "HDR Bad Format, bad scanline data (run)";
+                                }
+                                while (count-- > 0) {
+                                    scanLineArray[index++] = b;
+                                }
+                            }
+                            else {
+                                // a non-run
+                                count = a;
+                                if ((count == 0) || (count > endIndex - index)) {
+                                    throw "HDR Bad Format, bad scanline data (non-run)";
+                                }
+                                scanLineArray[index++] = b;
+                                if (--count > 0) {
+                                    for (var j = 0; j < count; j++) {
+                                        scanLineArray[index++] = uint8array[dataIndex++];
+                                    }
+                                }
+                            }
+                        }
+                    }
+                    // now convert data from buffer into floats
+                    for (i = 0; i < scanline_width; i++) {
+                        a = scanLineArray[i];
+                        b = scanLineArray[i + scanline_width];
+                        c = scanLineArray[i + 2 * scanline_width];
+                        d = scanLineArray[i + 3 * scanline_width];
+                        this.Rgbe2float(resultArray, a, b, c, d, (hdrInfo.height - num_scanlines) * scanline_width * 3 + i * 3);
+                    }
+                    num_scanlines--;
+                }
+                return resultArray;
+            };
+            return HDRTools;
+        })();
+        Internals.HDRTools = HDRTools;
+    })(Internals = BABYLON.Internals || (BABYLON.Internals = {}));
+})(BABYLON || (BABYLON = {}));

+ 0 - 2
materialsLibrary/materials/pbr/babylon.tools.hdr.ts

@@ -1,5 +1,3 @@
-/// <reference path="../../../dist/preview release/babylon.d.ts"/>
-
 module BABYLON.Internals {
     export interface HDRInfo {
         height: number;

+ 127 - 0
src/Tools/HDR/babylon.tools.panoramaToCubemap.js

@@ -0,0 +1,127 @@
+var BABYLON;
+(function (BABYLON) {
+    var Internals;
+    (function (Internals) {
+        var PanoramaToCubeMapTools = (function () {
+            function PanoramaToCubeMapTools() {
+            }
+            PanoramaToCubeMapTools.ConvertPanoramaToCubemap = function (float32Array, inputWidth, inputHeight, size) {
+                if (!float32Array) {
+                    throw "ConvertPanoramaToCubemap: input cannot be null";
+                }
+                if (float32Array.length != inputWidth * inputHeight * 3) {
+                    throw "ConvertPanoramaToCubemap: input size is wrong";
+                }
+                var textureFront = this.CreateCubemapTexture(size, this.FACE_FRONT, float32Array, inputWidth, inputHeight);
+                var textureBack = this.CreateCubemapTexture(size, this.FACE_BACK, float32Array, inputWidth, inputHeight);
+                var textureLeft = this.CreateCubemapTexture(size, this.FACE_LEFT, float32Array, inputWidth, inputHeight);
+                var textureRight = this.CreateCubemapTexture(size, this.FACE_RIGHT, float32Array, inputWidth, inputHeight);
+                var textureUp = this.CreateCubemapTexture(size, this.FACE_UP, float32Array, inputWidth, inputHeight);
+                var textureDown = this.CreateCubemapTexture(size, this.FACE_DOWN, float32Array, inputWidth, inputHeight);
+                return {
+                    front: textureFront,
+                    back: textureBack,
+                    left: textureLeft,
+                    right: textureRight,
+                    up: textureUp,
+                    down: textureDown,
+                    size: size
+                };
+            };
+            PanoramaToCubeMapTools.CreateCubemapTexture = function (texSize, faceData, float32Array, inputWidth, inputHeight) {
+                var buffer = new ArrayBuffer(texSize * texSize * 4 * 3);
+                var textureArray = new Float32Array(buffer);
+                var rotDX1 = faceData[1].subtract(faceData[0]).scale(1 / texSize);
+                var rotDX2 = faceData[3].subtract(faceData[2]).scale(1 / texSize);
+                var dy = 1 / texSize;
+                var fy = 0;
+                for (var y = 0; y < texSize; y++) {
+                    var xv1 = faceData[0];
+                    var xv2 = faceData[2];
+                    for (var x = 0; x < texSize; x++) {
+                        var v = xv2.subtract(xv1).scale(fy).add(xv1);
+                        v.normalize();
+                        var color = this.CalcProjectionSpherical(v, float32Array, inputWidth, inputHeight);
+                        // 3 channels per pixels
+                        textureArray[y * texSize * 3 + (x * 3) + 0] = color.r;
+                        textureArray[y * texSize * 3 + (x * 3) + 1] = color.g;
+                        textureArray[y * texSize * 3 + (x * 3) + 2] = color.b;
+                        xv1 = xv1.add(rotDX1);
+                        xv2 = xv2.add(rotDX2);
+                    }
+                    fy += dy;
+                }
+                return textureArray;
+            };
+            PanoramaToCubeMapTools.CalcProjectionSpherical = function (vDir, float32Array, inputWidth, inputHeight) {
+                var theta = Math.atan2(vDir.z, vDir.x);
+                var phi = Math.acos(vDir.y);
+                while (theta < -Math.PI)
+                    theta += 2 * Math.PI;
+                while (theta > Math.PI)
+                    theta -= 2 * Math.PI;
+                var dx = theta / Math.PI;
+                var dy = phi / Math.PI;
+                // recenter.
+                dx = dx * 0.5 + 0.5;
+                var px = Math.round(dx * inputWidth);
+                if (px < 0)
+                    px = 0;
+                else if (px >= inputWidth)
+                    px = inputWidth - 1;
+                var py = Math.round(dy * inputHeight);
+                if (py < 0)
+                    py = 0;
+                else if (py >= inputHeight)
+                    py = inputHeight - 1;
+                var inputY = (inputHeight - py - 1);
+                var r = float32Array[inputY * inputWidth * 3 + (px * 3) + 0];
+                var g = float32Array[inputY * inputWidth * 3 + (px * 3) + 1];
+                var b = float32Array[inputY * inputWidth * 3 + (px * 3) + 2];
+                return {
+                    r: r,
+                    g: g,
+                    b: b
+                };
+            };
+            PanoramaToCubeMapTools.FACE_FRONT = [
+                new BABYLON.Vector3(-1.0, -1.0, -1.0),
+                new BABYLON.Vector3(1.0, -1.0, -1.0),
+                new BABYLON.Vector3(-1.0, 1.0, -1.0),
+                new BABYLON.Vector3(1.0, 1.0, -1.0)
+            ];
+            PanoramaToCubeMapTools.FACE_BACK = [
+                new BABYLON.Vector3(1.0, -1.0, 1.0),
+                new BABYLON.Vector3(-1.0, -1.0, 1.0),
+                new BABYLON.Vector3(1.0, 1.0, 1.0),
+                new BABYLON.Vector3(-1.0, 1.0, 1.0)
+            ];
+            PanoramaToCubeMapTools.FACE_LEFT = [
+                new BABYLON.Vector3(1.0, -1.0, -1.0),
+                new BABYLON.Vector3(1.0, -1.0, 1.0),
+                new BABYLON.Vector3(1.0, 1.0, -1.0),
+                new BABYLON.Vector3(1.0, 1.0, 1.0)
+            ];
+            PanoramaToCubeMapTools.FACE_RIGHT = [
+                new BABYLON.Vector3(-1.0, -1.0, 1.0),
+                new BABYLON.Vector3(-1.0, -1.0, -1.0),
+                new BABYLON.Vector3(-1.0, 1.0, 1.0),
+                new BABYLON.Vector3(-1.0, 1.0, -1.0)
+            ];
+            PanoramaToCubeMapTools.FACE_UP = [
+                new BABYLON.Vector3(-1.0, 1.0, -1.0),
+                new BABYLON.Vector3(1.0, 1.0, -1.0),
+                new BABYLON.Vector3(-1.0, 1.0, 1.0),
+                new BABYLON.Vector3(1.0, 1.0, 1.0)
+            ];
+            PanoramaToCubeMapTools.FACE_DOWN = [
+                new BABYLON.Vector3(-1.0, -1.0, 1.0),
+                new BABYLON.Vector3(1.0, -1.0, 1.0),
+                new BABYLON.Vector3(-1.0, -1.0, -1.0),
+                new BABYLON.Vector3(1.0, -1.0, -1.0)
+            ];
+            return PanoramaToCubeMapTools;
+        })();
+        Internals.PanoramaToCubeMapTools = PanoramaToCubeMapTools;
+    })(Internals = BABYLON.Internals || (BABYLON.Internals = {}));
+})(BABYLON || (BABYLON = {}));

+ 0 - 2
materialsLibrary/materials/pbr/babylon.tools.panoramatocubemap.ts

@@ -1,5 +1,3 @@
-/// <reference path="../../../dist/preview release/babylon.d.ts"/>
-
 module BABYLON.Internals {
     export interface CubeMapInfo {
         front: Float32Array;