David Catuhe 7 年之前
父節點
當前提交
23c70c7d13

File diff suppressed because it is too large
+ 4530 - 4367
Playground/babylon.d.txt


File diff suppressed because it is too large
+ 4183 - 4027
dist/preview release/babylon.d.ts


File diff suppressed because it is too large
+ 47 - 47
dist/preview release/babylon.js


+ 320 - 83
dist/preview release/babylon.max.js

@@ -1117,6 +1117,22 @@ var BABYLON;
             return this;
         };
         /**
+         * Clamps the rgb values by the min and max values and stores the result into "result".
+         * Returns the unmodified current Color3.
+         * @param min - minimum clamping value.  Defaults to 0
+         * @param max - maximum clamping value.  Defaults to 1
+         * @param result - color to store the result into.
+         * @returns - the original Color3
+         */
+        Color3.prototype.clampToRef = function (min, max, result) {
+            if (min === void 0) { min = 0; }
+            if (max === void 0) { max = 1; }
+            result.r = BABYLON.Scalar.Clamp(this.r, min, max);
+            result.g = BABYLON.Scalar.Clamp(this.g, min, max);
+            result.b = BABYLON.Scalar.Clamp(this.b, min, max);
+            return this;
+        };
+        /**
          * Returns a new Color3 set with the added values of the current Color3 and of the passed one.
          */
         Color3.prototype.add = function (otherColor) {
@@ -1365,6 +1381,23 @@ var BABYLON;
             return this;
         };
         /**
+         * Clamps the rgb values by the min and max values and stores the result into "result".
+         * Returns the unmodified current Color4.
+         * @param min - minimum clamping value.  Defaults to 0
+         * @param max - maximum clamping value.  Defaults to 1
+         * @param result - color to store the result into.
+         * @returns - the original Color4
+         */
+        Color4.prototype.clampToRef = function (min, max, result) {
+            if (min === void 0) { min = 0; }
+            if (max === void 0) { max = 1; }
+            result.r = BABYLON.Scalar.Clamp(this.r, min, max);
+            result.g = BABYLON.Scalar.Clamp(this.g, min, max);
+            result.b = BABYLON.Scalar.Clamp(this.b, min, max);
+            result.a = BABYLON.Scalar.Clamp(this.a, min, max);
+            return this;
+        };
+        /**
           * Multipy an RGBA Color4 value by another and return a new Color4 object
           * @param color The Color4 (RGBA) value to multiply by
           * @returns A new Color4.
@@ -2357,6 +2390,23 @@ var BABYLON;
             return s;
         };
         /**
+         * Get angle between two vectors.
+         * @param vector0 angle between vector0 and vector1
+         * @param vector1 angle between vector0 and vector1
+         * @param normal direction of the normal.
+         * @return the angle between vector0 and vector1.
+         */
+        Vector3.GetAngleBetweenVectors = function (vector0, vector1, normal) {
+            var v0 = vector0.clone().normalize();
+            var v1 = vector1.clone().normalize();
+            var dot = Vector3.Dot(v0, v1);
+            var n = Vector3.Cross(v0, v1);
+            if (Vector3.Dot(n, normal) > 0) {
+                return Math.acos(dot);
+            }
+            return -Math.acos(dot);
+        };
+        /**
          * Returns a new Vector3 set from the index "offset" of the passed array.
          */
         Vector3.FromArray = function (array, offset) {
@@ -17769,14 +17819,17 @@ var BABYLON;
         __extends(Camera, _super);
         function Camera(name, position, scene) {
             var _this = _super.call(this, name, scene) || this;
+            /**
+             * The vector the camera should consider as up.
+             * (default is Vector3(0, 1, 0) aka Vector3.Up())
+             */
             _this.upVector = BABYLON.Vector3.Up();
             _this.orthoLeft = null;
             _this.orthoRight = null;
             _this.orthoBottom = null;
             _this.orthoTop = null;
             /**
-             * default : 0.8
-             * FOV is set in Radians.
+             * FOV is set in Radians. (default is 0.8)
              */
             _this.fov = 0.8;
             _this.minZ = 1;
@@ -17786,14 +17839,13 @@ var BABYLON;
             _this.isIntermediate = false;
             _this.viewport = new BABYLON.Viewport(0, 0, 1.0, 1.0);
             /**
-            * Restricts the camera to viewing objects with the same layerMask.
-            * A camera with a layerMask of 1 will render meshes with no layerMask and meshes with a layerMask of 1.
-            */
+             * Restricts the camera to viewing objects with the same layerMask.
+             * A camera with a layerMask of 1 will render mesh.layerMask & camera.layerMask!== 0
+             */
             _this.layerMask = 0x0FFFFFFF;
             /**
-            * default : FOVMODE_VERTICAL_FIXED
-            * fovMode sets the camera frustum bounds to the viewport bounds.
-            */
+             * fovMode sets the camera frustum bounds to the viewport bounds. (default is FOVMODE_VERTICAL_FIXED)
+             */
             _this.fovMode = Camera.FOVMODE_VERTICAL_FIXED;
             // Camera rig members
             _this.cameraRigMode = Camera.RIG_MODE_NONE;
@@ -19988,6 +20040,24 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        Object.defineProperty(Scene.prototype, "geometryBufferRenderer", {
+            /**
+             * Gets the current geometry buffer associated to the scene.
+             */
+            get: function () {
+                return this._geometryBufferRenderer;
+            },
+            /**
+             * Sets the current geometry buffer for the scene.
+             */
+            set: function (geometryBufferRenderer) {
+                if (geometryBufferRenderer && geometryBufferRenderer.isSupported) {
+                    this._geometryBufferRenderer = geometryBufferRenderer;
+                }
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(Scene.prototype, "debugLayer", {
             // Properties
             get: function () {
@@ -39125,6 +39195,12 @@ var BABYLON;
             this.camera = camera;
             this.checkInputs = function () { };
         }
+        /**
+         * Add an input method to a camera.
+         * builtin inputs example: camera.inputs.addGamepad();
+         * custom inputs example: camera.inputs.add(new BABYLON.FreeCameraGamepadInput());
+         * @param input camera input method
+         */
         CameraInputsManager.prototype.add = function (input) {
             var type = input.getSimpleName();
             if (this.attached[type]) {
@@ -39142,6 +39218,11 @@ var BABYLON;
                 input.attachControl(this.attachedElement);
             }
         };
+        /**
+         * Remove a specific input method from a camera
+         * example: camera.inputs.remove(camera.inputs.attached.mouse);
+         * @param inputToRemove camera input method
+         */
         CameraInputsManager.prototype.remove = function (inputToRemove) {
             for (var cam in this.attached) {
                 var input = this.attached[cam];
@@ -39210,6 +39291,9 @@ var BABYLON;
                 }
             }
         };
+        /**
+         * Remove all attached input methods from a camera
+         */
         CameraInputsManager.prototype.clear = function () {
             if (this.attachedElement) {
                 this.detachElement(this.attachedElement, true);
@@ -39914,12 +39998,20 @@ var BABYLON;
         }
         Object.defineProperty(FreeCamera.prototype, "angularSensibility", {
             //-- begin properties for backward compatibility for inputs
+            /**
+             * Gets the input sensibility for a mouse input. (default is 2000.0)
+             * Higher values reduce sensitivity.
+             */
             get: function () {
                 var mouse = this.inputs.attached["mouse"];
                 if (mouse)
                     return mouse.angularSensibility;
                 return 0;
             },
+            /**
+             * Sets the input sensibility for a mouse input. (default is 2000.0)
+             * Higher values reduce sensitivity.
+             */
             set: function (value) {
                 var mouse = this.inputs.attached["mouse"];
                 if (mouse)
@@ -44482,6 +44574,24 @@ var BABYLON;
             return action;
         };
         /**
+         * Unregisters an action to this action manager
+         * @param action The action to be unregistered
+         * @return whether the action has been unregistered
+         */
+        ActionManager.prototype.unregisterAction = function (action) {
+            var index = this.actions.indexOf(action);
+            if (index !== -1) {
+                this.actions.splice(index, 1);
+                ActionManager.Triggers[action.trigger] -= 1;
+                if (ActionManager.Triggers[action.trigger] === 0) {
+                    delete ActionManager.Triggers[action.trigger];
+                }
+                delete action._actionManager;
+                return true;
+            }
+            return false;
+        };
+        /**
          * Process a specific trigger
          * @param {number} trigger - the trigger to process
          * @param evt {BABYLON.ActionEvent} the event details to be processed
@@ -53998,104 +54108,167 @@ var BABYLON;
 
 var BABYLON;
 (function (BABYLON) {
+    var getName = function (src) {
+        if (src instanceof HTMLVideoElement) {
+            return src.currentSrc;
+        }
+        if (typeof src === "object") {
+            return src.toString();
+        }
+        return src;
+    };
+    var getVideo = function (src) {
+        if (src instanceof HTMLVideoElement) {
+            return src;
+        }
+        var video = document.createElement("video");
+        if (typeof src === "string") {
+            video.src = src;
+        }
+        else {
+            src.forEach(function (url) {
+                var source = document.createElement("source");
+                source.src = url;
+                video.appendChild(source);
+            });
+        }
+        return video;
+    };
     var VideoTexture = /** @class */ (function (_super) {
         __extends(VideoTexture, _super);
         /**
          * Creates a video texture.
-         * Sample : https://doc.babylonjs.com/tutorials/01._Advanced_Texturing
-         * @param {Array} urlsOrVideo can be used to provide an array of urls or an already setup HTML video element.
+         * Sample : https://doc.babylonjs.com/how_to/video_texture
+         * @param {string | null} name optional name, will detect from video source, if not defined
+         * @param {(string | string[] | HTMLVideoElement)} src can be used to provide an url, array of urls or an already setup HTML video element.
          * @param {BABYLON.Scene} scene is obviously the current scene.
          * @param {boolean} generateMipMaps can be used to turn on mipmaps (Can be expensive for videoTextures because they are often updated).
          * @param {boolean} invertY is false by default but can be used to invert video on Y axis
          * @param {number} samplingMode controls the sampling method and is set to TRILINEAR_SAMPLINGMODE by default
+         * @param {VideoTextureSettings} [settings] allows finer control over video usage
          */
-        function VideoTexture(name, urlsOrVideo, scene, generateMipMaps, invertY, samplingMode) {
+        function VideoTexture(name, src, scene, generateMipMaps, invertY, samplingMode, settings) {
             if (generateMipMaps === void 0) { generateMipMaps = false; }
             if (invertY === void 0) { invertY = false; }
             if (samplingMode === void 0) { samplingMode = BABYLON.Texture.TRILINEAR_SAMPLINGMODE; }
+            if (settings === void 0) { settings = {
+                autoPlay: true,
+                loop: true,
+                autoUpdateTexture: true,
+            }; }
             var _this = _super.call(this, null, scene, !generateMipMaps, invertY) || this;
-            _this._autoLaunch = true;
-            var urls = null;
-            _this.name = name;
-            if (urlsOrVideo instanceof HTMLVideoElement) {
-                _this.video = urlsOrVideo;
-            }
-            else {
-                urls = urlsOrVideo;
-                _this.video = document.createElement("video");
-                _this.video.autoplay = false;
-                _this.video.loop = true;
-                BABYLON.Tools.SetCorsBehavior(urls, _this.video);
-            }
+            _this._createInternalTexture = function () {
+                if (_this._texture != null) {
+                    return;
+                }
+                if (!_this._engine.needPOTTextures ||
+                    (BABYLON.Tools.IsExponentOfTwo(_this.video.videoWidth) && BABYLON.Tools.IsExponentOfTwo(_this.video.videoHeight))) {
+                    _this.wrapU = BABYLON.Texture.WRAP_ADDRESSMODE;
+                    _this.wrapV = BABYLON.Texture.WRAP_ADDRESSMODE;
+                }
+                else {
+                    _this.wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE;
+                    _this.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;
+                    _this._generateMipMaps = false;
+                }
+                _this._texture = _this._engine.createDynamicTexture(_this.video.videoWidth, _this.video.videoHeight, _this._generateMipMaps, _this._samplingMode);
+                _this._texture.width;
+                _this._updateInternalTexture();
+                _this._texture.isReady = true;
+            };
+            _this.reset = function () {
+                if (_this._texture == null) {
+                    return;
+                }
+                _this._texture.dispose();
+                _this._texture = null;
+            };
+            _this._updateInternalTexture = function (e) {
+                if (_this._texture == null || !_this._texture.isReady) {
+                    return;
+                }
+                if (_this.video.readyState < _this.video.HAVE_CURRENT_DATA) {
+                    return;
+                }
+                _this._engine.updateVideoTexture(_this._texture, _this.video, _this._invertY);
+            };
             _this._engine = _this.getScene().getEngine();
             _this._generateMipMaps = generateMipMaps;
             _this._samplingMode = samplingMode;
-            if (!_this._engine.needPOTTextures || (BABYLON.Tools.IsExponentOfTwo(_this.video.videoWidth) && BABYLON.Tools.IsExponentOfTwo(_this.video.videoHeight))) {
-                _this.wrapU = BABYLON.Texture.WRAP_ADDRESSMODE;
-                _this.wrapV = BABYLON.Texture.WRAP_ADDRESSMODE;
-            }
-            else {
-                _this.wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE;
-                _this.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;
-                _this._generateMipMaps = false;
-            }
-            if (urls) {
-                _this.video.addEventListener("canplay", function () {
-                    if (_this._texture === undefined) {
-                        _this._createTexture();
-                    }
-                });
-                urls.forEach(function (url) {
-                    var source = document.createElement("source");
-                    source.src = url;
-                    _this.video.appendChild(source);
-                });
+            _this.autoUpdateTexture = settings.autoUpdateTexture;
+            _this.name = name || getName(src);
+            _this.video = getVideo(src);
+            if (settings.autoPlay !== undefined) {
+                _this.video.autoplay = settings.autoPlay;
+            }
+            if (settings.loop !== undefined) {
+                _this.video.loop = settings.loop;
+            }
+            _this.video.addEventListener("canplay", _this._createInternalTexture);
+            _this.video.addEventListener("paused", _this._updateInternalTexture);
+            _this.video.addEventListener("seeked", _this._updateInternalTexture);
+            _this.video.addEventListener("emptied", _this.reset);
+            if (_this.video.readyState >= _this.video.HAVE_CURRENT_DATA) {
+                _this._createInternalTexture();
             }
-            else {
-                _this._createTexture();
-            }
-            _this._lastUpdate = BABYLON.Tools.Now;
             return _this;
         }
-        VideoTexture.prototype.__setTextureReady = function () {
-            if (this._texture) {
-                this._texture.isReady = true;
-            }
-        };
-        VideoTexture.prototype._createTexture = function () {
-            this._texture = this._engine.createDynamicTexture(this.video.videoWidth, this.video.videoHeight, this._generateMipMaps, this._samplingMode);
-            if (this._autoLaunch) {
-                this._autoLaunch = false;
-                this.video.play();
-            }
-            this._setTextureReady = this.__setTextureReady.bind(this);
-            this.video.addEventListener("playing", this._setTextureReady);
-        };
+        /**
+         * Internal method to initiate `update`.
+         */
         VideoTexture.prototype._rebuild = function () {
             this.update();
         };
+        /**
+         * Update Texture in the `auto` mode. Does not do anything if `settings.autoUpdateTexture` is false.
+         */
         VideoTexture.prototype.update = function () {
-            var now = BABYLON.Tools.Now;
-            if (now - this._lastUpdate < 15 || this.video.readyState !== this.video.HAVE_ENOUGH_DATA) {
-                return false;
+            if (!this.autoUpdateTexture) {
+                // Expecting user to call `updateTexture` manually
+                return;
             }
-            this._lastUpdate = now;
-            this._engine.updateVideoTexture(this._texture, this.video, this._invertY);
-            return true;
+            this.updateTexture(true);
+        };
+        /**
+         * Update Texture in `manual` mode. Does not do anything if not visible or paused.
+         * @param isVisible Visibility state, detected by user using `scene.getActiveMeshes()` or othervise.
+         */
+        VideoTexture.prototype.updateTexture = function (isVisible) {
+            if (!isVisible) {
+                return;
+            }
+            if (this.video.paused) {
+                return;
+            }
+            this._updateInternalTexture();
+        };
+        /**
+         * Change video content. Changing video instance or setting multiple urls (as in constructor) is not supported.
+         * @param url New url.
+         */
+        VideoTexture.prototype.updateURL = function (url) {
+            this.video.src = url;
         };
         VideoTexture.prototype.dispose = function () {
             _super.prototype.dispose.call(this);
-            this.video.removeEventListener("playing", this._setTextureReady);
+            this.video.removeEventListener("canplay", this._createInternalTexture);
+            this.video.removeEventListener("paused", this._updateInternalTexture);
+            this.video.removeEventListener("seeked", this._updateInternalTexture);
+            this.video.removeEventListener("emptied", this.reset);
         };
         VideoTexture.CreateFromWebCam = function (scene, onReady, constraints) {
             var video = document.createElement("video");
             var constraintsDeviceId;
             if (constraints && constraints.deviceId) {
                 constraintsDeviceId = {
-                    exact: constraints.deviceId
+                    exact: constraints.deviceId,
                 };
             }
-            navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
+            navigator.getUserMedia =
+                navigator.getUserMedia ||
+                    navigator.webkitGetUserMedia ||
+                    navigator.mozGetUserMedia ||
+                    navigator.msGetUserMedia;
             window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL;
             if (navigator.getUserMedia) {
                 navigator.getUserMedia({
@@ -54103,15 +54276,16 @@ var BABYLON;
                         deviceId: constraintsDeviceId,
                         width: {
                             min: (constraints && constraints.minWidth) || 256,
-                            max: (constraints && constraints.maxWidth) || 640
+                            max: (constraints && constraints.maxWidth) || 640,
                         },
                         height: {
                             min: (constraints && constraints.minHeight) || 256,
-                            max: (constraints && constraints.maxHeight) || 480
-                        }
-                    }
+                            max: (constraints && constraints.maxHeight) || 480,
+                        },
+                    },
                 }, function (stream) {
                     if (video.mozSrcObject !== undefined) {
+                        // hack for Firefox < 19
                         video.mozSrcObject = stream;
                     }
                     else {
@@ -63217,7 +63391,15 @@ var BABYLON;
 
 var BABYLON;
 (function (BABYLON) {
+    /**
+     * This renderer is helpfull to fill one of the render target with a geometry buffer.
+     */
     var GeometryBufferRenderer = /** @class */ (function () {
+        /**
+         * Creates a new G Buffer for the scene. @see GeometryBufferRenderer
+         * @param scene The scene the buffer belongs to
+         * @param ratio How big is the buffer related to the main canvas.
+         */
         function GeometryBufferRenderer(scene, ratio) {
             if (ratio === void 0) { ratio = 1; }
             this._enablePosition = false;
@@ -63227,6 +63409,9 @@ var BABYLON;
             this._createRenderTargets();
         }
         Object.defineProperty(GeometryBufferRenderer.prototype, "renderList", {
+            /**
+             * Set the render list (meshes to be rendered) used in the G buffer.
+             */
             set: function (meshes) {
                 this._multiRenderTarget.renderList = meshes;
             },
@@ -63234,6 +63419,10 @@ var BABYLON;
             configurable: true
         });
         Object.defineProperty(GeometryBufferRenderer.prototype, "isSupported", {
+            /**
+             * Gets wether or not G buffer are supported by the running hardware.
+             * This requires draw buffer supports
+             */
             get: function () {
                 return this._multiRenderTarget.isSupported;
             },
@@ -63241,9 +63430,15 @@ var BABYLON;
             configurable: true
         });
         Object.defineProperty(GeometryBufferRenderer.prototype, "enablePosition", {
+            /**
+             * Gets wether or not position are enabled for the G buffer.
+             */
             get: function () {
                 return this._enablePosition;
             },
+            /**
+             * Sets wether or not position are enabled for the G buffer.
+             */
             set: function (enable) {
                 this._enablePosition = enable;
                 this.dispose();
@@ -63252,6 +63447,33 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        Object.defineProperty(GeometryBufferRenderer.prototype, "scene", {
+            /**
+             * Gets the scene associated with the buffer.
+             */
+            get: function () {
+                return this._scene;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(GeometryBufferRenderer.prototype, "ratio", {
+            /**
+             * Gets the ratio used by the buffer during its creation.
+             * How big is the buffer related to the main canvas.
+             */
+            get: function () {
+                return this._ratio;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        /**
+         * Checks wether everything is ready to render a submesh to the G buffer.
+         * @param subMesh the submesh to check readiness for
+         * @param useInstances is the mesh drawn using instance or not
+         * @returns true if ready otherwise false
+         */
         GeometryBufferRenderer.prototype.isReady = function (subMesh, useInstances) {
             var material = subMesh.getMaterial();
             if (material && material.disableDepthWrite) {
@@ -63306,20 +63528,32 @@ var BABYLON;
             }
             return this._effect.isReady();
         };
+        /**
+         * Gets the current underlying G Buffer.
+         * @returns the buffer
+         */
         GeometryBufferRenderer.prototype.getGBuffer = function () {
             return this._multiRenderTarget;
         };
         Object.defineProperty(GeometryBufferRenderer.prototype, "samples", {
+            /**
+             * Gets the number of samples used to render the buffer (anti aliasing).
+             */
             get: function () {
                 return this._multiRenderTarget.samples;
             },
+            /**
+             * Sets the number of samples used to render the buffer (anti aliasing).
+             */
             set: function (value) {
                 this._multiRenderTarget.samples = value;
             },
             enumerable: true,
             configurable: true
         });
-        // Methods
+        /**
+         * Disposes the renderer and frees up associated resources.
+         */
         GeometryBufferRenderer.prototype.dispose = function () {
             this.getGBuffer().dispose();
         };
@@ -73147,7 +73381,7 @@ var BABYLON;
             engine.setDepthFunctionToLess();
             this._scene.resetCachedMaterial();
             this._colorShader.bind(worldMatrix);
-            engine.drawElementsType(BABYLON.Material.TriangleFillMode, 0, 24);
+            engine.drawElementsType(BABYLON.Material.LineListDrawMode, 0, 24);
             this._colorShader.unbind();
             engine.setDepthFunctionToLessOrEqual();
             engine.setDepthWrite(true);
@@ -73768,6 +74002,10 @@ var BABYLON;
 
 var BABYLON;
 (function (BABYLON) {
+    /**
+     * Takes information about the orientation of the device as reported by the deviceorientation event to orient the camera.
+     * Screen rotation is taken into account.
+     */
     var FreeCameraDeviceOrientationInput = /** @class */ (function () {
         function FreeCameraDeviceOrientationInput() {
             var _this = this;
@@ -73994,16 +74232,15 @@ var BABYLON;
             _this.onControllersAttachedObservable = new BABYLON.Observable();
             _this.onControllerMeshLoadedObservable = new BABYLON.Observable();
             _this.rigParenting = true; // should the rig cameras be used as parent instead of this camera.
-            _this._defaultHeight = 0;
+            _this._defaultHeight = undefined;
             _this.deviceDistanceToRoomGround = function () {
-                if (_this._standingMatrix) {
+                if (_this._standingMatrix && _this._defaultHeight === undefined) {
                     // Add standing matrix offset to get real offset from ground in room
                     _this._standingMatrix.getTranslationToRef(_this._workingVector);
                     return _this._deviceRoomPosition.y + _this._workingVector.y;
                 }
-                else {
-                    return _this._defaultHeight;
-                }
+                //If VRDisplay does not inform stage parameters and no default height is set we fallback to zero.
+                return _this._defaultHeight || 0;
             };
             _this.useStandingMatrix = function (callback) {
                 if (callback === void 0) { callback = function (bool) { }; }
@@ -74415,7 +74652,7 @@ var BABYLON;
         /**
          * Creates a new device orientation camera. @see DeviceOrientationCamera
          * @param name The name of the camera
-         * @param position The starts position camera
+         * @param position The start position camera
          * @param scene The scene the camera belongs to
          */
         function DeviceOrientationCamera(name, position, scene) {

File diff suppressed because it is too large
+ 48 - 48
dist/preview release/babylon.worker.js


File diff suppressed because it is too large
+ 9136 - 8980
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts


File diff suppressed because it is too large
+ 47 - 47
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js


+ 320 - 83
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js

@@ -1117,6 +1117,22 @@ var BABYLON;
             return this;
         };
         /**
+         * Clamps the rgb values by the min and max values and stores the result into "result".
+         * Returns the unmodified current Color3.
+         * @param min - minimum clamping value.  Defaults to 0
+         * @param max - maximum clamping value.  Defaults to 1
+         * @param result - color to store the result into.
+         * @returns - the original Color3
+         */
+        Color3.prototype.clampToRef = function (min, max, result) {
+            if (min === void 0) { min = 0; }
+            if (max === void 0) { max = 1; }
+            result.r = BABYLON.Scalar.Clamp(this.r, min, max);
+            result.g = BABYLON.Scalar.Clamp(this.g, min, max);
+            result.b = BABYLON.Scalar.Clamp(this.b, min, max);
+            return this;
+        };
+        /**
          * Returns a new Color3 set with the added values of the current Color3 and of the passed one.
          */
         Color3.prototype.add = function (otherColor) {
@@ -1365,6 +1381,23 @@ var BABYLON;
             return this;
         };
         /**
+         * Clamps the rgb values by the min and max values and stores the result into "result".
+         * Returns the unmodified current Color4.
+         * @param min - minimum clamping value.  Defaults to 0
+         * @param max - maximum clamping value.  Defaults to 1
+         * @param result - color to store the result into.
+         * @returns - the original Color4
+         */
+        Color4.prototype.clampToRef = function (min, max, result) {
+            if (min === void 0) { min = 0; }
+            if (max === void 0) { max = 1; }
+            result.r = BABYLON.Scalar.Clamp(this.r, min, max);
+            result.g = BABYLON.Scalar.Clamp(this.g, min, max);
+            result.b = BABYLON.Scalar.Clamp(this.b, min, max);
+            result.a = BABYLON.Scalar.Clamp(this.a, min, max);
+            return this;
+        };
+        /**
           * Multipy an RGBA Color4 value by another and return a new Color4 object
           * @param color The Color4 (RGBA) value to multiply by
           * @returns A new Color4.
@@ -2357,6 +2390,23 @@ var BABYLON;
             return s;
         };
         /**
+         * Get angle between two vectors.
+         * @param vector0 angle between vector0 and vector1
+         * @param vector1 angle between vector0 and vector1
+         * @param normal direction of the normal.
+         * @return the angle between vector0 and vector1.
+         */
+        Vector3.GetAngleBetweenVectors = function (vector0, vector1, normal) {
+            var v0 = vector0.clone().normalize();
+            var v1 = vector1.clone().normalize();
+            var dot = Vector3.Dot(v0, v1);
+            var n = Vector3.Cross(v0, v1);
+            if (Vector3.Dot(n, normal) > 0) {
+                return Math.acos(dot);
+            }
+            return -Math.acos(dot);
+        };
+        /**
          * Returns a new Vector3 set from the index "offset" of the passed array.
          */
         Vector3.FromArray = function (array, offset) {
@@ -17769,14 +17819,17 @@ var BABYLON;
         __extends(Camera, _super);
         function Camera(name, position, scene) {
             var _this = _super.call(this, name, scene) || this;
+            /**
+             * The vector the camera should consider as up.
+             * (default is Vector3(0, 1, 0) aka Vector3.Up())
+             */
             _this.upVector = BABYLON.Vector3.Up();
             _this.orthoLeft = null;
             _this.orthoRight = null;
             _this.orthoBottom = null;
             _this.orthoTop = null;
             /**
-             * default : 0.8
-             * FOV is set in Radians.
+             * FOV is set in Radians. (default is 0.8)
              */
             _this.fov = 0.8;
             _this.minZ = 1;
@@ -17786,14 +17839,13 @@ var BABYLON;
             _this.isIntermediate = false;
             _this.viewport = new BABYLON.Viewport(0, 0, 1.0, 1.0);
             /**
-            * Restricts the camera to viewing objects with the same layerMask.
-            * A camera with a layerMask of 1 will render meshes with no layerMask and meshes with a layerMask of 1.
-            */
+             * Restricts the camera to viewing objects with the same layerMask.
+             * A camera with a layerMask of 1 will render mesh.layerMask & camera.layerMask!== 0
+             */
             _this.layerMask = 0x0FFFFFFF;
             /**
-            * default : FOVMODE_VERTICAL_FIXED
-            * fovMode sets the camera frustum bounds to the viewport bounds.
-            */
+             * fovMode sets the camera frustum bounds to the viewport bounds. (default is FOVMODE_VERTICAL_FIXED)
+             */
             _this.fovMode = Camera.FOVMODE_VERTICAL_FIXED;
             // Camera rig members
             _this.cameraRigMode = Camera.RIG_MODE_NONE;
@@ -19988,6 +20040,24 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        Object.defineProperty(Scene.prototype, "geometryBufferRenderer", {
+            /**
+             * Gets the current geometry buffer associated to the scene.
+             */
+            get: function () {
+                return this._geometryBufferRenderer;
+            },
+            /**
+             * Sets the current geometry buffer for the scene.
+             */
+            set: function (geometryBufferRenderer) {
+                if (geometryBufferRenderer && geometryBufferRenderer.isSupported) {
+                    this._geometryBufferRenderer = geometryBufferRenderer;
+                }
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(Scene.prototype, "debugLayer", {
             // Properties
             get: function () {
@@ -39125,6 +39195,12 @@ var BABYLON;
             this.camera = camera;
             this.checkInputs = function () { };
         }
+        /**
+         * Add an input method to a camera.
+         * builtin inputs example: camera.inputs.addGamepad();
+         * custom inputs example: camera.inputs.add(new BABYLON.FreeCameraGamepadInput());
+         * @param input camera input method
+         */
         CameraInputsManager.prototype.add = function (input) {
             var type = input.getSimpleName();
             if (this.attached[type]) {
@@ -39142,6 +39218,11 @@ var BABYLON;
                 input.attachControl(this.attachedElement);
             }
         };
+        /**
+         * Remove a specific input method from a camera
+         * example: camera.inputs.remove(camera.inputs.attached.mouse);
+         * @param inputToRemove camera input method
+         */
         CameraInputsManager.prototype.remove = function (inputToRemove) {
             for (var cam in this.attached) {
                 var input = this.attached[cam];
@@ -39210,6 +39291,9 @@ var BABYLON;
                 }
             }
         };
+        /**
+         * Remove all attached input methods from a camera
+         */
         CameraInputsManager.prototype.clear = function () {
             if (this.attachedElement) {
                 this.detachElement(this.attachedElement, true);
@@ -39914,12 +39998,20 @@ var BABYLON;
         }
         Object.defineProperty(FreeCamera.prototype, "angularSensibility", {
             //-- begin properties for backward compatibility for inputs
+            /**
+             * Gets the input sensibility for a mouse input. (default is 2000.0)
+             * Higher values reduce sensitivity.
+             */
             get: function () {
                 var mouse = this.inputs.attached["mouse"];
                 if (mouse)
                     return mouse.angularSensibility;
                 return 0;
             },
+            /**
+             * Sets the input sensibility for a mouse input. (default is 2000.0)
+             * Higher values reduce sensitivity.
+             */
             set: function (value) {
                 var mouse = this.inputs.attached["mouse"];
                 if (mouse)
@@ -44482,6 +44574,24 @@ var BABYLON;
             return action;
         };
         /**
+         * Unregisters an action to this action manager
+         * @param action The action to be unregistered
+         * @return whether the action has been unregistered
+         */
+        ActionManager.prototype.unregisterAction = function (action) {
+            var index = this.actions.indexOf(action);
+            if (index !== -1) {
+                this.actions.splice(index, 1);
+                ActionManager.Triggers[action.trigger] -= 1;
+                if (ActionManager.Triggers[action.trigger] === 0) {
+                    delete ActionManager.Triggers[action.trigger];
+                }
+                delete action._actionManager;
+                return true;
+            }
+            return false;
+        };
+        /**
          * Process a specific trigger
          * @param {number} trigger - the trigger to process
          * @param evt {BABYLON.ActionEvent} the event details to be processed
@@ -53792,104 +53902,167 @@ var BABYLON;
 
 var BABYLON;
 (function (BABYLON) {
+    var getName = function (src) {
+        if (src instanceof HTMLVideoElement) {
+            return src.currentSrc;
+        }
+        if (typeof src === "object") {
+            return src.toString();
+        }
+        return src;
+    };
+    var getVideo = function (src) {
+        if (src instanceof HTMLVideoElement) {
+            return src;
+        }
+        var video = document.createElement("video");
+        if (typeof src === "string") {
+            video.src = src;
+        }
+        else {
+            src.forEach(function (url) {
+                var source = document.createElement("source");
+                source.src = url;
+                video.appendChild(source);
+            });
+        }
+        return video;
+    };
     var VideoTexture = /** @class */ (function (_super) {
         __extends(VideoTexture, _super);
         /**
          * Creates a video texture.
-         * Sample : https://doc.babylonjs.com/tutorials/01._Advanced_Texturing
-         * @param {Array} urlsOrVideo can be used to provide an array of urls or an already setup HTML video element.
+         * Sample : https://doc.babylonjs.com/how_to/video_texture
+         * @param {string | null} name optional name, will detect from video source, if not defined
+         * @param {(string | string[] | HTMLVideoElement)} src can be used to provide an url, array of urls or an already setup HTML video element.
          * @param {BABYLON.Scene} scene is obviously the current scene.
          * @param {boolean} generateMipMaps can be used to turn on mipmaps (Can be expensive for videoTextures because they are often updated).
          * @param {boolean} invertY is false by default but can be used to invert video on Y axis
          * @param {number} samplingMode controls the sampling method and is set to TRILINEAR_SAMPLINGMODE by default
+         * @param {VideoTextureSettings} [settings] allows finer control over video usage
          */
-        function VideoTexture(name, urlsOrVideo, scene, generateMipMaps, invertY, samplingMode) {
+        function VideoTexture(name, src, scene, generateMipMaps, invertY, samplingMode, settings) {
             if (generateMipMaps === void 0) { generateMipMaps = false; }
             if (invertY === void 0) { invertY = false; }
             if (samplingMode === void 0) { samplingMode = BABYLON.Texture.TRILINEAR_SAMPLINGMODE; }
+            if (settings === void 0) { settings = {
+                autoPlay: true,
+                loop: true,
+                autoUpdateTexture: true,
+            }; }
             var _this = _super.call(this, null, scene, !generateMipMaps, invertY) || this;
-            _this._autoLaunch = true;
-            var urls = null;
-            _this.name = name;
-            if (urlsOrVideo instanceof HTMLVideoElement) {
-                _this.video = urlsOrVideo;
-            }
-            else {
-                urls = urlsOrVideo;
-                _this.video = document.createElement("video");
-                _this.video.autoplay = false;
-                _this.video.loop = true;
-                BABYLON.Tools.SetCorsBehavior(urls, _this.video);
-            }
+            _this._createInternalTexture = function () {
+                if (_this._texture != null) {
+                    return;
+                }
+                if (!_this._engine.needPOTTextures ||
+                    (BABYLON.Tools.IsExponentOfTwo(_this.video.videoWidth) && BABYLON.Tools.IsExponentOfTwo(_this.video.videoHeight))) {
+                    _this.wrapU = BABYLON.Texture.WRAP_ADDRESSMODE;
+                    _this.wrapV = BABYLON.Texture.WRAP_ADDRESSMODE;
+                }
+                else {
+                    _this.wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE;
+                    _this.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;
+                    _this._generateMipMaps = false;
+                }
+                _this._texture = _this._engine.createDynamicTexture(_this.video.videoWidth, _this.video.videoHeight, _this._generateMipMaps, _this._samplingMode);
+                _this._texture.width;
+                _this._updateInternalTexture();
+                _this._texture.isReady = true;
+            };
+            _this.reset = function () {
+                if (_this._texture == null) {
+                    return;
+                }
+                _this._texture.dispose();
+                _this._texture = null;
+            };
+            _this._updateInternalTexture = function (e) {
+                if (_this._texture == null || !_this._texture.isReady) {
+                    return;
+                }
+                if (_this.video.readyState < _this.video.HAVE_CURRENT_DATA) {
+                    return;
+                }
+                _this._engine.updateVideoTexture(_this._texture, _this.video, _this._invertY);
+            };
             _this._engine = _this.getScene().getEngine();
             _this._generateMipMaps = generateMipMaps;
             _this._samplingMode = samplingMode;
-            if (!_this._engine.needPOTTextures || (BABYLON.Tools.IsExponentOfTwo(_this.video.videoWidth) && BABYLON.Tools.IsExponentOfTwo(_this.video.videoHeight))) {
-                _this.wrapU = BABYLON.Texture.WRAP_ADDRESSMODE;
-                _this.wrapV = BABYLON.Texture.WRAP_ADDRESSMODE;
-            }
-            else {
-                _this.wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE;
-                _this.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;
-                _this._generateMipMaps = false;
-            }
-            if (urls) {
-                _this.video.addEventListener("canplay", function () {
-                    if (_this._texture === undefined) {
-                        _this._createTexture();
-                    }
-                });
-                urls.forEach(function (url) {
-                    var source = document.createElement("source");
-                    source.src = url;
-                    _this.video.appendChild(source);
-                });
-            }
-            else {
-                _this._createTexture();
+            _this.autoUpdateTexture = settings.autoUpdateTexture;
+            _this.name = name || getName(src);
+            _this.video = getVideo(src);
+            if (settings.autoPlay !== undefined) {
+                _this.video.autoplay = settings.autoPlay;
+            }
+            if (settings.loop !== undefined) {
+                _this.video.loop = settings.loop;
+            }
+            _this.video.addEventListener("canplay", _this._createInternalTexture);
+            _this.video.addEventListener("paused", _this._updateInternalTexture);
+            _this.video.addEventListener("seeked", _this._updateInternalTexture);
+            _this.video.addEventListener("emptied", _this.reset);
+            if (_this.video.readyState >= _this.video.HAVE_CURRENT_DATA) {
+                _this._createInternalTexture();
             }
-            _this._lastUpdate = BABYLON.Tools.Now;
             return _this;
         }
-        VideoTexture.prototype.__setTextureReady = function () {
-            if (this._texture) {
-                this._texture.isReady = true;
-            }
-        };
-        VideoTexture.prototype._createTexture = function () {
-            this._texture = this._engine.createDynamicTexture(this.video.videoWidth, this.video.videoHeight, this._generateMipMaps, this._samplingMode);
-            if (this._autoLaunch) {
-                this._autoLaunch = false;
-                this.video.play();
-            }
-            this._setTextureReady = this.__setTextureReady.bind(this);
-            this.video.addEventListener("playing", this._setTextureReady);
-        };
+        /**
+         * Internal method to initiate `update`.
+         */
         VideoTexture.prototype._rebuild = function () {
             this.update();
         };
+        /**
+         * Update Texture in the `auto` mode. Does not do anything if `settings.autoUpdateTexture` is false.
+         */
         VideoTexture.prototype.update = function () {
-            var now = BABYLON.Tools.Now;
-            if (now - this._lastUpdate < 15 || this.video.readyState !== this.video.HAVE_ENOUGH_DATA) {
-                return false;
+            if (!this.autoUpdateTexture) {
+                // Expecting user to call `updateTexture` manually
+                return;
             }
-            this._lastUpdate = now;
-            this._engine.updateVideoTexture(this._texture, this.video, this._invertY);
-            return true;
+            this.updateTexture(true);
+        };
+        /**
+         * Update Texture in `manual` mode. Does not do anything if not visible or paused.
+         * @param isVisible Visibility state, detected by user using `scene.getActiveMeshes()` or othervise.
+         */
+        VideoTexture.prototype.updateTexture = function (isVisible) {
+            if (!isVisible) {
+                return;
+            }
+            if (this.video.paused) {
+                return;
+            }
+            this._updateInternalTexture();
+        };
+        /**
+         * Change video content. Changing video instance or setting multiple urls (as in constructor) is not supported.
+         * @param url New url.
+         */
+        VideoTexture.prototype.updateURL = function (url) {
+            this.video.src = url;
         };
         VideoTexture.prototype.dispose = function () {
             _super.prototype.dispose.call(this);
-            this.video.removeEventListener("playing", this._setTextureReady);
+            this.video.removeEventListener("canplay", this._createInternalTexture);
+            this.video.removeEventListener("paused", this._updateInternalTexture);
+            this.video.removeEventListener("seeked", this._updateInternalTexture);
+            this.video.removeEventListener("emptied", this.reset);
         };
         VideoTexture.CreateFromWebCam = function (scene, onReady, constraints) {
             var video = document.createElement("video");
             var constraintsDeviceId;
             if (constraints && constraints.deviceId) {
                 constraintsDeviceId = {
-                    exact: constraints.deviceId
+                    exact: constraints.deviceId,
                 };
             }
-            navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
+            navigator.getUserMedia =
+                navigator.getUserMedia ||
+                    navigator.webkitGetUserMedia ||
+                    navigator.mozGetUserMedia ||
+                    navigator.msGetUserMedia;
             window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL;
             if (navigator.getUserMedia) {
                 navigator.getUserMedia({
@@ -53897,15 +54070,16 @@ var BABYLON;
                         deviceId: constraintsDeviceId,
                         width: {
                             min: (constraints && constraints.minWidth) || 256,
-                            max: (constraints && constraints.maxWidth) || 640
+                            max: (constraints && constraints.maxWidth) || 640,
                         },
                         height: {
                             min: (constraints && constraints.minHeight) || 256,
-                            max: (constraints && constraints.maxHeight) || 480
-                        }
-                    }
+                            max: (constraints && constraints.maxHeight) || 480,
+                        },
+                    },
                 }, function (stream) {
                     if (video.mozSrcObject !== undefined) {
+                        // hack for Firefox < 19
                         video.mozSrcObject = stream;
                     }
                     else {
@@ -63011,7 +63185,15 @@ var BABYLON;
 
 var BABYLON;
 (function (BABYLON) {
+    /**
+     * This renderer is helpfull to fill one of the render target with a geometry buffer.
+     */
     var GeometryBufferRenderer = /** @class */ (function () {
+        /**
+         * Creates a new G Buffer for the scene. @see GeometryBufferRenderer
+         * @param scene The scene the buffer belongs to
+         * @param ratio How big is the buffer related to the main canvas.
+         */
         function GeometryBufferRenderer(scene, ratio) {
             if (ratio === void 0) { ratio = 1; }
             this._enablePosition = false;
@@ -63021,6 +63203,9 @@ var BABYLON;
             this._createRenderTargets();
         }
         Object.defineProperty(GeometryBufferRenderer.prototype, "renderList", {
+            /**
+             * Set the render list (meshes to be rendered) used in the G buffer.
+             */
             set: function (meshes) {
                 this._multiRenderTarget.renderList = meshes;
             },
@@ -63028,6 +63213,10 @@ var BABYLON;
             configurable: true
         });
         Object.defineProperty(GeometryBufferRenderer.prototype, "isSupported", {
+            /**
+             * Gets wether or not G buffer are supported by the running hardware.
+             * This requires draw buffer supports
+             */
             get: function () {
                 return this._multiRenderTarget.isSupported;
             },
@@ -63035,9 +63224,15 @@ var BABYLON;
             configurable: true
         });
         Object.defineProperty(GeometryBufferRenderer.prototype, "enablePosition", {
+            /**
+             * Gets wether or not position are enabled for the G buffer.
+             */
             get: function () {
                 return this._enablePosition;
             },
+            /**
+             * Sets wether or not position are enabled for the G buffer.
+             */
             set: function (enable) {
                 this._enablePosition = enable;
                 this.dispose();
@@ -63046,6 +63241,33 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        Object.defineProperty(GeometryBufferRenderer.prototype, "scene", {
+            /**
+             * Gets the scene associated with the buffer.
+             */
+            get: function () {
+                return this._scene;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(GeometryBufferRenderer.prototype, "ratio", {
+            /**
+             * Gets the ratio used by the buffer during its creation.
+             * How big is the buffer related to the main canvas.
+             */
+            get: function () {
+                return this._ratio;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        /**
+         * Checks wether everything is ready to render a submesh to the G buffer.
+         * @param subMesh the submesh to check readiness for
+         * @param useInstances is the mesh drawn using instance or not
+         * @returns true if ready otherwise false
+         */
         GeometryBufferRenderer.prototype.isReady = function (subMesh, useInstances) {
             var material = subMesh.getMaterial();
             if (material && material.disableDepthWrite) {
@@ -63100,20 +63322,32 @@ var BABYLON;
             }
             return this._effect.isReady();
         };
+        /**
+         * Gets the current underlying G Buffer.
+         * @returns the buffer
+         */
         GeometryBufferRenderer.prototype.getGBuffer = function () {
             return this._multiRenderTarget;
         };
         Object.defineProperty(GeometryBufferRenderer.prototype, "samples", {
+            /**
+             * Gets the number of samples used to render the buffer (anti aliasing).
+             */
             get: function () {
                 return this._multiRenderTarget.samples;
             },
+            /**
+             * Sets the number of samples used to render the buffer (anti aliasing).
+             */
             set: function (value) {
                 this._multiRenderTarget.samples = value;
             },
             enumerable: true,
             configurable: true
         });
-        // Methods
+        /**
+         * Disposes the renderer and frees up associated resources.
+         */
         GeometryBufferRenderer.prototype.dispose = function () {
             this.getGBuffer().dispose();
         };
@@ -72941,7 +73175,7 @@ var BABYLON;
             engine.setDepthFunctionToLess();
             this._scene.resetCachedMaterial();
             this._colorShader.bind(worldMatrix);
-            engine.drawElementsType(BABYLON.Material.TriangleFillMode, 0, 24);
+            engine.drawElementsType(BABYLON.Material.LineListDrawMode, 0, 24);
             this._colorShader.unbind();
             engine.setDepthFunctionToLessOrEqual();
             engine.setDepthWrite(true);
@@ -73562,6 +73796,10 @@ var BABYLON;
 
 var BABYLON;
 (function (BABYLON) {
+    /**
+     * Takes information about the orientation of the device as reported by the deviceorientation event to orient the camera.
+     * Screen rotation is taken into account.
+     */
     var FreeCameraDeviceOrientationInput = /** @class */ (function () {
         function FreeCameraDeviceOrientationInput() {
             var _this = this;
@@ -73788,16 +74026,15 @@ var BABYLON;
             _this.onControllersAttachedObservable = new BABYLON.Observable();
             _this.onControllerMeshLoadedObservable = new BABYLON.Observable();
             _this.rigParenting = true; // should the rig cameras be used as parent instead of this camera.
-            _this._defaultHeight = 0;
+            _this._defaultHeight = undefined;
             _this.deviceDistanceToRoomGround = function () {
-                if (_this._standingMatrix) {
+                if (_this._standingMatrix && _this._defaultHeight === undefined) {
                     // Add standing matrix offset to get real offset from ground in room
                     _this._standingMatrix.getTranslationToRef(_this._workingVector);
                     return _this._deviceRoomPosition.y + _this._workingVector.y;
                 }
-                else {
-                    return _this._defaultHeight;
-                }
+                //If VRDisplay does not inform stage parameters and no default height is set we fallback to zero.
+                return _this._defaultHeight || 0;
             };
             _this.useStandingMatrix = function (callback) {
                 if (callback === void 0) { callback = function (bool) { }; }
@@ -74209,7 +74446,7 @@ var BABYLON;
         /**
          * Creates a new device orientation camera. @see DeviceOrientationCamera
          * @param name The name of the camera
-         * @param position The starts position camera
+         * @param position The start position camera
          * @param scene The scene the camera belongs to
          */
         function DeviceOrientationCamera(name, position, scene) {

+ 320 - 83
dist/preview release/customConfigurations/minimalGLTFViewer/es6.js

@@ -1103,6 +1103,22 @@ var BABYLON;
             return this;
         };
         /**
+         * Clamps the rgb values by the min and max values and stores the result into "result".
+         * Returns the unmodified current Color3.
+         * @param min - minimum clamping value.  Defaults to 0
+         * @param max - maximum clamping value.  Defaults to 1
+         * @param result - color to store the result into.
+         * @returns - the original Color3
+         */
+        Color3.prototype.clampToRef = function (min, max, result) {
+            if (min === void 0) { min = 0; }
+            if (max === void 0) { max = 1; }
+            result.r = BABYLON.Scalar.Clamp(this.r, min, max);
+            result.g = BABYLON.Scalar.Clamp(this.g, min, max);
+            result.b = BABYLON.Scalar.Clamp(this.b, min, max);
+            return this;
+        };
+        /**
          * Returns a new Color3 set with the added values of the current Color3 and of the passed one.
          */
         Color3.prototype.add = function (otherColor) {
@@ -1351,6 +1367,23 @@ var BABYLON;
             return this;
         };
         /**
+         * Clamps the rgb values by the min and max values and stores the result into "result".
+         * Returns the unmodified current Color4.
+         * @param min - minimum clamping value.  Defaults to 0
+         * @param max - maximum clamping value.  Defaults to 1
+         * @param result - color to store the result into.
+         * @returns - the original Color4
+         */
+        Color4.prototype.clampToRef = function (min, max, result) {
+            if (min === void 0) { min = 0; }
+            if (max === void 0) { max = 1; }
+            result.r = BABYLON.Scalar.Clamp(this.r, min, max);
+            result.g = BABYLON.Scalar.Clamp(this.g, min, max);
+            result.b = BABYLON.Scalar.Clamp(this.b, min, max);
+            result.a = BABYLON.Scalar.Clamp(this.a, min, max);
+            return this;
+        };
+        /**
           * Multipy an RGBA Color4 value by another and return a new Color4 object
           * @param color The Color4 (RGBA) value to multiply by
           * @returns A new Color4.
@@ -2343,6 +2376,23 @@ var BABYLON;
             return s;
         };
         /**
+         * Get angle between two vectors.
+         * @param vector0 angle between vector0 and vector1
+         * @param vector1 angle between vector0 and vector1
+         * @param normal direction of the normal.
+         * @return the angle between vector0 and vector1.
+         */
+        Vector3.GetAngleBetweenVectors = function (vector0, vector1, normal) {
+            var v0 = vector0.clone().normalize();
+            var v1 = vector1.clone().normalize();
+            var dot = Vector3.Dot(v0, v1);
+            var n = Vector3.Cross(v0, v1);
+            if (Vector3.Dot(n, normal) > 0) {
+                return Math.acos(dot);
+            }
+            return -Math.acos(dot);
+        };
+        /**
          * Returns a new Vector3 set from the index "offset" of the passed array.
          */
         Vector3.FromArray = function (array, offset) {
@@ -17755,14 +17805,17 @@ var BABYLON;
         __extends(Camera, _super);
         function Camera(name, position, scene) {
             var _this = _super.call(this, name, scene) || this;
+            /**
+             * The vector the camera should consider as up.
+             * (default is Vector3(0, 1, 0) aka Vector3.Up())
+             */
             _this.upVector = BABYLON.Vector3.Up();
             _this.orthoLeft = null;
             _this.orthoRight = null;
             _this.orthoBottom = null;
             _this.orthoTop = null;
             /**
-             * default : 0.8
-             * FOV is set in Radians.
+             * FOV is set in Radians. (default is 0.8)
              */
             _this.fov = 0.8;
             _this.minZ = 1;
@@ -17772,14 +17825,13 @@ var BABYLON;
             _this.isIntermediate = false;
             _this.viewport = new BABYLON.Viewport(0, 0, 1.0, 1.0);
             /**
-            * Restricts the camera to viewing objects with the same layerMask.
-            * A camera with a layerMask of 1 will render meshes with no layerMask and meshes with a layerMask of 1.
-            */
+             * Restricts the camera to viewing objects with the same layerMask.
+             * A camera with a layerMask of 1 will render mesh.layerMask & camera.layerMask!== 0
+             */
             _this.layerMask = 0x0FFFFFFF;
             /**
-            * default : FOVMODE_VERTICAL_FIXED
-            * fovMode sets the camera frustum bounds to the viewport bounds.
-            */
+             * fovMode sets the camera frustum bounds to the viewport bounds. (default is FOVMODE_VERTICAL_FIXED)
+             */
             _this.fovMode = Camera.FOVMODE_VERTICAL_FIXED;
             // Camera rig members
             _this.cameraRigMode = Camera.RIG_MODE_NONE;
@@ -19974,6 +20026,24 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        Object.defineProperty(Scene.prototype, "geometryBufferRenderer", {
+            /**
+             * Gets the current geometry buffer associated to the scene.
+             */
+            get: function () {
+                return this._geometryBufferRenderer;
+            },
+            /**
+             * Sets the current geometry buffer for the scene.
+             */
+            set: function (geometryBufferRenderer) {
+                if (geometryBufferRenderer && geometryBufferRenderer.isSupported) {
+                    this._geometryBufferRenderer = geometryBufferRenderer;
+                }
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(Scene.prototype, "debugLayer", {
             // Properties
             get: function () {
@@ -39111,6 +39181,12 @@ var BABYLON;
             this.camera = camera;
             this.checkInputs = function () { };
         }
+        /**
+         * Add an input method to a camera.
+         * builtin inputs example: camera.inputs.addGamepad();
+         * custom inputs example: camera.inputs.add(new BABYLON.FreeCameraGamepadInput());
+         * @param input camera input method
+         */
         CameraInputsManager.prototype.add = function (input) {
             var type = input.getSimpleName();
             if (this.attached[type]) {
@@ -39128,6 +39204,11 @@ var BABYLON;
                 input.attachControl(this.attachedElement);
             }
         };
+        /**
+         * Remove a specific input method from a camera
+         * example: camera.inputs.remove(camera.inputs.attached.mouse);
+         * @param inputToRemove camera input method
+         */
         CameraInputsManager.prototype.remove = function (inputToRemove) {
             for (var cam in this.attached) {
                 var input = this.attached[cam];
@@ -39196,6 +39277,9 @@ var BABYLON;
                 }
             }
         };
+        /**
+         * Remove all attached input methods from a camera
+         */
         CameraInputsManager.prototype.clear = function () {
             if (this.attachedElement) {
                 this.detachElement(this.attachedElement, true);
@@ -39900,12 +39984,20 @@ var BABYLON;
         }
         Object.defineProperty(FreeCamera.prototype, "angularSensibility", {
             //-- begin properties for backward compatibility for inputs
+            /**
+             * Gets the input sensibility for a mouse input. (default is 2000.0)
+             * Higher values reduce sensitivity.
+             */
             get: function () {
                 var mouse = this.inputs.attached["mouse"];
                 if (mouse)
                     return mouse.angularSensibility;
                 return 0;
             },
+            /**
+             * Sets the input sensibility for a mouse input. (default is 2000.0)
+             * Higher values reduce sensitivity.
+             */
             set: function (value) {
                 var mouse = this.inputs.attached["mouse"];
                 if (mouse)
@@ -44468,6 +44560,24 @@ var BABYLON;
             return action;
         };
         /**
+         * Unregisters an action to this action manager
+         * @param action The action to be unregistered
+         * @return whether the action has been unregistered
+         */
+        ActionManager.prototype.unregisterAction = function (action) {
+            var index = this.actions.indexOf(action);
+            if (index !== -1) {
+                this.actions.splice(index, 1);
+                ActionManager.Triggers[action.trigger] -= 1;
+                if (ActionManager.Triggers[action.trigger] === 0) {
+                    delete ActionManager.Triggers[action.trigger];
+                }
+                delete action._actionManager;
+                return true;
+            }
+            return false;
+        };
+        /**
          * Process a specific trigger
          * @param {number} trigger - the trigger to process
          * @param evt {BABYLON.ActionEvent} the event details to be processed
@@ -53778,104 +53888,167 @@ var BABYLON;
 
 var BABYLON;
 (function (BABYLON) {
+    var getName = function (src) {
+        if (src instanceof HTMLVideoElement) {
+            return src.currentSrc;
+        }
+        if (typeof src === "object") {
+            return src.toString();
+        }
+        return src;
+    };
+    var getVideo = function (src) {
+        if (src instanceof HTMLVideoElement) {
+            return src;
+        }
+        var video = document.createElement("video");
+        if (typeof src === "string") {
+            video.src = src;
+        }
+        else {
+            src.forEach(function (url) {
+                var source = document.createElement("source");
+                source.src = url;
+                video.appendChild(source);
+            });
+        }
+        return video;
+    };
     var VideoTexture = /** @class */ (function (_super) {
         __extends(VideoTexture, _super);
         /**
          * Creates a video texture.
-         * Sample : https://doc.babylonjs.com/tutorials/01._Advanced_Texturing
-         * @param {Array} urlsOrVideo can be used to provide an array of urls or an already setup HTML video element.
+         * Sample : https://doc.babylonjs.com/how_to/video_texture
+         * @param {string | null} name optional name, will detect from video source, if not defined
+         * @param {(string | string[] | HTMLVideoElement)} src can be used to provide an url, array of urls or an already setup HTML video element.
          * @param {BABYLON.Scene} scene is obviously the current scene.
          * @param {boolean} generateMipMaps can be used to turn on mipmaps (Can be expensive for videoTextures because they are often updated).
          * @param {boolean} invertY is false by default but can be used to invert video on Y axis
          * @param {number} samplingMode controls the sampling method and is set to TRILINEAR_SAMPLINGMODE by default
+         * @param {VideoTextureSettings} [settings] allows finer control over video usage
          */
-        function VideoTexture(name, urlsOrVideo, scene, generateMipMaps, invertY, samplingMode) {
+        function VideoTexture(name, src, scene, generateMipMaps, invertY, samplingMode, settings) {
             if (generateMipMaps === void 0) { generateMipMaps = false; }
             if (invertY === void 0) { invertY = false; }
             if (samplingMode === void 0) { samplingMode = BABYLON.Texture.TRILINEAR_SAMPLINGMODE; }
+            if (settings === void 0) { settings = {
+                autoPlay: true,
+                loop: true,
+                autoUpdateTexture: true,
+            }; }
             var _this = _super.call(this, null, scene, !generateMipMaps, invertY) || this;
-            _this._autoLaunch = true;
-            var urls = null;
-            _this.name = name;
-            if (urlsOrVideo instanceof HTMLVideoElement) {
-                _this.video = urlsOrVideo;
-            }
-            else {
-                urls = urlsOrVideo;
-                _this.video = document.createElement("video");
-                _this.video.autoplay = false;
-                _this.video.loop = true;
-                BABYLON.Tools.SetCorsBehavior(urls, _this.video);
-            }
+            _this._createInternalTexture = function () {
+                if (_this._texture != null) {
+                    return;
+                }
+                if (!_this._engine.needPOTTextures ||
+                    (BABYLON.Tools.IsExponentOfTwo(_this.video.videoWidth) && BABYLON.Tools.IsExponentOfTwo(_this.video.videoHeight))) {
+                    _this.wrapU = BABYLON.Texture.WRAP_ADDRESSMODE;
+                    _this.wrapV = BABYLON.Texture.WRAP_ADDRESSMODE;
+                }
+                else {
+                    _this.wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE;
+                    _this.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;
+                    _this._generateMipMaps = false;
+                }
+                _this._texture = _this._engine.createDynamicTexture(_this.video.videoWidth, _this.video.videoHeight, _this._generateMipMaps, _this._samplingMode);
+                _this._texture.width;
+                _this._updateInternalTexture();
+                _this._texture.isReady = true;
+            };
+            _this.reset = function () {
+                if (_this._texture == null) {
+                    return;
+                }
+                _this._texture.dispose();
+                _this._texture = null;
+            };
+            _this._updateInternalTexture = function (e) {
+                if (_this._texture == null || !_this._texture.isReady) {
+                    return;
+                }
+                if (_this.video.readyState < _this.video.HAVE_CURRENT_DATA) {
+                    return;
+                }
+                _this._engine.updateVideoTexture(_this._texture, _this.video, _this._invertY);
+            };
             _this._engine = _this.getScene().getEngine();
             _this._generateMipMaps = generateMipMaps;
             _this._samplingMode = samplingMode;
-            if (!_this._engine.needPOTTextures || (BABYLON.Tools.IsExponentOfTwo(_this.video.videoWidth) && BABYLON.Tools.IsExponentOfTwo(_this.video.videoHeight))) {
-                _this.wrapU = BABYLON.Texture.WRAP_ADDRESSMODE;
-                _this.wrapV = BABYLON.Texture.WRAP_ADDRESSMODE;
-            }
-            else {
-                _this.wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE;
-                _this.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;
-                _this._generateMipMaps = false;
-            }
-            if (urls) {
-                _this.video.addEventListener("canplay", function () {
-                    if (_this._texture === undefined) {
-                        _this._createTexture();
-                    }
-                });
-                urls.forEach(function (url) {
-                    var source = document.createElement("source");
-                    source.src = url;
-                    _this.video.appendChild(source);
-                });
-            }
-            else {
-                _this._createTexture();
+            _this.autoUpdateTexture = settings.autoUpdateTexture;
+            _this.name = name || getName(src);
+            _this.video = getVideo(src);
+            if (settings.autoPlay !== undefined) {
+                _this.video.autoplay = settings.autoPlay;
+            }
+            if (settings.loop !== undefined) {
+                _this.video.loop = settings.loop;
+            }
+            _this.video.addEventListener("canplay", _this._createInternalTexture);
+            _this.video.addEventListener("paused", _this._updateInternalTexture);
+            _this.video.addEventListener("seeked", _this._updateInternalTexture);
+            _this.video.addEventListener("emptied", _this.reset);
+            if (_this.video.readyState >= _this.video.HAVE_CURRENT_DATA) {
+                _this._createInternalTexture();
             }
-            _this._lastUpdate = BABYLON.Tools.Now;
             return _this;
         }
-        VideoTexture.prototype.__setTextureReady = function () {
-            if (this._texture) {
-                this._texture.isReady = true;
-            }
-        };
-        VideoTexture.prototype._createTexture = function () {
-            this._texture = this._engine.createDynamicTexture(this.video.videoWidth, this.video.videoHeight, this._generateMipMaps, this._samplingMode);
-            if (this._autoLaunch) {
-                this._autoLaunch = false;
-                this.video.play();
-            }
-            this._setTextureReady = this.__setTextureReady.bind(this);
-            this.video.addEventListener("playing", this._setTextureReady);
-        };
+        /**
+         * Internal method to initiate `update`.
+         */
         VideoTexture.prototype._rebuild = function () {
             this.update();
         };
+        /**
+         * Update Texture in the `auto` mode. Does not do anything if `settings.autoUpdateTexture` is false.
+         */
         VideoTexture.prototype.update = function () {
-            var now = BABYLON.Tools.Now;
-            if (now - this._lastUpdate < 15 || this.video.readyState !== this.video.HAVE_ENOUGH_DATA) {
-                return false;
+            if (!this.autoUpdateTexture) {
+                // Expecting user to call `updateTexture` manually
+                return;
             }
-            this._lastUpdate = now;
-            this._engine.updateVideoTexture(this._texture, this.video, this._invertY);
-            return true;
+            this.updateTexture(true);
+        };
+        /**
+         * Update Texture in `manual` mode. Does not do anything if not visible or paused.
+         * @param isVisible Visibility state, detected by user using `scene.getActiveMeshes()` or othervise.
+         */
+        VideoTexture.prototype.updateTexture = function (isVisible) {
+            if (!isVisible) {
+                return;
+            }
+            if (this.video.paused) {
+                return;
+            }
+            this._updateInternalTexture();
+        };
+        /**
+         * Change video content. Changing video instance or setting multiple urls (as in constructor) is not supported.
+         * @param url New url.
+         */
+        VideoTexture.prototype.updateURL = function (url) {
+            this.video.src = url;
         };
         VideoTexture.prototype.dispose = function () {
             _super.prototype.dispose.call(this);
-            this.video.removeEventListener("playing", this._setTextureReady);
+            this.video.removeEventListener("canplay", this._createInternalTexture);
+            this.video.removeEventListener("paused", this._updateInternalTexture);
+            this.video.removeEventListener("seeked", this._updateInternalTexture);
+            this.video.removeEventListener("emptied", this.reset);
         };
         VideoTexture.CreateFromWebCam = function (scene, onReady, constraints) {
             var video = document.createElement("video");
             var constraintsDeviceId;
             if (constraints && constraints.deviceId) {
                 constraintsDeviceId = {
-                    exact: constraints.deviceId
+                    exact: constraints.deviceId,
                 };
             }
-            navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
+            navigator.getUserMedia =
+                navigator.getUserMedia ||
+                    navigator.webkitGetUserMedia ||
+                    navigator.mozGetUserMedia ||
+                    navigator.msGetUserMedia;
             window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL;
             if (navigator.getUserMedia) {
                 navigator.getUserMedia({
@@ -53883,15 +54056,16 @@ var BABYLON;
                         deviceId: constraintsDeviceId,
                         width: {
                             min: (constraints && constraints.minWidth) || 256,
-                            max: (constraints && constraints.maxWidth) || 640
+                            max: (constraints && constraints.maxWidth) || 640,
                         },
                         height: {
                             min: (constraints && constraints.minHeight) || 256,
-                            max: (constraints && constraints.maxHeight) || 480
-                        }
-                    }
+                            max: (constraints && constraints.maxHeight) || 480,
+                        },
+                    },
                 }, function (stream) {
                     if (video.mozSrcObject !== undefined) {
+                        // hack for Firefox < 19
                         video.mozSrcObject = stream;
                     }
                     else {
@@ -62997,7 +63171,15 @@ var BABYLON;
 
 var BABYLON;
 (function (BABYLON) {
+    /**
+     * This renderer is helpfull to fill one of the render target with a geometry buffer.
+     */
     var GeometryBufferRenderer = /** @class */ (function () {
+        /**
+         * Creates a new G Buffer for the scene. @see GeometryBufferRenderer
+         * @param scene The scene the buffer belongs to
+         * @param ratio How big is the buffer related to the main canvas.
+         */
         function GeometryBufferRenderer(scene, ratio) {
             if (ratio === void 0) { ratio = 1; }
             this._enablePosition = false;
@@ -63007,6 +63189,9 @@ var BABYLON;
             this._createRenderTargets();
         }
         Object.defineProperty(GeometryBufferRenderer.prototype, "renderList", {
+            /**
+             * Set the render list (meshes to be rendered) used in the G buffer.
+             */
             set: function (meshes) {
                 this._multiRenderTarget.renderList = meshes;
             },
@@ -63014,6 +63199,10 @@ var BABYLON;
             configurable: true
         });
         Object.defineProperty(GeometryBufferRenderer.prototype, "isSupported", {
+            /**
+             * Gets wether or not G buffer are supported by the running hardware.
+             * This requires draw buffer supports
+             */
             get: function () {
                 return this._multiRenderTarget.isSupported;
             },
@@ -63021,9 +63210,15 @@ var BABYLON;
             configurable: true
         });
         Object.defineProperty(GeometryBufferRenderer.prototype, "enablePosition", {
+            /**
+             * Gets wether or not position are enabled for the G buffer.
+             */
             get: function () {
                 return this._enablePosition;
             },
+            /**
+             * Sets wether or not position are enabled for the G buffer.
+             */
             set: function (enable) {
                 this._enablePosition = enable;
                 this.dispose();
@@ -63032,6 +63227,33 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        Object.defineProperty(GeometryBufferRenderer.prototype, "scene", {
+            /**
+             * Gets the scene associated with the buffer.
+             */
+            get: function () {
+                return this._scene;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(GeometryBufferRenderer.prototype, "ratio", {
+            /**
+             * Gets the ratio used by the buffer during its creation.
+             * How big is the buffer related to the main canvas.
+             */
+            get: function () {
+                return this._ratio;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        /**
+         * Checks wether everything is ready to render a submesh to the G buffer.
+         * @param subMesh the submesh to check readiness for
+         * @param useInstances is the mesh drawn using instance or not
+         * @returns true if ready otherwise false
+         */
         GeometryBufferRenderer.prototype.isReady = function (subMesh, useInstances) {
             var material = subMesh.getMaterial();
             if (material && material.disableDepthWrite) {
@@ -63086,20 +63308,32 @@ var BABYLON;
             }
             return this._effect.isReady();
         };
+        /**
+         * Gets the current underlying G Buffer.
+         * @returns the buffer
+         */
         GeometryBufferRenderer.prototype.getGBuffer = function () {
             return this._multiRenderTarget;
         };
         Object.defineProperty(GeometryBufferRenderer.prototype, "samples", {
+            /**
+             * Gets the number of samples used to render the buffer (anti aliasing).
+             */
             get: function () {
                 return this._multiRenderTarget.samples;
             },
+            /**
+             * Sets the number of samples used to render the buffer (anti aliasing).
+             */
             set: function (value) {
                 this._multiRenderTarget.samples = value;
             },
             enumerable: true,
             configurable: true
         });
-        // Methods
+        /**
+         * Disposes the renderer and frees up associated resources.
+         */
         GeometryBufferRenderer.prototype.dispose = function () {
             this.getGBuffer().dispose();
         };
@@ -72927,7 +73161,7 @@ var BABYLON;
             engine.setDepthFunctionToLess();
             this._scene.resetCachedMaterial();
             this._colorShader.bind(worldMatrix);
-            engine.drawElementsType(BABYLON.Material.TriangleFillMode, 0, 24);
+            engine.drawElementsType(BABYLON.Material.LineListDrawMode, 0, 24);
             this._colorShader.unbind();
             engine.setDepthFunctionToLessOrEqual();
             engine.setDepthWrite(true);
@@ -73548,6 +73782,10 @@ var BABYLON;
 
 var BABYLON;
 (function (BABYLON) {
+    /**
+     * Takes information about the orientation of the device as reported by the deviceorientation event to orient the camera.
+     * Screen rotation is taken into account.
+     */
     var FreeCameraDeviceOrientationInput = /** @class */ (function () {
         function FreeCameraDeviceOrientationInput() {
             var _this = this;
@@ -73774,16 +74012,15 @@ var BABYLON;
             _this.onControllersAttachedObservable = new BABYLON.Observable();
             _this.onControllerMeshLoadedObservable = new BABYLON.Observable();
             _this.rigParenting = true; // should the rig cameras be used as parent instead of this camera.
-            _this._defaultHeight = 0;
+            _this._defaultHeight = undefined;
             _this.deviceDistanceToRoomGround = function () {
-                if (_this._standingMatrix) {
+                if (_this._standingMatrix && _this._defaultHeight === undefined) {
                     // Add standing matrix offset to get real offset from ground in room
                     _this._standingMatrix.getTranslationToRef(_this._workingVector);
                     return _this._deviceRoomPosition.y + _this._workingVector.y;
                 }
-                else {
-                    return _this._defaultHeight;
-                }
+                //If VRDisplay does not inform stage parameters and no default height is set we fallback to zero.
+                return _this._defaultHeight || 0;
             };
             _this.useStandingMatrix = function (callback) {
                 if (callback === void 0) { callback = function (bool) { }; }
@@ -74195,7 +74432,7 @@ var BABYLON;
         /**
          * Creates a new device orientation camera. @see DeviceOrientationCamera
          * @param name The name of the camera
-         * @param position The starts position camera
+         * @param position The start position camera
          * @param scene The scene the camera belongs to
          */
         function DeviceOrientationCamera(name, position, scene) {

+ 320 - 83
dist/preview release/es6.js

@@ -1103,6 +1103,22 @@ var BABYLON;
             return this;
         };
         /**
+         * Clamps the rgb values by the min and max values and stores the result into "result".
+         * Returns the unmodified current Color3.
+         * @param min - minimum clamping value.  Defaults to 0
+         * @param max - maximum clamping value.  Defaults to 1
+         * @param result - color to store the result into.
+         * @returns - the original Color3
+         */
+        Color3.prototype.clampToRef = function (min, max, result) {
+            if (min === void 0) { min = 0; }
+            if (max === void 0) { max = 1; }
+            result.r = BABYLON.Scalar.Clamp(this.r, min, max);
+            result.g = BABYLON.Scalar.Clamp(this.g, min, max);
+            result.b = BABYLON.Scalar.Clamp(this.b, min, max);
+            return this;
+        };
+        /**
          * Returns a new Color3 set with the added values of the current Color3 and of the passed one.
          */
         Color3.prototype.add = function (otherColor) {
@@ -1351,6 +1367,23 @@ var BABYLON;
             return this;
         };
         /**
+         * Clamps the rgb values by the min and max values and stores the result into "result".
+         * Returns the unmodified current Color4.
+         * @param min - minimum clamping value.  Defaults to 0
+         * @param max - maximum clamping value.  Defaults to 1
+         * @param result - color to store the result into.
+         * @returns - the original Color4
+         */
+        Color4.prototype.clampToRef = function (min, max, result) {
+            if (min === void 0) { min = 0; }
+            if (max === void 0) { max = 1; }
+            result.r = BABYLON.Scalar.Clamp(this.r, min, max);
+            result.g = BABYLON.Scalar.Clamp(this.g, min, max);
+            result.b = BABYLON.Scalar.Clamp(this.b, min, max);
+            result.a = BABYLON.Scalar.Clamp(this.a, min, max);
+            return this;
+        };
+        /**
           * Multipy an RGBA Color4 value by another and return a new Color4 object
           * @param color The Color4 (RGBA) value to multiply by
           * @returns A new Color4.
@@ -2343,6 +2376,23 @@ var BABYLON;
             return s;
         };
         /**
+         * Get angle between two vectors.
+         * @param vector0 angle between vector0 and vector1
+         * @param vector1 angle between vector0 and vector1
+         * @param normal direction of the normal.
+         * @return the angle between vector0 and vector1.
+         */
+        Vector3.GetAngleBetweenVectors = function (vector0, vector1, normal) {
+            var v0 = vector0.clone().normalize();
+            var v1 = vector1.clone().normalize();
+            var dot = Vector3.Dot(v0, v1);
+            var n = Vector3.Cross(v0, v1);
+            if (Vector3.Dot(n, normal) > 0) {
+                return Math.acos(dot);
+            }
+            return -Math.acos(dot);
+        };
+        /**
          * Returns a new Vector3 set from the index "offset" of the passed array.
          */
         Vector3.FromArray = function (array, offset) {
@@ -17755,14 +17805,17 @@ var BABYLON;
         __extends(Camera, _super);
         function Camera(name, position, scene) {
             var _this = _super.call(this, name, scene) || this;
+            /**
+             * The vector the camera should consider as up.
+             * (default is Vector3(0, 1, 0) aka Vector3.Up())
+             */
             _this.upVector = BABYLON.Vector3.Up();
             _this.orthoLeft = null;
             _this.orthoRight = null;
             _this.orthoBottom = null;
             _this.orthoTop = null;
             /**
-             * default : 0.8
-             * FOV is set in Radians.
+             * FOV is set in Radians. (default is 0.8)
              */
             _this.fov = 0.8;
             _this.minZ = 1;
@@ -17772,14 +17825,13 @@ var BABYLON;
             _this.isIntermediate = false;
             _this.viewport = new BABYLON.Viewport(0, 0, 1.0, 1.0);
             /**
-            * Restricts the camera to viewing objects with the same layerMask.
-            * A camera with a layerMask of 1 will render meshes with no layerMask and meshes with a layerMask of 1.
-            */
+             * Restricts the camera to viewing objects with the same layerMask.
+             * A camera with a layerMask of 1 will render mesh.layerMask & camera.layerMask!== 0
+             */
             _this.layerMask = 0x0FFFFFFF;
             /**
-            * default : FOVMODE_VERTICAL_FIXED
-            * fovMode sets the camera frustum bounds to the viewport bounds.
-            */
+             * fovMode sets the camera frustum bounds to the viewport bounds. (default is FOVMODE_VERTICAL_FIXED)
+             */
             _this.fovMode = Camera.FOVMODE_VERTICAL_FIXED;
             // Camera rig members
             _this.cameraRigMode = Camera.RIG_MODE_NONE;
@@ -19974,6 +20026,24 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        Object.defineProperty(Scene.prototype, "geometryBufferRenderer", {
+            /**
+             * Gets the current geometry buffer associated to the scene.
+             */
+            get: function () {
+                return this._geometryBufferRenderer;
+            },
+            /**
+             * Sets the current geometry buffer for the scene.
+             */
+            set: function (geometryBufferRenderer) {
+                if (geometryBufferRenderer && geometryBufferRenderer.isSupported) {
+                    this._geometryBufferRenderer = geometryBufferRenderer;
+                }
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(Scene.prototype, "debugLayer", {
             // Properties
             get: function () {
@@ -39111,6 +39181,12 @@ var BABYLON;
             this.camera = camera;
             this.checkInputs = function () { };
         }
+        /**
+         * Add an input method to a camera.
+         * builtin inputs example: camera.inputs.addGamepad();
+         * custom inputs example: camera.inputs.add(new BABYLON.FreeCameraGamepadInput());
+         * @param input camera input method
+         */
         CameraInputsManager.prototype.add = function (input) {
             var type = input.getSimpleName();
             if (this.attached[type]) {
@@ -39128,6 +39204,11 @@ var BABYLON;
                 input.attachControl(this.attachedElement);
             }
         };
+        /**
+         * Remove a specific input method from a camera
+         * example: camera.inputs.remove(camera.inputs.attached.mouse);
+         * @param inputToRemove camera input method
+         */
         CameraInputsManager.prototype.remove = function (inputToRemove) {
             for (var cam in this.attached) {
                 var input = this.attached[cam];
@@ -39196,6 +39277,9 @@ var BABYLON;
                 }
             }
         };
+        /**
+         * Remove all attached input methods from a camera
+         */
         CameraInputsManager.prototype.clear = function () {
             if (this.attachedElement) {
                 this.detachElement(this.attachedElement, true);
@@ -39900,12 +39984,20 @@ var BABYLON;
         }
         Object.defineProperty(FreeCamera.prototype, "angularSensibility", {
             //-- begin properties for backward compatibility for inputs
+            /**
+             * Gets the input sensibility for a mouse input. (default is 2000.0)
+             * Higher values reduce sensitivity.
+             */
             get: function () {
                 var mouse = this.inputs.attached["mouse"];
                 if (mouse)
                     return mouse.angularSensibility;
                 return 0;
             },
+            /**
+             * Sets the input sensibility for a mouse input. (default is 2000.0)
+             * Higher values reduce sensitivity.
+             */
             set: function (value) {
                 var mouse = this.inputs.attached["mouse"];
                 if (mouse)
@@ -44468,6 +44560,24 @@ var BABYLON;
             return action;
         };
         /**
+         * Unregisters an action to this action manager
+         * @param action The action to be unregistered
+         * @return whether the action has been unregistered
+         */
+        ActionManager.prototype.unregisterAction = function (action) {
+            var index = this.actions.indexOf(action);
+            if (index !== -1) {
+                this.actions.splice(index, 1);
+                ActionManager.Triggers[action.trigger] -= 1;
+                if (ActionManager.Triggers[action.trigger] === 0) {
+                    delete ActionManager.Triggers[action.trigger];
+                }
+                delete action._actionManager;
+                return true;
+            }
+            return false;
+        };
+        /**
          * Process a specific trigger
          * @param {number} trigger - the trigger to process
          * @param evt {BABYLON.ActionEvent} the event details to be processed
@@ -53984,104 +54094,167 @@ var BABYLON;
 
 var BABYLON;
 (function (BABYLON) {
+    var getName = function (src) {
+        if (src instanceof HTMLVideoElement) {
+            return src.currentSrc;
+        }
+        if (typeof src === "object") {
+            return src.toString();
+        }
+        return src;
+    };
+    var getVideo = function (src) {
+        if (src instanceof HTMLVideoElement) {
+            return src;
+        }
+        var video = document.createElement("video");
+        if (typeof src === "string") {
+            video.src = src;
+        }
+        else {
+            src.forEach(function (url) {
+                var source = document.createElement("source");
+                source.src = url;
+                video.appendChild(source);
+            });
+        }
+        return video;
+    };
     var VideoTexture = /** @class */ (function (_super) {
         __extends(VideoTexture, _super);
         /**
          * Creates a video texture.
-         * Sample : https://doc.babylonjs.com/tutorials/01._Advanced_Texturing
-         * @param {Array} urlsOrVideo can be used to provide an array of urls or an already setup HTML video element.
+         * Sample : https://doc.babylonjs.com/how_to/video_texture
+         * @param {string | null} name optional name, will detect from video source, if not defined
+         * @param {(string | string[] | HTMLVideoElement)} src can be used to provide an url, array of urls or an already setup HTML video element.
          * @param {BABYLON.Scene} scene is obviously the current scene.
          * @param {boolean} generateMipMaps can be used to turn on mipmaps (Can be expensive for videoTextures because they are often updated).
          * @param {boolean} invertY is false by default but can be used to invert video on Y axis
          * @param {number} samplingMode controls the sampling method and is set to TRILINEAR_SAMPLINGMODE by default
+         * @param {VideoTextureSettings} [settings] allows finer control over video usage
          */
-        function VideoTexture(name, urlsOrVideo, scene, generateMipMaps, invertY, samplingMode) {
+        function VideoTexture(name, src, scene, generateMipMaps, invertY, samplingMode, settings) {
             if (generateMipMaps === void 0) { generateMipMaps = false; }
             if (invertY === void 0) { invertY = false; }
             if (samplingMode === void 0) { samplingMode = BABYLON.Texture.TRILINEAR_SAMPLINGMODE; }
+            if (settings === void 0) { settings = {
+                autoPlay: true,
+                loop: true,
+                autoUpdateTexture: true,
+            }; }
             var _this = _super.call(this, null, scene, !generateMipMaps, invertY) || this;
-            _this._autoLaunch = true;
-            var urls = null;
-            _this.name = name;
-            if (urlsOrVideo instanceof HTMLVideoElement) {
-                _this.video = urlsOrVideo;
-            }
-            else {
-                urls = urlsOrVideo;
-                _this.video = document.createElement("video");
-                _this.video.autoplay = false;
-                _this.video.loop = true;
-                BABYLON.Tools.SetCorsBehavior(urls, _this.video);
-            }
+            _this._createInternalTexture = function () {
+                if (_this._texture != null) {
+                    return;
+                }
+                if (!_this._engine.needPOTTextures ||
+                    (BABYLON.Tools.IsExponentOfTwo(_this.video.videoWidth) && BABYLON.Tools.IsExponentOfTwo(_this.video.videoHeight))) {
+                    _this.wrapU = BABYLON.Texture.WRAP_ADDRESSMODE;
+                    _this.wrapV = BABYLON.Texture.WRAP_ADDRESSMODE;
+                }
+                else {
+                    _this.wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE;
+                    _this.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;
+                    _this._generateMipMaps = false;
+                }
+                _this._texture = _this._engine.createDynamicTexture(_this.video.videoWidth, _this.video.videoHeight, _this._generateMipMaps, _this._samplingMode);
+                _this._texture.width;
+                _this._updateInternalTexture();
+                _this._texture.isReady = true;
+            };
+            _this.reset = function () {
+                if (_this._texture == null) {
+                    return;
+                }
+                _this._texture.dispose();
+                _this._texture = null;
+            };
+            _this._updateInternalTexture = function (e) {
+                if (_this._texture == null || !_this._texture.isReady) {
+                    return;
+                }
+                if (_this.video.readyState < _this.video.HAVE_CURRENT_DATA) {
+                    return;
+                }
+                _this._engine.updateVideoTexture(_this._texture, _this.video, _this._invertY);
+            };
             _this._engine = _this.getScene().getEngine();
             _this._generateMipMaps = generateMipMaps;
             _this._samplingMode = samplingMode;
-            if (!_this._engine.needPOTTextures || (BABYLON.Tools.IsExponentOfTwo(_this.video.videoWidth) && BABYLON.Tools.IsExponentOfTwo(_this.video.videoHeight))) {
-                _this.wrapU = BABYLON.Texture.WRAP_ADDRESSMODE;
-                _this.wrapV = BABYLON.Texture.WRAP_ADDRESSMODE;
-            }
-            else {
-                _this.wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE;
-                _this.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;
-                _this._generateMipMaps = false;
-            }
-            if (urls) {
-                _this.video.addEventListener("canplay", function () {
-                    if (_this._texture === undefined) {
-                        _this._createTexture();
-                    }
-                });
-                urls.forEach(function (url) {
-                    var source = document.createElement("source");
-                    source.src = url;
-                    _this.video.appendChild(source);
-                });
+            _this.autoUpdateTexture = settings.autoUpdateTexture;
+            _this.name = name || getName(src);
+            _this.video = getVideo(src);
+            if (settings.autoPlay !== undefined) {
+                _this.video.autoplay = settings.autoPlay;
+            }
+            if (settings.loop !== undefined) {
+                _this.video.loop = settings.loop;
+            }
+            _this.video.addEventListener("canplay", _this._createInternalTexture);
+            _this.video.addEventListener("paused", _this._updateInternalTexture);
+            _this.video.addEventListener("seeked", _this._updateInternalTexture);
+            _this.video.addEventListener("emptied", _this.reset);
+            if (_this.video.readyState >= _this.video.HAVE_CURRENT_DATA) {
+                _this._createInternalTexture();
             }
-            else {
-                _this._createTexture();
-            }
-            _this._lastUpdate = BABYLON.Tools.Now;
             return _this;
         }
-        VideoTexture.prototype.__setTextureReady = function () {
-            if (this._texture) {
-                this._texture.isReady = true;
-            }
-        };
-        VideoTexture.prototype._createTexture = function () {
-            this._texture = this._engine.createDynamicTexture(this.video.videoWidth, this.video.videoHeight, this._generateMipMaps, this._samplingMode);
-            if (this._autoLaunch) {
-                this._autoLaunch = false;
-                this.video.play();
-            }
-            this._setTextureReady = this.__setTextureReady.bind(this);
-            this.video.addEventListener("playing", this._setTextureReady);
-        };
+        /**
+         * Internal method to initiate `update`.
+         */
         VideoTexture.prototype._rebuild = function () {
             this.update();
         };
+        /**
+         * Update Texture in the `auto` mode. Does not do anything if `settings.autoUpdateTexture` is false.
+         */
         VideoTexture.prototype.update = function () {
-            var now = BABYLON.Tools.Now;
-            if (now - this._lastUpdate < 15 || this.video.readyState !== this.video.HAVE_ENOUGH_DATA) {
-                return false;
+            if (!this.autoUpdateTexture) {
+                // Expecting user to call `updateTexture` manually
+                return;
             }
-            this._lastUpdate = now;
-            this._engine.updateVideoTexture(this._texture, this.video, this._invertY);
-            return true;
+            this.updateTexture(true);
+        };
+        /**
+         * Update Texture in `manual` mode. Does not do anything if not visible or paused.
+         * @param isVisible Visibility state, detected by user using `scene.getActiveMeshes()` or othervise.
+         */
+        VideoTexture.prototype.updateTexture = function (isVisible) {
+            if (!isVisible) {
+                return;
+            }
+            if (this.video.paused) {
+                return;
+            }
+            this._updateInternalTexture();
+        };
+        /**
+         * Change video content. Changing video instance or setting multiple urls (as in constructor) is not supported.
+         * @param url New url.
+         */
+        VideoTexture.prototype.updateURL = function (url) {
+            this.video.src = url;
         };
         VideoTexture.prototype.dispose = function () {
             _super.prototype.dispose.call(this);
-            this.video.removeEventListener("playing", this._setTextureReady);
+            this.video.removeEventListener("canplay", this._createInternalTexture);
+            this.video.removeEventListener("paused", this._updateInternalTexture);
+            this.video.removeEventListener("seeked", this._updateInternalTexture);
+            this.video.removeEventListener("emptied", this.reset);
         };
         VideoTexture.CreateFromWebCam = function (scene, onReady, constraints) {
             var video = document.createElement("video");
             var constraintsDeviceId;
             if (constraints && constraints.deviceId) {
                 constraintsDeviceId = {
-                    exact: constraints.deviceId
+                    exact: constraints.deviceId,
                 };
             }
-            navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
+            navigator.getUserMedia =
+                navigator.getUserMedia ||
+                    navigator.webkitGetUserMedia ||
+                    navigator.mozGetUserMedia ||
+                    navigator.msGetUserMedia;
             window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL;
             if (navigator.getUserMedia) {
                 navigator.getUserMedia({
@@ -54089,15 +54262,16 @@ var BABYLON;
                         deviceId: constraintsDeviceId,
                         width: {
                             min: (constraints && constraints.minWidth) || 256,
-                            max: (constraints && constraints.maxWidth) || 640
+                            max: (constraints && constraints.maxWidth) || 640,
                         },
                         height: {
                             min: (constraints && constraints.minHeight) || 256,
-                            max: (constraints && constraints.maxHeight) || 480
-                        }
-                    }
+                            max: (constraints && constraints.maxHeight) || 480,
+                        },
+                    },
                 }, function (stream) {
                     if (video.mozSrcObject !== undefined) {
+                        // hack for Firefox < 19
                         video.mozSrcObject = stream;
                     }
                     else {
@@ -63203,7 +63377,15 @@ var BABYLON;
 
 var BABYLON;
 (function (BABYLON) {
+    /**
+     * This renderer is helpfull to fill one of the render target with a geometry buffer.
+     */
     var GeometryBufferRenderer = /** @class */ (function () {
+        /**
+         * Creates a new G Buffer for the scene. @see GeometryBufferRenderer
+         * @param scene The scene the buffer belongs to
+         * @param ratio How big is the buffer related to the main canvas.
+         */
         function GeometryBufferRenderer(scene, ratio) {
             if (ratio === void 0) { ratio = 1; }
             this._enablePosition = false;
@@ -63213,6 +63395,9 @@ var BABYLON;
             this._createRenderTargets();
         }
         Object.defineProperty(GeometryBufferRenderer.prototype, "renderList", {
+            /**
+             * Set the render list (meshes to be rendered) used in the G buffer.
+             */
             set: function (meshes) {
                 this._multiRenderTarget.renderList = meshes;
             },
@@ -63220,6 +63405,10 @@ var BABYLON;
             configurable: true
         });
         Object.defineProperty(GeometryBufferRenderer.prototype, "isSupported", {
+            /**
+             * Gets wether or not G buffer are supported by the running hardware.
+             * This requires draw buffer supports
+             */
             get: function () {
                 return this._multiRenderTarget.isSupported;
             },
@@ -63227,9 +63416,15 @@ var BABYLON;
             configurable: true
         });
         Object.defineProperty(GeometryBufferRenderer.prototype, "enablePosition", {
+            /**
+             * Gets wether or not position are enabled for the G buffer.
+             */
             get: function () {
                 return this._enablePosition;
             },
+            /**
+             * Sets wether or not position are enabled for the G buffer.
+             */
             set: function (enable) {
                 this._enablePosition = enable;
                 this.dispose();
@@ -63238,6 +63433,33 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        Object.defineProperty(GeometryBufferRenderer.prototype, "scene", {
+            /**
+             * Gets the scene associated with the buffer.
+             */
+            get: function () {
+                return this._scene;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(GeometryBufferRenderer.prototype, "ratio", {
+            /**
+             * Gets the ratio used by the buffer during its creation.
+             * How big is the buffer related to the main canvas.
+             */
+            get: function () {
+                return this._ratio;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        /**
+         * Checks wether everything is ready to render a submesh to the G buffer.
+         * @param subMesh the submesh to check readiness for
+         * @param useInstances is the mesh drawn using instance or not
+         * @returns true if ready otherwise false
+         */
         GeometryBufferRenderer.prototype.isReady = function (subMesh, useInstances) {
             var material = subMesh.getMaterial();
             if (material && material.disableDepthWrite) {
@@ -63292,20 +63514,32 @@ var BABYLON;
             }
             return this._effect.isReady();
         };
+        /**
+         * Gets the current underlying G Buffer.
+         * @returns the buffer
+         */
         GeometryBufferRenderer.prototype.getGBuffer = function () {
             return this._multiRenderTarget;
         };
         Object.defineProperty(GeometryBufferRenderer.prototype, "samples", {
+            /**
+             * Gets the number of samples used to render the buffer (anti aliasing).
+             */
             get: function () {
                 return this._multiRenderTarget.samples;
             },
+            /**
+             * Sets the number of samples used to render the buffer (anti aliasing).
+             */
             set: function (value) {
                 this._multiRenderTarget.samples = value;
             },
             enumerable: true,
             configurable: true
         });
-        // Methods
+        /**
+         * Disposes the renderer and frees up associated resources.
+         */
         GeometryBufferRenderer.prototype.dispose = function () {
             this.getGBuffer().dispose();
         };
@@ -73133,7 +73367,7 @@ var BABYLON;
             engine.setDepthFunctionToLess();
             this._scene.resetCachedMaterial();
             this._colorShader.bind(worldMatrix);
-            engine.drawElementsType(BABYLON.Material.TriangleFillMode, 0, 24);
+            engine.drawElementsType(BABYLON.Material.LineListDrawMode, 0, 24);
             this._colorShader.unbind();
             engine.setDepthFunctionToLessOrEqual();
             engine.setDepthWrite(true);
@@ -73754,6 +73988,10 @@ var BABYLON;
 
 var BABYLON;
 (function (BABYLON) {
+    /**
+     * Takes information about the orientation of the device as reported by the deviceorientation event to orient the camera.
+     * Screen rotation is taken into account.
+     */
     var FreeCameraDeviceOrientationInput = /** @class */ (function () {
         function FreeCameraDeviceOrientationInput() {
             var _this = this;
@@ -73980,16 +74218,15 @@ var BABYLON;
             _this.onControllersAttachedObservable = new BABYLON.Observable();
             _this.onControllerMeshLoadedObservable = new BABYLON.Observable();
             _this.rigParenting = true; // should the rig cameras be used as parent instead of this camera.
-            _this._defaultHeight = 0;
+            _this._defaultHeight = undefined;
             _this.deviceDistanceToRoomGround = function () {
-                if (_this._standingMatrix) {
+                if (_this._standingMatrix && _this._defaultHeight === undefined) {
                     // Add standing matrix offset to get real offset from ground in room
                     _this._standingMatrix.getTranslationToRef(_this._workingVector);
                     return _this._deviceRoomPosition.y + _this._workingVector.y;
                 }
-                else {
-                    return _this._defaultHeight;
-                }
+                //If VRDisplay does not inform stage parameters and no default height is set we fallback to zero.
+                return _this._defaultHeight || 0;
             };
             _this.useStandingMatrix = function (callback) {
                 if (callback === void 0) { callback = function (bool) { }; }
@@ -74401,7 +74638,7 @@ var BABYLON;
         /**
          * Creates a new device orientation camera. @see DeviceOrientationCamera
          * @param name The name of the camera
-         * @param position The starts position camera
+         * @param position The start position camera
          * @param scene The scene the camera belongs to
          */
         function DeviceOrientationCamera(name, position, scene) {

+ 11 - 0
dist/preview release/gui/babylon.gui.d.ts

@@ -56,6 +56,17 @@ declare module BABYLON.GUI {
         private _manageFocus();
         private _attachToOnPointerOut(scene);
         static CreateForMesh(mesh: AbstractMesh, width?: number, height?: number, supportPointerMove?: boolean): AdvancedDynamicTexture;
+        /**
+         * FullScreenUI is created in a layer. This allows it to be treated like any other layer.
+         * As such, if you have a multi camera setup, you can set the layerMask on the GUI as well.
+         * When the GUI is not Created as FullscreenUI it does not respect the layerMask.
+         * layerMask is set through advancedTexture.layer.layerMask
+         * @param name name for the Texture
+         * @param foreground render in foreground (default is true)
+         * @param scene scene to be rendered in
+         * @param sampling method for scaling to fit screen
+         * @returns AdvancedDynamicTexture
+         */
         static CreateFullscreenUI(name: string, foreground?: boolean, scene?: Nullable<Scene>, sampling?: number): AdvancedDynamicTexture;
     }
 }

+ 11 - 0
dist/preview release/gui/babylon.gui.js

@@ -476,6 +476,17 @@ var BABYLON;
                 result.attachToMesh(mesh, supportPointerMove);
                 return result;
             };
+            /**
+             * FullScreenUI is created in a layer. This allows it to be treated like any other layer.
+             * As such, if you have a multi camera setup, you can set the layerMask on the GUI as well.
+             * When the GUI is not Created as FullscreenUI it does not respect the layerMask.
+             * layerMask is set through advancedTexture.layer.layerMask
+             * @param name name for the Texture
+             * @param foreground render in foreground (default is true)
+             * @param scene scene to be rendered in
+             * @param sampling method for scaling to fit screen
+             * @returns AdvancedDynamicTexture
+             */
             AdvancedDynamicTexture.CreateFullscreenUI = function (name, foreground, scene, sampling) {
                 if (foreground === void 0) { foreground = true; }
                 if (scene === void 0) { scene = null; }

+ 11 - 0
dist/preview release/gui/babylon.gui.module.d.ts

@@ -62,6 +62,17 @@ declare module BABYLON.GUI {
         private _manageFocus();
         private _attachToOnPointerOut(scene);
         static CreateForMesh(mesh: AbstractMesh, width?: number, height?: number, supportPointerMove?: boolean): AdvancedDynamicTexture;
+        /**
+         * FullScreenUI is created in a layer. This allows it to be treated like any other layer.
+         * As such, if you have a multi camera setup, you can set the layerMask on the GUI as well.
+         * When the GUI is not Created as FullscreenUI it does not respect the layerMask.
+         * layerMask is set through advancedTexture.layer.layerMask
+         * @param name name for the Texture
+         * @param foreground render in foreground (default is true)
+         * @param scene scene to be rendered in
+         * @param sampling method for scaling to fit screen
+         * @returns AdvancedDynamicTexture
+         */
         static CreateFullscreenUI(name: string, foreground?: boolean, scene?: Nullable<Scene>, sampling?: number): AdvancedDynamicTexture;
     }
 }

+ 111 - 31
dist/preview release/serializers/babylon.glTF2Serializer.d.ts

@@ -1,28 +1,65 @@
 
 declare module BABYLON {
+    interface IGLTFExporterOptions {
+        /**
+         * Interface function which indicates whether a babylon mesh should be exported or not.
+         * @param mesh
+         * @returns boolean, which indicates whether the mesh should be exported (true) or not (false)
+         */
+        shouldExportMesh?(mesh: AbstractMesh): boolean;
+    }
     class GLTF2Export {
         /**
          * Exports the geometry of a Mesh array in .gltf file format.
-         * If glb is set to true, exports as .glb.
          * @param meshes
          * @param materials
+         * @param options
          *
-         * @returns {[fileName: string]: string | Blob} Returns an object with a .gltf, .glb and associates textures
+         * @returns - Returns an object with a .gltf, .glb and associates textures
          * as keys and their data and paths as values.
          */
-        static GLTF(scene: BABYLON.Scene, filename: string): _GLTFData;
+        static GLTF(scene: Scene, filename: string, options?: IGLTFExporterOptions): _GLTFData;
         /**
          *
          * @param meshes
          * @param filename
          *
-         * @returns {[fileName: string]: string | Blob} Returns an object with a .glb filename as key and data as value
+         * @returns - Returns an object with a .glb filename as key and data as value
          */
-        static GLB(scene: BABYLON.Scene, filename: string): _GLTFData;
+        static GLB(scene: Scene, filename: string, options?: IGLTFExporterOptions): _GLTFData;
     }
 }
 
 declare module BABYLON {
+    /**
+     * glTF Alpha Mode Enum
+     */
+    enum _EGLTFAlphaModeEnum {
+        OPAQUE = "OPAQUE",
+        MASK = "MASK",
+        BLEND = "BLEND",
+    }
+    /**
+     * Babylon Specular Glossiness interface
+     */
+    interface _IBabylonSpecularGlossiness {
+        diffuse: Color3;
+        opacity: number;
+        specular: Color3;
+        glossiness: number;
+    }
+    /**
+     * Babylon Metallic Roughness interface
+     */
+    interface _IBabylonMetallicRoughness {
+        baseColor: Color3;
+        opacity: number;
+        metallic: number;
+        roughness: number;
+    }
+    /**
+     * Converts Babylon Scene into glTF 2.0
+     */
     class _GLTF2Exporter {
         private bufferViews;
         private accessors;
@@ -30,18 +67,22 @@ declare module BABYLON {
         private asset;
         private scenes;
         private meshes;
+        private materials;
+        private textures;
+        private images;
         private totalByteLength;
         private babylonScene;
-        constructor(babylonScene: BABYLON.Scene);
+        private options?;
+        private imageData;
+        constructor(babylonScene: Scene, options?: IGLTFExporterOptions);
         /**
          * Creates a buffer view based on teh supplied arguments
-         * @param bufferIndex
-         * @param byteOffset
-         * @param byteLength
-         *
-         * @returns {_IGLTFBufferView}
+         * @param {number} bufferIndex - index value of the specified buffer
+         * @param {number} byteOffset - byte offset value
+         * @param {number} byteLength - byte length of the bufferView
+         * @returns - bufferView for glTF
          */
-        private createBufferView(bufferIndex, byteOffset, byteLength);
+        private createBufferView(bufferIndex, byteOffset, byteLength, name?);
         /**
          * Creates an accessor based on the supplied arguments
          * @param bufferviewIndex
@@ -51,8 +92,7 @@ declare module BABYLON {
          * @param count
          * @param min
          * @param max
-         *
-         * @returns {_IGLTFAccessor}
+         * @returns - accessor for glTF
          */
         private createAccessor(bufferviewIndex, name, type, componentType, count, min?, max?);
         /**
@@ -62,8 +102,7 @@ declare module BABYLON {
          * @param vertexCount
          * @param arrayOffset
          * @param stride
-         *
-         * @returns {min: number[], max: number[]} min number array and max number array
+         * @returns - min number array and max number array
          */
         private calculateMinMax(buff, vertexStart, vertexCount, arrayOffset, stride);
         /**
@@ -76,8 +115,7 @@ declare module BABYLON {
          * @param byteOffset
          * @param dataBuffer
          * @param useRightHandedSystem
-         *
-         * @returns {number} byte length
+         * @returns - byte length
          */
         private writeAttributeData(vertexBufferType, submesh, meshAttributeArray, strideSize, byteOffset, dataBuffer, useRightHandedSystem);
         /**
@@ -85,32 +123,34 @@ declare module BABYLON {
          * @param glb
          * @param glTFPrefix
          * @param prettyPrint
-         *
-         * @returns {string} json data as string
+         * @returns - json data as string
          */
         private generateJSON(glb, glTFPrefix?, prettyPrint?);
         /**
          * Generates data for .gltf and .bin files based on the glTF prefix string
          * @param glTFPrefix
-         *
-         * @returns {[x: string]: string | Blob} object with glTF json tex filename
+         * @returns - object with glTF json tex filename
          * and binary file name as keys and their data as values
          */
         _generateGLTF(glTFPrefix: string): _GLTFData;
         /**
          * Creates a binary buffer for glTF
-         *
-         * @returns {ArrayBuffer}
+         * @returns - array buffer for binary data
          */
         private generateBinary();
         /**
+         * Pads the number to a power of 4
+         * @param num - number to pad
+         * @returns - padded number
+         */
+        private _getPadding(num);
+        /**
          * Generates a glb file from the json and binary data.
          * Returns an object with the glb file name as the key and data as the value.
          * @param jsonText
          * @param binaryBuffer
          * @param glTFPrefix
-         *
-         * @returns {[glbFileName: string]: Blob} object with glb filename as key and data as value
+         * @returns - object with glb filename as key and data as value
          */
         _generateGLB(glTFPrefix: string): _GLTFData;
         /**
@@ -121,14 +161,19 @@ declare module BABYLON {
          */
         private setNodeTransformation(node, babylonMesh, useRightHandedSystem);
         /**
+         *
+         * @param babylonTexture
+         * @return - glTF texture, or null if the texture format is not supported
+         */
+        private exportTexture(babylonTexture, mimeType?);
+        /**
          * Sets data for the primitive attributes of each submesh
          * @param mesh
          * @param babylonMesh
          * @param byteOffset
          * @param useRightHandedSystem
          * @param dataBuffer
-         *
-         * @returns {number} bytelength of the primitive attributes plus the passed in byteOffset
+         * @returns - bytelength of the primitive attributes plus the passed in byteOffset
          */
         private setPrimitiveAttributes(mesh, babylonMesh, byteOffset, useRightHandedSystem, dataBuffer?);
         /**
@@ -138,8 +183,7 @@ declare module BABYLON {
          * @param byteOffset
          * @param buffer
          * @param dataBuffer
-         *
-         * @returns {number} bytelength + byteoffset
+         * @returns bytelength + byteoffset
          */
         private createScene(babylonScene, byteOffset, dataBuffer?);
     }
@@ -150,7 +194,7 @@ declare module BABYLON {
      * Class for holding and downloading glTF file data
      */
     class _GLTFData {
-        _glTFFiles: {
+        glTFFiles: {
             [fileName: string]: string | Blob;
         };
         constructor();
@@ -160,3 +204,39 @@ declare module BABYLON {
         downloadFiles(): void;
     }
 }
+
+declare module BABYLON {
+    /**
+     * Utility methods for working with glTF material conversion properties
+     */
+    class _GLTFMaterial {
+        private static dielectricSpecular;
+        private static epsilon;
+        /**
+         * Converts Specular Glossiness to Metallic Roughness
+         * @param  babylonSpecularGlossiness - Babylon specular glossiness parameters
+         * @returns - Babylon metallic roughness values
+         */
+        static ConvertToMetallicRoughness(babylonSpecularGlossiness: _IBabylonSpecularGlossiness): _IBabylonMetallicRoughness;
+        /**
+         * Returns the perceived brightness value based on the provided color
+         * @param color - color used in calculating the perceived brightness
+         * @returns - perceived brightness value
+         */
+        private static PerceivedBrightness(color);
+        /**
+         * Computes the metallic factor
+         * @param diffuse - diffused value
+         * @param specular - specular value
+         * @param oneMinusSpecularStrength - one minus the specular strength
+         * @returns - metallic value
+         */
+        static SolveMetallic(diffuse: number, specular: number, oneMinusSpecularStrength: number): number;
+        /**
+         * Gets the glTF alpha mode from the Babylon Material
+         * @param babylonMaterial - Babylon Material
+         * @returns - The Babylon alpha mode value
+         */
+        static GetAlphaMode(babylonMaterial: Material): string;
+    }
+}

+ 493 - 83
dist/preview release/serializers/babylon.glTF2Serializer.js

@@ -1,34 +1,45 @@
 /// <reference path="../../../../dist/preview release/babylon.d.ts"/>
 var BABYLON;
 (function (BABYLON) {
+    ;
     var GLTF2Export = /** @class */ (function () {
         function GLTF2Export() {
         }
         /**
          * Exports the geometry of a Mesh array in .gltf file format.
-         * If glb is set to true, exports as .glb.
          * @param meshes
          * @param materials
+         * @param options
          *
-         * @returns {[fileName: string]: string | Blob} Returns an object with a .gltf, .glb and associates textures
+         * @returns - Returns an object with a .gltf, .glb and associates textures
          * as keys and their data and paths as values.
          */
-        GLTF2Export.GLTF = function (scene, filename) {
+        GLTF2Export.GLTF = function (scene, filename, options) {
             var glTFPrefix = filename.replace(/\.[^/.]+$/, "");
-            var gltfGenerator = new BABYLON._GLTF2Exporter(scene);
-            return gltfGenerator._generateGLTF(glTFPrefix);
+            var gltfGenerator = new BABYLON._GLTF2Exporter(scene, options);
+            if (scene.isReady) {
+                return gltfGenerator._generateGLTF(glTFPrefix);
+            }
+            else {
+                throw new Error("glTF Serializer: Scene is not ready!");
+            }
         };
         /**
          *
          * @param meshes
          * @param filename
          *
-         * @returns {[fileName: string]: string | Blob} Returns an object with a .glb filename as key and data as value
+         * @returns - Returns an object with a .glb filename as key and data as value
          */
-        GLTF2Export.GLB = function (scene, filename) {
+        GLTF2Export.GLB = function (scene, filename, options) {
             var glTFPrefix = filename.replace(/\.[^/.]+$/, "");
-            var gltfGenerator = new BABYLON._GLTF2Exporter(scene);
-            return gltfGenerator._generateGLB(glTFPrefix);
+            var gltfGenerator = new BABYLON._GLTF2Exporter(scene, options);
+            if (scene.isReady) {
+                return gltfGenerator._generateGLB(glTFPrefix);
+            }
+            else {
+                throw new Error("glTF Serializer: Scene is not ready!");
+            }
         };
         return GLTF2Export;
     }());
@@ -39,8 +50,28 @@ var BABYLON;
 
 var BABYLON;
 (function (BABYLON) {
+    /**
+     * glTF Image mimetype enum
+     */
+    var _EGLTFImageMimeTypeEnum;
+    (function (_EGLTFImageMimeTypeEnum) {
+        _EGLTFImageMimeTypeEnum["PNG"] = "image/png";
+        _EGLTFImageMimeTypeEnum["JPG"] = "image/jpeg";
+    })(_EGLTFImageMimeTypeEnum || (_EGLTFImageMimeTypeEnum = {}));
+    /**
+     * glTF Alpha Mode Enum
+     */
+    var _EGLTFAlphaModeEnum;
+    (function (_EGLTFAlphaModeEnum) {
+        _EGLTFAlphaModeEnum["OPAQUE"] = "OPAQUE";
+        _EGLTFAlphaModeEnum["MASK"] = "MASK";
+        _EGLTFAlphaModeEnum["BLEND"] = "BLEND";
+    })(_EGLTFAlphaModeEnum = BABYLON._EGLTFAlphaModeEnum || (BABYLON._EGLTFAlphaModeEnum = {}));
+    /**
+     * Converts Babylon Scene into glTF 2.0
+     */
     var _GLTF2Exporter = /** @class */ (function () {
-        function _GLTF2Exporter(babylonScene) {
+        function _GLTF2Exporter(babylonScene, options) {
             this.asset = { generator: "BabylonJS", version: "2.0" };
             this.babylonScene = babylonScene;
             this.bufferViews = new Array();
@@ -48,23 +79,31 @@ var BABYLON;
             this.meshes = new Array();
             this.scenes = new Array();
             this.nodes = new Array();
+            this.images = new Array();
+            this.materials = new Array();
+            this.imageData = {};
+            if (options !== undefined) {
+                this.options = options;
+            }
             var totalByteLength = 0;
             totalByteLength = this.createScene(this.babylonScene, totalByteLength);
             this.totalByteLength = totalByteLength;
         }
         /**
          * Creates a buffer view based on teh supplied arguments
-         * @param bufferIndex
-         * @param byteOffset
-         * @param byteLength
-         *
-         * @returns {_IGLTFBufferView}
+         * @param {number} bufferIndex - index value of the specified buffer
+         * @param {number} byteOffset - byte offset value
+         * @param {number} byteLength - byte length of the bufferView
+         * @returns - bufferView for glTF
          */
-        _GLTF2Exporter.prototype.createBufferView = function (bufferIndex, byteOffset, byteLength) {
+        _GLTF2Exporter.prototype.createBufferView = function (bufferIndex, byteOffset, byteLength, name) {
             var bufferview = { buffer: bufferIndex, byteLength: byteLength };
             if (byteOffset > 0) {
                 bufferview.byteOffset = byteOffset;
             }
+            if (name) {
+                bufferview.name = name;
+            }
             return bufferview;
         };
         /**
@@ -76,8 +115,7 @@ var BABYLON;
          * @param count
          * @param min
          * @param max
-         *
-         * @returns {_IGLTFAccessor}
+         * @returns - accessor for glTF
          */
         _GLTF2Exporter.prototype.createAccessor = function (bufferviewIndex, name, type, componentType, count, min, max) {
             var accessor = { name: name, bufferView: bufferviewIndex, componentType: componentType, count: count, type: type };
@@ -96,8 +134,7 @@ var BABYLON;
          * @param vertexCount
          * @param arrayOffset
          * @param stride
-         *
-         * @returns {min: number[], max: number[]} min number array and max number array
+         * @returns - min number array and max number array
          */
         _GLTF2Exporter.prototype.calculateMinMax = function (buff, vertexStart, vertexCount, arrayOffset, stride) {
             var min = [Infinity, Infinity, Infinity];
@@ -129,8 +166,7 @@ var BABYLON;
          * @param byteOffset
          * @param dataBuffer
          * @param useRightHandedSystem
-         *
-         * @returns {number} byte length
+         * @returns - byte length
          */
         _GLTF2Exporter.prototype.writeAttributeData = function (vertexBufferType, submesh, meshAttributeArray, strideSize, byteOffset, dataBuffer, useRightHandedSystem) {
             var byteOff = byteOffset;
@@ -241,23 +277,65 @@ var BABYLON;
          * @param glb
          * @param glTFPrefix
          * @param prettyPrint
-         *
-         * @returns {string} json data as string
+         * @returns - json data as string
          */
         _GLTF2Exporter.prototype.generateJSON = function (glb, glTFPrefix, prettyPrint) {
             var buffer = { byteLength: this.totalByteLength };
             var glTF = {
-                buffers: [buffer],
-                asset: this.asset,
-                meshes: this.meshes,
-                scenes: this.scenes,
-                nodes: this.nodes,
-                bufferViews: this.bufferViews,
-                accessors: this.accessors
+                asset: this.asset
             };
-            if (this.scenes.length > 0) {
+            if (buffer.byteLength > 0) {
+                glTF.buffers = [buffer];
+            }
+            if (this.nodes && this.nodes.length !== 0) {
+                glTF.nodes = this.nodes;
+            }
+            if (this.meshes && this.meshes.length !== 0) {
+                glTF.meshes = this.meshes;
+            }
+            if (this.scenes && this.scenes.length !== 0) {
+                glTF.scenes = this.scenes;
                 glTF.scene = 0;
             }
+            if (this.bufferViews && this.bufferViews.length !== 0) {
+                glTF.bufferViews = this.bufferViews;
+            }
+            if (this.accessors && this.accessors.length !== 0) {
+                glTF.accessors = this.accessors;
+            }
+            if (this.materials && this.materials.length !== 0) {
+                glTF.materials = this.materials;
+            }
+            if (this.textures && this.textures.length !== 0) {
+                glTF.textures = this.textures;
+            }
+            if (this.images && this.images.length !== 0) {
+                if (!glb) {
+                    glTF.images = this.images;
+                }
+                else {
+                    glTF.images = [];
+                    // Replace uri with bufferview and mime type for glb
+                    var imageLength = this.images.length;
+                    var byteOffset = this.totalByteLength;
+                    for (var i = 0; i < imageLength; ++i) {
+                        var image = this.images[i];
+                        if (image.uri !== undefined) {
+                            var imageData = this.imageData[image.uri];
+                            var imageName = image.uri.split('.')[0] + " image";
+                            var bufferView = this.createBufferView(0, byteOffset, imageData.data.length, imageName);
+                            byteOffset += imageData.data.buffer.byteLength;
+                            this.bufferViews.push(bufferView);
+                            image.bufferView = this.bufferViews.length - 1;
+                            image.name = imageName;
+                            image.mimeType = imageData.mimeType;
+                            image.uri = undefined;
+                            glTF.images.push(image);
+                        }
+                    }
+                    buffer.byteLength = byteOffset;
+                }
+            }
             if (!glb) {
                 buffer.uri = glTFPrefix + ".bin";
             }
@@ -267,8 +345,7 @@ var BABYLON;
         /**
          * Generates data for .gltf and .bin files based on the glTF prefix string
          * @param glTFPrefix
-         *
-         * @returns {[x: string]: string | Blob} object with glTF json tex filename
+         * @returns - object with glTF json tex filename
          * and binary file name as keys and their data as values
          */
         _GLTF2Exporter.prototype._generateGLTF = function (glTFPrefix) {
@@ -278,14 +355,18 @@ var BABYLON;
             var glTFFileName = glTFPrefix + '.gltf';
             var glTFBinFile = glTFPrefix + '.bin';
             var container = new BABYLON._GLTFData();
-            container._glTFFiles[glTFFileName] = jsonText;
-            container._glTFFiles[glTFBinFile] = bin;
+            container.glTFFiles[glTFFileName] = jsonText;
+            container.glTFFiles[glTFBinFile] = bin;
+            if (this.imageData !== null) {
+                for (var image in this.imageData) {
+                    container.glTFFiles[image] = new Blob([this.imageData[image].data], { type: this.imageData[image].mimeType });
+                }
+            }
             return container;
         };
         /**
          * Creates a binary buffer for glTF
-         *
-         * @returns {ArrayBuffer}
+         * @returns - array buffer for binary data
          */
         _GLTF2Exporter.prototype.generateBinary = function () {
             var byteOffset = 0;
@@ -295,13 +376,22 @@ var BABYLON;
             return binaryBuffer;
         };
         /**
+         * Pads the number to a power of 4
+         * @param num - number to pad
+         * @returns - padded number
+         */
+        _GLTF2Exporter.prototype._getPadding = function (num) {
+            var remainder = num % 4;
+            var padding = remainder === 0 ? remainder : 4 - remainder;
+            return padding;
+        };
+        /**
          * Generates a glb file from the json and binary data.
          * Returns an object with the glb file name as the key and data as the value.
          * @param jsonText
          * @param binaryBuffer
          * @param glTFPrefix
-         *
-         * @returns {[glbFileName: string]: Blob} object with glb filename as key and data as value
+         * @returns - object with glb filename as key and data as value
          */
         _GLTF2Exporter.prototype._generateGLB = function (glTFPrefix) {
             var jsonText = this.generateJSON(true);
@@ -310,11 +400,13 @@ var BABYLON;
             var headerLength = 12;
             var chunkLengthPrefix = 8;
             var jsonLength = jsonText.length;
-            var jsonRemainder = jsonLength % 4;
-            var binRemainder = binaryBuffer.byteLength % 4;
-            var jsonPadding = jsonRemainder === 0 ? jsonRemainder : 4 - jsonRemainder;
-            var binPadding = binRemainder === 0 ? binRemainder : 4 - binRemainder;
-            var byteLength = headerLength + (2 * chunkLengthPrefix) + jsonLength + jsonPadding + binaryBuffer.byteLength + binPadding;
+            var imageByteLength = 0;
+            for (var key in this.imageData) {
+                imageByteLength += this.imageData[key].data.byteLength;
+            }
+            var jsonPadding = this._getPadding(jsonLength);
+            var binPadding = this._getPadding(binaryBuffer.byteLength);
+            var byteLength = headerLength + (2 * chunkLengthPrefix) + jsonLength + jsonPadding + binaryBuffer.byteLength + binPadding + imageByteLength;
             //header
             var headerBuffer = new ArrayBuffer(headerLength);
             var headerBufferView = new DataView(headerBuffer);
@@ -339,7 +431,7 @@ var BABYLON;
             //binary chunk
             var binaryChunkBuffer = new ArrayBuffer(chunkLengthPrefix);
             var binaryChunkBufferView = new DataView(binaryChunkBuffer);
-            binaryChunkBufferView.setUint32(0, binaryBuffer.byteLength, true);
+            binaryChunkBufferView.setUint32(0, binaryBuffer.byteLength + imageByteLength, true);
             binaryChunkBufferView.setUint32(4, 0x004E4942, true);
             // binary padding
             var binPaddingBuffer = new ArrayBuffer(binPadding);
@@ -347,10 +439,15 @@ var BABYLON;
             for (var i = 0; i < binPadding; ++i) {
                 binPaddingView[i] = 0;
             }
+            var glbData = [headerBuffer, jsonChunkBuffer, binaryChunkBuffer, binaryBuffer];
             // binary data
-            var glbFile = new Blob([headerBuffer, jsonChunkBuffer, binaryChunkBuffer, binaryBuffer, binPaddingBuffer], { type: 'application/octet-stream' });
+            for (var key in this.imageData) {
+                glbData.push(this.imageData[key].data.buffer);
+            }
+            glbData.push(binPaddingBuffer);
+            var glbFile = new Blob(glbData, { type: 'application/octet-stream' });
             var container = new BABYLON._GLTFData();
-            container._glTFFiles[glbFileName] = glbFile;
+            container.glTFFiles[glbFileName] = glbFile;
             return container;
         };
         /**
@@ -390,14 +487,90 @@ var BABYLON;
             }
         };
         /**
+         *
+         * @param babylonTexture
+         * @return - glTF texture, or null if the texture format is not supported
+         */
+        _GLTF2Exporter.prototype.exportTexture = function (babylonTexture, mimeType) {
+            if (mimeType === void 0) { mimeType = _EGLTFImageMimeTypeEnum.JPG; }
+            var textureInfo = null;
+            var glTFTexture;
+            glTFTexture = {
+                source: this.images.length
+            };
+            var textureName = babylonTexture.getInternalTexture().url;
+            if (textureName.search('/') !== -1) {
+                var splitFilename = textureName.split('/');
+                textureName = splitFilename[splitFilename.length - 1];
+                var basefile = textureName.split('.')[0];
+                var extension = textureName.split('.')[1];
+                if (mimeType === _EGLTFImageMimeTypeEnum.JPG) {
+                    extension = ".jpg";
+                }
+                else if (mimeType === _EGLTFImageMimeTypeEnum.PNG) {
+                    extension = ".png";
+                }
+                else {
+                    throw new Error("Unsupported mime type " + mimeType);
+                }
+                textureName = basefile + extension;
+            }
+            var pixels = babylonTexture.readPixels();
+            var imageCanvas = document.createElement('canvas');
+            imageCanvas.id = "ImageCanvas";
+            var ctx = imageCanvas.getContext('2d');
+            var size = babylonTexture.getSize();
+            imageCanvas.width = size.width;
+            imageCanvas.height = size.height;
+            var imgData = ctx.createImageData(size.width, size.height);
+            imgData.data.set(pixels);
+            ctx.putImageData(imgData, 0, 0);
+            var base64Data = imageCanvas.toDataURL(mimeType);
+            var binStr = atob(base64Data.split(',')[1]);
+            var arr = new Uint8Array(binStr.length);
+            for (var i = 0; i < binStr.length; ++i) {
+                arr[i] = binStr.charCodeAt(i);
+            }
+            var imageValues = { data: arr, mimeType: mimeType };
+            this.imageData[textureName] = imageValues;
+            if (mimeType === _EGLTFImageMimeTypeEnum.JPG) {
+                var glTFImage = {
+                    uri: textureName
+                };
+                var foundIndex = -1;
+                for (var i = 0; i < this.images.length; ++i) {
+                    if (this.images[i].uri === textureName) {
+                        foundIndex = i;
+                        break;
+                    }
+                }
+                if (foundIndex === -1) {
+                    this.images.push(glTFImage);
+                    glTFTexture.source = this.images.length - 1;
+                    this.textures.push({
+                        source: this.images.length - 1
+                    });
+                    textureInfo = {
+                        index: this.images.length - 1
+                    };
+                }
+                else {
+                    glTFTexture.source = foundIndex;
+                    textureInfo = {
+                        index: foundIndex
+                    };
+                }
+            }
+            return textureInfo;
+        };
+        /**
          * Sets data for the primitive attributes of each submesh
          * @param mesh
          * @param babylonMesh
          * @param byteOffset
          * @param useRightHandedSystem
          * @param dataBuffer
-         *
-         * @returns {number} bytelength of the primitive attributes plus the passed in byteOffset
+         * @returns - bytelength of the primitive attributes plus the passed in byteOffset
          */
         _GLTF2Exporter.prototype.setPrimitiveAttributes = function (mesh, babylonMesh, byteOffset, useRightHandedSystem, dataBuffer) {
             // go through all mesh primitives (submeshes)
@@ -423,7 +596,7 @@ var BABYLON;
                     else {
                         // Create bufferview
                         var byteLength = submesh.verticesCount * 12;
-                        var bufferview = this.createBufferView(0, byteOffset, byteLength);
+                        var bufferview = this.createBufferView(0, byteOffset, byteLength, "Positions");
                         byteOffset += byteLength;
                         this.bufferViews.push(bufferview);
                         // Create accessor
@@ -443,7 +616,7 @@ var BABYLON;
                     else {
                         // Create bufferview
                         var byteLength = submesh.verticesCount * 12;
-                        var bufferview = this.createBufferView(0, byteOffset, byteLength);
+                        var bufferview = this.createBufferView(0, byteOffset, byteLength, "Normals");
                         byteOffset += byteLength;
                         this.bufferViews.push(bufferview);
                         // Create accessor
@@ -462,7 +635,7 @@ var BABYLON;
                     else {
                         // Create bufferview
                         var byteLength = submesh.verticesCount * 16;
-                        var bufferview = this.createBufferView(0, byteOffset, byteLength);
+                        var bufferview = this.createBufferView(0, byteOffset, byteLength, "Tangents");
                         byteOffset += byteLength;
                         this.bufferViews.push(bufferview);
                         // Create accessor
@@ -481,7 +654,7 @@ var BABYLON;
                     else {
                         // Create bufferview
                         var byteLength = submesh.verticesCount * 16;
-                        var bufferview = this.createBufferView(0, byteOffset, byteLength);
+                        var bufferview = this.createBufferView(0, byteOffset, byteLength, "Colors");
                         byteOffset += byteLength;
                         this.bufferViews.push(bufferview);
                         // Create accessor
@@ -500,7 +673,7 @@ var BABYLON;
                     else {
                         // Create bufferview
                         var byteLength = submesh.verticesCount * 8;
-                        var bufferview = this.createBufferView(0, byteOffset, byteLength);
+                        var bufferview = this.createBufferView(0, byteOffset, byteLength, "Texture Coords0");
                         byteOffset += byteLength;
                         this.bufferViews.push(bufferview);
                         // Create accessor
@@ -519,7 +692,7 @@ var BABYLON;
                     else {
                         // Create bufferview
                         var byteLength = submesh.verticesCount * 8;
-                        var bufferview = this.createBufferView(0, byteOffset, byteLength);
+                        var bufferview = this.createBufferView(0, byteOffset, byteLength, "Texture Coords 1");
                         byteOffset += byteLength;
                         this.bufferViews.push(bufferview);
                         // Create accessor
@@ -549,7 +722,7 @@ var BABYLON;
                         // Create bufferview
                         var indicesCount = submesh.indexCount;
                         var byteLength = indicesCount * 4;
-                        var bufferview = this.createBufferView(0, byteOffset, byteLength);
+                        var bufferview = this.createBufferView(0, byteOffset, byteLength, "Indices");
                         byteOffset += byteLength;
                         this.bufferViews.push(bufferview);
                         // Create accessor
@@ -559,7 +732,127 @@ var BABYLON;
                     }
                 }
                 if (bufferMesh.material) {
-                    //TODO: Implement Material
+                    if (bufferMesh.material instanceof BABYLON.StandardMaterial) {
+                        var babylonStandardMaterial = bufferMesh.material;
+                        var glTFMaterial = { name: babylonStandardMaterial.name };
+                        if (!babylonStandardMaterial.backFaceCulling) {
+                            glTFMaterial.doubleSided = true;
+                        }
+                        if (babylonStandardMaterial.bumpTexture) {
+                            var glTFTexture = this.exportTexture(babylonStandardMaterial.bumpTexture);
+                            if (glTFTexture) {
+                                glTFMaterial.normalTexture = glTFTexture;
+                            }
+                        }
+                        if (babylonStandardMaterial.emissiveTexture) {
+                            var glTFEmissiveTexture = this.exportTexture(babylonStandardMaterial.emissiveTexture);
+                            if (glTFEmissiveTexture) {
+                                glTFMaterial.emissiveTexture = glTFEmissiveTexture;
+                            }
+                            glTFMaterial.emissiveFactor = [1.0, 1.0, 1.0];
+                        }
+                        if (babylonStandardMaterial.ambientTexture) {
+                            var glTFOcclusionTexture = this.exportTexture(babylonStandardMaterial.ambientTexture);
+                            if (glTFOcclusionTexture) {
+                                glTFMaterial.occlusionTexture = glTFOcclusionTexture;
+                            }
+                        }
+                        // Spec Gloss
+                        var babylonSpecularGlossiness = {
+                            diffuse: babylonStandardMaterial.diffuseColor,
+                            opacity: babylonStandardMaterial.alpha,
+                            specular: babylonStandardMaterial.specularColor || BABYLON.Color3.Black(),
+                            glossiness: babylonStandardMaterial.specularPower / 256
+                        };
+                        if (babylonStandardMaterial.specularTexture) {
+                        }
+                        var babylonMetallicRoughness = BABYLON._GLTFMaterial.ConvertToMetallicRoughness(babylonSpecularGlossiness);
+                        var glTFPbrMetallicRoughness = {
+                            baseColorFactor: [
+                                babylonMetallicRoughness.baseColor.r,
+                                babylonMetallicRoughness.baseColor.g,
+                                babylonMetallicRoughness.baseColor.b,
+                                babylonMetallicRoughness.opacity
+                            ],
+                            metallicFactor: babylonMetallicRoughness.metallic,
+                            roughnessFactor: babylonMetallicRoughness.roughness
+                        };
+                        glTFMaterial.pbrMetallicRoughness = glTFPbrMetallicRoughness;
+                        // TODO: Handle Textures
+                        this.materials.push(glTFMaterial);
+                        meshPrimitive.material = this.materials.length - 1;
+                    }
+                    else if (bufferMesh.material instanceof BABYLON.PBRMetallicRoughnessMaterial) {
+                        if (!this.textures) {
+                            this.textures = new Array();
+                        }
+                        var babylonPBRMaterial = bufferMesh.material;
+                        var glTFPbrMetallicRoughness = {};
+                        if (babylonPBRMaterial.baseColor) {
+                            glTFPbrMetallicRoughness.baseColorFactor = [
+                                babylonPBRMaterial.baseColor.r,
+                                babylonPBRMaterial.baseColor.g,
+                                babylonPBRMaterial.baseColor.b,
+                                babylonPBRMaterial.alpha
+                            ];
+                        }
+                        if (babylonPBRMaterial.baseTexture !== undefined) {
+                            var glTFTexture = this.exportTexture(babylonPBRMaterial.baseTexture);
+                            if (glTFTexture !== null) {
+                                glTFPbrMetallicRoughness.baseColorTexture = glTFTexture;
+                            }
+                            glTFPbrMetallicRoughness.baseColorTexture;
+                        }
+                        if (babylonPBRMaterial.metallic !== undefined) {
+                            glTFPbrMetallicRoughness.metallicFactor = babylonPBRMaterial.metallic;
+                        }
+                        if (babylonPBRMaterial.roughness !== undefined) {
+                            glTFPbrMetallicRoughness.roughnessFactor = babylonPBRMaterial.roughness;
+                        }
+                        var glTFMaterial = {
+                            name: babylonPBRMaterial.name
+                        };
+                        if (babylonPBRMaterial.doubleSided) {
+                            glTFMaterial.doubleSided = babylonPBRMaterial.doubleSided;
+                        }
+                        if (babylonPBRMaterial.normalTexture) {
+                            var glTFTexture = this.exportTexture(babylonPBRMaterial.normalTexture);
+                            if (glTFTexture) {
+                                glTFMaterial.normalTexture = glTFTexture;
+                            }
+                        }
+                        if (babylonPBRMaterial.occlusionTexture) {
+                            var glTFTexture = this.exportTexture(babylonPBRMaterial.occlusionTexture);
+                            if (glTFTexture) {
+                                glTFMaterial.occlusionTexture = glTFTexture;
+                                if (babylonPBRMaterial.occlusionStrength !== undefined) {
+                                    glTFMaterial.occlusionTexture.strength = babylonPBRMaterial.occlusionStrength;
+                                }
+                            }
+                        }
+                        if (babylonPBRMaterial.emissiveTexture) {
+                            var glTFTexture = this.exportTexture(babylonPBRMaterial.emissiveTexture);
+                            if (glTFTexture !== null) {
+                                glTFMaterial.emissiveTexture = glTFTexture;
+                            }
+                        }
+                        if (!babylonPBRMaterial.emissiveColor.equals(new BABYLON.Color3(0.0, 0.0, 0.0))) {
+                            glTFMaterial.emissiveFactor = babylonPBRMaterial.emissiveColor.asArray();
+                        }
+                        if (babylonPBRMaterial.transparencyMode) {
+                            var alphaMode = BABYLON._GLTFMaterial.GetAlphaMode(babylonPBRMaterial);
+                            if (alphaMode !== _EGLTFAlphaModeEnum.OPAQUE) {
+                                glTFMaterial.alphaMode = alphaMode;
+                                if (alphaMode === _EGLTFAlphaModeEnum.BLEND) {
+                                    glTFMaterial.alphaCutoff = babylonPBRMaterial.alphaCutOff;
+                                }
+                            }
+                        }
+                        glTFMaterial.pbrMetallicRoughness = glTFPbrMetallicRoughness;
+                        // TODO: Handle Textures
+                        this.materials.push(glTFMaterial);
+                        meshPrimitive.material = this.materials.length - 1;
+                    }
                 }
                 mesh.primitives.push(meshPrimitive);
             }
@@ -572,32 +865,38 @@ var BABYLON;
          * @param byteOffset
          * @param buffer
          * @param dataBuffer
-         *
-         * @returns {number} bytelength + byteoffset
+         * @returns bytelength + byteoffset
          */
         _GLTF2Exporter.prototype.createScene = function (babylonScene, byteOffset, dataBuffer) {
             if (babylonScene.meshes.length > 0) {
                 var babylonMeshes = babylonScene.meshes;
                 var scene = { nodes: new Array() };
                 for (var i = 0; i < babylonMeshes.length; ++i) {
-                    // create node to hold translation/rotation/scale and the mesh
-                    var node = { mesh: -1 };
-                    var babylonMesh = babylonMeshes[i];
-                    var useRightHandedSystem = babylonMesh.getScene().useRightHandedSystem;
-                    // Set transformation
-                    this.setNodeTransformation(node, babylonMesh, useRightHandedSystem);
-                    // create mesh
-                    var mesh = { primitives: new Array() };
-                    mesh.primitives = [];
-                    byteOffset = this.setPrimitiveAttributes(mesh, babylonMesh, byteOffset, useRightHandedSystem, dataBuffer);
-                    // go through all mesh primitives (submeshes)
-                    this.meshes.push(mesh);
-                    node.mesh = this.meshes.length - 1;
-                    if (babylonMesh.name) {
-                        node.name = babylonMesh.name;
-                    }
-                    this.nodes.push(node);
-                    scene.nodes.push(this.nodes.length - 1);
+                    if (this.options &&
+                        this.options.shouldExportMesh !== undefined &&
+                        !this.options.shouldExportMesh(babylonMeshes[i])) {
+                        continue;
+                    }
+                    else {
+                        // create node to hold translation/rotation/scale and the mesh
+                        var node = { mesh: -1 };
+                        var babylonMesh = babylonMeshes[i];
+                        var useRightHandedSystem = babylonMesh.getScene().useRightHandedSystem;
+                        // Set transformation
+                        this.setNodeTransformation(node, babylonMesh, useRightHandedSystem);
+                        // create mesh
+                        var mesh = { primitives: new Array() };
+                        mesh.primitives = [];
+                        byteOffset = this.setPrimitiveAttributes(mesh, babylonMesh, byteOffset, useRightHandedSystem, dataBuffer);
+                        // go through all mesh primitives (submeshes)
+                        this.meshes.push(mesh);
+                        node.mesh = this.meshes.length - 1;
+                        if (babylonMesh.name) {
+                            node.name = babylonMesh.name;
+                        }
+                        this.nodes.push(node);
+                        scene.nodes.push(this.nodes.length - 1);
+                    }
                 }
                 this.scenes.push(scene);
             }
@@ -617,7 +916,7 @@ var BABYLON;
      */
     var _GLTFData = /** @class */ (function () {
         function _GLTFData() {
-            this._glTFFiles = {};
+            this.glTFFiles = {};
         }
         /**
          * Downloads glTF data.
@@ -627,18 +926,17 @@ var BABYLON;
             * Checks for a matching suffix at the end of a string (for ES5 and lower)
             * @param str
             * @param suffix
-            *
-            * @returns {boolean} indicating whether the suffix matches or not
+            * @returns - indicating whether the suffix matches or not
             */
             function endsWith(str, suffix) {
                 return str.indexOf(suffix, str.length - suffix.length) !== -1;
             }
-            for (var key in this._glTFFiles) {
+            for (var key in this.glTFFiles) {
                 var link = document.createElement('a');
                 document.body.appendChild(link);
                 link.setAttribute("type", "hidden");
                 link.download = key;
-                var blob = this._glTFFiles[key];
+                var blob = this.glTFFiles[key];
                 var mimeType = void 0;
                 if (endsWith(key, ".glb")) {
                     mimeType = { type: "model/gltf-binary" };
@@ -659,3 +957,115 @@ var BABYLON;
 })(BABYLON || (BABYLON = {}));
 
 //# sourceMappingURL=babylon.glTFData.js.map
+
+var BABYLON;
+(function (BABYLON) {
+    /**
+     * Utility methods for working with glTF material conversion properties
+     */
+    var _GLTFMaterial = /** @class */ (function () {
+        function _GLTFMaterial() {
+        }
+        /**
+         * Converts Specular Glossiness to Metallic Roughness
+         * @param  babylonSpecularGlossiness - Babylon specular glossiness parameters
+         * @returns - Babylon metallic roughness values
+         */
+        _GLTFMaterial.ConvertToMetallicRoughness = function (babylonSpecularGlossiness) {
+            var diffuse = babylonSpecularGlossiness.diffuse;
+            var opacity = babylonSpecularGlossiness.opacity;
+            var specular = babylonSpecularGlossiness.specular;
+            var glossiness = babylonSpecularGlossiness.glossiness;
+            var oneMinusSpecularStrength = 1 - Math.max(specular.r, Math.max(specular.g, specular.b));
+            var diffusePerceivedBrightness = _GLTFMaterial.PerceivedBrightness(diffuse);
+            var specularPerceivedBrightness = _GLTFMaterial.PerceivedBrightness(specular);
+            var metallic = _GLTFMaterial.SolveMetallic(diffusePerceivedBrightness, specularPerceivedBrightness, oneMinusSpecularStrength);
+            var diffuseScaleFactor = oneMinusSpecularStrength / (1 - this.dielectricSpecular.r) / Math.max(1 - metallic, this.epsilon);
+            var baseColorFromDiffuse = diffuse.scale(diffuseScaleFactor);
+            var baseColorFromSpecular = specular.subtract(this.dielectricSpecular.scale(1 - metallic)).scale(1 / Math.max(metallic, this.epsilon));
+            var lerpColor = BABYLON.Color3.Lerp(baseColorFromDiffuse, baseColorFromSpecular, metallic * metallic);
+            var baseColor = new BABYLON.Color3();
+            lerpColor.clampToRef(0, 1, baseColor);
+            var babylonMetallicRoughness = {
+                baseColor: baseColor,
+                opacity: opacity,
+                metallic: metallic,
+                roughness: 1.0 - glossiness
+            };
+            return babylonMetallicRoughness;
+        };
+        /**
+         * Returns the perceived brightness value based on the provided color
+         * @param color - color used in calculating the perceived brightness
+         * @returns - perceived brightness value
+         */
+        _GLTFMaterial.PerceivedBrightness = function (color) {
+            return Math.sqrt(0.299 * color.r * color.r + 0.587 * color.g * color.g + 0.114 * color.b * color.b);
+        };
+        /**
+         * Computes the metallic factor
+         * @param diffuse - diffused value
+         * @param specular - specular value
+         * @param oneMinusSpecularStrength - one minus the specular strength
+         * @returns - metallic value
+         */
+        _GLTFMaterial.SolveMetallic = function (diffuse, specular, oneMinusSpecularStrength) {
+            if (specular < this.dielectricSpecular.r) {
+                return 0;
+            }
+            var a = this.dielectricSpecular.r;
+            var b = diffuse * oneMinusSpecularStrength / (1.0 - this.dielectricSpecular.r) + specular - 2.0 * this.dielectricSpecular.r;
+            var c = this.dielectricSpecular.r - specular;
+            var D = b * b - 4.0 * a * c;
+            return BABYLON.Scalar.Clamp((-b + Math.sqrt(D)) / (2.0 * a));
+        };
+        /**
+         * Gets the glTF alpha mode from the Babylon Material
+         * @param babylonMaterial - Babylon Material
+         * @returns - The Babylon alpha mode value
+         */
+        _GLTFMaterial.GetAlphaMode = function (babylonMaterial) {
+            if (babylonMaterial instanceof BABYLON.StandardMaterial) {
+                var babylonStandardMaterial = babylonMaterial;
+                if ((babylonStandardMaterial.alpha != 1.0) ||
+                    (babylonStandardMaterial.diffuseTexture != null && babylonStandardMaterial.diffuseTexture.hasAlpha) ||
+                    (babylonStandardMaterial.opacityTexture != null)) {
+                    return BABYLON._EGLTFAlphaModeEnum.BLEND;
+                }
+                else {
+                    return BABYLON._EGLTFAlphaModeEnum.OPAQUE;
+                }
+            }
+            else if (babylonMaterial instanceof BABYLON.PBRMetallicRoughnessMaterial) {
+                var babylonPBRMetallicRoughness = babylonMaterial;
+                switch (babylonPBRMetallicRoughness.transparencyMode) {
+                    case BABYLON.PBRMaterial.PBRMATERIAL_OPAQUE: {
+                        return BABYLON._EGLTFAlphaModeEnum.OPAQUE;
+                    }
+                    case BABYLON.PBRMaterial.PBRMATERIAL_ALPHABLEND: {
+                        return BABYLON._EGLTFAlphaModeEnum.BLEND;
+                    }
+                    case BABYLON.PBRMaterial.PBRMATERIAL_ALPHATEST: {
+                        return BABYLON._EGLTFAlphaModeEnum.MASK;
+                    }
+                    case BABYLON.PBRMaterial.PBRMATERIAL_ALPHATESTANDBLEND: {
+                        console.warn("GLTF Exporter | Alpha test and blend mode not supported in glTF.  Alpha blend used instead.");
+                        return BABYLON._EGLTFAlphaModeEnum.BLEND;
+                    }
+                    default: {
+                        throw new Error("Unsupported alpha mode " + babylonPBRMetallicRoughness.transparencyMode);
+                    }
+                }
+            }
+            else {
+                throw new Error("Unsupported Babylon material type");
+            }
+        };
+        _GLTFMaterial.dielectricSpecular = new BABYLON.Color3(0.04, 0.04, 0.04);
+        _GLTFMaterial.epsilon = 1e-6;
+        return _GLTFMaterial;
+    }());
+    BABYLON._GLTFMaterial = _GLTFMaterial;
+})(BABYLON || (BABYLON = {}));
+
+//# sourceMappingURL=babylon.glTFMaterial.js.map

File diff suppressed because it is too large
+ 1 - 1
dist/preview release/serializers/babylon.glTF2Serializer.min.js


+ 493 - 83
dist/preview release/serializers/babylonjs.serializers.js

@@ -145,34 +145,45 @@ var BABYLON;
 
 var BABYLON;
 (function (BABYLON) {
+    ;
     var GLTF2Export = /** @class */ (function () {
         function GLTF2Export() {
         }
         /**
          * Exports the geometry of a Mesh array in .gltf file format.
-         * If glb is set to true, exports as .glb.
          * @param meshes
          * @param materials
+         * @param options
          *
-         * @returns {[fileName: string]: string | Blob} Returns an object with a .gltf, .glb and associates textures
+         * @returns - Returns an object with a .gltf, .glb and associates textures
          * as keys and their data and paths as values.
          */
-        GLTF2Export.GLTF = function (scene, filename) {
+        GLTF2Export.GLTF = function (scene, filename, options) {
             var glTFPrefix = filename.replace(/\.[^/.]+$/, "");
-            var gltfGenerator = new BABYLON._GLTF2Exporter(scene);
-            return gltfGenerator._generateGLTF(glTFPrefix);
+            var gltfGenerator = new BABYLON._GLTF2Exporter(scene, options);
+            if (scene.isReady) {
+                return gltfGenerator._generateGLTF(glTFPrefix);
+            }
+            else {
+                throw new Error("glTF Serializer: Scene is not ready!");
+            }
         };
         /**
          *
          * @param meshes
          * @param filename
          *
-         * @returns {[fileName: string]: string | Blob} Returns an object with a .glb filename as key and data as value
+         * @returns - Returns an object with a .glb filename as key and data as value
          */
-        GLTF2Export.GLB = function (scene, filename) {
+        GLTF2Export.GLB = function (scene, filename, options) {
             var glTFPrefix = filename.replace(/\.[^/.]+$/, "");
-            var gltfGenerator = new BABYLON._GLTF2Exporter(scene);
-            return gltfGenerator._generateGLB(glTFPrefix);
+            var gltfGenerator = new BABYLON._GLTF2Exporter(scene, options);
+            if (scene.isReady) {
+                return gltfGenerator._generateGLB(glTFPrefix);
+            }
+            else {
+                throw new Error("glTF Serializer: Scene is not ready!");
+            }
         };
         return GLTF2Export;
     }());
@@ -183,8 +194,28 @@ var BABYLON;
 
 var BABYLON;
 (function (BABYLON) {
+    /**
+     * glTF Image mimetype enum
+     */
+    var _EGLTFImageMimeTypeEnum;
+    (function (_EGLTFImageMimeTypeEnum) {
+        _EGLTFImageMimeTypeEnum["PNG"] = "image/png";
+        _EGLTFImageMimeTypeEnum["JPG"] = "image/jpeg";
+    })(_EGLTFImageMimeTypeEnum || (_EGLTFImageMimeTypeEnum = {}));
+    /**
+     * glTF Alpha Mode Enum
+     */
+    var _EGLTFAlphaModeEnum;
+    (function (_EGLTFAlphaModeEnum) {
+        _EGLTFAlphaModeEnum["OPAQUE"] = "OPAQUE";
+        _EGLTFAlphaModeEnum["MASK"] = "MASK";
+        _EGLTFAlphaModeEnum["BLEND"] = "BLEND";
+    })(_EGLTFAlphaModeEnum = BABYLON._EGLTFAlphaModeEnum || (BABYLON._EGLTFAlphaModeEnum = {}));
+    /**
+     * Converts Babylon Scene into glTF 2.0
+     */
     var _GLTF2Exporter = /** @class */ (function () {
-        function _GLTF2Exporter(babylonScene) {
+        function _GLTF2Exporter(babylonScene, options) {
             this.asset = { generator: "BabylonJS", version: "2.0" };
             this.babylonScene = babylonScene;
             this.bufferViews = new Array();
@@ -192,23 +223,31 @@ var BABYLON;
             this.meshes = new Array();
             this.scenes = new Array();
             this.nodes = new Array();
+            this.images = new Array();
+            this.materials = new Array();
+            this.imageData = {};
+            if (options !== undefined) {
+                this.options = options;
+            }
             var totalByteLength = 0;
             totalByteLength = this.createScene(this.babylonScene, totalByteLength);
             this.totalByteLength = totalByteLength;
         }
         /**
          * Creates a buffer view based on teh supplied arguments
-         * @param bufferIndex
-         * @param byteOffset
-         * @param byteLength
-         *
-         * @returns {_IGLTFBufferView}
+         * @param {number} bufferIndex - index value of the specified buffer
+         * @param {number} byteOffset - byte offset value
+         * @param {number} byteLength - byte length of the bufferView
+         * @returns - bufferView for glTF
          */
-        _GLTF2Exporter.prototype.createBufferView = function (bufferIndex, byteOffset, byteLength) {
+        _GLTF2Exporter.prototype.createBufferView = function (bufferIndex, byteOffset, byteLength, name) {
             var bufferview = { buffer: bufferIndex, byteLength: byteLength };
             if (byteOffset > 0) {
                 bufferview.byteOffset = byteOffset;
             }
+            if (name) {
+                bufferview.name = name;
+            }
             return bufferview;
         };
         /**
@@ -220,8 +259,7 @@ var BABYLON;
          * @param count
          * @param min
          * @param max
-         *
-         * @returns {_IGLTFAccessor}
+         * @returns - accessor for glTF
          */
         _GLTF2Exporter.prototype.createAccessor = function (bufferviewIndex, name, type, componentType, count, min, max) {
             var accessor = { name: name, bufferView: bufferviewIndex, componentType: componentType, count: count, type: type };
@@ -240,8 +278,7 @@ var BABYLON;
          * @param vertexCount
          * @param arrayOffset
          * @param stride
-         *
-         * @returns {min: number[], max: number[]} min number array and max number array
+         * @returns - min number array and max number array
          */
         _GLTF2Exporter.prototype.calculateMinMax = function (buff, vertexStart, vertexCount, arrayOffset, stride) {
             var min = [Infinity, Infinity, Infinity];
@@ -273,8 +310,7 @@ var BABYLON;
          * @param byteOffset
          * @param dataBuffer
          * @param useRightHandedSystem
-         *
-         * @returns {number} byte length
+         * @returns - byte length
          */
         _GLTF2Exporter.prototype.writeAttributeData = function (vertexBufferType, submesh, meshAttributeArray, strideSize, byteOffset, dataBuffer, useRightHandedSystem) {
             var byteOff = byteOffset;
@@ -385,23 +421,65 @@ var BABYLON;
          * @param glb
          * @param glTFPrefix
          * @param prettyPrint
-         *
-         * @returns {string} json data as string
+         * @returns - json data as string
          */
         _GLTF2Exporter.prototype.generateJSON = function (glb, glTFPrefix, prettyPrint) {
             var buffer = { byteLength: this.totalByteLength };
             var glTF = {
-                buffers: [buffer],
-                asset: this.asset,
-                meshes: this.meshes,
-                scenes: this.scenes,
-                nodes: this.nodes,
-                bufferViews: this.bufferViews,
-                accessors: this.accessors
+                asset: this.asset
             };
-            if (this.scenes.length > 0) {
+            if (buffer.byteLength > 0) {
+                glTF.buffers = [buffer];
+            }
+            if (this.nodes && this.nodes.length !== 0) {
+                glTF.nodes = this.nodes;
+            }
+            if (this.meshes && this.meshes.length !== 0) {
+                glTF.meshes = this.meshes;
+            }
+            if (this.scenes && this.scenes.length !== 0) {
+                glTF.scenes = this.scenes;
                 glTF.scene = 0;
             }
+            if (this.bufferViews && this.bufferViews.length !== 0) {
+                glTF.bufferViews = this.bufferViews;
+            }
+            if (this.accessors && this.accessors.length !== 0) {
+                glTF.accessors = this.accessors;
+            }
+            if (this.materials && this.materials.length !== 0) {
+                glTF.materials = this.materials;
+            }
+            if (this.textures && this.textures.length !== 0) {
+                glTF.textures = this.textures;
+            }
+            if (this.images && this.images.length !== 0) {
+                if (!glb) {
+                    glTF.images = this.images;
+                }
+                else {
+                    glTF.images = [];
+                    // Replace uri with bufferview and mime type for glb
+                    var imageLength = this.images.length;
+                    var byteOffset = this.totalByteLength;
+                    for (var i = 0; i < imageLength; ++i) {
+                        var image = this.images[i];
+                        if (image.uri !== undefined) {
+                            var imageData = this.imageData[image.uri];
+                            var imageName = image.uri.split('.')[0] + " image";
+                            var bufferView = this.createBufferView(0, byteOffset, imageData.data.length, imageName);
+                            byteOffset += imageData.data.buffer.byteLength;
+                            this.bufferViews.push(bufferView);
+                            image.bufferView = this.bufferViews.length - 1;
+                            image.name = imageName;
+                            image.mimeType = imageData.mimeType;
+                            image.uri = undefined;
+                            glTF.images.push(image);
+                        }
+                    }
+                    buffer.byteLength = byteOffset;
+                }
+            }
             if (!glb) {
                 buffer.uri = glTFPrefix + ".bin";
             }
@@ -411,8 +489,7 @@ var BABYLON;
         /**
          * Generates data for .gltf and .bin files based on the glTF prefix string
          * @param glTFPrefix
-         *
-         * @returns {[x: string]: string | Blob} object with glTF json tex filename
+         * @returns - object with glTF json tex filename
          * and binary file name as keys and their data as values
          */
         _GLTF2Exporter.prototype._generateGLTF = function (glTFPrefix) {
@@ -422,14 +499,18 @@ var BABYLON;
             var glTFFileName = glTFPrefix + '.gltf';
             var glTFBinFile = glTFPrefix + '.bin';
             var container = new BABYLON._GLTFData();
-            container._glTFFiles[glTFFileName] = jsonText;
-            container._glTFFiles[glTFBinFile] = bin;
+            container.glTFFiles[glTFFileName] = jsonText;
+            container.glTFFiles[glTFBinFile] = bin;
+            if (this.imageData !== null) {
+                for (var image in this.imageData) {
+                    container.glTFFiles[image] = new Blob([this.imageData[image].data], { type: this.imageData[image].mimeType });
+                }
+            }
             return container;
         };
         /**
          * Creates a binary buffer for glTF
-         *
-         * @returns {ArrayBuffer}
+         * @returns - array buffer for binary data
          */
         _GLTF2Exporter.prototype.generateBinary = function () {
             var byteOffset = 0;
@@ -439,13 +520,22 @@ var BABYLON;
             return binaryBuffer;
         };
         /**
+         * Pads the number to a power of 4
+         * @param num - number to pad
+         * @returns - padded number
+         */
+        _GLTF2Exporter.prototype._getPadding = function (num) {
+            var remainder = num % 4;
+            var padding = remainder === 0 ? remainder : 4 - remainder;
+            return padding;
+        };
+        /**
          * Generates a glb file from the json and binary data.
          * Returns an object with the glb file name as the key and data as the value.
          * @param jsonText
          * @param binaryBuffer
          * @param glTFPrefix
-         *
-         * @returns {[glbFileName: string]: Blob} object with glb filename as key and data as value
+         * @returns - object with glb filename as key and data as value
          */
         _GLTF2Exporter.prototype._generateGLB = function (glTFPrefix) {
             var jsonText = this.generateJSON(true);
@@ -454,11 +544,13 @@ var BABYLON;
             var headerLength = 12;
             var chunkLengthPrefix = 8;
             var jsonLength = jsonText.length;
-            var jsonRemainder = jsonLength % 4;
-            var binRemainder = binaryBuffer.byteLength % 4;
-            var jsonPadding = jsonRemainder === 0 ? jsonRemainder : 4 - jsonRemainder;
-            var binPadding = binRemainder === 0 ? binRemainder : 4 - binRemainder;
-            var byteLength = headerLength + (2 * chunkLengthPrefix) + jsonLength + jsonPadding + binaryBuffer.byteLength + binPadding;
+            var imageByteLength = 0;
+            for (var key in this.imageData) {
+                imageByteLength += this.imageData[key].data.byteLength;
+            }
+            var jsonPadding = this._getPadding(jsonLength);
+            var binPadding = this._getPadding(binaryBuffer.byteLength);
+            var byteLength = headerLength + (2 * chunkLengthPrefix) + jsonLength + jsonPadding + binaryBuffer.byteLength + binPadding + imageByteLength;
             //header
             var headerBuffer = new ArrayBuffer(headerLength);
             var headerBufferView = new DataView(headerBuffer);
@@ -483,7 +575,7 @@ var BABYLON;
             //binary chunk
             var binaryChunkBuffer = new ArrayBuffer(chunkLengthPrefix);
             var binaryChunkBufferView = new DataView(binaryChunkBuffer);
-            binaryChunkBufferView.setUint32(0, binaryBuffer.byteLength, true);
+            binaryChunkBufferView.setUint32(0, binaryBuffer.byteLength + imageByteLength, true);
             binaryChunkBufferView.setUint32(4, 0x004E4942, true);
             // binary padding
             var binPaddingBuffer = new ArrayBuffer(binPadding);
@@ -491,10 +583,15 @@ var BABYLON;
             for (var i = 0; i < binPadding; ++i) {
                 binPaddingView[i] = 0;
             }
+            var glbData = [headerBuffer, jsonChunkBuffer, binaryChunkBuffer, binaryBuffer];
             // binary data
-            var glbFile = new Blob([headerBuffer, jsonChunkBuffer, binaryChunkBuffer, binaryBuffer, binPaddingBuffer], { type: 'application/octet-stream' });
+            for (var key in this.imageData) {
+                glbData.push(this.imageData[key].data.buffer);
+            }
+            glbData.push(binPaddingBuffer);
+            var glbFile = new Blob(glbData, { type: 'application/octet-stream' });
             var container = new BABYLON._GLTFData();
-            container._glTFFiles[glbFileName] = glbFile;
+            container.glTFFiles[glbFileName] = glbFile;
             return container;
         };
         /**
@@ -534,14 +631,90 @@ var BABYLON;
             }
         };
         /**
+         *
+         * @param babylonTexture
+         * @return - glTF texture, or null if the texture format is not supported
+         */
+        _GLTF2Exporter.prototype.exportTexture = function (babylonTexture, mimeType) {
+            if (mimeType === void 0) { mimeType = _EGLTFImageMimeTypeEnum.JPG; }
+            var textureInfo = null;
+            var glTFTexture;
+            glTFTexture = {
+                source: this.images.length
+            };
+            var textureName = babylonTexture.getInternalTexture().url;
+            if (textureName.search('/') !== -1) {
+                var splitFilename = textureName.split('/');
+                textureName = splitFilename[splitFilename.length - 1];
+                var basefile = textureName.split('.')[0];
+                var extension = textureName.split('.')[1];
+                if (mimeType === _EGLTFImageMimeTypeEnum.JPG) {
+                    extension = ".jpg";
+                }
+                else if (mimeType === _EGLTFImageMimeTypeEnum.PNG) {
+                    extension = ".png";
+                }
+                else {
+                    throw new Error("Unsupported mime type " + mimeType);
+                }
+                textureName = basefile + extension;
+            }
+            var pixels = babylonTexture.readPixels();
+            var imageCanvas = document.createElement('canvas');
+            imageCanvas.id = "ImageCanvas";
+            var ctx = imageCanvas.getContext('2d');
+            var size = babylonTexture.getSize();
+            imageCanvas.width = size.width;
+            imageCanvas.height = size.height;
+            var imgData = ctx.createImageData(size.width, size.height);
+            imgData.data.set(pixels);
+            ctx.putImageData(imgData, 0, 0);
+            var base64Data = imageCanvas.toDataURL(mimeType);
+            var binStr = atob(base64Data.split(',')[1]);
+            var arr = new Uint8Array(binStr.length);
+            for (var i = 0; i < binStr.length; ++i) {
+                arr[i] = binStr.charCodeAt(i);
+            }
+            var imageValues = { data: arr, mimeType: mimeType };
+            this.imageData[textureName] = imageValues;
+            if (mimeType === _EGLTFImageMimeTypeEnum.JPG) {
+                var glTFImage = {
+                    uri: textureName
+                };
+                var foundIndex = -1;
+                for (var i = 0; i < this.images.length; ++i) {
+                    if (this.images[i].uri === textureName) {
+                        foundIndex = i;
+                        break;
+                    }
+                }
+                if (foundIndex === -1) {
+                    this.images.push(glTFImage);
+                    glTFTexture.source = this.images.length - 1;
+                    this.textures.push({
+                        source: this.images.length - 1
+                    });
+                    textureInfo = {
+                        index: this.images.length - 1
+                    };
+                }
+                else {
+                    glTFTexture.source = foundIndex;
+                    textureInfo = {
+                        index: foundIndex
+                    };
+                }
+            }
+            return textureInfo;
+        };
+        /**
          * Sets data for the primitive attributes of each submesh
          * @param mesh
          * @param babylonMesh
          * @param byteOffset
          * @param useRightHandedSystem
          * @param dataBuffer
-         *
-         * @returns {number} bytelength of the primitive attributes plus the passed in byteOffset
+         * @returns - bytelength of the primitive attributes plus the passed in byteOffset
          */
         _GLTF2Exporter.prototype.setPrimitiveAttributes = function (mesh, babylonMesh, byteOffset, useRightHandedSystem, dataBuffer) {
             // go through all mesh primitives (submeshes)
@@ -567,7 +740,7 @@ var BABYLON;
                     else {
                         // Create bufferview
                         var byteLength = submesh.verticesCount * 12;
-                        var bufferview = this.createBufferView(0, byteOffset, byteLength);
+                        var bufferview = this.createBufferView(0, byteOffset, byteLength, "Positions");
                         byteOffset += byteLength;
                         this.bufferViews.push(bufferview);
                         // Create accessor
@@ -587,7 +760,7 @@ var BABYLON;
                     else {
                         // Create bufferview
                         var byteLength = submesh.verticesCount * 12;
-                        var bufferview = this.createBufferView(0, byteOffset, byteLength);
+                        var bufferview = this.createBufferView(0, byteOffset, byteLength, "Normals");
                         byteOffset += byteLength;
                         this.bufferViews.push(bufferview);
                         // Create accessor
@@ -606,7 +779,7 @@ var BABYLON;
                     else {
                         // Create bufferview
                         var byteLength = submesh.verticesCount * 16;
-                        var bufferview = this.createBufferView(0, byteOffset, byteLength);
+                        var bufferview = this.createBufferView(0, byteOffset, byteLength, "Tangents");
                         byteOffset += byteLength;
                         this.bufferViews.push(bufferview);
                         // Create accessor
@@ -625,7 +798,7 @@ var BABYLON;
                     else {
                         // Create bufferview
                         var byteLength = submesh.verticesCount * 16;
-                        var bufferview = this.createBufferView(0, byteOffset, byteLength);
+                        var bufferview = this.createBufferView(0, byteOffset, byteLength, "Colors");
                         byteOffset += byteLength;
                         this.bufferViews.push(bufferview);
                         // Create accessor
@@ -644,7 +817,7 @@ var BABYLON;
                     else {
                         // Create bufferview
                         var byteLength = submesh.verticesCount * 8;
-                        var bufferview = this.createBufferView(0, byteOffset, byteLength);
+                        var bufferview = this.createBufferView(0, byteOffset, byteLength, "Texture Coords0");
                         byteOffset += byteLength;
                         this.bufferViews.push(bufferview);
                         // Create accessor
@@ -663,7 +836,7 @@ var BABYLON;
                     else {
                         // Create bufferview
                         var byteLength = submesh.verticesCount * 8;
-                        var bufferview = this.createBufferView(0, byteOffset, byteLength);
+                        var bufferview = this.createBufferView(0, byteOffset, byteLength, "Texture Coords 1");
                         byteOffset += byteLength;
                         this.bufferViews.push(bufferview);
                         // Create accessor
@@ -693,7 +866,7 @@ var BABYLON;
                         // Create bufferview
                         var indicesCount = submesh.indexCount;
                         var byteLength = indicesCount * 4;
-                        var bufferview = this.createBufferView(0, byteOffset, byteLength);
+                        var bufferview = this.createBufferView(0, byteOffset, byteLength, "Indices");
                         byteOffset += byteLength;
                         this.bufferViews.push(bufferview);
                         // Create accessor
@@ -703,7 +876,127 @@ var BABYLON;
                     }
                 }
                 if (bufferMesh.material) {
-                    //TODO: Implement Material
+                    if (bufferMesh.material instanceof BABYLON.StandardMaterial) {
+                        var babylonStandardMaterial = bufferMesh.material;
+                        var glTFMaterial = { name: babylonStandardMaterial.name };
+                        if (!babylonStandardMaterial.backFaceCulling) {
+                            glTFMaterial.doubleSided = true;
+                        }
+                        if (babylonStandardMaterial.bumpTexture) {
+                            var glTFTexture = this.exportTexture(babylonStandardMaterial.bumpTexture);
+                            if (glTFTexture) {
+                                glTFMaterial.normalTexture = glTFTexture;
+                            }
+                        }
+                        if (babylonStandardMaterial.emissiveTexture) {
+                            var glTFEmissiveTexture = this.exportTexture(babylonStandardMaterial.emissiveTexture);
+                            if (glTFEmissiveTexture) {
+                                glTFMaterial.emissiveTexture = glTFEmissiveTexture;
+                            }
+                            glTFMaterial.emissiveFactor = [1.0, 1.0, 1.0];
+                        }
+                        if (babylonStandardMaterial.ambientTexture) {
+                            var glTFOcclusionTexture = this.exportTexture(babylonStandardMaterial.ambientTexture);
+                            if (glTFOcclusionTexture) {
+                                glTFMaterial.occlusionTexture = glTFOcclusionTexture;
+                            }
+                        }
+                        // Spec Gloss
+                        var babylonSpecularGlossiness = {
+                            diffuse: babylonStandardMaterial.diffuseColor,
+                            opacity: babylonStandardMaterial.alpha,
+                            specular: babylonStandardMaterial.specularColor || BABYLON.Color3.Black(),
+                            glossiness: babylonStandardMaterial.specularPower / 256
+                        };
+                        if (babylonStandardMaterial.specularTexture) {
+                        }
+                        var babylonMetallicRoughness = BABYLON._GLTFMaterial.ConvertToMetallicRoughness(babylonSpecularGlossiness);
+                        var glTFPbrMetallicRoughness = {
+                            baseColorFactor: [
+                                babylonMetallicRoughness.baseColor.r,
+                                babylonMetallicRoughness.baseColor.g,
+                                babylonMetallicRoughness.baseColor.b,
+                                babylonMetallicRoughness.opacity
+                            ],
+                            metallicFactor: babylonMetallicRoughness.metallic,
+                            roughnessFactor: babylonMetallicRoughness.roughness
+                        };
+                        glTFMaterial.pbrMetallicRoughness = glTFPbrMetallicRoughness;
+                        // TODO: Handle Textures
+                        this.materials.push(glTFMaterial);
+                        meshPrimitive.material = this.materials.length - 1;
+                    }
+                    else if (bufferMesh.material instanceof BABYLON.PBRMetallicRoughnessMaterial) {
+                        if (!this.textures) {
+                            this.textures = new Array();
+                        }
+                        var babylonPBRMaterial = bufferMesh.material;
+                        var glTFPbrMetallicRoughness = {};
+                        if (babylonPBRMaterial.baseColor) {
+                            glTFPbrMetallicRoughness.baseColorFactor = [
+                                babylonPBRMaterial.baseColor.r,
+                                babylonPBRMaterial.baseColor.g,
+                                babylonPBRMaterial.baseColor.b,
+                                babylonPBRMaterial.alpha
+                            ];
+                        }
+                        if (babylonPBRMaterial.baseTexture !== undefined) {
+                            var glTFTexture = this.exportTexture(babylonPBRMaterial.baseTexture);
+                            if (glTFTexture !== null) {
+                                glTFPbrMetallicRoughness.baseColorTexture = glTFTexture;
+                            }
+                            glTFPbrMetallicRoughness.baseColorTexture;
+                        }
+                        if (babylonPBRMaterial.metallic !== undefined) {
+                            glTFPbrMetallicRoughness.metallicFactor = babylonPBRMaterial.metallic;
+                        }
+                        if (babylonPBRMaterial.roughness !== undefined) {
+                            glTFPbrMetallicRoughness.roughnessFactor = babylonPBRMaterial.roughness;
+                        }
+                        var glTFMaterial = {
+                            name: babylonPBRMaterial.name
+                        };
+                        if (babylonPBRMaterial.doubleSided) {
+                            glTFMaterial.doubleSided = babylonPBRMaterial.doubleSided;
+                        }
+                        if (babylonPBRMaterial.normalTexture) {
+                            var glTFTexture = this.exportTexture(babylonPBRMaterial.normalTexture);
+                            if (glTFTexture) {
+                                glTFMaterial.normalTexture = glTFTexture;
+                            }
+                        }
+                        if (babylonPBRMaterial.occlusionTexture) {
+                            var glTFTexture = this.exportTexture(babylonPBRMaterial.occlusionTexture);
+                            if (glTFTexture) {
+                                glTFMaterial.occlusionTexture = glTFTexture;
+                                if (babylonPBRMaterial.occlusionStrength !== undefined) {
+                                    glTFMaterial.occlusionTexture.strength = babylonPBRMaterial.occlusionStrength;
+                                }
+                            }
+                        }
+                        if (babylonPBRMaterial.emissiveTexture) {
+                            var glTFTexture = this.exportTexture(babylonPBRMaterial.emissiveTexture);
+                            if (glTFTexture !== null) {
+                                glTFMaterial.emissiveTexture = glTFTexture;
+                            }
+                        }
+                        if (!babylonPBRMaterial.emissiveColor.equals(new BABYLON.Color3(0.0, 0.0, 0.0))) {
+                            glTFMaterial.emissiveFactor = babylonPBRMaterial.emissiveColor.asArray();
+                        }
+                        if (babylonPBRMaterial.transparencyMode) {
+                            var alphaMode = BABYLON._GLTFMaterial.GetAlphaMode(babylonPBRMaterial);
+                            if (alphaMode !== _EGLTFAlphaModeEnum.OPAQUE) {
+                                glTFMaterial.alphaMode = alphaMode;
+                                if (alphaMode === _EGLTFAlphaModeEnum.BLEND) {
+                                    glTFMaterial.alphaCutoff = babylonPBRMaterial.alphaCutOff;
+                                }
+                            }
+                        }
+                        glTFMaterial.pbrMetallicRoughness = glTFPbrMetallicRoughness;
+                        // TODO: Handle Textures
+                        this.materials.push(glTFMaterial);
+                        meshPrimitive.material = this.materials.length - 1;
+                    }
                 }
                 mesh.primitives.push(meshPrimitive);
             }
@@ -716,32 +1009,38 @@ var BABYLON;
          * @param byteOffset
          * @param buffer
          * @param dataBuffer
-         *
-         * @returns {number} bytelength + byteoffset
+         * @returns bytelength + byteoffset
          */
         _GLTF2Exporter.prototype.createScene = function (babylonScene, byteOffset, dataBuffer) {
             if (babylonScene.meshes.length > 0) {
                 var babylonMeshes = babylonScene.meshes;
                 var scene = { nodes: new Array() };
                 for (var i = 0; i < babylonMeshes.length; ++i) {
-                    // create node to hold translation/rotation/scale and the mesh
-                    var node = { mesh: -1 };
-                    var babylonMesh = babylonMeshes[i];
-                    var useRightHandedSystem = babylonMesh.getScene().useRightHandedSystem;
-                    // Set transformation
-                    this.setNodeTransformation(node, babylonMesh, useRightHandedSystem);
-                    // create mesh
-                    var mesh = { primitives: new Array() };
-                    mesh.primitives = [];
-                    byteOffset = this.setPrimitiveAttributes(mesh, babylonMesh, byteOffset, useRightHandedSystem, dataBuffer);
-                    // go through all mesh primitives (submeshes)
-                    this.meshes.push(mesh);
-                    node.mesh = this.meshes.length - 1;
-                    if (babylonMesh.name) {
-                        node.name = babylonMesh.name;
-                    }
-                    this.nodes.push(node);
-                    scene.nodes.push(this.nodes.length - 1);
+                    if (this.options &&
+                        this.options.shouldExportMesh !== undefined &&
+                        !this.options.shouldExportMesh(babylonMeshes[i])) {
+                        continue;
+                    }
+                    else {
+                        // create node to hold translation/rotation/scale and the mesh
+                        var node = { mesh: -1 };
+                        var babylonMesh = babylonMeshes[i];
+                        var useRightHandedSystem = babylonMesh.getScene().useRightHandedSystem;
+                        // Set transformation
+                        this.setNodeTransformation(node, babylonMesh, useRightHandedSystem);
+                        // create mesh
+                        var mesh = { primitives: new Array() };
+                        mesh.primitives = [];
+                        byteOffset = this.setPrimitiveAttributes(mesh, babylonMesh, byteOffset, useRightHandedSystem, dataBuffer);
+                        // go through all mesh primitives (submeshes)
+                        this.meshes.push(mesh);
+                        node.mesh = this.meshes.length - 1;
+                        if (babylonMesh.name) {
+                            node.name = babylonMesh.name;
+                        }
+                        this.nodes.push(node);
+                        scene.nodes.push(this.nodes.length - 1);
+                    }
                 }
                 this.scenes.push(scene);
             }
@@ -761,7 +1060,7 @@ var BABYLON;
      */
     var _GLTFData = /** @class */ (function () {
         function _GLTFData() {
-            this._glTFFiles = {};
+            this.glTFFiles = {};
         }
         /**
          * Downloads glTF data.
@@ -771,18 +1070,17 @@ var BABYLON;
             * Checks for a matching suffix at the end of a string (for ES5 and lower)
             * @param str
             * @param suffix
-            *
-            * @returns {boolean} indicating whether the suffix matches or not
+            * @returns - indicating whether the suffix matches or not
             */
             function endsWith(str, suffix) {
                 return str.indexOf(suffix, str.length - suffix.length) !== -1;
             }
-            for (var key in this._glTFFiles) {
+            for (var key in this.glTFFiles) {
                 var link = document.createElement('a');
                 document.body.appendChild(link);
                 link.setAttribute("type", "hidden");
                 link.download = key;
-                var blob = this._glTFFiles[key];
+                var blob = this.glTFFiles[key];
                 var mimeType = void 0;
                 if (endsWith(key, ".glb")) {
                     mimeType = { type: "model/gltf-binary" };
@@ -804,6 +1102,118 @@ var BABYLON;
 
 //# sourceMappingURL=babylon.glTFData.js.map
 
+var BABYLON;
+(function (BABYLON) {
+    /**
+     * Utility methods for working with glTF material conversion properties
+     */
+    var _GLTFMaterial = /** @class */ (function () {
+        function _GLTFMaterial() {
+        }
+        /**
+         * Converts Specular Glossiness to Metallic Roughness
+         * @param  babylonSpecularGlossiness - Babylon specular glossiness parameters
+         * @returns - Babylon metallic roughness values
+         */
+        _GLTFMaterial.ConvertToMetallicRoughness = function (babylonSpecularGlossiness) {
+            var diffuse = babylonSpecularGlossiness.diffuse;
+            var opacity = babylonSpecularGlossiness.opacity;
+            var specular = babylonSpecularGlossiness.specular;
+            var glossiness = babylonSpecularGlossiness.glossiness;
+            var oneMinusSpecularStrength = 1 - Math.max(specular.r, Math.max(specular.g, specular.b));
+            var diffusePerceivedBrightness = _GLTFMaterial.PerceivedBrightness(diffuse);
+            var specularPerceivedBrightness = _GLTFMaterial.PerceivedBrightness(specular);
+            var metallic = _GLTFMaterial.SolveMetallic(diffusePerceivedBrightness, specularPerceivedBrightness, oneMinusSpecularStrength);
+            var diffuseScaleFactor = oneMinusSpecularStrength / (1 - this.dielectricSpecular.r) / Math.max(1 - metallic, this.epsilon);
+            var baseColorFromDiffuse = diffuse.scale(diffuseScaleFactor);
+            var baseColorFromSpecular = specular.subtract(this.dielectricSpecular.scale(1 - metallic)).scale(1 / Math.max(metallic, this.epsilon));
+            var lerpColor = BABYLON.Color3.Lerp(baseColorFromDiffuse, baseColorFromSpecular, metallic * metallic);
+            var baseColor = new BABYLON.Color3();
+            lerpColor.clampToRef(0, 1, baseColor);
+            var babylonMetallicRoughness = {
+                baseColor: baseColor,
+                opacity: opacity,
+                metallic: metallic,
+                roughness: 1.0 - glossiness
+            };
+            return babylonMetallicRoughness;
+        };
+        /**
+         * Returns the perceived brightness value based on the provided color
+         * @param color - color used in calculating the perceived brightness
+         * @returns - perceived brightness value
+         */
+        _GLTFMaterial.PerceivedBrightness = function (color) {
+            return Math.sqrt(0.299 * color.r * color.r + 0.587 * color.g * color.g + 0.114 * color.b * color.b);
+        };
+        /**
+         * Computes the metallic factor
+         * @param diffuse - diffused value
+         * @param specular - specular value
+         * @param oneMinusSpecularStrength - one minus the specular strength
+         * @returns - metallic value
+         */
+        _GLTFMaterial.SolveMetallic = function (diffuse, specular, oneMinusSpecularStrength) {
+            if (specular < this.dielectricSpecular.r) {
+                return 0;
+            }
+            var a = this.dielectricSpecular.r;
+            var b = diffuse * oneMinusSpecularStrength / (1.0 - this.dielectricSpecular.r) + specular - 2.0 * this.dielectricSpecular.r;
+            var c = this.dielectricSpecular.r - specular;
+            var D = b * b - 4.0 * a * c;
+            return BABYLON.Scalar.Clamp((-b + Math.sqrt(D)) / (2.0 * a));
+        };
+        /**
+         * Gets the glTF alpha mode from the Babylon Material
+         * @param babylonMaterial - Babylon Material
+         * @returns - The Babylon alpha mode value
+         */
+        _GLTFMaterial.GetAlphaMode = function (babylonMaterial) {
+            if (babylonMaterial instanceof BABYLON.StandardMaterial) {
+                var babylonStandardMaterial = babylonMaterial;
+                if ((babylonStandardMaterial.alpha != 1.0) ||
+                    (babylonStandardMaterial.diffuseTexture != null && babylonStandardMaterial.diffuseTexture.hasAlpha) ||
+                    (babylonStandardMaterial.opacityTexture != null)) {
+                    return BABYLON._EGLTFAlphaModeEnum.BLEND;
+                }
+                else {
+                    return BABYLON._EGLTFAlphaModeEnum.OPAQUE;
+                }
+            }
+            else if (babylonMaterial instanceof BABYLON.PBRMetallicRoughnessMaterial) {
+                var babylonPBRMetallicRoughness = babylonMaterial;
+                switch (babylonPBRMetallicRoughness.transparencyMode) {
+                    case BABYLON.PBRMaterial.PBRMATERIAL_OPAQUE: {
+                        return BABYLON._EGLTFAlphaModeEnum.OPAQUE;
+                    }
+                    case BABYLON.PBRMaterial.PBRMATERIAL_ALPHABLEND: {
+                        return BABYLON._EGLTFAlphaModeEnum.BLEND;
+                    }
+                    case BABYLON.PBRMaterial.PBRMATERIAL_ALPHATEST: {
+                        return BABYLON._EGLTFAlphaModeEnum.MASK;
+                    }
+                    case BABYLON.PBRMaterial.PBRMATERIAL_ALPHATESTANDBLEND: {
+                        console.warn("GLTF Exporter | Alpha test and blend mode not supported in glTF.  Alpha blend used instead.");
+                        return BABYLON._EGLTFAlphaModeEnum.BLEND;
+                    }
+                    default: {
+                        throw new Error("Unsupported alpha mode " + babylonPBRMetallicRoughness.transparencyMode);
+                    }
+                }
+            }
+            else {
+                throw new Error("Unsupported Babylon material type");
+            }
+        };
+        _GLTFMaterial.dielectricSpecular = new BABYLON.Color3(0.04, 0.04, 0.04);
+        _GLTFMaterial.epsilon = 1e-6;
+        return _GLTFMaterial;
+    }());
+    BABYLON._GLTFMaterial = _GLTFMaterial;
+})(BABYLON || (BABYLON = {}));
+
+//# sourceMappingURL=babylon.glTFMaterial.js.map
+
 
 (function universalModuleDefinition(root, factory) {
                 var f = factory();

File diff suppressed because it is too large
+ 1 - 1
dist/preview release/serializers/babylonjs.serializers.min.js


+ 111 - 31
dist/preview release/serializers/babylonjs.serializers.module.d.ts

@@ -14,29 +14,66 @@ declare module BABYLON {
 
 
 declare module BABYLON {
+    interface IGLTFExporterOptions {
+        /**
+         * Interface function which indicates whether a babylon mesh should be exported or not.
+         * @param mesh
+         * @returns boolean, which indicates whether the mesh should be exported (true) or not (false)
+         */
+        shouldExportMesh?(mesh: AbstractMesh): boolean;
+    }
     class GLTF2Export {
         /**
          * Exports the geometry of a Mesh array in .gltf file format.
-         * If glb is set to true, exports as .glb.
          * @param meshes
          * @param materials
+         * @param options
          *
-         * @returns {[fileName: string]: string | Blob} Returns an object with a .gltf, .glb and associates textures
+         * @returns - Returns an object with a .gltf, .glb and associates textures
          * as keys and their data and paths as values.
          */
-        static GLTF(scene: BABYLON.Scene, filename: string): _GLTFData;
+        static GLTF(scene: Scene, filename: string, options?: IGLTFExporterOptions): _GLTFData;
         /**
          *
          * @param meshes
          * @param filename
          *
-         * @returns {[fileName: string]: string | Blob} Returns an object with a .glb filename as key and data as value
+         * @returns - Returns an object with a .glb filename as key and data as value
          */
-        static GLB(scene: BABYLON.Scene, filename: string): _GLTFData;
+        static GLB(scene: Scene, filename: string, options?: IGLTFExporterOptions): _GLTFData;
     }
 }
 
 declare module BABYLON {
+    /**
+     * glTF Alpha Mode Enum
+     */
+    enum _EGLTFAlphaModeEnum {
+        OPAQUE = "OPAQUE",
+        MASK = "MASK",
+        BLEND = "BLEND",
+    }
+    /**
+     * Babylon Specular Glossiness interface
+     */
+    interface _IBabylonSpecularGlossiness {
+        diffuse: Color3;
+        opacity: number;
+        specular: Color3;
+        glossiness: number;
+    }
+    /**
+     * Babylon Metallic Roughness interface
+     */
+    interface _IBabylonMetallicRoughness {
+        baseColor: Color3;
+        opacity: number;
+        metallic: number;
+        roughness: number;
+    }
+    /**
+     * Converts Babylon Scene into glTF 2.0
+     */
     class _GLTF2Exporter {
         private bufferViews;
         private accessors;
@@ -44,18 +81,22 @@ declare module BABYLON {
         private asset;
         private scenes;
         private meshes;
+        private materials;
+        private textures;
+        private images;
         private totalByteLength;
         private babylonScene;
-        constructor(babylonScene: BABYLON.Scene);
+        private options?;
+        private imageData;
+        constructor(babylonScene: Scene, options?: IGLTFExporterOptions);
         /**
          * Creates a buffer view based on teh supplied arguments
-         * @param bufferIndex
-         * @param byteOffset
-         * @param byteLength
-         *
-         * @returns {_IGLTFBufferView}
+         * @param {number} bufferIndex - index value of the specified buffer
+         * @param {number} byteOffset - byte offset value
+         * @param {number} byteLength - byte length of the bufferView
+         * @returns - bufferView for glTF
          */
-        private createBufferView(bufferIndex, byteOffset, byteLength);
+        private createBufferView(bufferIndex, byteOffset, byteLength, name?);
         /**
          * Creates an accessor based on the supplied arguments
          * @param bufferviewIndex
@@ -65,8 +106,7 @@ declare module BABYLON {
          * @param count
          * @param min
          * @param max
-         *
-         * @returns {_IGLTFAccessor}
+         * @returns - accessor for glTF
          */
         private createAccessor(bufferviewIndex, name, type, componentType, count, min?, max?);
         /**
@@ -76,8 +116,7 @@ declare module BABYLON {
          * @param vertexCount
          * @param arrayOffset
          * @param stride
-         *
-         * @returns {min: number[], max: number[]} min number array and max number array
+         * @returns - min number array and max number array
          */
         private calculateMinMax(buff, vertexStart, vertexCount, arrayOffset, stride);
         /**
@@ -90,8 +129,7 @@ declare module BABYLON {
          * @param byteOffset
          * @param dataBuffer
          * @param useRightHandedSystem
-         *
-         * @returns {number} byte length
+         * @returns - byte length
          */
         private writeAttributeData(vertexBufferType, submesh, meshAttributeArray, strideSize, byteOffset, dataBuffer, useRightHandedSystem);
         /**
@@ -99,32 +137,34 @@ declare module BABYLON {
          * @param glb
          * @param glTFPrefix
          * @param prettyPrint
-         *
-         * @returns {string} json data as string
+         * @returns - json data as string
          */
         private generateJSON(glb, glTFPrefix?, prettyPrint?);
         /**
          * Generates data for .gltf and .bin files based on the glTF prefix string
          * @param glTFPrefix
-         *
-         * @returns {[x: string]: string | Blob} object with glTF json tex filename
+         * @returns - object with glTF json tex filename
          * and binary file name as keys and their data as values
          */
         _generateGLTF(glTFPrefix: string): _GLTFData;
         /**
          * Creates a binary buffer for glTF
-         *
-         * @returns {ArrayBuffer}
+         * @returns - array buffer for binary data
          */
         private generateBinary();
         /**
+         * Pads the number to a power of 4
+         * @param num - number to pad
+         * @returns - padded number
+         */
+        private _getPadding(num);
+        /**
          * Generates a glb file from the json and binary data.
          * Returns an object with the glb file name as the key and data as the value.
          * @param jsonText
          * @param binaryBuffer
          * @param glTFPrefix
-         *
-         * @returns {[glbFileName: string]: Blob} object with glb filename as key and data as value
+         * @returns - object with glb filename as key and data as value
          */
         _generateGLB(glTFPrefix: string): _GLTFData;
         /**
@@ -135,14 +175,19 @@ declare module BABYLON {
          */
         private setNodeTransformation(node, babylonMesh, useRightHandedSystem);
         /**
+         *
+         * @param babylonTexture
+         * @return - glTF texture, or null if the texture format is not supported
+         */
+        private exportTexture(babylonTexture, mimeType?);
+        /**
          * Sets data for the primitive attributes of each submesh
          * @param mesh
          * @param babylonMesh
          * @param byteOffset
          * @param useRightHandedSystem
          * @param dataBuffer
-         *
-         * @returns {number} bytelength of the primitive attributes plus the passed in byteOffset
+         * @returns - bytelength of the primitive attributes plus the passed in byteOffset
          */
         private setPrimitiveAttributes(mesh, babylonMesh, byteOffset, useRightHandedSystem, dataBuffer?);
         /**
@@ -152,8 +197,7 @@ declare module BABYLON {
          * @param byteOffset
          * @param buffer
          * @param dataBuffer
-         *
-         * @returns {number} bytelength + byteoffset
+         * @returns bytelength + byteoffset
          */
         private createScene(babylonScene, byteOffset, dataBuffer?);
     }
@@ -164,7 +208,7 @@ declare module BABYLON {
      * Class for holding and downloading glTF file data
      */
     class _GLTFData {
-        _glTFFiles: {
+        glTFFiles: {
             [fileName: string]: string | Blob;
         };
         constructor();
@@ -174,3 +218,39 @@ declare module BABYLON {
         downloadFiles(): void;
     }
 }
+
+declare module BABYLON {
+    /**
+     * Utility methods for working with glTF material conversion properties
+     */
+    class _GLTFMaterial {
+        private static dielectricSpecular;
+        private static epsilon;
+        /**
+         * Converts Specular Glossiness to Metallic Roughness
+         * @param  babylonSpecularGlossiness - Babylon specular glossiness parameters
+         * @returns - Babylon metallic roughness values
+         */
+        static ConvertToMetallicRoughness(babylonSpecularGlossiness: _IBabylonSpecularGlossiness): _IBabylonMetallicRoughness;
+        /**
+         * Returns the perceived brightness value based on the provided color
+         * @param color - color used in calculating the perceived brightness
+         * @returns - perceived brightness value
+         */
+        private static PerceivedBrightness(color);
+        /**
+         * Computes the metallic factor
+         * @param diffuse - diffused value
+         * @param specular - specular value
+         * @param oneMinusSpecularStrength - one minus the specular strength
+         * @returns - metallic value
+         */
+        static SolveMetallic(diffuse: number, specular: number, oneMinusSpecularStrength: number): number;
+        /**
+         * Gets the glTF alpha mode from the Babylon Material
+         * @param babylonMaterial - Babylon Material
+         * @returns - The Babylon alpha mode value
+         */
+        static GetAlphaMode(babylonMaterial: Material): string;
+    }
+}

+ 2 - 63
dist/preview release/typedocValidationBaseline.json

@@ -1,7 +1,7 @@
 {
-  "errors": 10550,
+  "errors": 10526,
   "babylon.typedoc.json": {
-    "errors": 10550,
+    "errors": 10526,
     "AnimationKeyInterpolation": {
       "Enumeration": {
         "Comments": {
@@ -7449,11 +7449,6 @@
             "MissingText": true
           }
         },
-        "upVector": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
         "viewport": {
           "Comments": {
             "MissingText": true
@@ -7977,18 +7972,6 @@
         }
       },
       "Method": {
-        "add": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "input": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
         "attachElement": {
           "Comments": {
             "MissingText": true
@@ -8018,11 +8001,6 @@
             }
           }
         },
-        "clear": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
         "detachElement": {
           "Comments": {
             "MissingText": true
@@ -8057,18 +8035,6 @@
             "MissingText": true
           }
         },
-        "remove": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "inputToRemove": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
         "removeByType": {
           "Comments": {
             "MissingText": true
@@ -17760,11 +17726,6 @@
             "MissingText": true
           }
         },
-        "angularSensibility": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
         "applyGravity": {
           "Comments": {
             "MissingText": true
@@ -17891,11 +17852,6 @@
       }
     },
     "FreeCameraDeviceOrientationInput": {
-      "Class": {
-        "Comments": {
-          "MissingText": true
-        }
-      },
       "Constructor": {
         "new FreeCameraDeviceOrientationInput": {
           "Comments": {
@@ -54262,29 +54218,12 @@
           "MissingText": true
         }
       },
-      "Property": {
-        "video": {
-          "Comments": {
-            "MissingText": true
-          }
-        }
-      },
       "Method": {
-        "_rebuild": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
         "dispose": {
           "Comments": {
             "MissingText": true
           }
         },
-        "update": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
         "CreateFromWebCam": {
           "Comments": {
             "MissingText": true

File diff suppressed because it is too large
+ 47 - 47
dist/preview release/viewer/babylon.viewer.js