فهرست منبع

Merge branch 'master' into addRemoveCameraDefaultPipeline

Trevor Baron 7 سال پیش
والد
کامیت
ea6fa0aff6
46فایلهای تغییر یافته به همراه16100 افزوده شده و 15242 حذف شده
  1. 1797 1798
      Playground/babylon.d.txt
  2. 1 4
      Tools/Gulp/config.json
  3. 20 0
      Viewer/assets/templates/default/navbar.html
  4. 4 0
      Viewer/src/configuration/mappers.ts
  5. 1 1
      Viewer/src/templating/templateManager.ts
  6. 11619 11613
      dist/preview release/babylon.d.ts
  7. 37 37
      dist/preview release/babylon.js
  8. 195 43
      dist/preview release/babylon.max.js
  9. 195 43
      dist/preview release/babylon.no-module.max.js
  10. 37 37
      dist/preview release/babylon.worker.js
  11. 195 43
      dist/preview release/es6.js
  12. 9 4
      dist/preview release/loaders/babylon.objFileLoader.d.ts
  13. 60 44
      dist/preview release/loaders/babylon.objFileLoader.js
  14. 1 1
      dist/preview release/loaders/babylon.objFileLoader.min.js
  15. 9 4
      dist/preview release/loaders/babylonjs.loaders.d.ts
  16. 60 44
      dist/preview release/loaders/babylonjs.loaders.js
  17. 4 4
      dist/preview release/loaders/babylonjs.loaders.min.js
  18. 9 4
      dist/preview release/loaders/babylonjs.loaders.module.d.ts
  19. 69 82
      dist/preview release/serializers/babylon.glTF2Serializer.d.ts
  20. 350 315
      dist/preview release/serializers/babylon.glTF2Serializer.js
  21. 2 2
      dist/preview release/serializers/babylon.glTF2Serializer.min.js
  22. 69 82
      dist/preview release/serializers/babylonjs.serializers.d.ts
  23. 350 315
      dist/preview release/serializers/babylonjs.serializers.js
  24. 2 2
      dist/preview release/serializers/babylonjs.serializers.min.js
  25. 69 82
      dist/preview release/serializers/babylonjs.serializers.module.d.ts
  26. 65 65
      dist/preview release/viewer/babylon.viewer.js
  27. 265 91
      dist/preview release/viewer/babylon.viewer.max.js
  28. 4 1
      dist/preview release/what's new.md
  29. 153 125
      serializers/src/glTF/2.0/babylon.glTFExporter.ts
  30. 229 208
      serializers/src/glTF/2.0/babylon.glTFMaterial.ts
  31. 0 10
      serializers/src/glTF/2.0/shaders/setAlphaToOne.fragment.fx
  32. 16 2
      src/Collisions/babylon.pickingInfo.ts
  33. 17 6
      src/Engine/babylon.engine.ts
  34. 32 6
      src/Gizmos/babylon.axisDragGizmo.ts
  35. 39 7
      src/Gizmos/babylon.axisScaleGizmo.ts
  36. 16 0
      src/Gizmos/babylon.boundingBoxGizmo.ts
  37. 12 13
      src/Gizmos/babylon.gizmo.ts
  38. 43 14
      src/Gizmos/babylon.planeRotationGizmo.ts
  39. 7 10
      src/Gizmos/babylon.positionGizmo.ts
  40. 6 9
      src/Gizmos/babylon.rotationGizmo.ts
  41. 6 9
      src/Gizmos/babylon.scaleGizmo.ts
  42. 3 1
      src/Materials/Textures/babylon.renderTargetTexture.ts
  43. 9 0
      src/Mesh/babylon.mesh.vertexData.ts
  44. 7 2
      src/Particles/babylon.particleSystem.ts
  45. 3 3
      src/Tools/babylon.khronosTextureContainer.ts
  46. 4 56
      tests/unit/babylon/serializers/babylon.glTFSerializer.tests.ts

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1797 - 1798
Playground/babylon.d.txt


+ 1 - 4
Tools/Gulp/config.json

@@ -1691,13 +1691,10 @@
                     "../../serializers/src/glTF/2.0/babylon.glTFSerializer.ts",
                     "../../serializers/src/glTF/2.0/babylon.glTFExporter.ts",
                     "../../serializers/src/glTF/2.0/babylon.glTFData.ts",
-                    "../../serializers/src/glTF/2.0/babylon.glTFMaterial.ts",
+                    "../../serializers/src/glTF/2.0/babylon.glTFMaterialExporter.ts",
                     "../../serializers/src/glTF/2.0/babylon.glTFAnimation.ts",
                     "../../serializers/src/glTF/2.0/babylon.glTFUtilities.ts"
                 ],
-                "shaderFiles": [
-                    "../../serializers/src/glTF/2.0/shaders/setAlphaToOne.fragment.fx"
-                ],
                 "output": "babylon.glTF2Serializer.js"
             }
         ],

+ 20 - 0
Viewer/assets/templates/default/navbar.html

@@ -139,6 +139,26 @@
         content: "\E740";
     }
 
+    /*
+    A few browsers dont support combining the next rule to one. Redudant.
+    */
+
+    viewer:fullscreen .fullscreen-icon:after {
+        content: "\E73F";
+    }
+
+    viewer:-webkit-full-screen .fullscreen-icon:after {
+        content: "\E73F";
+    }
+
+    viewer:-moz-full-screen .fullscreen-icon:after {
+        content: "\E73F";
+    }
+
+    viewer:-ms-full-screen .fullscreen-icon:after {
+        content: "\E73F";
+    }
+
     .help-icon:after {
         font-size: 16px;
         content: "\EF4E";

+ 4 - 0
Viewer/src/configuration/mappers.ts

@@ -52,6 +52,10 @@ class HTMLMapper implements IMapper {
                         val = true;
                     } else if (val === "false") {
                         val = false;
+                    } else if (val === "undefined") {
+                        val = undefined;
+                    } else if (val === "null") {
+                        val = null;
                     } else {
                         var isnum = !isNaN(parseFloat(val)) && isFinite(val);///^\d+$/.test(val);
                         if (isnum) {

+ 1 - 1
Viewer/src/templating/templateManager.ts

@@ -530,7 +530,7 @@ export class Template {
     private _getTemplateAsHtml(templateConfig: ITemplateConfiguration): Promise<string> {
         if (!templateConfig) {
             return Promise.reject('No templateConfig provided');
-        } else if (templateConfig.html !== undefined) {
+        } else if (templateConfig.html) {
             return Promise.resolve(templateConfig.html);
         } else {
             let location = this._getTemplateLocation(templateConfig);

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 11619 - 11613
dist/preview release/babylon.d.ts


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 37 - 37
dist/preview release/babylon.js


+ 195 - 43
dist/preview release/babylon.max.js

@@ -14067,11 +14067,16 @@ var BABYLON;
             if (defines === void 0) { defines = ""; }
             var attributesNamesOrOptions = BABYLON.ParticleSystem._GetAttributeNamesOrOptions();
             var effectCreationOption = BABYLON.ParticleSystem._GetEffectCreationOptions();
-            defines += "\n#define BILLBOARD\n";
+            if (defines.indexOf(" BILLBOARD") === -1) {
+                defines += "\n#define BILLBOARD\n";
+            }
+            if (samplers.indexOf("diffuseSampler") === -1) {
+                samplers.push("diffuseSampler");
+            }
             return this.createEffect({
                 vertex: "particles",
                 fragmentElement: fragmentName
-            }, attributesNamesOrOptions, effectCreationOption.concat(uniformsNames), ["diffuseSampler"].concat(samplers), defines, fallbacks, onCompiled, onError);
+            }, attributesNamesOrOptions, effectCreationOption.concat(uniformsNames), samplers, defines, fallbacks, onCompiled, onError);
         };
         /**
          * Directly creates a webGL program
@@ -36956,6 +36961,7 @@ var BABYLON;
          * @returns the VertexData
          */
         VertexData.prototype.transform = function (matrix) {
+            var flip = matrix.m[0] * matrix.m[5] * matrix.m[10] < 0;
             var transformed = BABYLON.Vector3.Zero();
             var index;
             if (this.positions) {
@@ -36990,6 +36996,13 @@ var BABYLON;
                     this.tangents[index + 3] = tangentTransformed.w;
                 }
             }
+            if (flip && this.indices) {
+                for (index = 0; index < this.indices.length; index += 3) {
+                    var tmp = this.indices[index + 1];
+                    this.indices[index + 1] = this.indices[index + 2];
+                    this.indices[index + 2] = tmp;
+                }
+            }
             return this;
         };
         /**
@@ -54136,9 +54149,19 @@ var BABYLON;
                 result = BABYLON.Vector3.Cross(p1p2, p3p2);
             }
             if (useWorldCoordinates) {
-                result = BABYLON.Vector3.TransformNormal(result, this.pickedMesh.getWorldMatrix());
+                var wm = this.pickedMesh.getWorldMatrix();
+                if (this.pickedMesh.nonUniformScaling) {
+                    BABYLON.Tmp.Matrix[0].copyFrom(wm);
+                    wm = BABYLON.Tmp.Matrix[0];
+                    wm.setTranslationFromFloats(0, 0, 0);
+                    wm.invert();
+                    wm.transposeToRef(BABYLON.Tmp.Matrix[1]);
+                    wm = BABYLON.Tmp.Matrix[1];
+                }
+                result = BABYLON.Vector3.TransformNormal(result, wm);
             }
-            return BABYLON.Vector3.Normalize(result);
+            result.normalize();
+            return result;
         };
         /**
          * Gets the texture coordinates of where the pick occured
@@ -56342,6 +56365,9 @@ var BABYLON;
                 var defines = (program.shaderOptions.defines.length > 0) ? program.shaderOptions.defines.join("\n") : "";
                 custom = this._scene.getEngine().createEffectForParticles(program.shaderPath.fragmentElement, program.shaderOptions.uniforms, program.shaderOptions.samplers, defines);
             }
+            else if (this._customEffect) {
+                custom = this._customEffect;
+            }
             var result = new ParticleSystem(name, this._capacity, this._scene, custom);
             result.customShader = program;
             BABYLON.Tools.DeepCopy(this, result, ["particles", "customShader"]);
@@ -56519,8 +56545,8 @@ var BABYLON;
                 }
             }
             // Emitter
+            var emitterType;
             if (parsedParticleSystem.particleEmitterType) {
-                var emitterType = void 0;
                 switch (parsedParticleSystem.particleEmitterType.type) {
                     case "SphereEmitter":
                         emitterType = new BABYLON.SphereParticleEmitter();
@@ -56537,8 +56563,12 @@ var BABYLON;
                         break;
                 }
                 emitterType.parse(parsedParticleSystem.particleEmitterType);
-                particleSystem.particleEmitterType = emitterType;
             }
+            else {
+                emitterType = new BABYLON.BoxParticleEmitter();
+                emitterType.parse(parsedParticleSystem);
+            }
+            particleSystem.particleEmitterType = emitterType;
         };
         /**
          * Parses a JSON object to create a particle system.
@@ -89345,27 +89375,32 @@ var BABYLON;
          */
         function AxisDragGizmo(gizmoLayer, dragAxis, color) {
             var _this = _super.call(this, gizmoLayer) || this;
-            _this.updateGizmoRotationToMatchAttachedMesh = false;
+            _this._pointerObserver = null;
             // Create Material
             var coloredMaterial = new BABYLON.StandardMaterial("", gizmoLayer.utilityLayerScene);
             coloredMaterial.disableLighting = true;
             coloredMaterial.emissiveColor = color;
+            var hoverMaterial = new BABYLON.StandardMaterial("", gizmoLayer.utilityLayerScene);
+            hoverMaterial.disableLighting = true;
+            hoverMaterial.emissiveColor = color.add(new BABYLON.Color3(0.2, 0.2, 0.2));
             // Build mesh on root node
+            var arrow = new BABYLON.AbstractMesh("", gizmoLayer.utilityLayerScene);
             var arrowMesh = BABYLON.MeshBuilder.CreateCylinder("yPosMesh", { diameterTop: 0, height: 2, tessellation: 96 }, gizmoLayer.utilityLayerScene);
-            var arrowTail = BABYLON.MeshBuilder.CreateCylinder("yPosMesh", { diameter: 0.03, height: 0.2, tessellation: 96 }, gizmoLayer.utilityLayerScene);
-            _this._rootMesh.addChild(arrowMesh);
-            _this._rootMesh.addChild(arrowTail);
+            var arrowTail = BABYLON.MeshBuilder.CreateCylinder("yPosMesh", { diameter: 0.015, height: 0.3, tessellation: 96 }, gizmoLayer.utilityLayerScene);
+            arrow.addChild(arrowMesh);
+            arrow.addChild(arrowTail);
             // Position arrow pointing in its drag axis
-            arrowMesh.scaling.scaleInPlace(0.1);
+            arrowMesh.scaling.scaleInPlace(0.05);
             arrowMesh.material = coloredMaterial;
             arrowMesh.rotation.x = Math.PI / 2;
             arrowMesh.position.z += 0.3;
             arrowTail.rotation.x = Math.PI / 2;
             arrowTail.material = coloredMaterial;
-            arrowTail.position.z += 0.2;
-            _this._rootMesh.lookAt(_this._rootMesh.position.subtract(dragAxis));
+            arrowTail.position.z += 0.15;
+            arrow.lookAt(_this._rootMesh.position.subtract(dragAxis));
+            _this._rootMesh.addChild(arrow);
             // Add drag behavior to handle events when the gizmo is dragged
-            _this._dragBehavior = new BABYLON.PointerDragBehavior({ dragAxis: new BABYLON.Vector3(0, 0, 1) });
+            _this._dragBehavior = new BABYLON.PointerDragBehavior({ dragAxis: dragAxis });
             _this._dragBehavior.moveAttached = false;
             _this._rootMesh.addBehavior(_this._dragBehavior);
             _this._dragBehavior.onDragObservable.add(function (event) {
@@ -89376,6 +89411,18 @@ var BABYLON;
                     _this.attachedMesh.position.addInPlace(event.delta);
                 }
             });
+            _this._pointerObserver = gizmoLayer.utilityLayerScene.onPointerObservable.add(function (pointerInfo, eventState) {
+                if (pointerInfo.pickInfo && (_this._rootMesh.getChildMeshes().indexOf(pointerInfo.pickInfo.pickedMesh) != -1)) {
+                    _this._rootMesh.getChildMeshes().forEach(function (m) {
+                        m.material = hoverMaterial;
+                    });
+                }
+                else {
+                    _this._rootMesh.getChildMeshes().forEach(function (m) {
+                        m.material = coloredMaterial;
+                    });
+                }
+            });
             return _this;
         }
         AxisDragGizmo.prototype._onInteractionsEnabledChanged = function (value) {
@@ -89385,6 +89432,7 @@ var BABYLON;
          * Disposes of the gizmo
          */
         AxisDragGizmo.prototype.dispose = function () {
+            this.gizmoLayer.utilityLayerScene.onPointerObservable.remove(this._pointerObserver);
             this._dragBehavior.detach();
             _super.prototype.dispose.call(this);
         };
@@ -89411,16 +89459,20 @@ var BABYLON;
          */
         function AxisScaleGizmo(gizmoLayer, dragAxis, color) {
             var _this = _super.call(this, gizmoLayer) || this;
-            _this.updateGizmoRotationToMatchAttachedMesh = false;
+            _this._pointerObserver = null;
             // Create Material
             var coloredMaterial = new BABYLON.StandardMaterial("", gizmoLayer.utilityLayerScene);
             coloredMaterial.disableLighting = true;
             coloredMaterial.emissiveColor = color;
+            var hoverMaterial = new BABYLON.StandardMaterial("", gizmoLayer.utilityLayerScene);
+            hoverMaterial.disableLighting = true;
+            hoverMaterial.emissiveColor = color.add(new BABYLON.Color3(0.2, 0.2, 0.2));
             // Build mesh on root node
-            var arrowMesh = BABYLON.MeshBuilder.CreateBox("yPosMesh", { size: 1 }, gizmoLayer.utilityLayerScene);
-            var arrowTail = BABYLON.MeshBuilder.CreateCylinder("yPosMesh", { diameter: 0.03, height: 0.2, tessellation: 96 }, gizmoLayer.utilityLayerScene);
-            _this._rootMesh.addChild(arrowMesh);
-            _this._rootMesh.addChild(arrowTail);
+            var arrow = new BABYLON.AbstractMesh("", gizmoLayer.utilityLayerScene);
+            var arrowMesh = BABYLON.MeshBuilder.CreateBox("yPosMesh", { size: 0.5 }, gizmoLayer.utilityLayerScene);
+            var arrowTail = BABYLON.MeshBuilder.CreateCylinder("yPosMesh", { diameter: 0.015, height: 0.3, tessellation: 96 }, gizmoLayer.utilityLayerScene);
+            arrow.addChild(arrowMesh);
+            arrow.addChild(arrowTail);
             // Position arrow pointing in its drag axis
             arrowMesh.scaling.scaleInPlace(0.1);
             arrowMesh.material = coloredMaterial;
@@ -89428,18 +89480,48 @@ var BABYLON;
             arrowMesh.position.z += 0.3;
             arrowTail.rotation.x = Math.PI / 2;
             arrowTail.material = coloredMaterial;
-            arrowTail.position.z += 0.2;
-            _this._rootMesh.lookAt(_this._rootMesh.position.subtract(dragAxis));
+            arrowTail.position.z += 0.15;
+            arrow.lookAt(_this._rootMesh.position.subtract(dragAxis));
+            _this._rootMesh.addChild(arrow);
             // Add drag behavior to handle events when the gizmo is dragged
-            _this._dragBehavior = new BABYLON.PointerDragBehavior({ dragAxis: new BABYLON.Vector3(0, 0, 1) });
+            _this._dragBehavior = new BABYLON.PointerDragBehavior({ dragAxis: dragAxis });
             _this._dragBehavior.moveAttached = false;
             _this._rootMesh.addBehavior(_this._dragBehavior);
+            var tmpVector = new BABYLON.Vector3();
             _this._dragBehavior.onDragObservable.add(function (event) {
                 if (!_this.interactionsEnabled) {
                     return;
                 }
                 if (_this.attachedMesh) {
-                    _this.attachedMesh.scaling.addInPlace(event.delta);
+                    dragAxis.scaleToRef(event.dragDistance, tmpVector);
+                    var invertCount = 0;
+                    if (_this.attachedMesh.scaling["x"] < 0) {
+                        invertCount++;
+                    }
+                    if (_this.attachedMesh.scaling["y"] < 0) {
+                        invertCount++;
+                    }
+                    if (_this.attachedMesh.scaling["z"] < 0) {
+                        invertCount++;
+                    }
+                    if (invertCount % 2 == 0) {
+                        _this.attachedMesh.scaling.addInPlace(tmpVector);
+                    }
+                    else {
+                        _this.attachedMesh.scaling.subtractInPlace(tmpVector);
+                    }
+                }
+            });
+            _this._pointerObserver = gizmoLayer.utilityLayerScene.onPointerObservable.add(function (pointerInfo, eventState) {
+                if (pointerInfo.pickInfo && (_this._rootMesh.getChildMeshes().indexOf(pointerInfo.pickInfo.pickedMesh) != -1)) {
+                    _this._rootMesh.getChildMeshes().forEach(function (m) {
+                        m.material = hoverMaterial;
+                    });
+                }
+                else {
+                    _this._rootMesh.getChildMeshes().forEach(function (m) {
+                        m.material = coloredMaterial;
+                    });
                 }
             });
             return _this;
@@ -89451,6 +89533,7 @@ var BABYLON;
          * Disposes of the gizmo
          */
         AxisScaleGizmo.prototype.dispose = function () {
+            this.gizmoLayer.utilityLayerScene.onPointerObservable.remove(this._pointerObserver);
             this._dragBehavior.detach();
             _super.prototype.dispose.call(this);
         };
@@ -89477,21 +89560,26 @@ var BABYLON;
          */
         function PlaneRotationGizmo(gizmoLayer, planeNormal, color) {
             var _this = _super.call(this, gizmoLayer) || this;
-            _this.updateGizmoRotationToMatchAttachedMesh = false;
+            _this._pointerObserver = null;
             // Create Material
             var coloredMaterial = new BABYLON.StandardMaterial("", gizmoLayer.utilityLayerScene);
             coloredMaterial.disableLighting = true;
             coloredMaterial.emissiveColor = color;
+            var hoverMaterial = new BABYLON.StandardMaterial("", gizmoLayer.utilityLayerScene);
+            hoverMaterial.disableLighting = true;
+            hoverMaterial.emissiveColor = color.add(new BABYLON.Color3(0.2, 0.2, 0.2));
             // Build mesh on root node
-            var rotationMesh = BABYLON.Mesh.CreateTorus("torus", 3, 0.3, 20, gizmoLayer.utilityLayerScene, false);
-            _this._rootMesh.addChild(rotationMesh);
+            var parentMesh = new BABYLON.AbstractMesh("", gizmoLayer.utilityLayerScene);
+            var rotationMesh = BABYLON.Mesh.CreateTorus("torus", 3, 0.15, 20, gizmoLayer.utilityLayerScene, false);
             // Position arrow pointing in its drag axis
             rotationMesh.scaling.scaleInPlace(0.1);
             rotationMesh.material = coloredMaterial;
             rotationMesh.rotation.x = Math.PI / 2;
-            _this._rootMesh.lookAt(_this._rootMesh.position.subtract(planeNormal));
+            parentMesh.addChild(rotationMesh);
+            parentMesh.lookAt(_this._rootMesh.position.subtract(planeNormal));
+            _this._rootMesh.addChild(parentMesh);
             // Add drag behavior to handle events when the gizmo is dragged
-            _this._dragBehavior = new BABYLON.PointerDragBehavior({ dragPlaneNormal: new BABYLON.Vector3(0, 0, 1) });
+            _this._dragBehavior = new BABYLON.PointerDragBehavior({ dragPlaneNormal: planeNormal });
             _this._dragBehavior.moveAttached = false;
             _this._rootMesh.addBehavior(_this._dragBehavior);
             var lastDragPosition = null;
@@ -89501,6 +89589,9 @@ var BABYLON;
                 }
                 lastDragPosition = e.dragPlanePoint;
             });
+            var rotationMatrix = new BABYLON.Matrix();
+            var planeNormalTowardsCamera = new BABYLON.Vector3();
+            var localPlaneNormalTowardsCamera = new BABYLON.Vector3();
             _this._dragBehavior.onDragObservable.add(function (event) {
                 if (!_this.interactionsEnabled) {
                     return;
@@ -89515,25 +89606,43 @@ var BABYLON;
                     var cross = BABYLON.Vector3.Cross(newVector, originalVector);
                     var dot = BABYLON.Vector3.Dot(newVector, originalVector);
                     var angle = Math.atan2(cross.length(), dot);
-                    var up = planeNormal.clone();
+                    planeNormalTowardsCamera.copyFrom(planeNormal);
+                    localPlaneNormalTowardsCamera.copyFrom(planeNormal);
+                    if (_this.updateGizmoRotationToMatchAttachedMesh) {
+                        _this.attachedMesh.rotationQuaternion.toRotationMatrix(rotationMatrix);
+                        localPlaneNormalTowardsCamera = BABYLON.Vector3.TransformCoordinates(planeNormalTowardsCamera, rotationMatrix);
+                    }
                     // Flip up vector depending on which side the camera is on
                     if (gizmoLayer.utilityLayerScene.activeCamera) {
                         var camVec = gizmoLayer.utilityLayerScene.activeCamera.position.subtract(_this.attachedMesh.position);
-                        if (BABYLON.Vector3.Dot(camVec, up) > 0) {
-                            up.scaleInPlace(-1);
+                        if (BABYLON.Vector3.Dot(camVec, localPlaneNormalTowardsCamera) > 0) {
+                            planeNormalTowardsCamera.scaleInPlace(-1);
+                            localPlaneNormalTowardsCamera.scaleInPlace(-1);
                         }
                     }
-                    var halfCircleSide = BABYLON.Vector3.Dot(up, cross) > 0.0;
+                    var halfCircleSide = BABYLON.Vector3.Dot(localPlaneNormalTowardsCamera, cross) > 0.0;
                     if (halfCircleSide)
                         angle = -angle;
                     // Convert angle and axis to quaternion (http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm)
                     var quaternionCoefficient = Math.sin(angle / 2);
-                    var amountToRotate = new BABYLON.Quaternion(up.x * quaternionCoefficient, up.y * quaternionCoefficient, up.z * quaternionCoefficient, Math.cos(angle / 2));
+                    var amountToRotate = new BABYLON.Quaternion(planeNormalTowardsCamera.x * quaternionCoefficient, planeNormalTowardsCamera.y * quaternionCoefficient, planeNormalTowardsCamera.z * quaternionCoefficient, Math.cos(angle / 2));
                     // Rotate selected mesh quaternion over fixed axis
-                    amountToRotate.multiplyToRef(_this.attachedMesh.rotationQuaternion, _this.attachedMesh.rotationQuaternion);
+                    _this.attachedMesh.rotationQuaternion.multiplyToRef(amountToRotate, _this.attachedMesh.rotationQuaternion);
                     lastDragPosition = event.dragPlanePoint;
                 }
             });
+            _this._pointerObserver = gizmoLayer.utilityLayerScene.onPointerObservable.add(function (pointerInfo, eventState) {
+                if (pointerInfo.pickInfo && (_this._rootMesh.getChildMeshes().indexOf(pointerInfo.pickInfo.pickedMesh) != -1)) {
+                    _this._rootMesh.getChildMeshes().forEach(function (m) {
+                        m.material = hoverMaterial;
+                    });
+                }
+                else {
+                    _this._rootMesh.getChildMeshes().forEach(function (m) {
+                        m.material = coloredMaterial;
+                    });
+                }
+            });
             return _this;
         }
         PlaneRotationGizmo.prototype._onInteractionsEnabledChanged = function (value) {
@@ -89543,6 +89652,7 @@ var BABYLON;
          * Disposes of the gizmo
          */
         PlaneRotationGizmo.prototype.dispose = function () {
+            this.gizmoLayer.utilityLayerScene.onPointerObservable.remove(this._pointerObserver);
             this._dragBehavior.detach();
             _super.prototype.dispose.call(this);
         };
@@ -89567,9 +89677,9 @@ var BABYLON;
          */
         function PositionGizmo(gizmoLayer) {
             var _this = _super.call(this, gizmoLayer) || this;
-            _this._xDrag = new BABYLON.AxisDragGizmo(gizmoLayer, new BABYLON.Vector3(1, 0, 0), BABYLON.Color3.FromHexString("#00b894"));
-            _this._yDrag = new BABYLON.AxisDragGizmo(gizmoLayer, new BABYLON.Vector3(0, 1, 0), BABYLON.Color3.FromHexString("#d63031"));
-            _this._zDrag = new BABYLON.AxisDragGizmo(gizmoLayer, new BABYLON.Vector3(0, 0, 1), BABYLON.Color3.FromHexString("#0984e3"));
+            _this._xDrag = new BABYLON.AxisDragGizmo(gizmoLayer, new BABYLON.Vector3(1, 0, 0), BABYLON.Color3.Green().scale(0.5));
+            _this._yDrag = new BABYLON.AxisDragGizmo(gizmoLayer, new BABYLON.Vector3(0, 1, 0), BABYLON.Color3.Red().scale(0.5));
+            _this._zDrag = new BABYLON.AxisDragGizmo(gizmoLayer, new BABYLON.Vector3(0, 0, 1), BABYLON.Color3.Blue().scale(0.5));
             return _this;
         }
         Object.defineProperty(PositionGizmo.prototype, "attachedMesh", {
@@ -89586,6 +89696,20 @@ var BABYLON;
             this._yDrag.interactionsEnabled = value;
             this._zDrag.interactionsEnabled = value;
         };
+        Object.defineProperty(PositionGizmo.prototype, "updateGizmoRotationToMatchAttachedMesh", {
+            get: function () {
+                return this._xDrag.updateGizmoRotationToMatchAttachedMesh;
+            },
+            set: function (value) {
+                if (this._xDrag) {
+                    this._xDrag.updateGizmoRotationToMatchAttachedMesh = value;
+                    this._yDrag.updateGizmoRotationToMatchAttachedMesh = value;
+                    this._zDrag.updateGizmoRotationToMatchAttachedMesh = value;
+                }
+            },
+            enumerable: true,
+            configurable: true
+        });
         /**
          * Disposes of the gizmo
          */
@@ -89615,9 +89739,9 @@ var BABYLON;
          */
         function RotationGizmo(gizmoLayer) {
             var _this = _super.call(this, gizmoLayer) || this;
-            _this._xDrag = new BABYLON.PlaneRotationGizmo(gizmoLayer, new BABYLON.Vector3(1, 0, 0), BABYLON.Color3.FromHexString("#00b894"));
-            _this._yDrag = new BABYLON.PlaneRotationGizmo(gizmoLayer, new BABYLON.Vector3(0, 1, 0), BABYLON.Color3.FromHexString("#d63031"));
-            _this._zDrag = new BABYLON.PlaneRotationGizmo(gizmoLayer, new BABYLON.Vector3(0, 0, 1), BABYLON.Color3.FromHexString("#0984e3"));
+            _this._xDrag = new BABYLON.PlaneRotationGizmo(gizmoLayer, new BABYLON.Vector3(1, 0, 0), BABYLON.Color3.Green().scale(0.5));
+            _this._yDrag = new BABYLON.PlaneRotationGizmo(gizmoLayer, new BABYLON.Vector3(0, 1, 0), BABYLON.Color3.Red().scale(0.5));
+            _this._zDrag = new BABYLON.PlaneRotationGizmo(gizmoLayer, new BABYLON.Vector3(0, 0, 1), BABYLON.Color3.Blue().scale(0.5));
             return _this;
         }
         Object.defineProperty(RotationGizmo.prototype, "attachedMesh", {
@@ -89634,6 +89758,20 @@ var BABYLON;
             this._yDrag.interactionsEnabled = value;
             this._zDrag.interactionsEnabled = value;
         };
+        Object.defineProperty(RotationGizmo.prototype, "updateGizmoRotationToMatchAttachedMesh", {
+            get: function () {
+                return this._xDrag.updateGizmoRotationToMatchAttachedMesh;
+            },
+            set: function (value) {
+                if (this._xDrag) {
+                    this._xDrag.updateGizmoRotationToMatchAttachedMesh = value;
+                    this._yDrag.updateGizmoRotationToMatchAttachedMesh = value;
+                    this._zDrag.updateGizmoRotationToMatchAttachedMesh = value;
+                }
+            },
+            enumerable: true,
+            configurable: true
+        });
         /**
          * Disposes of the gizmo
          */
@@ -89663,9 +89801,9 @@ var BABYLON;
          */
         function ScaleGizmo(gizmoLayer) {
             var _this = _super.call(this, gizmoLayer) || this;
-            _this._xDrag = new BABYLON.AxisScaleGizmo(gizmoLayer, new BABYLON.Vector3(1, 0, 0), BABYLON.Color3.FromHexString("#00b894"));
-            _this._yDrag = new BABYLON.AxisScaleGizmo(gizmoLayer, new BABYLON.Vector3(0, 1, 0), BABYLON.Color3.FromHexString("#d63031"));
-            _this._zDrag = new BABYLON.AxisScaleGizmo(gizmoLayer, new BABYLON.Vector3(0, 0, 1), BABYLON.Color3.FromHexString("#0984e3"));
+            _this._xDrag = new BABYLON.AxisScaleGizmo(gizmoLayer, new BABYLON.Vector3(1, 0, 0), BABYLON.Color3.Green().scale(0.5));
+            _this._yDrag = new BABYLON.AxisScaleGizmo(gizmoLayer, new BABYLON.Vector3(0, 1, 0), BABYLON.Color3.Red().scale(0.5));
+            _this._zDrag = new BABYLON.AxisScaleGizmo(gizmoLayer, new BABYLON.Vector3(0, 0, 1), BABYLON.Color3.Blue().scale(0.5));
             return _this;
         }
         Object.defineProperty(ScaleGizmo.prototype, "attachedMesh", {
@@ -89682,6 +89820,20 @@ var BABYLON;
             this._yDrag.interactionsEnabled = value;
             this._zDrag.interactionsEnabled = value;
         };
+        Object.defineProperty(ScaleGizmo.prototype, "updateGizmoRotationToMatchAttachedMesh", {
+            get: function () {
+                return this._xDrag.updateGizmoRotationToMatchAttachedMesh;
+            },
+            set: function (value) {
+                if (this._xDrag) {
+                    this._xDrag.updateGizmoRotationToMatchAttachedMesh = value;
+                    this._yDrag.updateGizmoRotationToMatchAttachedMesh = value;
+                    this._zDrag.updateGizmoRotationToMatchAttachedMesh = value;
+                }
+            },
+            enumerable: true,
+            configurable: true
+        });
         /**
          * Disposes of the gizmo
          */

+ 195 - 43
dist/preview release/babylon.no-module.max.js

@@ -14034,11 +14034,16 @@ var BABYLON;
             if (defines === void 0) { defines = ""; }
             var attributesNamesOrOptions = BABYLON.ParticleSystem._GetAttributeNamesOrOptions();
             var effectCreationOption = BABYLON.ParticleSystem._GetEffectCreationOptions();
-            defines += "\n#define BILLBOARD\n";
+            if (defines.indexOf(" BILLBOARD") === -1) {
+                defines += "\n#define BILLBOARD\n";
+            }
+            if (samplers.indexOf("diffuseSampler") === -1) {
+                samplers.push("diffuseSampler");
+            }
             return this.createEffect({
                 vertex: "particles",
                 fragmentElement: fragmentName
-            }, attributesNamesOrOptions, effectCreationOption.concat(uniformsNames), ["diffuseSampler"].concat(samplers), defines, fallbacks, onCompiled, onError);
+            }, attributesNamesOrOptions, effectCreationOption.concat(uniformsNames), samplers, defines, fallbacks, onCompiled, onError);
         };
         /**
          * Directly creates a webGL program
@@ -36923,6 +36928,7 @@ var BABYLON;
          * @returns the VertexData
          */
         VertexData.prototype.transform = function (matrix) {
+            var flip = matrix.m[0] * matrix.m[5] * matrix.m[10] < 0;
             var transformed = BABYLON.Vector3.Zero();
             var index;
             if (this.positions) {
@@ -36957,6 +36963,13 @@ var BABYLON;
                     this.tangents[index + 3] = tangentTransformed.w;
                 }
             }
+            if (flip && this.indices) {
+                for (index = 0; index < this.indices.length; index += 3) {
+                    var tmp = this.indices[index + 1];
+                    this.indices[index + 1] = this.indices[index + 2];
+                    this.indices[index + 2] = tmp;
+                }
+            }
             return this;
         };
         /**
@@ -54103,9 +54116,19 @@ var BABYLON;
                 result = BABYLON.Vector3.Cross(p1p2, p3p2);
             }
             if (useWorldCoordinates) {
-                result = BABYLON.Vector3.TransformNormal(result, this.pickedMesh.getWorldMatrix());
+                var wm = this.pickedMesh.getWorldMatrix();
+                if (this.pickedMesh.nonUniformScaling) {
+                    BABYLON.Tmp.Matrix[0].copyFrom(wm);
+                    wm = BABYLON.Tmp.Matrix[0];
+                    wm.setTranslationFromFloats(0, 0, 0);
+                    wm.invert();
+                    wm.transposeToRef(BABYLON.Tmp.Matrix[1]);
+                    wm = BABYLON.Tmp.Matrix[1];
+                }
+                result = BABYLON.Vector3.TransformNormal(result, wm);
             }
-            return BABYLON.Vector3.Normalize(result);
+            result.normalize();
+            return result;
         };
         /**
          * Gets the texture coordinates of where the pick occured
@@ -56309,6 +56332,9 @@ var BABYLON;
                 var defines = (program.shaderOptions.defines.length > 0) ? program.shaderOptions.defines.join("\n") : "";
                 custom = this._scene.getEngine().createEffectForParticles(program.shaderPath.fragmentElement, program.shaderOptions.uniforms, program.shaderOptions.samplers, defines);
             }
+            else if (this._customEffect) {
+                custom = this._customEffect;
+            }
             var result = new ParticleSystem(name, this._capacity, this._scene, custom);
             result.customShader = program;
             BABYLON.Tools.DeepCopy(this, result, ["particles", "customShader"]);
@@ -56486,8 +56512,8 @@ var BABYLON;
                 }
             }
             // Emitter
+            var emitterType;
             if (parsedParticleSystem.particleEmitterType) {
-                var emitterType = void 0;
                 switch (parsedParticleSystem.particleEmitterType.type) {
                     case "SphereEmitter":
                         emitterType = new BABYLON.SphereParticleEmitter();
@@ -56504,8 +56530,12 @@ var BABYLON;
                         break;
                 }
                 emitterType.parse(parsedParticleSystem.particleEmitterType);
-                particleSystem.particleEmitterType = emitterType;
             }
+            else {
+                emitterType = new BABYLON.BoxParticleEmitter();
+                emitterType.parse(parsedParticleSystem);
+            }
+            particleSystem.particleEmitterType = emitterType;
         };
         /**
          * Parses a JSON object to create a particle system.
@@ -89312,27 +89342,32 @@ var BABYLON;
          */
         function AxisDragGizmo(gizmoLayer, dragAxis, color) {
             var _this = _super.call(this, gizmoLayer) || this;
-            _this.updateGizmoRotationToMatchAttachedMesh = false;
+            _this._pointerObserver = null;
             // Create Material
             var coloredMaterial = new BABYLON.StandardMaterial("", gizmoLayer.utilityLayerScene);
             coloredMaterial.disableLighting = true;
             coloredMaterial.emissiveColor = color;
+            var hoverMaterial = new BABYLON.StandardMaterial("", gizmoLayer.utilityLayerScene);
+            hoverMaterial.disableLighting = true;
+            hoverMaterial.emissiveColor = color.add(new BABYLON.Color3(0.2, 0.2, 0.2));
             // Build mesh on root node
+            var arrow = new BABYLON.AbstractMesh("", gizmoLayer.utilityLayerScene);
             var arrowMesh = BABYLON.MeshBuilder.CreateCylinder("yPosMesh", { diameterTop: 0, height: 2, tessellation: 96 }, gizmoLayer.utilityLayerScene);
-            var arrowTail = BABYLON.MeshBuilder.CreateCylinder("yPosMesh", { diameter: 0.03, height: 0.2, tessellation: 96 }, gizmoLayer.utilityLayerScene);
-            _this._rootMesh.addChild(arrowMesh);
-            _this._rootMesh.addChild(arrowTail);
+            var arrowTail = BABYLON.MeshBuilder.CreateCylinder("yPosMesh", { diameter: 0.015, height: 0.3, tessellation: 96 }, gizmoLayer.utilityLayerScene);
+            arrow.addChild(arrowMesh);
+            arrow.addChild(arrowTail);
             // Position arrow pointing in its drag axis
-            arrowMesh.scaling.scaleInPlace(0.1);
+            arrowMesh.scaling.scaleInPlace(0.05);
             arrowMesh.material = coloredMaterial;
             arrowMesh.rotation.x = Math.PI / 2;
             arrowMesh.position.z += 0.3;
             arrowTail.rotation.x = Math.PI / 2;
             arrowTail.material = coloredMaterial;
-            arrowTail.position.z += 0.2;
-            _this._rootMesh.lookAt(_this._rootMesh.position.subtract(dragAxis));
+            arrowTail.position.z += 0.15;
+            arrow.lookAt(_this._rootMesh.position.subtract(dragAxis));
+            _this._rootMesh.addChild(arrow);
             // Add drag behavior to handle events when the gizmo is dragged
-            _this._dragBehavior = new BABYLON.PointerDragBehavior({ dragAxis: new BABYLON.Vector3(0, 0, 1) });
+            _this._dragBehavior = new BABYLON.PointerDragBehavior({ dragAxis: dragAxis });
             _this._dragBehavior.moveAttached = false;
             _this._rootMesh.addBehavior(_this._dragBehavior);
             _this._dragBehavior.onDragObservable.add(function (event) {
@@ -89343,6 +89378,18 @@ var BABYLON;
                     _this.attachedMesh.position.addInPlace(event.delta);
                 }
             });
+            _this._pointerObserver = gizmoLayer.utilityLayerScene.onPointerObservable.add(function (pointerInfo, eventState) {
+                if (pointerInfo.pickInfo && (_this._rootMesh.getChildMeshes().indexOf(pointerInfo.pickInfo.pickedMesh) != -1)) {
+                    _this._rootMesh.getChildMeshes().forEach(function (m) {
+                        m.material = hoverMaterial;
+                    });
+                }
+                else {
+                    _this._rootMesh.getChildMeshes().forEach(function (m) {
+                        m.material = coloredMaterial;
+                    });
+                }
+            });
             return _this;
         }
         AxisDragGizmo.prototype._onInteractionsEnabledChanged = function (value) {
@@ -89352,6 +89399,7 @@ var BABYLON;
          * Disposes of the gizmo
          */
         AxisDragGizmo.prototype.dispose = function () {
+            this.gizmoLayer.utilityLayerScene.onPointerObservable.remove(this._pointerObserver);
             this._dragBehavior.detach();
             _super.prototype.dispose.call(this);
         };
@@ -89378,16 +89426,20 @@ var BABYLON;
          */
         function AxisScaleGizmo(gizmoLayer, dragAxis, color) {
             var _this = _super.call(this, gizmoLayer) || this;
-            _this.updateGizmoRotationToMatchAttachedMesh = false;
+            _this._pointerObserver = null;
             // Create Material
             var coloredMaterial = new BABYLON.StandardMaterial("", gizmoLayer.utilityLayerScene);
             coloredMaterial.disableLighting = true;
             coloredMaterial.emissiveColor = color;
+            var hoverMaterial = new BABYLON.StandardMaterial("", gizmoLayer.utilityLayerScene);
+            hoverMaterial.disableLighting = true;
+            hoverMaterial.emissiveColor = color.add(new BABYLON.Color3(0.2, 0.2, 0.2));
             // Build mesh on root node
-            var arrowMesh = BABYLON.MeshBuilder.CreateBox("yPosMesh", { size: 1 }, gizmoLayer.utilityLayerScene);
-            var arrowTail = BABYLON.MeshBuilder.CreateCylinder("yPosMesh", { diameter: 0.03, height: 0.2, tessellation: 96 }, gizmoLayer.utilityLayerScene);
-            _this._rootMesh.addChild(arrowMesh);
-            _this._rootMesh.addChild(arrowTail);
+            var arrow = new BABYLON.AbstractMesh("", gizmoLayer.utilityLayerScene);
+            var arrowMesh = BABYLON.MeshBuilder.CreateBox("yPosMesh", { size: 0.5 }, gizmoLayer.utilityLayerScene);
+            var arrowTail = BABYLON.MeshBuilder.CreateCylinder("yPosMesh", { diameter: 0.015, height: 0.3, tessellation: 96 }, gizmoLayer.utilityLayerScene);
+            arrow.addChild(arrowMesh);
+            arrow.addChild(arrowTail);
             // Position arrow pointing in its drag axis
             arrowMesh.scaling.scaleInPlace(0.1);
             arrowMesh.material = coloredMaterial;
@@ -89395,18 +89447,48 @@ var BABYLON;
             arrowMesh.position.z += 0.3;
             arrowTail.rotation.x = Math.PI / 2;
             arrowTail.material = coloredMaterial;
-            arrowTail.position.z += 0.2;
-            _this._rootMesh.lookAt(_this._rootMesh.position.subtract(dragAxis));
+            arrowTail.position.z += 0.15;
+            arrow.lookAt(_this._rootMesh.position.subtract(dragAxis));
+            _this._rootMesh.addChild(arrow);
             // Add drag behavior to handle events when the gizmo is dragged
-            _this._dragBehavior = new BABYLON.PointerDragBehavior({ dragAxis: new BABYLON.Vector3(0, 0, 1) });
+            _this._dragBehavior = new BABYLON.PointerDragBehavior({ dragAxis: dragAxis });
             _this._dragBehavior.moveAttached = false;
             _this._rootMesh.addBehavior(_this._dragBehavior);
+            var tmpVector = new BABYLON.Vector3();
             _this._dragBehavior.onDragObservable.add(function (event) {
                 if (!_this.interactionsEnabled) {
                     return;
                 }
                 if (_this.attachedMesh) {
-                    _this.attachedMesh.scaling.addInPlace(event.delta);
+                    dragAxis.scaleToRef(event.dragDistance, tmpVector);
+                    var invertCount = 0;
+                    if (_this.attachedMesh.scaling["x"] < 0) {
+                        invertCount++;
+                    }
+                    if (_this.attachedMesh.scaling["y"] < 0) {
+                        invertCount++;
+                    }
+                    if (_this.attachedMesh.scaling["z"] < 0) {
+                        invertCount++;
+                    }
+                    if (invertCount % 2 == 0) {
+                        _this.attachedMesh.scaling.addInPlace(tmpVector);
+                    }
+                    else {
+                        _this.attachedMesh.scaling.subtractInPlace(tmpVector);
+                    }
+                }
+            });
+            _this._pointerObserver = gizmoLayer.utilityLayerScene.onPointerObservable.add(function (pointerInfo, eventState) {
+                if (pointerInfo.pickInfo && (_this._rootMesh.getChildMeshes().indexOf(pointerInfo.pickInfo.pickedMesh) != -1)) {
+                    _this._rootMesh.getChildMeshes().forEach(function (m) {
+                        m.material = hoverMaterial;
+                    });
+                }
+                else {
+                    _this._rootMesh.getChildMeshes().forEach(function (m) {
+                        m.material = coloredMaterial;
+                    });
                 }
             });
             return _this;
@@ -89418,6 +89500,7 @@ var BABYLON;
          * Disposes of the gizmo
          */
         AxisScaleGizmo.prototype.dispose = function () {
+            this.gizmoLayer.utilityLayerScene.onPointerObservable.remove(this._pointerObserver);
             this._dragBehavior.detach();
             _super.prototype.dispose.call(this);
         };
@@ -89444,21 +89527,26 @@ var BABYLON;
          */
         function PlaneRotationGizmo(gizmoLayer, planeNormal, color) {
             var _this = _super.call(this, gizmoLayer) || this;
-            _this.updateGizmoRotationToMatchAttachedMesh = false;
+            _this._pointerObserver = null;
             // Create Material
             var coloredMaterial = new BABYLON.StandardMaterial("", gizmoLayer.utilityLayerScene);
             coloredMaterial.disableLighting = true;
             coloredMaterial.emissiveColor = color;
+            var hoverMaterial = new BABYLON.StandardMaterial("", gizmoLayer.utilityLayerScene);
+            hoverMaterial.disableLighting = true;
+            hoverMaterial.emissiveColor = color.add(new BABYLON.Color3(0.2, 0.2, 0.2));
             // Build mesh on root node
-            var rotationMesh = BABYLON.Mesh.CreateTorus("torus", 3, 0.3, 20, gizmoLayer.utilityLayerScene, false);
-            _this._rootMesh.addChild(rotationMesh);
+            var parentMesh = new BABYLON.AbstractMesh("", gizmoLayer.utilityLayerScene);
+            var rotationMesh = BABYLON.Mesh.CreateTorus("torus", 3, 0.15, 20, gizmoLayer.utilityLayerScene, false);
             // Position arrow pointing in its drag axis
             rotationMesh.scaling.scaleInPlace(0.1);
             rotationMesh.material = coloredMaterial;
             rotationMesh.rotation.x = Math.PI / 2;
-            _this._rootMesh.lookAt(_this._rootMesh.position.subtract(planeNormal));
+            parentMesh.addChild(rotationMesh);
+            parentMesh.lookAt(_this._rootMesh.position.subtract(planeNormal));
+            _this._rootMesh.addChild(parentMesh);
             // Add drag behavior to handle events when the gizmo is dragged
-            _this._dragBehavior = new BABYLON.PointerDragBehavior({ dragPlaneNormal: new BABYLON.Vector3(0, 0, 1) });
+            _this._dragBehavior = new BABYLON.PointerDragBehavior({ dragPlaneNormal: planeNormal });
             _this._dragBehavior.moveAttached = false;
             _this._rootMesh.addBehavior(_this._dragBehavior);
             var lastDragPosition = null;
@@ -89468,6 +89556,9 @@ var BABYLON;
                 }
                 lastDragPosition = e.dragPlanePoint;
             });
+            var rotationMatrix = new BABYLON.Matrix();
+            var planeNormalTowardsCamera = new BABYLON.Vector3();
+            var localPlaneNormalTowardsCamera = new BABYLON.Vector3();
             _this._dragBehavior.onDragObservable.add(function (event) {
                 if (!_this.interactionsEnabled) {
                     return;
@@ -89482,25 +89573,43 @@ var BABYLON;
                     var cross = BABYLON.Vector3.Cross(newVector, originalVector);
                     var dot = BABYLON.Vector3.Dot(newVector, originalVector);
                     var angle = Math.atan2(cross.length(), dot);
-                    var up = planeNormal.clone();
+                    planeNormalTowardsCamera.copyFrom(planeNormal);
+                    localPlaneNormalTowardsCamera.copyFrom(planeNormal);
+                    if (_this.updateGizmoRotationToMatchAttachedMesh) {
+                        _this.attachedMesh.rotationQuaternion.toRotationMatrix(rotationMatrix);
+                        localPlaneNormalTowardsCamera = BABYLON.Vector3.TransformCoordinates(planeNormalTowardsCamera, rotationMatrix);
+                    }
                     // Flip up vector depending on which side the camera is on
                     if (gizmoLayer.utilityLayerScene.activeCamera) {
                         var camVec = gizmoLayer.utilityLayerScene.activeCamera.position.subtract(_this.attachedMesh.position);
-                        if (BABYLON.Vector3.Dot(camVec, up) > 0) {
-                            up.scaleInPlace(-1);
+                        if (BABYLON.Vector3.Dot(camVec, localPlaneNormalTowardsCamera) > 0) {
+                            planeNormalTowardsCamera.scaleInPlace(-1);
+                            localPlaneNormalTowardsCamera.scaleInPlace(-1);
                         }
                     }
-                    var halfCircleSide = BABYLON.Vector3.Dot(up, cross) > 0.0;
+                    var halfCircleSide = BABYLON.Vector3.Dot(localPlaneNormalTowardsCamera, cross) > 0.0;
                     if (halfCircleSide)
                         angle = -angle;
                     // Convert angle and axis to quaternion (http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm)
                     var quaternionCoefficient = Math.sin(angle / 2);
-                    var amountToRotate = new BABYLON.Quaternion(up.x * quaternionCoefficient, up.y * quaternionCoefficient, up.z * quaternionCoefficient, Math.cos(angle / 2));
+                    var amountToRotate = new BABYLON.Quaternion(planeNormalTowardsCamera.x * quaternionCoefficient, planeNormalTowardsCamera.y * quaternionCoefficient, planeNormalTowardsCamera.z * quaternionCoefficient, Math.cos(angle / 2));
                     // Rotate selected mesh quaternion over fixed axis
-                    amountToRotate.multiplyToRef(_this.attachedMesh.rotationQuaternion, _this.attachedMesh.rotationQuaternion);
+                    _this.attachedMesh.rotationQuaternion.multiplyToRef(amountToRotate, _this.attachedMesh.rotationQuaternion);
                     lastDragPosition = event.dragPlanePoint;
                 }
             });
+            _this._pointerObserver = gizmoLayer.utilityLayerScene.onPointerObservable.add(function (pointerInfo, eventState) {
+                if (pointerInfo.pickInfo && (_this._rootMesh.getChildMeshes().indexOf(pointerInfo.pickInfo.pickedMesh) != -1)) {
+                    _this._rootMesh.getChildMeshes().forEach(function (m) {
+                        m.material = hoverMaterial;
+                    });
+                }
+                else {
+                    _this._rootMesh.getChildMeshes().forEach(function (m) {
+                        m.material = coloredMaterial;
+                    });
+                }
+            });
             return _this;
         }
         PlaneRotationGizmo.prototype._onInteractionsEnabledChanged = function (value) {
@@ -89510,6 +89619,7 @@ var BABYLON;
          * Disposes of the gizmo
          */
         PlaneRotationGizmo.prototype.dispose = function () {
+            this.gizmoLayer.utilityLayerScene.onPointerObservable.remove(this._pointerObserver);
             this._dragBehavior.detach();
             _super.prototype.dispose.call(this);
         };
@@ -89534,9 +89644,9 @@ var BABYLON;
          */
         function PositionGizmo(gizmoLayer) {
             var _this = _super.call(this, gizmoLayer) || this;
-            _this._xDrag = new BABYLON.AxisDragGizmo(gizmoLayer, new BABYLON.Vector3(1, 0, 0), BABYLON.Color3.FromHexString("#00b894"));
-            _this._yDrag = new BABYLON.AxisDragGizmo(gizmoLayer, new BABYLON.Vector3(0, 1, 0), BABYLON.Color3.FromHexString("#d63031"));
-            _this._zDrag = new BABYLON.AxisDragGizmo(gizmoLayer, new BABYLON.Vector3(0, 0, 1), BABYLON.Color3.FromHexString("#0984e3"));
+            _this._xDrag = new BABYLON.AxisDragGizmo(gizmoLayer, new BABYLON.Vector3(1, 0, 0), BABYLON.Color3.Green().scale(0.5));
+            _this._yDrag = new BABYLON.AxisDragGizmo(gizmoLayer, new BABYLON.Vector3(0, 1, 0), BABYLON.Color3.Red().scale(0.5));
+            _this._zDrag = new BABYLON.AxisDragGizmo(gizmoLayer, new BABYLON.Vector3(0, 0, 1), BABYLON.Color3.Blue().scale(0.5));
             return _this;
         }
         Object.defineProperty(PositionGizmo.prototype, "attachedMesh", {
@@ -89553,6 +89663,20 @@ var BABYLON;
             this._yDrag.interactionsEnabled = value;
             this._zDrag.interactionsEnabled = value;
         };
+        Object.defineProperty(PositionGizmo.prototype, "updateGizmoRotationToMatchAttachedMesh", {
+            get: function () {
+                return this._xDrag.updateGizmoRotationToMatchAttachedMesh;
+            },
+            set: function (value) {
+                if (this._xDrag) {
+                    this._xDrag.updateGizmoRotationToMatchAttachedMesh = value;
+                    this._yDrag.updateGizmoRotationToMatchAttachedMesh = value;
+                    this._zDrag.updateGizmoRotationToMatchAttachedMesh = value;
+                }
+            },
+            enumerable: true,
+            configurable: true
+        });
         /**
          * Disposes of the gizmo
          */
@@ -89582,9 +89706,9 @@ var BABYLON;
          */
         function RotationGizmo(gizmoLayer) {
             var _this = _super.call(this, gizmoLayer) || this;
-            _this._xDrag = new BABYLON.PlaneRotationGizmo(gizmoLayer, new BABYLON.Vector3(1, 0, 0), BABYLON.Color3.FromHexString("#00b894"));
-            _this._yDrag = new BABYLON.PlaneRotationGizmo(gizmoLayer, new BABYLON.Vector3(0, 1, 0), BABYLON.Color3.FromHexString("#d63031"));
-            _this._zDrag = new BABYLON.PlaneRotationGizmo(gizmoLayer, new BABYLON.Vector3(0, 0, 1), BABYLON.Color3.FromHexString("#0984e3"));
+            _this._xDrag = new BABYLON.PlaneRotationGizmo(gizmoLayer, new BABYLON.Vector3(1, 0, 0), BABYLON.Color3.Green().scale(0.5));
+            _this._yDrag = new BABYLON.PlaneRotationGizmo(gizmoLayer, new BABYLON.Vector3(0, 1, 0), BABYLON.Color3.Red().scale(0.5));
+            _this._zDrag = new BABYLON.PlaneRotationGizmo(gizmoLayer, new BABYLON.Vector3(0, 0, 1), BABYLON.Color3.Blue().scale(0.5));
             return _this;
         }
         Object.defineProperty(RotationGizmo.prototype, "attachedMesh", {
@@ -89601,6 +89725,20 @@ var BABYLON;
             this._yDrag.interactionsEnabled = value;
             this._zDrag.interactionsEnabled = value;
         };
+        Object.defineProperty(RotationGizmo.prototype, "updateGizmoRotationToMatchAttachedMesh", {
+            get: function () {
+                return this._xDrag.updateGizmoRotationToMatchAttachedMesh;
+            },
+            set: function (value) {
+                if (this._xDrag) {
+                    this._xDrag.updateGizmoRotationToMatchAttachedMesh = value;
+                    this._yDrag.updateGizmoRotationToMatchAttachedMesh = value;
+                    this._zDrag.updateGizmoRotationToMatchAttachedMesh = value;
+                }
+            },
+            enumerable: true,
+            configurable: true
+        });
         /**
          * Disposes of the gizmo
          */
@@ -89630,9 +89768,9 @@ var BABYLON;
          */
         function ScaleGizmo(gizmoLayer) {
             var _this = _super.call(this, gizmoLayer) || this;
-            _this._xDrag = new BABYLON.AxisScaleGizmo(gizmoLayer, new BABYLON.Vector3(1, 0, 0), BABYLON.Color3.FromHexString("#00b894"));
-            _this._yDrag = new BABYLON.AxisScaleGizmo(gizmoLayer, new BABYLON.Vector3(0, 1, 0), BABYLON.Color3.FromHexString("#d63031"));
-            _this._zDrag = new BABYLON.AxisScaleGizmo(gizmoLayer, new BABYLON.Vector3(0, 0, 1), BABYLON.Color3.FromHexString("#0984e3"));
+            _this._xDrag = new BABYLON.AxisScaleGizmo(gizmoLayer, new BABYLON.Vector3(1, 0, 0), BABYLON.Color3.Green().scale(0.5));
+            _this._yDrag = new BABYLON.AxisScaleGizmo(gizmoLayer, new BABYLON.Vector3(0, 1, 0), BABYLON.Color3.Red().scale(0.5));
+            _this._zDrag = new BABYLON.AxisScaleGizmo(gizmoLayer, new BABYLON.Vector3(0, 0, 1), BABYLON.Color3.Blue().scale(0.5));
             return _this;
         }
         Object.defineProperty(ScaleGizmo.prototype, "attachedMesh", {
@@ -89649,6 +89787,20 @@ var BABYLON;
             this._yDrag.interactionsEnabled = value;
             this._zDrag.interactionsEnabled = value;
         };
+        Object.defineProperty(ScaleGizmo.prototype, "updateGizmoRotationToMatchAttachedMesh", {
+            get: function () {
+                return this._xDrag.updateGizmoRotationToMatchAttachedMesh;
+            },
+            set: function (value) {
+                if (this._xDrag) {
+                    this._xDrag.updateGizmoRotationToMatchAttachedMesh = value;
+                    this._yDrag.updateGizmoRotationToMatchAttachedMesh = value;
+                    this._zDrag.updateGizmoRotationToMatchAttachedMesh = value;
+                }
+            },
+            enumerable: true,
+            configurable: true
+        });
         /**
          * Disposes of the gizmo
          */

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 37 - 37
dist/preview release/babylon.worker.js


+ 195 - 43
dist/preview release/es6.js

@@ -14034,11 +14034,16 @@ var BABYLON;
             if (defines === void 0) { defines = ""; }
             var attributesNamesOrOptions = BABYLON.ParticleSystem._GetAttributeNamesOrOptions();
             var effectCreationOption = BABYLON.ParticleSystem._GetEffectCreationOptions();
-            defines += "\n#define BILLBOARD\n";
+            if (defines.indexOf(" BILLBOARD") === -1) {
+                defines += "\n#define BILLBOARD\n";
+            }
+            if (samplers.indexOf("diffuseSampler") === -1) {
+                samplers.push("diffuseSampler");
+            }
             return this.createEffect({
                 vertex: "particles",
                 fragmentElement: fragmentName
-            }, attributesNamesOrOptions, effectCreationOption.concat(uniformsNames), ["diffuseSampler"].concat(samplers), defines, fallbacks, onCompiled, onError);
+            }, attributesNamesOrOptions, effectCreationOption.concat(uniformsNames), samplers, defines, fallbacks, onCompiled, onError);
         };
         /**
          * Directly creates a webGL program
@@ -36923,6 +36928,7 @@ var BABYLON;
          * @returns the VertexData
          */
         VertexData.prototype.transform = function (matrix) {
+            var flip = matrix.m[0] * matrix.m[5] * matrix.m[10] < 0;
             var transformed = BABYLON.Vector3.Zero();
             var index;
             if (this.positions) {
@@ -36957,6 +36963,13 @@ var BABYLON;
                     this.tangents[index + 3] = tangentTransformed.w;
                 }
             }
+            if (flip && this.indices) {
+                for (index = 0; index < this.indices.length; index += 3) {
+                    var tmp = this.indices[index + 1];
+                    this.indices[index + 1] = this.indices[index + 2];
+                    this.indices[index + 2] = tmp;
+                }
+            }
             return this;
         };
         /**
@@ -54103,9 +54116,19 @@ var BABYLON;
                 result = BABYLON.Vector3.Cross(p1p2, p3p2);
             }
             if (useWorldCoordinates) {
-                result = BABYLON.Vector3.TransformNormal(result, this.pickedMesh.getWorldMatrix());
+                var wm = this.pickedMesh.getWorldMatrix();
+                if (this.pickedMesh.nonUniformScaling) {
+                    BABYLON.Tmp.Matrix[0].copyFrom(wm);
+                    wm = BABYLON.Tmp.Matrix[0];
+                    wm.setTranslationFromFloats(0, 0, 0);
+                    wm.invert();
+                    wm.transposeToRef(BABYLON.Tmp.Matrix[1]);
+                    wm = BABYLON.Tmp.Matrix[1];
+                }
+                result = BABYLON.Vector3.TransformNormal(result, wm);
             }
-            return BABYLON.Vector3.Normalize(result);
+            result.normalize();
+            return result;
         };
         /**
          * Gets the texture coordinates of where the pick occured
@@ -56309,6 +56332,9 @@ var BABYLON;
                 var defines = (program.shaderOptions.defines.length > 0) ? program.shaderOptions.defines.join("\n") : "";
                 custom = this._scene.getEngine().createEffectForParticles(program.shaderPath.fragmentElement, program.shaderOptions.uniforms, program.shaderOptions.samplers, defines);
             }
+            else if (this._customEffect) {
+                custom = this._customEffect;
+            }
             var result = new ParticleSystem(name, this._capacity, this._scene, custom);
             result.customShader = program;
             BABYLON.Tools.DeepCopy(this, result, ["particles", "customShader"]);
@@ -56486,8 +56512,8 @@ var BABYLON;
                 }
             }
             // Emitter
+            var emitterType;
             if (parsedParticleSystem.particleEmitterType) {
-                var emitterType = void 0;
                 switch (parsedParticleSystem.particleEmitterType.type) {
                     case "SphereEmitter":
                         emitterType = new BABYLON.SphereParticleEmitter();
@@ -56504,8 +56530,12 @@ var BABYLON;
                         break;
                 }
                 emitterType.parse(parsedParticleSystem.particleEmitterType);
-                particleSystem.particleEmitterType = emitterType;
             }
+            else {
+                emitterType = new BABYLON.BoxParticleEmitter();
+                emitterType.parse(parsedParticleSystem);
+            }
+            particleSystem.particleEmitterType = emitterType;
         };
         /**
          * Parses a JSON object to create a particle system.
@@ -89312,27 +89342,32 @@ var BABYLON;
          */
         function AxisDragGizmo(gizmoLayer, dragAxis, color) {
             var _this = _super.call(this, gizmoLayer) || this;
-            _this.updateGizmoRotationToMatchAttachedMesh = false;
+            _this._pointerObserver = null;
             // Create Material
             var coloredMaterial = new BABYLON.StandardMaterial("", gizmoLayer.utilityLayerScene);
             coloredMaterial.disableLighting = true;
             coloredMaterial.emissiveColor = color;
+            var hoverMaterial = new BABYLON.StandardMaterial("", gizmoLayer.utilityLayerScene);
+            hoverMaterial.disableLighting = true;
+            hoverMaterial.emissiveColor = color.add(new BABYLON.Color3(0.2, 0.2, 0.2));
             // Build mesh on root node
+            var arrow = new BABYLON.AbstractMesh("", gizmoLayer.utilityLayerScene);
             var arrowMesh = BABYLON.MeshBuilder.CreateCylinder("yPosMesh", { diameterTop: 0, height: 2, tessellation: 96 }, gizmoLayer.utilityLayerScene);
-            var arrowTail = BABYLON.MeshBuilder.CreateCylinder("yPosMesh", { diameter: 0.03, height: 0.2, tessellation: 96 }, gizmoLayer.utilityLayerScene);
-            _this._rootMesh.addChild(arrowMesh);
-            _this._rootMesh.addChild(arrowTail);
+            var arrowTail = BABYLON.MeshBuilder.CreateCylinder("yPosMesh", { diameter: 0.015, height: 0.3, tessellation: 96 }, gizmoLayer.utilityLayerScene);
+            arrow.addChild(arrowMesh);
+            arrow.addChild(arrowTail);
             // Position arrow pointing in its drag axis
-            arrowMesh.scaling.scaleInPlace(0.1);
+            arrowMesh.scaling.scaleInPlace(0.05);
             arrowMesh.material = coloredMaterial;
             arrowMesh.rotation.x = Math.PI / 2;
             arrowMesh.position.z += 0.3;
             arrowTail.rotation.x = Math.PI / 2;
             arrowTail.material = coloredMaterial;
-            arrowTail.position.z += 0.2;
-            _this._rootMesh.lookAt(_this._rootMesh.position.subtract(dragAxis));
+            arrowTail.position.z += 0.15;
+            arrow.lookAt(_this._rootMesh.position.subtract(dragAxis));
+            _this._rootMesh.addChild(arrow);
             // Add drag behavior to handle events when the gizmo is dragged
-            _this._dragBehavior = new BABYLON.PointerDragBehavior({ dragAxis: new BABYLON.Vector3(0, 0, 1) });
+            _this._dragBehavior = new BABYLON.PointerDragBehavior({ dragAxis: dragAxis });
             _this._dragBehavior.moveAttached = false;
             _this._rootMesh.addBehavior(_this._dragBehavior);
             _this._dragBehavior.onDragObservable.add(function (event) {
@@ -89343,6 +89378,18 @@ var BABYLON;
                     _this.attachedMesh.position.addInPlace(event.delta);
                 }
             });
+            _this._pointerObserver = gizmoLayer.utilityLayerScene.onPointerObservable.add(function (pointerInfo, eventState) {
+                if (pointerInfo.pickInfo && (_this._rootMesh.getChildMeshes().indexOf(pointerInfo.pickInfo.pickedMesh) != -1)) {
+                    _this._rootMesh.getChildMeshes().forEach(function (m) {
+                        m.material = hoverMaterial;
+                    });
+                }
+                else {
+                    _this._rootMesh.getChildMeshes().forEach(function (m) {
+                        m.material = coloredMaterial;
+                    });
+                }
+            });
             return _this;
         }
         AxisDragGizmo.prototype._onInteractionsEnabledChanged = function (value) {
@@ -89352,6 +89399,7 @@ var BABYLON;
          * Disposes of the gizmo
          */
         AxisDragGizmo.prototype.dispose = function () {
+            this.gizmoLayer.utilityLayerScene.onPointerObservable.remove(this._pointerObserver);
             this._dragBehavior.detach();
             _super.prototype.dispose.call(this);
         };
@@ -89378,16 +89426,20 @@ var BABYLON;
          */
         function AxisScaleGizmo(gizmoLayer, dragAxis, color) {
             var _this = _super.call(this, gizmoLayer) || this;
-            _this.updateGizmoRotationToMatchAttachedMesh = false;
+            _this._pointerObserver = null;
             // Create Material
             var coloredMaterial = new BABYLON.StandardMaterial("", gizmoLayer.utilityLayerScene);
             coloredMaterial.disableLighting = true;
             coloredMaterial.emissiveColor = color;
+            var hoverMaterial = new BABYLON.StandardMaterial("", gizmoLayer.utilityLayerScene);
+            hoverMaterial.disableLighting = true;
+            hoverMaterial.emissiveColor = color.add(new BABYLON.Color3(0.2, 0.2, 0.2));
             // Build mesh on root node
-            var arrowMesh = BABYLON.MeshBuilder.CreateBox("yPosMesh", { size: 1 }, gizmoLayer.utilityLayerScene);
-            var arrowTail = BABYLON.MeshBuilder.CreateCylinder("yPosMesh", { diameter: 0.03, height: 0.2, tessellation: 96 }, gizmoLayer.utilityLayerScene);
-            _this._rootMesh.addChild(arrowMesh);
-            _this._rootMesh.addChild(arrowTail);
+            var arrow = new BABYLON.AbstractMesh("", gizmoLayer.utilityLayerScene);
+            var arrowMesh = BABYLON.MeshBuilder.CreateBox("yPosMesh", { size: 0.5 }, gizmoLayer.utilityLayerScene);
+            var arrowTail = BABYLON.MeshBuilder.CreateCylinder("yPosMesh", { diameter: 0.015, height: 0.3, tessellation: 96 }, gizmoLayer.utilityLayerScene);
+            arrow.addChild(arrowMesh);
+            arrow.addChild(arrowTail);
             // Position arrow pointing in its drag axis
             arrowMesh.scaling.scaleInPlace(0.1);
             arrowMesh.material = coloredMaterial;
@@ -89395,18 +89447,48 @@ var BABYLON;
             arrowMesh.position.z += 0.3;
             arrowTail.rotation.x = Math.PI / 2;
             arrowTail.material = coloredMaterial;
-            arrowTail.position.z += 0.2;
-            _this._rootMesh.lookAt(_this._rootMesh.position.subtract(dragAxis));
+            arrowTail.position.z += 0.15;
+            arrow.lookAt(_this._rootMesh.position.subtract(dragAxis));
+            _this._rootMesh.addChild(arrow);
             // Add drag behavior to handle events when the gizmo is dragged
-            _this._dragBehavior = new BABYLON.PointerDragBehavior({ dragAxis: new BABYLON.Vector3(0, 0, 1) });
+            _this._dragBehavior = new BABYLON.PointerDragBehavior({ dragAxis: dragAxis });
             _this._dragBehavior.moveAttached = false;
             _this._rootMesh.addBehavior(_this._dragBehavior);
+            var tmpVector = new BABYLON.Vector3();
             _this._dragBehavior.onDragObservable.add(function (event) {
                 if (!_this.interactionsEnabled) {
                     return;
                 }
                 if (_this.attachedMesh) {
-                    _this.attachedMesh.scaling.addInPlace(event.delta);
+                    dragAxis.scaleToRef(event.dragDistance, tmpVector);
+                    var invertCount = 0;
+                    if (_this.attachedMesh.scaling["x"] < 0) {
+                        invertCount++;
+                    }
+                    if (_this.attachedMesh.scaling["y"] < 0) {
+                        invertCount++;
+                    }
+                    if (_this.attachedMesh.scaling["z"] < 0) {
+                        invertCount++;
+                    }
+                    if (invertCount % 2 == 0) {
+                        _this.attachedMesh.scaling.addInPlace(tmpVector);
+                    }
+                    else {
+                        _this.attachedMesh.scaling.subtractInPlace(tmpVector);
+                    }
+                }
+            });
+            _this._pointerObserver = gizmoLayer.utilityLayerScene.onPointerObservable.add(function (pointerInfo, eventState) {
+                if (pointerInfo.pickInfo && (_this._rootMesh.getChildMeshes().indexOf(pointerInfo.pickInfo.pickedMesh) != -1)) {
+                    _this._rootMesh.getChildMeshes().forEach(function (m) {
+                        m.material = hoverMaterial;
+                    });
+                }
+                else {
+                    _this._rootMesh.getChildMeshes().forEach(function (m) {
+                        m.material = coloredMaterial;
+                    });
                 }
             });
             return _this;
@@ -89418,6 +89500,7 @@ var BABYLON;
          * Disposes of the gizmo
          */
         AxisScaleGizmo.prototype.dispose = function () {
+            this.gizmoLayer.utilityLayerScene.onPointerObservable.remove(this._pointerObserver);
             this._dragBehavior.detach();
             _super.prototype.dispose.call(this);
         };
@@ -89444,21 +89527,26 @@ var BABYLON;
          */
         function PlaneRotationGizmo(gizmoLayer, planeNormal, color) {
             var _this = _super.call(this, gizmoLayer) || this;
-            _this.updateGizmoRotationToMatchAttachedMesh = false;
+            _this._pointerObserver = null;
             // Create Material
             var coloredMaterial = new BABYLON.StandardMaterial("", gizmoLayer.utilityLayerScene);
             coloredMaterial.disableLighting = true;
             coloredMaterial.emissiveColor = color;
+            var hoverMaterial = new BABYLON.StandardMaterial("", gizmoLayer.utilityLayerScene);
+            hoverMaterial.disableLighting = true;
+            hoverMaterial.emissiveColor = color.add(new BABYLON.Color3(0.2, 0.2, 0.2));
             // Build mesh on root node
-            var rotationMesh = BABYLON.Mesh.CreateTorus("torus", 3, 0.3, 20, gizmoLayer.utilityLayerScene, false);
-            _this._rootMesh.addChild(rotationMesh);
+            var parentMesh = new BABYLON.AbstractMesh("", gizmoLayer.utilityLayerScene);
+            var rotationMesh = BABYLON.Mesh.CreateTorus("torus", 3, 0.15, 20, gizmoLayer.utilityLayerScene, false);
             // Position arrow pointing in its drag axis
             rotationMesh.scaling.scaleInPlace(0.1);
             rotationMesh.material = coloredMaterial;
             rotationMesh.rotation.x = Math.PI / 2;
-            _this._rootMesh.lookAt(_this._rootMesh.position.subtract(planeNormal));
+            parentMesh.addChild(rotationMesh);
+            parentMesh.lookAt(_this._rootMesh.position.subtract(planeNormal));
+            _this._rootMesh.addChild(parentMesh);
             // Add drag behavior to handle events when the gizmo is dragged
-            _this._dragBehavior = new BABYLON.PointerDragBehavior({ dragPlaneNormal: new BABYLON.Vector3(0, 0, 1) });
+            _this._dragBehavior = new BABYLON.PointerDragBehavior({ dragPlaneNormal: planeNormal });
             _this._dragBehavior.moveAttached = false;
             _this._rootMesh.addBehavior(_this._dragBehavior);
             var lastDragPosition = null;
@@ -89468,6 +89556,9 @@ var BABYLON;
                 }
                 lastDragPosition = e.dragPlanePoint;
             });
+            var rotationMatrix = new BABYLON.Matrix();
+            var planeNormalTowardsCamera = new BABYLON.Vector3();
+            var localPlaneNormalTowardsCamera = new BABYLON.Vector3();
             _this._dragBehavior.onDragObservable.add(function (event) {
                 if (!_this.interactionsEnabled) {
                     return;
@@ -89482,25 +89573,43 @@ var BABYLON;
                     var cross = BABYLON.Vector3.Cross(newVector, originalVector);
                     var dot = BABYLON.Vector3.Dot(newVector, originalVector);
                     var angle = Math.atan2(cross.length(), dot);
-                    var up = planeNormal.clone();
+                    planeNormalTowardsCamera.copyFrom(planeNormal);
+                    localPlaneNormalTowardsCamera.copyFrom(planeNormal);
+                    if (_this.updateGizmoRotationToMatchAttachedMesh) {
+                        _this.attachedMesh.rotationQuaternion.toRotationMatrix(rotationMatrix);
+                        localPlaneNormalTowardsCamera = BABYLON.Vector3.TransformCoordinates(planeNormalTowardsCamera, rotationMatrix);
+                    }
                     // Flip up vector depending on which side the camera is on
                     if (gizmoLayer.utilityLayerScene.activeCamera) {
                         var camVec = gizmoLayer.utilityLayerScene.activeCamera.position.subtract(_this.attachedMesh.position);
-                        if (BABYLON.Vector3.Dot(camVec, up) > 0) {
-                            up.scaleInPlace(-1);
+                        if (BABYLON.Vector3.Dot(camVec, localPlaneNormalTowardsCamera) > 0) {
+                            planeNormalTowardsCamera.scaleInPlace(-1);
+                            localPlaneNormalTowardsCamera.scaleInPlace(-1);
                         }
                     }
-                    var halfCircleSide = BABYLON.Vector3.Dot(up, cross) > 0.0;
+                    var halfCircleSide = BABYLON.Vector3.Dot(localPlaneNormalTowardsCamera, cross) > 0.0;
                     if (halfCircleSide)
                         angle = -angle;
                     // Convert angle and axis to quaternion (http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm)
                     var quaternionCoefficient = Math.sin(angle / 2);
-                    var amountToRotate = new BABYLON.Quaternion(up.x * quaternionCoefficient, up.y * quaternionCoefficient, up.z * quaternionCoefficient, Math.cos(angle / 2));
+                    var amountToRotate = new BABYLON.Quaternion(planeNormalTowardsCamera.x * quaternionCoefficient, planeNormalTowardsCamera.y * quaternionCoefficient, planeNormalTowardsCamera.z * quaternionCoefficient, Math.cos(angle / 2));
                     // Rotate selected mesh quaternion over fixed axis
-                    amountToRotate.multiplyToRef(_this.attachedMesh.rotationQuaternion, _this.attachedMesh.rotationQuaternion);
+                    _this.attachedMesh.rotationQuaternion.multiplyToRef(amountToRotate, _this.attachedMesh.rotationQuaternion);
                     lastDragPosition = event.dragPlanePoint;
                 }
             });
+            _this._pointerObserver = gizmoLayer.utilityLayerScene.onPointerObservable.add(function (pointerInfo, eventState) {
+                if (pointerInfo.pickInfo && (_this._rootMesh.getChildMeshes().indexOf(pointerInfo.pickInfo.pickedMesh) != -1)) {
+                    _this._rootMesh.getChildMeshes().forEach(function (m) {
+                        m.material = hoverMaterial;
+                    });
+                }
+                else {
+                    _this._rootMesh.getChildMeshes().forEach(function (m) {
+                        m.material = coloredMaterial;
+                    });
+                }
+            });
             return _this;
         }
         PlaneRotationGizmo.prototype._onInteractionsEnabledChanged = function (value) {
@@ -89510,6 +89619,7 @@ var BABYLON;
          * Disposes of the gizmo
          */
         PlaneRotationGizmo.prototype.dispose = function () {
+            this.gizmoLayer.utilityLayerScene.onPointerObservable.remove(this._pointerObserver);
             this._dragBehavior.detach();
             _super.prototype.dispose.call(this);
         };
@@ -89534,9 +89644,9 @@ var BABYLON;
          */
         function PositionGizmo(gizmoLayer) {
             var _this = _super.call(this, gizmoLayer) || this;
-            _this._xDrag = new BABYLON.AxisDragGizmo(gizmoLayer, new BABYLON.Vector3(1, 0, 0), BABYLON.Color3.FromHexString("#00b894"));
-            _this._yDrag = new BABYLON.AxisDragGizmo(gizmoLayer, new BABYLON.Vector3(0, 1, 0), BABYLON.Color3.FromHexString("#d63031"));
-            _this._zDrag = new BABYLON.AxisDragGizmo(gizmoLayer, new BABYLON.Vector3(0, 0, 1), BABYLON.Color3.FromHexString("#0984e3"));
+            _this._xDrag = new BABYLON.AxisDragGizmo(gizmoLayer, new BABYLON.Vector3(1, 0, 0), BABYLON.Color3.Green().scale(0.5));
+            _this._yDrag = new BABYLON.AxisDragGizmo(gizmoLayer, new BABYLON.Vector3(0, 1, 0), BABYLON.Color3.Red().scale(0.5));
+            _this._zDrag = new BABYLON.AxisDragGizmo(gizmoLayer, new BABYLON.Vector3(0, 0, 1), BABYLON.Color3.Blue().scale(0.5));
             return _this;
         }
         Object.defineProperty(PositionGizmo.prototype, "attachedMesh", {
@@ -89553,6 +89663,20 @@ var BABYLON;
             this._yDrag.interactionsEnabled = value;
             this._zDrag.interactionsEnabled = value;
         };
+        Object.defineProperty(PositionGizmo.prototype, "updateGizmoRotationToMatchAttachedMesh", {
+            get: function () {
+                return this._xDrag.updateGizmoRotationToMatchAttachedMesh;
+            },
+            set: function (value) {
+                if (this._xDrag) {
+                    this._xDrag.updateGizmoRotationToMatchAttachedMesh = value;
+                    this._yDrag.updateGizmoRotationToMatchAttachedMesh = value;
+                    this._zDrag.updateGizmoRotationToMatchAttachedMesh = value;
+                }
+            },
+            enumerable: true,
+            configurable: true
+        });
         /**
          * Disposes of the gizmo
          */
@@ -89582,9 +89706,9 @@ var BABYLON;
          */
         function RotationGizmo(gizmoLayer) {
             var _this = _super.call(this, gizmoLayer) || this;
-            _this._xDrag = new BABYLON.PlaneRotationGizmo(gizmoLayer, new BABYLON.Vector3(1, 0, 0), BABYLON.Color3.FromHexString("#00b894"));
-            _this._yDrag = new BABYLON.PlaneRotationGizmo(gizmoLayer, new BABYLON.Vector3(0, 1, 0), BABYLON.Color3.FromHexString("#d63031"));
-            _this._zDrag = new BABYLON.PlaneRotationGizmo(gizmoLayer, new BABYLON.Vector3(0, 0, 1), BABYLON.Color3.FromHexString("#0984e3"));
+            _this._xDrag = new BABYLON.PlaneRotationGizmo(gizmoLayer, new BABYLON.Vector3(1, 0, 0), BABYLON.Color3.Green().scale(0.5));
+            _this._yDrag = new BABYLON.PlaneRotationGizmo(gizmoLayer, new BABYLON.Vector3(0, 1, 0), BABYLON.Color3.Red().scale(0.5));
+            _this._zDrag = new BABYLON.PlaneRotationGizmo(gizmoLayer, new BABYLON.Vector3(0, 0, 1), BABYLON.Color3.Blue().scale(0.5));
             return _this;
         }
         Object.defineProperty(RotationGizmo.prototype, "attachedMesh", {
@@ -89601,6 +89725,20 @@ var BABYLON;
             this._yDrag.interactionsEnabled = value;
             this._zDrag.interactionsEnabled = value;
         };
+        Object.defineProperty(RotationGizmo.prototype, "updateGizmoRotationToMatchAttachedMesh", {
+            get: function () {
+                return this._xDrag.updateGizmoRotationToMatchAttachedMesh;
+            },
+            set: function (value) {
+                if (this._xDrag) {
+                    this._xDrag.updateGizmoRotationToMatchAttachedMesh = value;
+                    this._yDrag.updateGizmoRotationToMatchAttachedMesh = value;
+                    this._zDrag.updateGizmoRotationToMatchAttachedMesh = value;
+                }
+            },
+            enumerable: true,
+            configurable: true
+        });
         /**
          * Disposes of the gizmo
          */
@@ -89630,9 +89768,9 @@ var BABYLON;
          */
         function ScaleGizmo(gizmoLayer) {
             var _this = _super.call(this, gizmoLayer) || this;
-            _this._xDrag = new BABYLON.AxisScaleGizmo(gizmoLayer, new BABYLON.Vector3(1, 0, 0), BABYLON.Color3.FromHexString("#00b894"));
-            _this._yDrag = new BABYLON.AxisScaleGizmo(gizmoLayer, new BABYLON.Vector3(0, 1, 0), BABYLON.Color3.FromHexString("#d63031"));
-            _this._zDrag = new BABYLON.AxisScaleGizmo(gizmoLayer, new BABYLON.Vector3(0, 0, 1), BABYLON.Color3.FromHexString("#0984e3"));
+            _this._xDrag = new BABYLON.AxisScaleGizmo(gizmoLayer, new BABYLON.Vector3(1, 0, 0), BABYLON.Color3.Green().scale(0.5));
+            _this._yDrag = new BABYLON.AxisScaleGizmo(gizmoLayer, new BABYLON.Vector3(0, 1, 0), BABYLON.Color3.Red().scale(0.5));
+            _this._zDrag = new BABYLON.AxisScaleGizmo(gizmoLayer, new BABYLON.Vector3(0, 0, 1), BABYLON.Color3.Blue().scale(0.5));
             return _this;
         }
         Object.defineProperty(ScaleGizmo.prototype, "attachedMesh", {
@@ -89649,6 +89787,20 @@ var BABYLON;
             this._yDrag.interactionsEnabled = value;
             this._zDrag.interactionsEnabled = value;
         };
+        Object.defineProperty(ScaleGizmo.prototype, "updateGizmoRotationToMatchAttachedMesh", {
+            get: function () {
+                return this._xDrag.updateGizmoRotationToMatchAttachedMesh;
+            },
+            set: function (value) {
+                if (this._xDrag) {
+                    this._xDrag.updateGizmoRotationToMatchAttachedMesh = value;
+                    this._yDrag.updateGizmoRotationToMatchAttachedMesh = value;
+                    this._zDrag.updateGizmoRotationToMatchAttachedMesh = value;
+                }
+            },
+            enumerable: true,
+            configurable: true
+        });
         /**
          * Disposes of the gizmo
          */

+ 9 - 4
dist/preview release/loaders/babylon.objFileLoader.d.ts

@@ -28,7 +28,7 @@ declare module BABYLON {
          */
         private static _getTexture(rootUrl, value, scene);
     }
-    class OBJFileLoader implements ISceneLoaderPlugin {
+    class OBJFileLoader implements ISceneLoaderPluginAsync {
         static OPTIMIZE_WITH_UV: boolean;
         static INVERT_Y: boolean;
         name: string;
@@ -57,9 +57,14 @@ declare module BABYLON {
          * @private
          */
         private _loadMTL(url, rootUrl, onSuccess);
-        importMesh(meshesNames: any, scene: Scene, data: any, rootUrl: string, meshes: Nullable<AbstractMesh[]>, particleSystems: Nullable<ParticleSystem[]>, skeletons: Nullable<Skeleton[]>): boolean;
-        load(scene: Scene, data: string, rootUrl: string): boolean;
-        loadAssetContainer(scene: Scene, data: string, rootUrl: string, onError?: (message: string, exception?: any) => void): AssetContainer;
+        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{
+            meshes: AbstractMesh[];
+            particleSystems: ParticleSystem[];
+            skeletons: Skeleton[];
+            animationGroups: AnimationGroup[];
+        }>;
+        loadAsync(scene: Scene, data: string, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<void>;
+        loadAssetContainerAsync(scene: Scene, data: string, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<AssetContainer>;
         /**
          * Read the OBJ file and create an Array of meshes.
          * Each mesh contains all information given by the OBJ and the MTL file.

+ 60 - 44
dist/preview release/loaders/babylon.objFileLoader.js

@@ -249,26 +249,30 @@ var BABYLON;
             // Loads through the babylon tools to allow fileInput search.
             BABYLON.Tools.LoadFile(pathOfFile, onSuccess, undefined, undefined, false, function () { console.warn("Error - Unable to load " + pathOfFile); });
         };
-        OBJFileLoader.prototype.importMesh = function (meshesNames, scene, data, rootUrl, meshes, particleSystems, skeletons) {
+        OBJFileLoader.prototype.importMeshAsync = function (meshesNames, scene, data, rootUrl, onProgress) {
             //get the meshes from OBJ file
-            var loadedMeshes = this._parseSolid(meshesNames, scene, data, rootUrl);
-            //Push meshes from OBJ file into the variable mesh of this function
-            if (meshes) {
-                loadedMeshes.forEach(function (mesh) {
-                    meshes.push(mesh);
-                });
-            }
-            return true;
+            return this._parseSolid(meshesNames, scene, data, rootUrl).then(function (meshes) {
+                return {
+                    meshes: meshes,
+                    particleSystems: [],
+                    skeletons: [],
+                    animationGroups: []
+                };
+            });
         };
-        OBJFileLoader.prototype.load = function (scene, data, rootUrl) {
+        OBJFileLoader.prototype.loadAsync = function (scene, data, rootUrl, onProgress) {
             //Get the 3D model
-            return this.importMesh(null, scene, data, rootUrl, null, null, null);
+            return this.importMeshAsync(null, scene, data, rootUrl, onProgress).then(function () {
+                // return void
+            });
         };
-        OBJFileLoader.prototype.loadAssetContainer = function (scene, data, rootUrl, onError) {
-            var container = new BABYLON.AssetContainer(scene);
-            this.importMesh(null, scene, data, rootUrl, container.meshes, null, null);
-            container.removeAllFromScene();
-            return container;
+        OBJFileLoader.prototype.loadAssetContainerAsync = function (scene, data, rootUrl, onProgress) {
+            return this.importMeshAsync(null, scene, data, rootUrl).then(function (result) {
+                var container = new BABYLON.AssetContainer(scene);
+                result.meshes.forEach(function (mesh) { return container.meshes.push(mesh); });
+                container.removeAllFromScene();
+                return container;
+            });
         };
         /**
          * Read the OBJ file and create an Array of meshes.
@@ -283,6 +287,7 @@ var BABYLON;
          * @private
          */
         OBJFileLoader.prototype._parseSolid = function (meshesNames, scene, data, rootUrl) {
+            var _this = this;
             var positions = []; //values for the positions of vertices
             var normals = []; //Values for the normals
             var uvs = []; //Values for the textures
@@ -752,42 +757,53 @@ var BABYLON;
                 //Push the mesh into an array
                 babylonMeshesArray.push(babylonMesh);
             }
+            var mtlPromises = [];
             //load the materials
             //Check if we have a file to load
             if (fileToLoad !== "") {
                 //Load the file synchronously
-                this._loadMTL(fileToLoad, rootUrl, function (dataLoaded) {
-                    //Create materials thanks MTLLoader function
-                    materialsFromMTLFile.parseMTL(scene, dataLoaded, rootUrl);
-                    //Look at each material loaded in the mtl file
-                    for (var n = 0; n < materialsFromMTLFile.materials.length; n++) {
-                        //Three variables to get all meshes with the same material
-                        var startIndex = 0;
-                        var _indices = [];
-                        var _index;
-                        //The material from MTL file is used in the meshes loaded
-                        //Push the indice in an array
-                        //Check if the material is not used for another mesh
-                        while ((_index = materialToUse.indexOf(materialsFromMTLFile.materials[n].name, startIndex)) > -1) {
-                            _indices.push(_index);
-                            startIndex = _index + 1;
-                        }
-                        //If the material is not used dispose it
-                        if (_index == -1 && _indices.length == 0) {
-                            //If the material is not needed, remove it
-                            materialsFromMTLFile.materials[n].dispose();
-                        }
-                        else {
-                            for (var o = 0; o < _indices.length; o++) {
-                                //Apply the material to the BABYLON.Mesh for each mesh with the material
-                                babylonMeshesArray[_indices[o]].material = materialsFromMTLFile.materials[n];
+                mtlPromises.push(new Promise(function (resolve, reject) {
+                    _this._loadMTL(fileToLoad, rootUrl, function (dataLoaded) {
+                        try {
+                            //Create materials thanks MTLLoader function
+                            materialsFromMTLFile.parseMTL(scene, dataLoaded, rootUrl);
+                            //Look at each material loaded in the mtl file
+                            for (var n = 0; n < materialsFromMTLFile.materials.length; n++) {
+                                //Three variables to get all meshes with the same material
+                                var startIndex = 0;
+                                var _indices = [];
+                                var _index;
+                                //The material from MTL file is used in the meshes loaded
+                                //Push the indice in an array
+                                //Check if the material is not used for another mesh
+                                while ((_index = materialToUse.indexOf(materialsFromMTLFile.materials[n].name, startIndex)) > -1) {
+                                    _indices.push(_index);
+                                    startIndex = _index + 1;
+                                }
+                                //If the material is not used dispose it
+                                if (_index == -1 && _indices.length == 0) {
+                                    //If the material is not needed, remove it
+                                    materialsFromMTLFile.materials[n].dispose();
+                                }
+                                else {
+                                    for (var o = 0; o < _indices.length; o++) {
+                                        //Apply the material to the BABYLON.Mesh for each mesh with the material
+                                        babylonMeshesArray[_indices[o]].material = materialsFromMTLFile.materials[n];
+                                    }
+                                }
                             }
+                            resolve();
                         }
-                    }
-                });
+                        catch (e) {
+                            reject(e);
+                        }
+                    });
+                }));
             }
             //Return an array with all BABYLON.Mesh
-            return babylonMeshesArray;
+            return Promise.all(mtlPromises).then(function () {
+                return babylonMeshesArray;
+            });
         };
         OBJFileLoader.OPTIMIZE_WITH_UV = false;
         OBJFileLoader.INVERT_Y = false;

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 1
dist/preview release/loaders/babylon.objFileLoader.min.js


+ 9 - 4
dist/preview release/loaders/babylonjs.loaders.d.ts

@@ -46,7 +46,7 @@ declare module BABYLON {
          */
         private static _getTexture(rootUrl, value, scene);
     }
-    class OBJFileLoader implements ISceneLoaderPlugin {
+    class OBJFileLoader implements ISceneLoaderPluginAsync {
         static OPTIMIZE_WITH_UV: boolean;
         static INVERT_Y: boolean;
         name: string;
@@ -75,9 +75,14 @@ declare module BABYLON {
          * @private
          */
         private _loadMTL(url, rootUrl, onSuccess);
-        importMesh(meshesNames: any, scene: Scene, data: any, rootUrl: string, meshes: Nullable<AbstractMesh[]>, particleSystems: Nullable<ParticleSystem[]>, skeletons: Nullable<Skeleton[]>): boolean;
-        load(scene: Scene, data: string, rootUrl: string): boolean;
-        loadAssetContainer(scene: Scene, data: string, rootUrl: string, onError?: (message: string, exception?: any) => void): AssetContainer;
+        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{
+            meshes: AbstractMesh[];
+            particleSystems: ParticleSystem[];
+            skeletons: Skeleton[];
+            animationGroups: AnimationGroup[];
+        }>;
+        loadAsync(scene: Scene, data: string, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<void>;
+        loadAssetContainerAsync(scene: Scene, data: string, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<AssetContainer>;
         /**
          * Read the OBJ file and create an Array of meshes.
          * Each mesh contains all information given by the OBJ and the MTL file.

+ 60 - 44
dist/preview release/loaders/babylonjs.loaders.js

@@ -448,26 +448,30 @@ var BABYLON;
             // Loads through the babylon tools to allow fileInput search.
             BABYLON.Tools.LoadFile(pathOfFile, onSuccess, undefined, undefined, false, function () { console.warn("Error - Unable to load " + pathOfFile); });
         };
-        OBJFileLoader.prototype.importMesh = function (meshesNames, scene, data, rootUrl, meshes, particleSystems, skeletons) {
+        OBJFileLoader.prototype.importMeshAsync = function (meshesNames, scene, data, rootUrl, onProgress) {
             //get the meshes from OBJ file
-            var loadedMeshes = this._parseSolid(meshesNames, scene, data, rootUrl);
-            //Push meshes from OBJ file into the variable mesh of this function
-            if (meshes) {
-                loadedMeshes.forEach(function (mesh) {
-                    meshes.push(mesh);
-                });
-            }
-            return true;
+            return this._parseSolid(meshesNames, scene, data, rootUrl).then(function (meshes) {
+                return {
+                    meshes: meshes,
+                    particleSystems: [],
+                    skeletons: [],
+                    animationGroups: []
+                };
+            });
         };
-        OBJFileLoader.prototype.load = function (scene, data, rootUrl) {
+        OBJFileLoader.prototype.loadAsync = function (scene, data, rootUrl, onProgress) {
             //Get the 3D model
-            return this.importMesh(null, scene, data, rootUrl, null, null, null);
+            return this.importMeshAsync(null, scene, data, rootUrl, onProgress).then(function () {
+                // return void
+            });
         };
-        OBJFileLoader.prototype.loadAssetContainer = function (scene, data, rootUrl, onError) {
-            var container = new BABYLON.AssetContainer(scene);
-            this.importMesh(null, scene, data, rootUrl, container.meshes, null, null);
-            container.removeAllFromScene();
-            return container;
+        OBJFileLoader.prototype.loadAssetContainerAsync = function (scene, data, rootUrl, onProgress) {
+            return this.importMeshAsync(null, scene, data, rootUrl).then(function (result) {
+                var container = new BABYLON.AssetContainer(scene);
+                result.meshes.forEach(function (mesh) { return container.meshes.push(mesh); });
+                container.removeAllFromScene();
+                return container;
+            });
         };
         /**
          * Read the OBJ file and create an Array of meshes.
@@ -482,6 +486,7 @@ var BABYLON;
          * @private
          */
         OBJFileLoader.prototype._parseSolid = function (meshesNames, scene, data, rootUrl) {
+            var _this = this;
             var positions = []; //values for the positions of vertices
             var normals = []; //Values for the normals
             var uvs = []; //Values for the textures
@@ -951,42 +956,53 @@ var BABYLON;
                 //Push the mesh into an array
                 babylonMeshesArray.push(babylonMesh);
             }
+            var mtlPromises = [];
             //load the materials
             //Check if we have a file to load
             if (fileToLoad !== "") {
                 //Load the file synchronously
-                this._loadMTL(fileToLoad, rootUrl, function (dataLoaded) {
-                    //Create materials thanks MTLLoader function
-                    materialsFromMTLFile.parseMTL(scene, dataLoaded, rootUrl);
-                    //Look at each material loaded in the mtl file
-                    for (var n = 0; n < materialsFromMTLFile.materials.length; n++) {
-                        //Three variables to get all meshes with the same material
-                        var startIndex = 0;
-                        var _indices = [];
-                        var _index;
-                        //The material from MTL file is used in the meshes loaded
-                        //Push the indice in an array
-                        //Check if the material is not used for another mesh
-                        while ((_index = materialToUse.indexOf(materialsFromMTLFile.materials[n].name, startIndex)) > -1) {
-                            _indices.push(_index);
-                            startIndex = _index + 1;
-                        }
-                        //If the material is not used dispose it
-                        if (_index == -1 && _indices.length == 0) {
-                            //If the material is not needed, remove it
-                            materialsFromMTLFile.materials[n].dispose();
-                        }
-                        else {
-                            for (var o = 0; o < _indices.length; o++) {
-                                //Apply the material to the BABYLON.Mesh for each mesh with the material
-                                babylonMeshesArray[_indices[o]].material = materialsFromMTLFile.materials[n];
+                mtlPromises.push(new Promise(function (resolve, reject) {
+                    _this._loadMTL(fileToLoad, rootUrl, function (dataLoaded) {
+                        try {
+                            //Create materials thanks MTLLoader function
+                            materialsFromMTLFile.parseMTL(scene, dataLoaded, rootUrl);
+                            //Look at each material loaded in the mtl file
+                            for (var n = 0; n < materialsFromMTLFile.materials.length; n++) {
+                                //Three variables to get all meshes with the same material
+                                var startIndex = 0;
+                                var _indices = [];
+                                var _index;
+                                //The material from MTL file is used in the meshes loaded
+                                //Push the indice in an array
+                                //Check if the material is not used for another mesh
+                                while ((_index = materialToUse.indexOf(materialsFromMTLFile.materials[n].name, startIndex)) > -1) {
+                                    _indices.push(_index);
+                                    startIndex = _index + 1;
+                                }
+                                //If the material is not used dispose it
+                                if (_index == -1 && _indices.length == 0) {
+                                    //If the material is not needed, remove it
+                                    materialsFromMTLFile.materials[n].dispose();
+                                }
+                                else {
+                                    for (var o = 0; o < _indices.length; o++) {
+                                        //Apply the material to the BABYLON.Mesh for each mesh with the material
+                                        babylonMeshesArray[_indices[o]].material = materialsFromMTLFile.materials[n];
+                                    }
+                                }
                             }
+                            resolve();
                         }
-                    }
-                });
+                        catch (e) {
+                            reject(e);
+                        }
+                    });
+                }));
             }
             //Return an array with all BABYLON.Mesh
-            return babylonMeshesArray;
+            return Promise.all(mtlPromises).then(function () {
+                return babylonMeshesArray;
+            });
         };
         OBJFileLoader.OPTIMIZE_WITH_UV = false;
         OBJFileLoader.INVERT_Y = false;

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 4 - 4
dist/preview release/loaders/babylonjs.loaders.min.js


+ 9 - 4
dist/preview release/loaders/babylonjs.loaders.module.d.ts

@@ -53,7 +53,7 @@ declare module BABYLON {
          */
         private static _getTexture(rootUrl, value, scene);
     }
-    class OBJFileLoader implements ISceneLoaderPlugin {
+    class OBJFileLoader implements ISceneLoaderPluginAsync {
         static OPTIMIZE_WITH_UV: boolean;
         static INVERT_Y: boolean;
         name: string;
@@ -82,9 +82,14 @@ declare module BABYLON {
          * @private
          */
         private _loadMTL(url, rootUrl, onSuccess);
-        importMesh(meshesNames: any, scene: Scene, data: any, rootUrl: string, meshes: Nullable<AbstractMesh[]>, particleSystems: Nullable<ParticleSystem[]>, skeletons: Nullable<Skeleton[]>): boolean;
-        load(scene: Scene, data: string, rootUrl: string): boolean;
-        loadAssetContainer(scene: Scene, data: string, rootUrl: string, onError?: (message: string, exception?: any) => void): AssetContainer;
+        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{
+            meshes: AbstractMesh[];
+            particleSystems: ParticleSystem[];
+            skeletons: Skeleton[];
+            animationGroups: AnimationGroup[];
+        }>;
+        loadAsync(scene: Scene, data: string, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<void>;
+        loadAssetContainerAsync(scene: Scene, data: string, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<AssetContainer>;
         /**
          * Read the OBJ file and create an Array of meshes.
          * Each mesh contains all information given by the OBJ and the MTL file.

+ 69 - 82
dist/preview release/serializers/babylon.glTF2Serializer.d.ts

@@ -49,86 +49,99 @@ declare module BABYLON.GLTF2 {
         /**
          * Stores all generated buffer views, which represents views into the main glTF buffer data
          */
-        private bufferViews;
+        private _bufferViews;
         /**
          * Stores all the generated accessors, which is used for accessing the data within the buffer views in glTF
          */
-        private accessors;
+        private _accessors;
         /**
          * Stores all the generated nodes, which contains transform and/or mesh information per node
          */
-        private nodes;
+        private _nodes;
         /**
          * Stores the glTF asset information, which represents the glTF version and this file generator
          */
-        private asset;
+        private _asset;
         /**
          * Stores all the generated glTF scenes, which stores multiple node hierarchies
          */
-        private scenes;
+        private _scenes;
         /**
          * Stores all the generated mesh information, each containing a set of primitives to render in glTF
          */
-        private meshes;
+        private _meshes;
         /**
          * Stores all the generated material information, which represents the appearance of each primitive
          */
-        private materials;
-        private materialMap;
+        _materials: IMaterial[];
+        _materialMap: {
+            [materialID: number]: number;
+        };
         /**
          * Stores all the generated texture information, which is referenced by glTF materials
          */
-        private textures;
+        _textures: ITexture[];
         /**
          * Stores all the generated image information, which is referenced by glTF textures
          */
-        private images;
+        _images: IImage[];
         /**
          * Stores all the texture samplers
          */
-        private samplers;
+        _samplers: ISampler[];
         /**
          * Stores all the generated animation samplers, which is referenced by glTF animations
          */
         /**
          * Stores the animations for glTF models
          */
-        private animations;
+        private _animations;
         /**
          * Stores the total amount of bytes stored in the glTF buffer
          */
-        private totalByteLength;
+        private _totalByteLength;
         /**
          * Stores a reference to the Babylon scene containing the source geometry and material information
          */
-        private babylonScene;
+        private _babylonScene;
         /**
          * Stores a map of the image data, where the key is the file name and the value
          * is the image data
          */
-        private imageData;
+        _imageData: {
+            [fileName: string]: {
+                data: Uint8Array;
+                mimeType: ImageMimeType;
+            };
+        };
         /**
          * Stores a map of the unique id of a node to its index in the node array
          */
-        private nodeMap;
+        private _nodeMap;
         /**
          * Specifies if the Babylon scene should be converted to right-handed on export
          */
-        private convertToRightHandedSystem;
+        private _convertToRightHandedSystem;
         /**
          * Baked animation sample rate
          */
-        private animationSampleRate;
+        private _animationSampleRate;
         /**
          * Callback which specifies if a transform node should be exported or not
          */
-        private shouldExportTransformNode;
+        private _shouldExportTransformNode;
+        private _localEngine;
+        private _glTFMaterialExporter;
         /**
          * Creates a glTF Exporter instance, which can accept optional exporter options
          * @param babylonScene Babylon scene object
          * @param options Options to modify the behavior of the exporter
          */
         constructor(babylonScene: Scene, options?: IExportOptions);
+        /**
+         * Lazy load a local engine with premultiplied alpha set to false
+         */
+        _getLocalEngine(): Engine;
         private reorderIndicesBasedOnPrimitiveMode(submesh, primitiveMode, babylonIndices, byteOffset, binaryWriter);
         /**
          * Reorders the vertex attribute data based on the primitive mode.  This is necessary when indices are not available and the winding order is
@@ -388,19 +401,28 @@ declare module BABYLON.GLTF2 {
      * Utility methods for working with glTF material conversion properties.  This class should only be used internally
      * @hidden
      */
-    class _GLTFMaterial {
+    class _GLTFMaterialExporter {
         /**
          * Represents the dielectric specular values for R, G and B
          */
-        private static readonly _dielectricSpecular;
+        private static readonly _DielectricSpecular;
         /**
          * Allows the maximum specular power to be defined for material calculations
          */
-        private static _maxSpecularPower;
+        private static readonly _MaxSpecularPower;
+        /**
+         * Mapping to store textures
+         */
+        private _textureMap;
         /**
          * Numeric tolerance value
          */
-        private static _epsilon;
+        private static readonly _Epsilon;
+        /**
+         * Reference to the glTF Exporter
+         */
+        private _exporter;
+        constructor(exporter: _Exporter);
         /**
          * Specifies if two colors are approximately equal in value
          * @param color1 first color to compare to
@@ -418,32 +440,25 @@ declare module BABYLON.GLTF2 {
          * @param imageData mapping of texture names to base64 textures
          * @param hasTextureCoords specifies if texture coordinates are present on the material
          */
-        static _ConvertMaterialsToGLTFAsync(babylonMaterials: Material[], mimeType: ImageMimeType, images: IImage[], textures: ITexture[], samplers: ISampler[], materials: IMaterial[], materialMap: {
-            [materialID: number]: number;
-        }, imageData: {
-            [fileName: string]: {
-                data: Uint8Array;
-                mimeType: ImageMimeType;
-            };
-        }, hasTextureCoords: boolean): Promise<void>;
+        _convertMaterialsToGLTFAsync(babylonMaterials: Material[], mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<void>;
         /**
          * Makes a copy of the glTF material without the texture parameters
          * @param originalMaterial original glTF material
          * @returns glTF material without texture parameters
          */
-        static _StripTexturesFromMaterial(originalMaterial: IMaterial): IMaterial;
+        _stripTexturesFromMaterial(originalMaterial: IMaterial): IMaterial;
         /**
          * Specifies if the material has any texture parameters present
          * @param material glTF Material
          * @returns boolean specifying if texture parameters are present
          */
-        static _HasTexturesPresent(material: IMaterial): boolean;
+        _hasTexturesPresent(material: IMaterial): boolean;
         /**
          * Converts a Babylon StandardMaterial to a glTF Metallic Roughness Material
          * @param babylonStandardMaterial
          * @returns glTF Metallic Roughness Material representation
          */
-        static _ConvertToGLTFPBRMetallicRoughness(babylonStandardMaterial: StandardMaterial): IMaterialPbrMetallicRoughness;
+        _convertToGLTFPBRMetallicRoughness(babylonStandardMaterial: StandardMaterial): IMaterialPbrMetallicRoughness;
         /**
          * Computes the metallic factor
          * @param diffuse diffused value
@@ -457,7 +472,7 @@ declare module BABYLON.GLTF2 {
          * @param babylonMaterial Babylon Material
          * @returns The Babylon alpha mode value
          */
-        static _GetAlphaMode(babylonMaterial: Material): MaterialAlphaMode;
+        _getAlphaMode(babylonMaterial: Material): MaterialAlphaMode;
         /**
          * Converts a Babylon Standard Material to a glTF Material
          * @param babylonStandardMaterial BJS Standard Material
@@ -468,21 +483,7 @@ declare module BABYLON.GLTF2 {
          * @param imageData map of image file name to data
          * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
          */
-        static _ConvertStandardMaterialAsync(babylonStandardMaterial: StandardMaterial, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], samplers: ISampler[], materials: IMaterial[], materialMap: {
-            [materialID: number]: number;
-        }, imageData: {
-            [fileName: string]: {
-                data: Uint8Array;
-                mimeType: ImageMimeType;
-            };
-        }, hasTextureCoords: boolean): Promise<void>;
-        /**
-         *
-         * @param texture Texture with alpha to overwrite to one
-         * @param useAlpha Specifies if alpha should be preserved or not
-         * @returns Promise with texture
-         */
-        static _SetAlphaToOneAsync(texture: BaseTexture, useAlpha: boolean): Promise<BaseTexture>;
+        _convertStandardMaterialAsync(babylonStandardMaterial: StandardMaterial, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<void>;
         /**
          * Converts a Babylon PBR Metallic Roughness Material to a glTF Material
          * @param babylonPBRMetalRoughMaterial BJS PBR Metallic Roughness Material
@@ -493,14 +494,7 @@ declare module BABYLON.GLTF2 {
          * @param imageData map of image file name to data
          * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
          */
-        static _ConvertPBRMetallicRoughnessMaterialAsync(babylonPBRMetalRoughMaterial: PBRMetallicRoughnessMaterial, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], samplers: ISampler[], materials: IMaterial[], materialMap: {
-            [materialID: number]: number;
-        }, imageData: {
-            [fileName: string]: {
-                data: Uint8Array;
-                mimeType: ImageMimeType;
-            };
-        }, hasTextureCoords: boolean): Promise<void>;
+        _convertPBRMetallicRoughnessMaterialAsync(babylonPBRMetalRoughMaterial: PBRMetallicRoughnessMaterial, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<void>;
         /**
          * Converts an image typed array buffer to a base64 image
          * @param buffer typed array buffer
@@ -509,7 +503,7 @@ declare module BABYLON.GLTF2 {
          * @param mimeType mimetype of the image
          * @returns base64 image string
          */
-        private static _CreateBase64FromCanvas(buffer, width, height, mimeType);
+        private _createBase64FromCanvasAsync(buffer, width, height, mimeType);
         /**
          * Generates a white texture based on the specified width and height
          * @param width width of the texture in pixels
@@ -517,7 +511,7 @@ declare module BABYLON.GLTF2 {
          * @param scene babylonjs scene
          * @returns white texture
          */
-        private static _CreateWhiteTexture(width, height, scene);
+        private _createWhiteTexture(width, height, scene);
         /**
          * Resizes the two source textures to the same dimensions.  If a texture is null, a default white texture is generated.  If both textures are null, returns null
          * @param texture1 first texture to resize
@@ -525,7 +519,7 @@ declare module BABYLON.GLTF2 {
          * @param scene babylonjs scene
          * @returns resized textures or null
          */
-        private static _ResizeTexturesToSameDimensions(texture1, texture2, scene);
+        private _resizeTexturesToSameDimensions(texture1, texture2, scene);
         /**
          * Convert Specular Glossiness Textures to Metallic Roughness
          * See link below for info on the material conversions from PBR Metallic/Roughness and Specular/Glossiness
@@ -536,25 +530,25 @@ declare module BABYLON.GLTF2 {
          * @param mimeType the mime type to use for the texture
          * @returns pbr metallic roughness interface or null
          */
-        private static _ConvertSpecularGlossinessTexturesToMetallicRoughness(diffuseTexture, specularGlossinessTexture, factors, mimeType);
+        private _convertSpecularGlossinessTexturesToMetallicRoughnessAsync(diffuseTexture, specularGlossinessTexture, factors, mimeType);
         /**
          * Converts specular glossiness material properties to metallic roughness
          * @param specularGlossiness interface with specular glossiness material properties
          * @returns interface with metallic roughness material properties
          */
-        private static _ConvertSpecularGlossinessToMetallicRoughness(specularGlossiness);
+        private _convertSpecularGlossinessToMetallicRoughness(specularGlossiness);
         /**
          * Calculates the surface reflectance, independent of lighting conditions
          * @param color Color source to calculate brightness from
          * @returns number representing the perceived brightness, or zero if color is undefined
          */
-        private static _GetPerceivedBrightness(color);
+        private _getPerceivedBrightness(color);
         /**
          * Returns the maximum color component value
          * @param color
          * @returns maximum color component value, or zero if color is null or undefined
          */
-        private static _GetMaxComponent(color);
+        private _getMaxComponent(color);
         /**
          * Convert a PBRMaterial (Metallic/Roughness) to Metallic Roughness factors
          * @param babylonPBRMaterial BJS PBR Metallic Roughness Material
@@ -566,10 +560,10 @@ declare module BABYLON.GLTF2 {
          * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
          * @returns glTF PBR Metallic Roughness factors
          */
-        private static _ConvertMetalRoughFactorsToMetallicRoughnessAsync(babylonPBRMaterial, mimeType, images, textures, samplers, glTFPbrMetallicRoughness, imageData, hasTextureCoords);
-        private static _GetGLTFTextureSampler(texture);
-        private static _GetGLTFTextureWrapMode(wrapMode);
-        private static _GetGLTFTextureWrapModesSampler(texture);
+        private _gonvertMetalRoughFactorsToMetallicRoughnessAsync(babylonPBRMaterial, mimeType, glTFPbrMetallicRoughness, hasTextureCoords);
+        private _getGLTFTextureSampler(texture);
+        private _getGLTFTextureWrapMode(wrapMode);
+        private _getGLTFTextureWrapModesSampler(texture);
         /**
          * Convert a PBRMaterial (Specular/Glossiness) to Metallic Roughness factors
          * @param babylonPBRMaterial BJS PBR Metallic Roughness Material
@@ -581,7 +575,7 @@ declare module BABYLON.GLTF2 {
          * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
          * @returns glTF PBR Metallic Roughness factors
          */
-        private static _ConvertSpecGlossFactorsToMetallicRoughness(babylonPBRMaterial, mimeType, images, textures, samplers, glTFPbrMetallicRoughness, imageData, hasTextureCoords);
+        private _convertSpecGlossFactorsToMetallicRoughness(babylonPBRMaterial, mimeType, glTFPbrMetallicRoughness, hasTextureCoords);
         /**
          * Converts a Babylon PBR Metallic Roughness Material to a glTF Material
          * @param babylonPBRMaterial BJS PBR Metallic Roughness Material
@@ -592,16 +586,9 @@ declare module BABYLON.GLTF2 {
          * @param imageData map of image file name to data
          * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
          */
-        static _ConvertPBRMaterialAsync(babylonPBRMaterial: PBRMaterial, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], samplers: ISampler[], materials: IMaterial[], materialMap: {
-            [materialID: number]: number;
-        }, imageData: {
-            [fileName: string]: {
-                data: Uint8Array;
-                mimeType: ImageMimeType;
-            };
-        }, hasTextureCoords: boolean): Promise<void>;
-        private static SetMetallicRoughnessPbrMaterial(metallicRoughness, babylonPBRMaterial, glTFMaterial, glTFPbrMetallicRoughness, mimeType, images, textures, samplers, materials, materialMap, imageData, hasTextureCoords);
-        private static GetPixelsFromTexture(babylonTexture);
+        _convertPBRMaterialAsync(babylonPBRMaterial: PBRMaterial, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<void>;
+        private setMetallicRoughnessPbrMaterial(metallicRoughness, babylonPBRMaterial, glTFMaterial, glTFPbrMetallicRoughness, mimeType, hasTextureCoords);
+        private getPixelsFromTexture(babylonTexture);
         /**
          * Extracts a texture from a Babylon texture into file data and glTF data
          * @param babylonTexture Babylon texture to extract
@@ -611,7 +598,7 @@ declare module BABYLON.GLTF2 {
          * @param imageData map of image file name and data
          * @return glTF texture info, or null if the texture format is not supported
          */
-        private static _ExportTextureAsync(babylonTexture, mimeType, images, textures, samplers, imageData, useAlpha);
+        private _exportTextureAsync(babylonTexture, mimeType);
         /**
          * Builds a texture from base64 string
          * @param base64Texture base64 texture string
@@ -622,7 +609,7 @@ declare module BABYLON.GLTF2 {
          * @param imageData map of image data
          * @returns glTF texture info, or null if the texture format is not supported
          */
-        private static _GetTextureInfoFromBase64(base64Texture, baseTextureName, mimeType, images, textures, texCoordIndex, samplerIndex, imageData);
+        private _getTextureInfoFromBase64(base64Texture, baseTextureName, mimeType, texCoordIndex, samplerIndex);
     }
 }
 

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 350 - 315
dist/preview release/serializers/babylon.glTF2Serializer.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 2 - 2
dist/preview release/serializers/babylon.glTF2Serializer.min.js


+ 69 - 82
dist/preview release/serializers/babylonjs.serializers.d.ts

@@ -57,86 +57,99 @@ declare module BABYLON.GLTF2 {
         /**
          * Stores all generated buffer views, which represents views into the main glTF buffer data
          */
-        private bufferViews;
+        private _bufferViews;
         /**
          * Stores all the generated accessors, which is used for accessing the data within the buffer views in glTF
          */
-        private accessors;
+        private _accessors;
         /**
          * Stores all the generated nodes, which contains transform and/or mesh information per node
          */
-        private nodes;
+        private _nodes;
         /**
          * Stores the glTF asset information, which represents the glTF version and this file generator
          */
-        private asset;
+        private _asset;
         /**
          * Stores all the generated glTF scenes, which stores multiple node hierarchies
          */
-        private scenes;
+        private _scenes;
         /**
          * Stores all the generated mesh information, each containing a set of primitives to render in glTF
          */
-        private meshes;
+        private _meshes;
         /**
          * Stores all the generated material information, which represents the appearance of each primitive
          */
-        private materials;
-        private materialMap;
+        _materials: IMaterial[];
+        _materialMap: {
+            [materialID: number]: number;
+        };
         /**
          * Stores all the generated texture information, which is referenced by glTF materials
          */
-        private textures;
+        _textures: ITexture[];
         /**
          * Stores all the generated image information, which is referenced by glTF textures
          */
-        private images;
+        _images: IImage[];
         /**
          * Stores all the texture samplers
          */
-        private samplers;
+        _samplers: ISampler[];
         /**
          * Stores all the generated animation samplers, which is referenced by glTF animations
          */
         /**
          * Stores the animations for glTF models
          */
-        private animations;
+        private _animations;
         /**
          * Stores the total amount of bytes stored in the glTF buffer
          */
-        private totalByteLength;
+        private _totalByteLength;
         /**
          * Stores a reference to the Babylon scene containing the source geometry and material information
          */
-        private babylonScene;
+        private _babylonScene;
         /**
          * Stores a map of the image data, where the key is the file name and the value
          * is the image data
          */
-        private imageData;
+        _imageData: {
+            [fileName: string]: {
+                data: Uint8Array;
+                mimeType: ImageMimeType;
+            };
+        };
         /**
          * Stores a map of the unique id of a node to its index in the node array
          */
-        private nodeMap;
+        private _nodeMap;
         /**
          * Specifies if the Babylon scene should be converted to right-handed on export
          */
-        private convertToRightHandedSystem;
+        private _convertToRightHandedSystem;
         /**
          * Baked animation sample rate
          */
-        private animationSampleRate;
+        private _animationSampleRate;
         /**
          * Callback which specifies if a transform node should be exported or not
          */
-        private shouldExportTransformNode;
+        private _shouldExportTransformNode;
+        private _localEngine;
+        private _glTFMaterialExporter;
         /**
          * Creates a glTF Exporter instance, which can accept optional exporter options
          * @param babylonScene Babylon scene object
          * @param options Options to modify the behavior of the exporter
          */
         constructor(babylonScene: Scene, options?: IExportOptions);
+        /**
+         * Lazy load a local engine with premultiplied alpha set to false
+         */
+        _getLocalEngine(): Engine;
         private reorderIndicesBasedOnPrimitiveMode(submesh, primitiveMode, babylonIndices, byteOffset, binaryWriter);
         /**
          * Reorders the vertex attribute data based on the primitive mode.  This is necessary when indices are not available and the winding order is
@@ -396,19 +409,28 @@ declare module BABYLON.GLTF2 {
      * Utility methods for working with glTF material conversion properties.  This class should only be used internally
      * @hidden
      */
-    class _GLTFMaterial {
+    class _GLTFMaterialExporter {
         /**
          * Represents the dielectric specular values for R, G and B
          */
-        private static readonly _dielectricSpecular;
+        private static readonly _DielectricSpecular;
         /**
          * Allows the maximum specular power to be defined for material calculations
          */
-        private static _maxSpecularPower;
+        private static readonly _MaxSpecularPower;
+        /**
+         * Mapping to store textures
+         */
+        private _textureMap;
         /**
          * Numeric tolerance value
          */
-        private static _epsilon;
+        private static readonly _Epsilon;
+        /**
+         * Reference to the glTF Exporter
+         */
+        private _exporter;
+        constructor(exporter: _Exporter);
         /**
          * Specifies if two colors are approximately equal in value
          * @param color1 first color to compare to
@@ -426,32 +448,25 @@ declare module BABYLON.GLTF2 {
          * @param imageData mapping of texture names to base64 textures
          * @param hasTextureCoords specifies if texture coordinates are present on the material
          */
-        static _ConvertMaterialsToGLTFAsync(babylonMaterials: Material[], mimeType: ImageMimeType, images: IImage[], textures: ITexture[], samplers: ISampler[], materials: IMaterial[], materialMap: {
-            [materialID: number]: number;
-        }, imageData: {
-            [fileName: string]: {
-                data: Uint8Array;
-                mimeType: ImageMimeType;
-            };
-        }, hasTextureCoords: boolean): Promise<void>;
+        _convertMaterialsToGLTFAsync(babylonMaterials: Material[], mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<void>;
         /**
          * Makes a copy of the glTF material without the texture parameters
          * @param originalMaterial original glTF material
          * @returns glTF material without texture parameters
          */
-        static _StripTexturesFromMaterial(originalMaterial: IMaterial): IMaterial;
+        _stripTexturesFromMaterial(originalMaterial: IMaterial): IMaterial;
         /**
          * Specifies if the material has any texture parameters present
          * @param material glTF Material
          * @returns boolean specifying if texture parameters are present
          */
-        static _HasTexturesPresent(material: IMaterial): boolean;
+        _hasTexturesPresent(material: IMaterial): boolean;
         /**
          * Converts a Babylon StandardMaterial to a glTF Metallic Roughness Material
          * @param babylonStandardMaterial
          * @returns glTF Metallic Roughness Material representation
          */
-        static _ConvertToGLTFPBRMetallicRoughness(babylonStandardMaterial: StandardMaterial): IMaterialPbrMetallicRoughness;
+        _convertToGLTFPBRMetallicRoughness(babylonStandardMaterial: StandardMaterial): IMaterialPbrMetallicRoughness;
         /**
          * Computes the metallic factor
          * @param diffuse diffused value
@@ -465,7 +480,7 @@ declare module BABYLON.GLTF2 {
          * @param babylonMaterial Babylon Material
          * @returns The Babylon alpha mode value
          */
-        static _GetAlphaMode(babylonMaterial: Material): MaterialAlphaMode;
+        _getAlphaMode(babylonMaterial: Material): MaterialAlphaMode;
         /**
          * Converts a Babylon Standard Material to a glTF Material
          * @param babylonStandardMaterial BJS Standard Material
@@ -476,21 +491,7 @@ declare module BABYLON.GLTF2 {
          * @param imageData map of image file name to data
          * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
          */
-        static _ConvertStandardMaterialAsync(babylonStandardMaterial: StandardMaterial, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], samplers: ISampler[], materials: IMaterial[], materialMap: {
-            [materialID: number]: number;
-        }, imageData: {
-            [fileName: string]: {
-                data: Uint8Array;
-                mimeType: ImageMimeType;
-            };
-        }, hasTextureCoords: boolean): Promise<void>;
-        /**
-         *
-         * @param texture Texture with alpha to overwrite to one
-         * @param useAlpha Specifies if alpha should be preserved or not
-         * @returns Promise with texture
-         */
-        static _SetAlphaToOneAsync(texture: BaseTexture, useAlpha: boolean): Promise<BaseTexture>;
+        _convertStandardMaterialAsync(babylonStandardMaterial: StandardMaterial, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<void>;
         /**
          * Converts a Babylon PBR Metallic Roughness Material to a glTF Material
          * @param babylonPBRMetalRoughMaterial BJS PBR Metallic Roughness Material
@@ -501,14 +502,7 @@ declare module BABYLON.GLTF2 {
          * @param imageData map of image file name to data
          * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
          */
-        static _ConvertPBRMetallicRoughnessMaterialAsync(babylonPBRMetalRoughMaterial: PBRMetallicRoughnessMaterial, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], samplers: ISampler[], materials: IMaterial[], materialMap: {
-            [materialID: number]: number;
-        }, imageData: {
-            [fileName: string]: {
-                data: Uint8Array;
-                mimeType: ImageMimeType;
-            };
-        }, hasTextureCoords: boolean): Promise<void>;
+        _convertPBRMetallicRoughnessMaterialAsync(babylonPBRMetalRoughMaterial: PBRMetallicRoughnessMaterial, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<void>;
         /**
          * Converts an image typed array buffer to a base64 image
          * @param buffer typed array buffer
@@ -517,7 +511,7 @@ declare module BABYLON.GLTF2 {
          * @param mimeType mimetype of the image
          * @returns base64 image string
          */
-        private static _CreateBase64FromCanvas(buffer, width, height, mimeType);
+        private _createBase64FromCanvasAsync(buffer, width, height, mimeType);
         /**
          * Generates a white texture based on the specified width and height
          * @param width width of the texture in pixels
@@ -525,7 +519,7 @@ declare module BABYLON.GLTF2 {
          * @param scene babylonjs scene
          * @returns white texture
          */
-        private static _CreateWhiteTexture(width, height, scene);
+        private _createWhiteTexture(width, height, scene);
         /**
          * Resizes the two source textures to the same dimensions.  If a texture is null, a default white texture is generated.  If both textures are null, returns null
          * @param texture1 first texture to resize
@@ -533,7 +527,7 @@ declare module BABYLON.GLTF2 {
          * @param scene babylonjs scene
          * @returns resized textures or null
          */
-        private static _ResizeTexturesToSameDimensions(texture1, texture2, scene);
+        private _resizeTexturesToSameDimensions(texture1, texture2, scene);
         /**
          * Convert Specular Glossiness Textures to Metallic Roughness
          * See link below for info on the material conversions from PBR Metallic/Roughness and Specular/Glossiness
@@ -544,25 +538,25 @@ declare module BABYLON.GLTF2 {
          * @param mimeType the mime type to use for the texture
          * @returns pbr metallic roughness interface or null
          */
-        private static _ConvertSpecularGlossinessTexturesToMetallicRoughness(diffuseTexture, specularGlossinessTexture, factors, mimeType);
+        private _convertSpecularGlossinessTexturesToMetallicRoughnessAsync(diffuseTexture, specularGlossinessTexture, factors, mimeType);
         /**
          * Converts specular glossiness material properties to metallic roughness
          * @param specularGlossiness interface with specular glossiness material properties
          * @returns interface with metallic roughness material properties
          */
-        private static _ConvertSpecularGlossinessToMetallicRoughness(specularGlossiness);
+        private _convertSpecularGlossinessToMetallicRoughness(specularGlossiness);
         /**
          * Calculates the surface reflectance, independent of lighting conditions
          * @param color Color source to calculate brightness from
          * @returns number representing the perceived brightness, or zero if color is undefined
          */
-        private static _GetPerceivedBrightness(color);
+        private _getPerceivedBrightness(color);
         /**
          * Returns the maximum color component value
          * @param color
          * @returns maximum color component value, or zero if color is null or undefined
          */
-        private static _GetMaxComponent(color);
+        private _getMaxComponent(color);
         /**
          * Convert a PBRMaterial (Metallic/Roughness) to Metallic Roughness factors
          * @param babylonPBRMaterial BJS PBR Metallic Roughness Material
@@ -574,10 +568,10 @@ declare module BABYLON.GLTF2 {
          * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
          * @returns glTF PBR Metallic Roughness factors
          */
-        private static _ConvertMetalRoughFactorsToMetallicRoughnessAsync(babylonPBRMaterial, mimeType, images, textures, samplers, glTFPbrMetallicRoughness, imageData, hasTextureCoords);
-        private static _GetGLTFTextureSampler(texture);
-        private static _GetGLTFTextureWrapMode(wrapMode);
-        private static _GetGLTFTextureWrapModesSampler(texture);
+        private _gonvertMetalRoughFactorsToMetallicRoughnessAsync(babylonPBRMaterial, mimeType, glTFPbrMetallicRoughness, hasTextureCoords);
+        private _getGLTFTextureSampler(texture);
+        private _getGLTFTextureWrapMode(wrapMode);
+        private _getGLTFTextureWrapModesSampler(texture);
         /**
          * Convert a PBRMaterial (Specular/Glossiness) to Metallic Roughness factors
          * @param babylonPBRMaterial BJS PBR Metallic Roughness Material
@@ -589,7 +583,7 @@ declare module BABYLON.GLTF2 {
          * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
          * @returns glTF PBR Metallic Roughness factors
          */
-        private static _ConvertSpecGlossFactorsToMetallicRoughness(babylonPBRMaterial, mimeType, images, textures, samplers, glTFPbrMetallicRoughness, imageData, hasTextureCoords);
+        private _convertSpecGlossFactorsToMetallicRoughness(babylonPBRMaterial, mimeType, glTFPbrMetallicRoughness, hasTextureCoords);
         /**
          * Converts a Babylon PBR Metallic Roughness Material to a glTF Material
          * @param babylonPBRMaterial BJS PBR Metallic Roughness Material
@@ -600,16 +594,9 @@ declare module BABYLON.GLTF2 {
          * @param imageData map of image file name to data
          * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
          */
-        static _ConvertPBRMaterialAsync(babylonPBRMaterial: PBRMaterial, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], samplers: ISampler[], materials: IMaterial[], materialMap: {
-            [materialID: number]: number;
-        }, imageData: {
-            [fileName: string]: {
-                data: Uint8Array;
-                mimeType: ImageMimeType;
-            };
-        }, hasTextureCoords: boolean): Promise<void>;
-        private static SetMetallicRoughnessPbrMaterial(metallicRoughness, babylonPBRMaterial, glTFMaterial, glTFPbrMetallicRoughness, mimeType, images, textures, samplers, materials, materialMap, imageData, hasTextureCoords);
-        private static GetPixelsFromTexture(babylonTexture);
+        _convertPBRMaterialAsync(babylonPBRMaterial: PBRMaterial, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<void>;
+        private setMetallicRoughnessPbrMaterial(metallicRoughness, babylonPBRMaterial, glTFMaterial, glTFPbrMetallicRoughness, mimeType, hasTextureCoords);
+        private getPixelsFromTexture(babylonTexture);
         /**
          * Extracts a texture from a Babylon texture into file data and glTF data
          * @param babylonTexture Babylon texture to extract
@@ -619,7 +606,7 @@ declare module BABYLON.GLTF2 {
          * @param imageData map of image file name and data
          * @return glTF texture info, or null if the texture format is not supported
          */
-        private static _ExportTextureAsync(babylonTexture, mimeType, images, textures, samplers, imageData, useAlpha);
+        private _exportTextureAsync(babylonTexture, mimeType);
         /**
          * Builds a texture from base64 string
          * @param base64Texture base64 texture string
@@ -630,7 +617,7 @@ declare module BABYLON.GLTF2 {
          * @param imageData map of image data
          * @returns glTF texture info, or null if the texture format is not supported
          */
-        private static _GetTextureInfoFromBase64(base64Texture, baseTextureName, mimeType, images, textures, texCoordIndex, samplerIndex, imageData);
+        private _getTextureInfoFromBase64(base64Texture, baseTextureName, mimeType, texCoordIndex, samplerIndex);
     }
 }
 

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 350 - 315
dist/preview release/serializers/babylonjs.serializers.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 2 - 2
dist/preview release/serializers/babylonjs.serializers.min.js


+ 69 - 82
dist/preview release/serializers/babylonjs.serializers.module.d.ts

@@ -64,86 +64,99 @@ declare module BABYLON.GLTF2 {
         /**
          * Stores all generated buffer views, which represents views into the main glTF buffer data
          */
-        private bufferViews;
+        private _bufferViews;
         /**
          * Stores all the generated accessors, which is used for accessing the data within the buffer views in glTF
          */
-        private accessors;
+        private _accessors;
         /**
          * Stores all the generated nodes, which contains transform and/or mesh information per node
          */
-        private nodes;
+        private _nodes;
         /**
          * Stores the glTF asset information, which represents the glTF version and this file generator
          */
-        private asset;
+        private _asset;
         /**
          * Stores all the generated glTF scenes, which stores multiple node hierarchies
          */
-        private scenes;
+        private _scenes;
         /**
          * Stores all the generated mesh information, each containing a set of primitives to render in glTF
          */
-        private meshes;
+        private _meshes;
         /**
          * Stores all the generated material information, which represents the appearance of each primitive
          */
-        private materials;
-        private materialMap;
+        _materials: IMaterial[];
+        _materialMap: {
+            [materialID: number]: number;
+        };
         /**
          * Stores all the generated texture information, which is referenced by glTF materials
          */
-        private textures;
+        _textures: ITexture[];
         /**
          * Stores all the generated image information, which is referenced by glTF textures
          */
-        private images;
+        _images: IImage[];
         /**
          * Stores all the texture samplers
          */
-        private samplers;
+        _samplers: ISampler[];
         /**
          * Stores all the generated animation samplers, which is referenced by glTF animations
          */
         /**
          * Stores the animations for glTF models
          */
-        private animations;
+        private _animations;
         /**
          * Stores the total amount of bytes stored in the glTF buffer
          */
-        private totalByteLength;
+        private _totalByteLength;
         /**
          * Stores a reference to the Babylon scene containing the source geometry and material information
          */
-        private babylonScene;
+        private _babylonScene;
         /**
          * Stores a map of the image data, where the key is the file name and the value
          * is the image data
          */
-        private imageData;
+        _imageData: {
+            [fileName: string]: {
+                data: Uint8Array;
+                mimeType: ImageMimeType;
+            };
+        };
         /**
          * Stores a map of the unique id of a node to its index in the node array
          */
-        private nodeMap;
+        private _nodeMap;
         /**
          * Specifies if the Babylon scene should be converted to right-handed on export
          */
-        private convertToRightHandedSystem;
+        private _convertToRightHandedSystem;
         /**
          * Baked animation sample rate
          */
-        private animationSampleRate;
+        private _animationSampleRate;
         /**
          * Callback which specifies if a transform node should be exported or not
          */
-        private shouldExportTransformNode;
+        private _shouldExportTransformNode;
+        private _localEngine;
+        private _glTFMaterialExporter;
         /**
          * Creates a glTF Exporter instance, which can accept optional exporter options
          * @param babylonScene Babylon scene object
          * @param options Options to modify the behavior of the exporter
          */
         constructor(babylonScene: Scene, options?: IExportOptions);
+        /**
+         * Lazy load a local engine with premultiplied alpha set to false
+         */
+        _getLocalEngine(): Engine;
         private reorderIndicesBasedOnPrimitiveMode(submesh, primitiveMode, babylonIndices, byteOffset, binaryWriter);
         /**
          * Reorders the vertex attribute data based on the primitive mode.  This is necessary when indices are not available and the winding order is
@@ -403,19 +416,28 @@ declare module BABYLON.GLTF2 {
      * Utility methods for working with glTF material conversion properties.  This class should only be used internally
      * @hidden
      */
-    class _GLTFMaterial {
+    class _GLTFMaterialExporter {
         /**
          * Represents the dielectric specular values for R, G and B
          */
-        private static readonly _dielectricSpecular;
+        private static readonly _DielectricSpecular;
         /**
          * Allows the maximum specular power to be defined for material calculations
          */
-        private static _maxSpecularPower;
+        private static readonly _MaxSpecularPower;
+        /**
+         * Mapping to store textures
+         */
+        private _textureMap;
         /**
          * Numeric tolerance value
          */
-        private static _epsilon;
+        private static readonly _Epsilon;
+        /**
+         * Reference to the glTF Exporter
+         */
+        private _exporter;
+        constructor(exporter: _Exporter);
         /**
          * Specifies if two colors are approximately equal in value
          * @param color1 first color to compare to
@@ -433,32 +455,25 @@ declare module BABYLON.GLTF2 {
          * @param imageData mapping of texture names to base64 textures
          * @param hasTextureCoords specifies if texture coordinates are present on the material
          */
-        static _ConvertMaterialsToGLTFAsync(babylonMaterials: Material[], mimeType: ImageMimeType, images: IImage[], textures: ITexture[], samplers: ISampler[], materials: IMaterial[], materialMap: {
-            [materialID: number]: number;
-        }, imageData: {
-            [fileName: string]: {
-                data: Uint8Array;
-                mimeType: ImageMimeType;
-            };
-        }, hasTextureCoords: boolean): Promise<void>;
+        _convertMaterialsToGLTFAsync(babylonMaterials: Material[], mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<void>;
         /**
          * Makes a copy of the glTF material without the texture parameters
          * @param originalMaterial original glTF material
          * @returns glTF material without texture parameters
          */
-        static _StripTexturesFromMaterial(originalMaterial: IMaterial): IMaterial;
+        _stripTexturesFromMaterial(originalMaterial: IMaterial): IMaterial;
         /**
          * Specifies if the material has any texture parameters present
          * @param material glTF Material
          * @returns boolean specifying if texture parameters are present
          */
-        static _HasTexturesPresent(material: IMaterial): boolean;
+        _hasTexturesPresent(material: IMaterial): boolean;
         /**
          * Converts a Babylon StandardMaterial to a glTF Metallic Roughness Material
          * @param babylonStandardMaterial
          * @returns glTF Metallic Roughness Material representation
          */
-        static _ConvertToGLTFPBRMetallicRoughness(babylonStandardMaterial: StandardMaterial): IMaterialPbrMetallicRoughness;
+        _convertToGLTFPBRMetallicRoughness(babylonStandardMaterial: StandardMaterial): IMaterialPbrMetallicRoughness;
         /**
          * Computes the metallic factor
          * @param diffuse diffused value
@@ -472,7 +487,7 @@ declare module BABYLON.GLTF2 {
          * @param babylonMaterial Babylon Material
          * @returns The Babylon alpha mode value
          */
-        static _GetAlphaMode(babylonMaterial: Material): MaterialAlphaMode;
+        _getAlphaMode(babylonMaterial: Material): MaterialAlphaMode;
         /**
          * Converts a Babylon Standard Material to a glTF Material
          * @param babylonStandardMaterial BJS Standard Material
@@ -483,21 +498,7 @@ declare module BABYLON.GLTF2 {
          * @param imageData map of image file name to data
          * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
          */
-        static _ConvertStandardMaterialAsync(babylonStandardMaterial: StandardMaterial, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], samplers: ISampler[], materials: IMaterial[], materialMap: {
-            [materialID: number]: number;
-        }, imageData: {
-            [fileName: string]: {
-                data: Uint8Array;
-                mimeType: ImageMimeType;
-            };
-        }, hasTextureCoords: boolean): Promise<void>;
-        /**
-         *
-         * @param texture Texture with alpha to overwrite to one
-         * @param useAlpha Specifies if alpha should be preserved or not
-         * @returns Promise with texture
-         */
-        static _SetAlphaToOneAsync(texture: BaseTexture, useAlpha: boolean): Promise<BaseTexture>;
+        _convertStandardMaterialAsync(babylonStandardMaterial: StandardMaterial, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<void>;
         /**
          * Converts a Babylon PBR Metallic Roughness Material to a glTF Material
          * @param babylonPBRMetalRoughMaterial BJS PBR Metallic Roughness Material
@@ -508,14 +509,7 @@ declare module BABYLON.GLTF2 {
          * @param imageData map of image file name to data
          * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
          */
-        static _ConvertPBRMetallicRoughnessMaterialAsync(babylonPBRMetalRoughMaterial: PBRMetallicRoughnessMaterial, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], samplers: ISampler[], materials: IMaterial[], materialMap: {
-            [materialID: number]: number;
-        }, imageData: {
-            [fileName: string]: {
-                data: Uint8Array;
-                mimeType: ImageMimeType;
-            };
-        }, hasTextureCoords: boolean): Promise<void>;
+        _convertPBRMetallicRoughnessMaterialAsync(babylonPBRMetalRoughMaterial: PBRMetallicRoughnessMaterial, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<void>;
         /**
          * Converts an image typed array buffer to a base64 image
          * @param buffer typed array buffer
@@ -524,7 +518,7 @@ declare module BABYLON.GLTF2 {
          * @param mimeType mimetype of the image
          * @returns base64 image string
          */
-        private static _CreateBase64FromCanvas(buffer, width, height, mimeType);
+        private _createBase64FromCanvasAsync(buffer, width, height, mimeType);
         /**
          * Generates a white texture based on the specified width and height
          * @param width width of the texture in pixels
@@ -532,7 +526,7 @@ declare module BABYLON.GLTF2 {
          * @param scene babylonjs scene
          * @returns white texture
          */
-        private static _CreateWhiteTexture(width, height, scene);
+        private _createWhiteTexture(width, height, scene);
         /**
          * Resizes the two source textures to the same dimensions.  If a texture is null, a default white texture is generated.  If both textures are null, returns null
          * @param texture1 first texture to resize
@@ -540,7 +534,7 @@ declare module BABYLON.GLTF2 {
          * @param scene babylonjs scene
          * @returns resized textures or null
          */
-        private static _ResizeTexturesToSameDimensions(texture1, texture2, scene);
+        private _resizeTexturesToSameDimensions(texture1, texture2, scene);
         /**
          * Convert Specular Glossiness Textures to Metallic Roughness
          * See link below for info on the material conversions from PBR Metallic/Roughness and Specular/Glossiness
@@ -551,25 +545,25 @@ declare module BABYLON.GLTF2 {
          * @param mimeType the mime type to use for the texture
          * @returns pbr metallic roughness interface or null
          */
-        private static _ConvertSpecularGlossinessTexturesToMetallicRoughness(diffuseTexture, specularGlossinessTexture, factors, mimeType);
+        private _convertSpecularGlossinessTexturesToMetallicRoughnessAsync(diffuseTexture, specularGlossinessTexture, factors, mimeType);
         /**
          * Converts specular glossiness material properties to metallic roughness
          * @param specularGlossiness interface with specular glossiness material properties
          * @returns interface with metallic roughness material properties
          */
-        private static _ConvertSpecularGlossinessToMetallicRoughness(specularGlossiness);
+        private _convertSpecularGlossinessToMetallicRoughness(specularGlossiness);
         /**
          * Calculates the surface reflectance, independent of lighting conditions
          * @param color Color source to calculate brightness from
          * @returns number representing the perceived brightness, or zero if color is undefined
          */
-        private static _GetPerceivedBrightness(color);
+        private _getPerceivedBrightness(color);
         /**
          * Returns the maximum color component value
          * @param color
          * @returns maximum color component value, or zero if color is null or undefined
          */
-        private static _GetMaxComponent(color);
+        private _getMaxComponent(color);
         /**
          * Convert a PBRMaterial (Metallic/Roughness) to Metallic Roughness factors
          * @param babylonPBRMaterial BJS PBR Metallic Roughness Material
@@ -581,10 +575,10 @@ declare module BABYLON.GLTF2 {
          * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
          * @returns glTF PBR Metallic Roughness factors
          */
-        private static _ConvertMetalRoughFactorsToMetallicRoughnessAsync(babylonPBRMaterial, mimeType, images, textures, samplers, glTFPbrMetallicRoughness, imageData, hasTextureCoords);
-        private static _GetGLTFTextureSampler(texture);
-        private static _GetGLTFTextureWrapMode(wrapMode);
-        private static _GetGLTFTextureWrapModesSampler(texture);
+        private _gonvertMetalRoughFactorsToMetallicRoughnessAsync(babylonPBRMaterial, mimeType, glTFPbrMetallicRoughness, hasTextureCoords);
+        private _getGLTFTextureSampler(texture);
+        private _getGLTFTextureWrapMode(wrapMode);
+        private _getGLTFTextureWrapModesSampler(texture);
         /**
          * Convert a PBRMaterial (Specular/Glossiness) to Metallic Roughness factors
          * @param babylonPBRMaterial BJS PBR Metallic Roughness Material
@@ -596,7 +590,7 @@ declare module BABYLON.GLTF2 {
          * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
          * @returns glTF PBR Metallic Roughness factors
          */
-        private static _ConvertSpecGlossFactorsToMetallicRoughness(babylonPBRMaterial, mimeType, images, textures, samplers, glTFPbrMetallicRoughness, imageData, hasTextureCoords);
+        private _convertSpecGlossFactorsToMetallicRoughness(babylonPBRMaterial, mimeType, glTFPbrMetallicRoughness, hasTextureCoords);
         /**
          * Converts a Babylon PBR Metallic Roughness Material to a glTF Material
          * @param babylonPBRMaterial BJS PBR Metallic Roughness Material
@@ -607,16 +601,9 @@ declare module BABYLON.GLTF2 {
          * @param imageData map of image file name to data
          * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
          */
-        static _ConvertPBRMaterialAsync(babylonPBRMaterial: PBRMaterial, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], samplers: ISampler[], materials: IMaterial[], materialMap: {
-            [materialID: number]: number;
-        }, imageData: {
-            [fileName: string]: {
-                data: Uint8Array;
-                mimeType: ImageMimeType;
-            };
-        }, hasTextureCoords: boolean): Promise<void>;
-        private static SetMetallicRoughnessPbrMaterial(metallicRoughness, babylonPBRMaterial, glTFMaterial, glTFPbrMetallicRoughness, mimeType, images, textures, samplers, materials, materialMap, imageData, hasTextureCoords);
-        private static GetPixelsFromTexture(babylonTexture);
+        _convertPBRMaterialAsync(babylonPBRMaterial: PBRMaterial, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<void>;
+        private setMetallicRoughnessPbrMaterial(metallicRoughness, babylonPBRMaterial, glTFMaterial, glTFPbrMetallicRoughness, mimeType, hasTextureCoords);
+        private getPixelsFromTexture(babylonTexture);
         /**
          * Extracts a texture from a Babylon texture into file data and glTF data
          * @param babylonTexture Babylon texture to extract
@@ -626,7 +613,7 @@ declare module BABYLON.GLTF2 {
          * @param imageData map of image file name and data
          * @return glTF texture info, or null if the texture format is not supported
          */
-        private static _ExportTextureAsync(babylonTexture, mimeType, images, textures, samplers, imageData, useAlpha);
+        private _exportTextureAsync(babylonTexture, mimeType);
         /**
          * Builds a texture from base64 string
          * @param base64Texture base64 texture string
@@ -637,7 +624,7 @@ declare module BABYLON.GLTF2 {
          * @param imageData map of image data
          * @returns glTF texture info, or null if the texture format is not supported
          */
-        private static _GetTextureInfoFromBase64(base64Texture, baseTextureName, mimeType, images, textures, texCoordIndex, samplerIndex, imageData);
+        private _getTextureInfoFromBase64(base64Texture, baseTextureName, mimeType, texCoordIndex, samplerIndex);
     }
 }
 

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 65 - 65
dist/preview release/viewer/babylon.viewer.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 265 - 91
dist/preview release/viewer/babylon.viewer.max.js


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

@@ -8,7 +8,7 @@
 - New GUI 3D controls toolset. [Complete doc + demos](http://doc.babylonjs.com/how_to/gui3d) ([Deltakosh](https://github.com/deltakosh))
 - Added [Environment Texture Tools](https://doc.babylonjs.com/how_to/physically_based_rendering#creating-a-compressed-environment-texture) to reduce the size of the usual .DDS file ([sebavan](http://www.github.com/sebavan))
 - New GUI control: the [Grid](http://doc.babylonjs.com/how_to/gui#grid) ([Deltakosh](https://github.com/deltakosh))
-- Gizmo and GizmoManager classes used to manipulate meshes in a scene. Gizmo types include: position, rotation, scale, and bounding box ([TrevorDev](https://github.com/TrevorDev))
+- Gizmo and GizmoManager classes used to manipulate meshes in a scene. Gizmo types include: position, rotation, scale and bounding box ([TrevorDev](https://github.com/TrevorDev))
 - Particle system improvements ([Deltakosh](https://github.com/deltakosh))
   - Improved CPU particles rendering performance (up to x2 on low end devices)
   - Added support for `isBillboardBased`. [Doc](http://doc.babylonjs.com/babylon101/particles#alignment)
@@ -55,6 +55,7 @@
 - Vector x, y and z constructor parameters are now optional and default to 0 ([TrevorDev](https://github.com/TrevorDev))
 - New vertical mode for sliders in 2D GUI. [Demo](https://www.babylonjs-playground.com/#U9AC0N#53) ([Saket Saurabh](https://github.com/ssaket))
 - Add and remove camera methods in the default pipeline ([TrevorDev](https://github.com/TrevorDev))
+- Add internal texture `format` support for RenderTargetCubeTexture ([PeapBoy](https://github.com/NicolasBuecher))
 
 ### glTF Loader
 
@@ -86,6 +87,7 @@
 - WindowsMotionController's trackpad field will be updated prior to it's onTrackpadChangedObservable event ([TrevorDev](https://github.com/TrevorDev))
 - VR experience helper's controllers will not fire pointer events when laser's are disabled, instead the camera ray pointer event will be used ([TrevorDev](https://github.com/TrevorDev))
 - Node's setParent(node.parent) will no longer throw an exception when parent is undefined and will behave the same as setParent(null) ([TrevorDev](https://github.com/TrevorDev))
+- Mesh.MergeMeshes flips triangles on meshes with negative scaling ([SvenFrankson](http://svenfrankson.com))
 
 ### Core Engine
 
@@ -113,6 +115,7 @@
 - Meshes with skeletons could have incorrect animations ([RaananW](https://github.com/RaananW))
 - Removed element IDs from viewer's templates to allow muitiple viewers in a single page [#4500](https://github.com/BabylonJS/Babylon.js/issues/4500) ([RaananW](https://github.com/RaananW))
 - Viewer is not using Engine.LastCreatedScene anymore, to support multiple viewers in a single page [#4500](https://github.com/BabylonJS/Babylon.js/issues/4500) ([RaananW](https://github.com/RaananW))
+- Template location was ignored if html was defined ([RaananW](https://github.com/RaananW))
 
 ### Loaders
 

+ 153 - 125
serializers/src/glTF/2.0/babylon.glTFExporter.ts

@@ -32,86 +32,90 @@ module BABYLON.GLTF2 {
         /**
          * Stores all generated buffer views, which represents views into the main glTF buffer data
          */
-        private bufferViews: IBufferView[];
+        private _bufferViews: IBufferView[];
         /**
          * Stores all the generated accessors, which is used for accessing the data within the buffer views in glTF
          */
-        private accessors: IAccessor[];
+        private _accessors: IAccessor[];
         /**
          * Stores all the generated nodes, which contains transform and/or mesh information per node
          */
-        private nodes: INode[];
+        private _nodes: INode[];
         /**
          * Stores the glTF asset information, which represents the glTF version and this file generator
          */
-        private asset: IAsset;
+        private _asset: IAsset;
         /**
          * Stores all the generated glTF scenes, which stores multiple node hierarchies
          */
-        private scenes: IScene[];
+        private _scenes: IScene[];
         /**
          * Stores all the generated mesh information, each containing a set of primitives to render in glTF
          */
-        private meshes: IMesh[];
+        private _meshes: IMesh[];
         /**
          * Stores all the generated material information, which represents the appearance of each primitive
          */
-        private materials: IMaterial[];
+        public _materials: IMaterial[];
 
-        private materialMap: { [materialID: number]: number };
+        public _materialMap: { [materialID: number]: number };
         /**
          * Stores all the generated texture information, which is referenced by glTF materials
          */
-        private textures: ITexture[];
+        public _textures: ITexture[];
         /**
          * Stores all the generated image information, which is referenced by glTF textures
          */
-        private images: IImage[];
+        public _images: IImage[];
 
         /**
          * Stores all the texture samplers
          */
-        private samplers: ISampler[];
+        public _samplers: ISampler[];
         /**
          * Stores all the generated animation samplers, which is referenced by glTF animations
          */
         /**
          * Stores the animations for glTF models
          */
-        private animations: IAnimation[];
+        private _animations: IAnimation[];
         /**
          * Stores the total amount of bytes stored in the glTF buffer
          */
-        private totalByteLength: number;
+        private _totalByteLength: number;
         /**
          * Stores a reference to the Babylon scene containing the source geometry and material information
          */
-        private babylonScene: Scene;
+        private _babylonScene: Scene;
         /**
          * Stores a map of the image data, where the key is the file name and the value
          * is the image data
          */
-        private imageData: { [fileName: string]: { data: Uint8Array, mimeType: ImageMimeType } };
+        public _imageData: { [fileName: string]: { data: Uint8Array, mimeType: ImageMimeType } };
 
         /**
          * Stores a map of the unique id of a node to its index in the node array
          */
-        private nodeMap: { [key: number]: number };
+        private _nodeMap: { [key: number]: number };
 
         /**
          * Specifies if the Babylon scene should be converted to right-handed on export
          */
-        private convertToRightHandedSystem: boolean;
+        private _convertToRightHandedSystem: boolean;
 
         /**
          * Baked animation sample rate
          */
-        private animationSampleRate: number;
+        private _animationSampleRate: number;
 
         /**
          * Callback which specifies if a transform node should be exported or not
          */
-        private shouldExportTransformNode: ((babylonTransformNode: TransformNode) => boolean);
+        private _shouldExportTransformNode: ((babylonTransformNode: TransformNode) => boolean);
+
+        private _localEngine: Engine;
+
+        private _glTFMaterialExporter: _GLTFMaterialExporter;
 
         /**
          * Creates a glTF Exporter instance, which can accept optional exporter options
@@ -119,24 +123,43 @@ module BABYLON.GLTF2 {
          * @param options Options to modify the behavior of the exporter
          */
         public constructor(babylonScene: Scene, options?: IExportOptions) {
-            this.asset = { generator: "BabylonJS", version: "2.0" };
-            this.babylonScene = babylonScene;
-            this.bufferViews = [];
-            this.accessors = [];
-            this.meshes = [];
-            this.scenes = [];
-            this.nodes = [];
-            this.images = [];
-            this.materials = [];
-            this.materialMap = [];
-            this.textures = [];
-            this.samplers = [];
-            this.animations = [];
-            this.imageData = {};
-            this.convertToRightHandedSystem = this.babylonScene.useRightHandedSystem ? false : true;
+            this._asset = { generator: "BabylonJS", version: "2.0" };
+            this._babylonScene = babylonScene;
+            this._bufferViews = [];
+            this._accessors = [];
+            this._meshes = [];
+            this._scenes = [];
+            this._nodes = [];
+            this._images = [];
+            this._materials = [];
+            this._materialMap = [];
+            this._textures = [];
+            this._samplers = [];
+            this._animations = [];
+            this._imageData = {};
+            this._convertToRightHandedSystem = this._babylonScene.useRightHandedSystem ? false : true;
             const _options = options || {};
-            this.shouldExportTransformNode = _options.shouldExportTransformNode ? _options.shouldExportTransformNode : (babylonTransformNode: TransformNode) => true;
-            this.animationSampleRate = _options.animationSampleRate ? _options.animationSampleRate : 1 / 60;
+            this._shouldExportTransformNode = _options.shouldExportTransformNode ? _options.shouldExportTransformNode : (babylonTransformNode: TransformNode) => true;
+            this._animationSampleRate = _options.animationSampleRate ? _options.animationSampleRate : 1 / 60;
+
+
+            this._glTFMaterialExporter = new _GLTFMaterialExporter(this);
+        }
+
+        /**
+         * Lazy load a local engine with premultiplied alpha set to false
+         */
+        public _getLocalEngine(): Engine {
+            if (!this._localEngine) {
+                const localCanvas = document.createElement('canvas');
+                localCanvas.id = "WriteCanvas";
+                localCanvas.width = 2048;
+                localCanvas.height = 2048;
+                this._localEngine = new Engine(localCanvas, true, { premultipliedAlpha: false, preserveDrawingBuffer: true });
+                this._localEngine.setViewport(new Viewport(0, 0, 1, 1));
+            }
+
+            return this._localEngine;
         }
 
         private reorderIndicesBasedOnPrimitiveMode(submesh: SubMesh, primitiveMode: number, babylonIndices: IndicesArray, byteOffset: number, binaryWriter: _BinaryWriter) {
@@ -182,7 +205,7 @@ module BABYLON.GLTF2 {
          * @param binaryWriter The binary data for the glTF file
          */
         private reorderVertexAttributeDataBasedOnPrimitiveMode(submesh: SubMesh, primitiveMode: number, sideOrientation: number, vertexBufferKind: string, meshAttributeArray: FloatArray, byteOffset: number, binaryWriter: _BinaryWriter): void {
-            if (this.convertToRightHandedSystem && sideOrientation === Material.ClockWiseSideOrientation) {
+            if (this._convertToRightHandedSystem && sideOrientation === Material.ClockWiseSideOrientation) {
                 switch (primitiveMode) {
                     case Material.TriangleFillMode: {
                         this.reorderTriangleFillMode(submesh, primitiveMode, sideOrientation, vertexBufferKind, meshAttributeArray, byteOffset, binaryWriter);
@@ -412,7 +435,7 @@ module BABYLON.GLTF2 {
          */
         private writeVertexAttributeData(vertices: Vector2[] | Vector3[] | Vector4[], byteOffset: number, vertexAttributeKind: string, meshAttributeArray: FloatArray, binaryWriter: _BinaryWriter) {
             for (let vertex of vertices) {
-                if (this.convertToRightHandedSystem && !(vertexAttributeKind === VertexBuffer.ColorKind) && !(vertex instanceof Vector2)) {
+                if (this._convertToRightHandedSystem && !(vertexAttributeKind === VertexBuffer.ColorKind) && !(vertex instanceof Vector2)) {
                     if (vertex instanceof Vector3) {
                         (vertexAttributeKind === VertexBuffer.PositionKind) ? _GLTFUtilities.GetRightHandedPositionVector3FromRef(vertex) : _GLTFUtilities.GetRightHandedNormalVector3FromRef(vertex);
                     }
@@ -445,7 +468,7 @@ module BABYLON.GLTF2 {
                     for (let k = 0, length = meshAttributeArray.length / stride; k < length; ++k) {
                         index = k * stride;
                         const vertexData = Vector3.FromArray(meshAttributeArray, index);
-                        if (this.convertToRightHandedSystem) {
+                        if (this._convertToRightHandedSystem) {
                             _GLTFUtilities.GetRightHandedPositionVector3FromRef(vertexData);
                         }
                         vertexAttributes.push(vertexData.asArray());
@@ -456,7 +479,7 @@ module BABYLON.GLTF2 {
                     for (let k = 0, length = meshAttributeArray.length / stride; k < length; ++k) {
                         index = k * stride;
                         const vertexData = Vector3.FromArray(meshAttributeArray, index);
-                        if (this.convertToRightHandedSystem) {
+                        if (this._convertToRightHandedSystem) {
                             _GLTFUtilities.GetRightHandedNormalVector3FromRef(vertexData);
                         }
                         vertexAttributes.push(vertexData.asArray());
@@ -467,7 +490,7 @@ module BABYLON.GLTF2 {
                     for (let k = 0, length = meshAttributeArray.length / stride; k < length; ++k) {
                         index = k * stride;
                         const vertexData = Vector4.FromArray(meshAttributeArray, index);
-                        if (this.convertToRightHandedSystem) {
+                        if (this._convertToRightHandedSystem) {
                             _GLTFUtilities.GetRightHandedVector4FromRef(vertexData);
                         }
                         vertexAttributes.push(vertexData.asArray());
@@ -486,7 +509,7 @@ module BABYLON.GLTF2 {
                 case VertexBuffer.UV2Kind: {
                     for (let k = 0, length = meshAttributeArray.length / stride; k < length; ++k) {
                         index = k * stride;
-                        vertexAttributes.push(this.convertToRightHandedSystem ? [meshAttributeArray[index], meshAttributeArray[index + 1]] : [meshAttributeArray[index], meshAttributeArray[index + 1]]);
+                        vertexAttributes.push(this._convertToRightHandedSystem ? [meshAttributeArray[index], meshAttributeArray[index + 1]] : [meshAttributeArray[index], meshAttributeArray[index + 1]]);
                     }
                     break;
                 }
@@ -510,61 +533,61 @@ module BABYLON.GLTF2 {
          * @returns json data as string
          */
         private generateJSON(shouldUseGlb: boolean, glTFPrefix?: string, prettyPrint?: boolean): string {
-            let buffer: IBuffer = { byteLength: this.totalByteLength };
+            let buffer: IBuffer = { byteLength: this._totalByteLength };
             let imageName: string;
             let imageData: { data: Uint8Array, mimeType: ImageMimeType };
             let bufferView: IBufferView;
-            let byteOffset: number = this.totalByteLength;
+            let byteOffset: number = this._totalByteLength;
 
             let glTF: IGLTF = {
-                asset: this.asset
+                asset: this._asset
             };
             if (buffer.byteLength) {
                 glTF.buffers = [buffer];
             }
-            if (this.nodes && this.nodes.length) {
-                glTF.nodes = this.nodes;
+            if (this._nodes && this._nodes.length) {
+                glTF.nodes = this._nodes;
             }
-            if (this.meshes && this.meshes.length) {
-                glTF.meshes = this.meshes;
+            if (this._meshes && this._meshes.length) {
+                glTF.meshes = this._meshes;
             }
-            if (this.scenes && this.scenes.length) {
-                glTF.scenes = this.scenes;
+            if (this._scenes && this._scenes.length) {
+                glTF.scenes = this._scenes;
                 glTF.scene = 0;
             }
-            if (this.bufferViews && this.bufferViews.length) {
-                glTF.bufferViews = this.bufferViews;
+            if (this._bufferViews && this._bufferViews.length) {
+                glTF.bufferViews = this._bufferViews;
             }
-            if (this.accessors && this.accessors.length) {
-                glTF.accessors = this.accessors;
+            if (this._accessors && this._accessors.length) {
+                glTF.accessors = this._accessors;
             }
-            if (this.animations && this.animations.length) {
-                glTF.animations = this.animations;
+            if (this._animations && this._animations.length) {
+                glTF.animations = this._animations;
             }
-            if (this.materials && this.materials.length) {
-                glTF.materials = this.materials;
+            if (this._materials && this._materials.length) {
+                glTF.materials = this._materials;
             }
-            if (this.textures && this.textures.length) {
-                glTF.textures = this.textures;
+            if (this._textures && this._textures.length) {
+                glTF.textures = this._textures;
             }
-            if (this.samplers && this.samplers.length) {
-                glTF.samplers = this.samplers;
+            if (this._samplers && this._samplers.length) {
+                glTF.samplers = this._samplers;
             }
-            if (this.images && this.images.length) {
+            if (this._images && this._images.length) {
                 if (!shouldUseGlb) {
-                    glTF.images = this.images;
+                    glTF.images = this._images;
                 }
                 else {
                     glTF.images = [];
 
-                    this.images.forEach((image) => {
+                    this._images.forEach((image) => {
                         if (image.uri) {
-                            imageData = this.imageData[image.uri];
+                            imageData = this._imageData[image.uri];
                             imageName = image.uri.split('.')[0] + " image";
                             bufferView = _GLTFUtilities.CreateBufferView(0, byteOffset, imageData.data.length, undefined, imageName);
                             byteOffset += imageData.data.buffer.byteLength;
-                            this.bufferViews.push(bufferView);
-                            image.bufferView = this.bufferViews.length - 1;
+                            this._bufferViews.push(bufferView);
+                            image.bufferView = this._bufferViews.length - 1;
                             image.name = imageName;
                             image.mimeType = imageData.mimeType;
                             image.uri = undefined;
@@ -606,9 +629,9 @@ module BABYLON.GLTF2 {
                 container.glTFFiles[glTFFileName] = jsonText;
                 container.glTFFiles[glTFBinFile] = bin;
 
-                if (this.imageData) {
-                    for (let image in this.imageData) {
-                        container.glTFFiles[image] = new Blob([this.imageData[image].data], { type: this.imageData[image].mimeType });
+                if (this._imageData) {
+                    for (let image in this._imageData) {
+                        container.glTFFiles[image] = new Blob([this._imageData[image].data], { type: this._imageData[image].mimeType });
                     }
                 }
 
@@ -623,7 +646,10 @@ module BABYLON.GLTF2 {
          */
         private _generateBinaryAsync(): Promise<ArrayBuffer> {
             let binaryWriter = new _BinaryWriter(4);
-            return this.createSceneAsync(this.babylonScene, binaryWriter).then(() => {
+            return this.createSceneAsync(this._babylonScene, binaryWriter).then(() => {
+                if (this._localEngine) {
+                    this._localEngine.dispose();
+                }
                 return binaryWriter.getArrayBuffer();
             });
         }
@@ -655,8 +681,8 @@ module BABYLON.GLTF2 {
                 const jsonLength = jsonText.length;
                 let imageByteLength = 0;
 
-                for (let key in this.imageData) {
-                    imageByteLength += this.imageData[key].data.byteLength;
+                for (let key in this._imageData) {
+                    imageByteLength += this._imageData[key].data.byteLength;
                 }
                 const jsonPadding = this._getPadding(jsonLength);
                 const binPadding = this._getPadding(binaryBuffer.byteLength);
@@ -711,8 +737,8 @@ module BABYLON.GLTF2 {
                 const glbData = [headerBuffer, jsonChunkBuffer, binaryChunkBuffer, binaryBuffer];
 
                 // binary data
-                for (let key in this.imageData) {
-                    glbData.push(this.imageData[key].data.buffer);
+                for (let key in this._imageData) {
+                    glbData.push(this._imageData[key].data.buffer);
                 }
                 glbData.push(binPaddingBuffer);
 
@@ -723,6 +749,8 @@ module BABYLON.GLTF2 {
                 const container = new GLTFData();
                 container.glTFFiles[glbFileName] = glbFile;
 
+                this._localEngine.dispose();
+
                 return container;
             });
         }
@@ -734,7 +762,7 @@ module BABYLON.GLTF2 {
          */
         private setNodeTransformation(node: INode, babylonTransformNode: TransformNode): void {
             if (!babylonTransformNode.position.equalsToFloats(0, 0, 0)) {
-                node.translation = this.convertToRightHandedSystem ? _GLTFUtilities.GetRightHandedPositionVector3(babylonTransformNode.position).asArray() : babylonTransformNode.position.asArray();
+                node.translation = this._convertToRightHandedSystem ? _GLTFUtilities.GetRightHandedPositionVector3(babylonTransformNode.position).asArray() : babylonTransformNode.position.asArray();
             }
 
             if (!babylonTransformNode.scaling.equalsToFloats(1, 1, 1)) {
@@ -746,7 +774,7 @@ module BABYLON.GLTF2 {
                 rotationQuaternion.multiplyInPlace(babylonTransformNode.rotationQuaternion);
             }
             if (!(rotationQuaternion.x === 0 && rotationQuaternion.y === 0 && rotationQuaternion.z === 0 && rotationQuaternion.w === 1)) {
-                if (this.convertToRightHandedSystem) {
+                if (this._convertToRightHandedSystem) {
                     _GLTFUtilities.GetRightHandedQuaternionFromRef(rotationQuaternion);
 
                 }
@@ -781,7 +809,7 @@ module BABYLON.GLTF2 {
                 if (vertexData) {
                     const byteLength = vertexData.length * 4;
                     const bufferView = _GLTFUtilities.CreateBufferView(0, binaryWriter.getByteOffset(), byteLength, byteStride, kind + " - " + bufferMesh.name);
-                    this.bufferViews.push(bufferView);
+                    this._bufferViews.push(bufferView);
 
                     this.writeAttributeData(
                         kind,
@@ -854,27 +882,27 @@ module BABYLON.GLTF2 {
         private setAttributeKind(meshPrimitive: IMeshPrimitive, attributeKind: string): void {
             switch (attributeKind) {
                 case VertexBuffer.PositionKind: {
-                    meshPrimitive.attributes.POSITION = this.accessors.length - 1;
+                    meshPrimitive.attributes.POSITION = this._accessors.length - 1;
                     break;
                 }
                 case VertexBuffer.NormalKind: {
-                    meshPrimitive.attributes.NORMAL = this.accessors.length - 1;
+                    meshPrimitive.attributes.NORMAL = this._accessors.length - 1;
                     break;
                 }
                 case VertexBuffer.ColorKind: {
-                    meshPrimitive.attributes.COLOR_0 = this.accessors.length - 1;
+                    meshPrimitive.attributes.COLOR_0 = this._accessors.length - 1;
                     break;
                 }
                 case VertexBuffer.TangentKind: {
-                    meshPrimitive.attributes.TANGENT = this.accessors.length - 1;
+                    meshPrimitive.attributes.TANGENT = this._accessors.length - 1;
                     break;
                 }
                 case VertexBuffer.UVKind: {
-                    meshPrimitive.attributes.TEXCOORD_0 = this.accessors.length - 1;
+                    meshPrimitive.attributes.TEXCOORD_0 = this._accessors.length - 1;
                     break;
                 }
                 case VertexBuffer.UV2Kind: {
-                    meshPrimitive.attributes.TEXCOORD_1 = this.accessors.length - 1;
+                    meshPrimitive.attributes.TEXCOORD_1 = this._accessors.length - 1;
                     break;
                 }
                 default: {
@@ -926,7 +954,7 @@ module BABYLON.GLTF2 {
                         }
 
                         this.createBufferViewKind(attributeKind, babylonTransformNode, binaryWriter, attribute.byteStride);
-                        attribute.bufferViewIndex = this.bufferViews.length - 1;
+                        attribute.bufferViewIndex = this._bufferViews.length - 1;
                         vertexAttributeBufferViews[attributeKind] = attribute.bufferViewIndex;
                     }
                 }
@@ -936,8 +964,8 @@ module BABYLON.GLTF2 {
                     if (indices) {
                         const byteLength = indices.length * 4;
                         bufferView = _GLTFUtilities.CreateBufferView(0, binaryWriter.getByteOffset(), byteLength, undefined, "Indices - " + bufferMesh.name);
-                        this.bufferViews.push(bufferView);
-                        indexBufferViewIndex = this.bufferViews.length - 1;
+                        this._bufferViews.push(bufferView);
+                        indexBufferViewIndex = this._bufferViews.length - 1;
 
                         for (let k = 0, length = indices.length; k < length; ++k) {
                             binaryWriter.setUInt32(indices[k]);
@@ -963,21 +991,21 @@ module BABYLON.GLTF2 {
                                         baseColorFactor: bufferMesh.color.asArray().concat([bufferMesh.alpha])
                                     }
                                 }
-                                this.materials.push(material);
-                                materialIndex = this.materials.length - 1;
+                                this._materials.push(material);
+                                materialIndex = this._materials.length - 1;
                             }
                             else if (babylonMaterial instanceof MultiMaterial) {
                                 babylonMaterial = babylonMaterial.subMaterials[submesh.materialIndex];
                                 if (babylonMaterial) {
-                                    materialIndex = this.materialMap[babylonMaterial.uniqueId];
+                                    materialIndex = this._materialMap[babylonMaterial.uniqueId];
                                 }
                             }
                             else {
-                                materialIndex = this.materialMap[babylonMaterial.uniqueId];
+                                materialIndex = this._materialMap[babylonMaterial.uniqueId];
                             }
                         }
 
-                        let glTFMaterial: Nullable<IMaterial> = materialIndex != null ? this.materials[materialIndex] : null;
+                        let glTFMaterial: Nullable<IMaterial> = materialIndex != null ? this._materials[materialIndex] : null;
 
                         const meshPrimitive: IMeshPrimitive = { attributes: {} };
                         this.setPrimitiveMode(meshPrimitive, primitiveMode);
@@ -985,7 +1013,7 @@ module BABYLON.GLTF2 {
                         for (const attribute of attributeData) {
                             const attributeKind = attribute.kind;
                             if (attributeKind === VertexBuffer.UVKind || attributeKind === VertexBuffer.UV2Kind) {
-                                if (glTFMaterial && !_GLTFMaterial._HasTexturesPresent(glTFMaterial)) {
+                                if (glTFMaterial && !this._glTFMaterialExporter._hasTexturesPresent(glTFMaterial)) {
                                     continue;
                                 }
                             }
@@ -998,10 +1026,10 @@ module BABYLON.GLTF2 {
                                     if (bufferViewIndex != undefined) { // check to see if bufferviewindex has a numeric value assigned.
                                         minMax = { min: null, max: null };
                                         if (attributeKind == VertexBuffer.PositionKind) {
-                                            minMax = _GLTFUtilities.CalculateMinMaxPositions(vertexData, 0, vertexData.length / stride, this.convertToRightHandedSystem);
+                                            minMax = _GLTFUtilities.CalculateMinMaxPositions(vertexData, 0, vertexData.length / stride, this._convertToRightHandedSystem);
                                         }
                                         const accessor = _GLTFUtilities.CreateAccessor(bufferViewIndex, attributeKind + " - " + babylonTransformNode.name, attribute.accessorType, AccessorComponentType.FLOAT, vertexData.length / stride, 0, minMax.min, minMax.max);
-                                        this.accessors.push(accessor);
+                                        this._accessors.push(accessor);
                                         this.setAttributeKind(meshPrimitive, attributeKind);
                                         if (meshPrimitive.attributes.TEXCOORD_0 != null || meshPrimitive.attributes.TEXCOORD_1 != null) {
                                             uvCoordsPresent = true;
@@ -1013,15 +1041,15 @@ module BABYLON.GLTF2 {
                         if (indexBufferViewIndex) {
                             // Create accessor
                             const accessor = _GLTFUtilities.CreateAccessor(indexBufferViewIndex, "indices - " + babylonTransformNode.name, AccessorType.SCALAR, AccessorComponentType.UNSIGNED_INT, submesh.indexCount, submesh.indexStart * 4, null, null);
-                            this.accessors.push(accessor);
-                            meshPrimitive.indices = this.accessors.length - 1;
+                            this._accessors.push(accessor);
+                            meshPrimitive.indices = this._accessors.length - 1;
                         }
                         if (materialIndex != null && Object.keys(meshPrimitive.attributes).length > 0) {
-                            let sideOrientation = this.babylonScene.materials[materialIndex].sideOrientation;
+                            let sideOrientation = this._babylonScene.materials[materialIndex].sideOrientation;
 
-                            if (this.convertToRightHandedSystem && sideOrientation === Material.ClockWiseSideOrientation) {
+                            if (this._convertToRightHandedSystem && sideOrientation === Material.ClockWiseSideOrientation) {
                                 //Overwrite the indices to be counter-clockwise
-                                let byteOffset = indexBufferViewIndex != null ? this.bufferViews[indexBufferViewIndex].byteOffset : null;
+                                let byteOffset = indexBufferViewIndex != null ? this._bufferViews[indexBufferViewIndex].byteOffset : null;
                                 if (byteOffset == null) { byteOffset = 0; }
                                 let babylonIndices: Nullable<IndicesArray> = null;
                                 if (indexBufferViewIndex != null) {
@@ -1034,7 +1062,7 @@ module BABYLON.GLTF2 {
                                     for (let attribute of attributeData) {
                                         let vertexData = bufferMesh.getVerticesData(attribute.kind);
                                         if (vertexData) {
-                                            let byteOffset = this.bufferViews[vertexAttributeBufferViews[attribute.kind]].byteOffset;
+                                            let byteOffset = this._bufferViews[vertexAttributeBufferViews[attribute.kind]].byteOffset;
                                             if (!byteOffset) {
                                                 byteOffset = 0
                                             }
@@ -1044,10 +1072,10 @@ module BABYLON.GLTF2 {
                                 }
                             }
 
-                            if (!uvCoordsPresent && _GLTFMaterial._HasTexturesPresent(this.materials[materialIndex])) {
-                                const newMat = _GLTFMaterial._StripTexturesFromMaterial(this.materials[materialIndex]);
-                                this.materials.push(newMat);
-                                materialIndex = this.materials.length - 1;
+                            if (!uvCoordsPresent && this._glTFMaterialExporter._hasTexturesPresent(this._materials[materialIndex])) {
+                                const newMat = this._glTFMaterialExporter._stripTexturesFromMaterial(this._materials[materialIndex]);
+                                this._materials.push(newMat);
+                                materialIndex = this._materials.length - 1;
                             }
 
                             meshPrimitive.material = materialIndex;
@@ -1072,23 +1100,23 @@ module BABYLON.GLTF2 {
             let directDescendents: Node[];
             const nodes = [...babylonScene.transformNodes, ...babylonScene.meshes];
 
-            return _GLTFMaterial._ConvertMaterialsToGLTFAsync(babylonScene.materials, ImageMimeType.PNG, this.images, this.textures, this.samplers, this.materials, this.materialMap, this.imageData, true).then(() => {
-                this.nodeMap = this.createNodeMapAndAnimations(babylonScene, nodes, this.shouldExportTransformNode, binaryWriter);
+            return this._glTFMaterialExporter._convertMaterialsToGLTFAsync(babylonScene.materials, ImageMimeType.PNG, true).then(() => {
+                this._nodeMap = this.createNodeMapAndAnimations(babylonScene, nodes, this._shouldExportTransformNode, binaryWriter);
 
-                this.totalByteLength = binaryWriter.getByteOffset();
+                this._totalByteLength = binaryWriter.getByteOffset();
 
 
                 // Build Hierarchy with the node map.
                 for (let babylonTransformNode of nodes) {
-                    glTFNodeIndex = this.nodeMap[babylonTransformNode.uniqueId];
+                    glTFNodeIndex = this._nodeMap[babylonTransformNode.uniqueId];
                     if (glTFNodeIndex != null) {
-                        glTFNode = this.nodes[glTFNodeIndex];
+                        glTFNode = this._nodes[glTFNodeIndex];
                         if (!babylonTransformNode.parent) {
-                            if (!this.shouldExportTransformNode(babylonTransformNode)) {
+                            if (!this._shouldExportTransformNode(babylonTransformNode)) {
                                 Tools.Log("Omitting " + babylonTransformNode.name + " from scene.");
                             }
                             else {
-                                if (this.convertToRightHandedSystem) {
+                                if (this._convertToRightHandedSystem) {
                                     if (glTFNode.translation) {
                                         glTFNode.translation[2] *= -1;
                                         glTFNode.translation[0] *= -1;
@@ -1104,15 +1132,15 @@ module BABYLON.GLTF2 {
                         if (!glTFNode.children && directDescendents && directDescendents.length) {
                             glTFNode.children = [];
                             for (let descendent of directDescendents) {
-                                if (this.nodeMap[descendent.uniqueId] != null) {
-                                    glTFNode.children.push(this.nodeMap[descendent.uniqueId]);
+                                if (this._nodeMap[descendent.uniqueId] != null) {
+                                    glTFNode.children.push(this._nodeMap[descendent.uniqueId]);
                                 }
                             }
                         }
                     }
                 };
                 if (scene.nodes.length) {
-                    this.scenes.push(scene);
+                    this._scenes.push(scene);
                 }
             });
         }
@@ -1140,12 +1168,12 @@ module BABYLON.GLTF2 {
                 if (shouldExportTransformNode(babylonTransformNode)) {
                     node = this.createNode(babylonTransformNode, binaryWriter);
 
-                    this.nodes.push(node);
-                    nodeIndex = this.nodes.length - 1;
+                    this._nodes.push(node);
+                    nodeIndex = this._nodes.length - 1;
                     nodeMap[babylonTransformNode.uniqueId] = nodeIndex;
 
                     if (!babylonScene.animationGroups.length && babylonTransformNode.animations.length) {
-                        _GLTFAnimation._CreateNodeAnimationFromTransformNodeAnimations(babylonTransformNode, runtimeGLTFAnimation, idleGLTFAnimations, nodeMap, this.nodes, binaryWriter, this.bufferViews, this.accessors, this.convertToRightHandedSystem, this.animationSampleRate);
+                        _GLTFAnimation._CreateNodeAnimationFromTransformNodeAnimations(babylonTransformNode, runtimeGLTFAnimation, idleGLTFAnimations, nodeMap, this._nodes, binaryWriter, this._bufferViews, this._accessors, this._convertToRightHandedSystem, this._animationSampleRate);
                     }
                 }
                 else {
@@ -1154,16 +1182,16 @@ module BABYLON.GLTF2 {
             };
 
             if (runtimeGLTFAnimation.channels.length && runtimeGLTFAnimation.samplers.length) {
-                this.animations.push(runtimeGLTFAnimation);
+                this._animations.push(runtimeGLTFAnimation);
             }
             idleGLTFAnimations.forEach((idleGLTFAnimation) => {
                 if (idleGLTFAnimation.channels.length && idleGLTFAnimation.samplers.length) {
-                    this.animations.push(idleGLTFAnimation);
+                    this._animations.push(idleGLTFAnimation);
                 }
             });
 
             if (babylonScene.animationGroups.length) {
-                _GLTFAnimation._CreateNodeAnimationFromAnimationGroups(babylonScene, this.animations, nodeMap, this.nodes, binaryWriter, this.bufferViews, this.accessors, this.convertToRightHandedSystem, this.animationSampleRate);
+                _GLTFAnimation._CreateNodeAnimationFromAnimationGroups(babylonScene, this._animations, nodeMap, this._nodes, binaryWriter, this._bufferViews, this._accessors, this._convertToRightHandedSystem, this._animationSampleRate);
             }
 
             return nodeMap;
@@ -1190,8 +1218,8 @@ module BABYLON.GLTF2 {
             this.setPrimitiveAttributes(mesh, babylonTransformNode, binaryWriter);
 
             if (mesh.primitives.length) {
-                this.meshes.push(mesh);
-                node.mesh = this.meshes.length - 1;
+                this._meshes.push(mesh);
+                node.mesh = this._meshes.length - 1;
             }
 
             return node;

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 229 - 208
serializers/src/glTF/2.0/babylon.glTFMaterial.ts


+ 0 - 10
serializers/src/glTF/2.0/shaders/setAlphaToOne.fragment.fx

@@ -1,10 +0,0 @@
-precision highp float;
-
-uniform sampler2D textureSampler;
-
-varying vec2 vUV;
-
-void main(void) {
-    vec4 color = texture2D(textureSampler, vUV);
-    gl_FragColor = vec4(color.rgb, 1.0);
-}

+ 16 - 2
src/Collisions/babylon.pickingInfo.ts

@@ -92,10 +92,24 @@
             }
 
             if (useWorldCoordinates) {
-                result = Vector3.TransformNormal(result, this.pickedMesh.getWorldMatrix());
+                let wm = this.pickedMesh.getWorldMatrix();
+
+                if (this.pickedMesh.nonUniformScaling) {
+                    Tmp.Matrix[0].copyFrom(wm);
+                    wm = Tmp.Matrix[0];
+                    wm.setTranslationFromFloats(0, 0, 0);
+                    wm.invert();
+                    wm.transposeToRef(Tmp.Matrix[1]);
+
+                    wm = Tmp.Matrix[1];
+                }
+
+                result = Vector3.TransformNormal(result, wm);
             }
 
-            return Vector3.Normalize(result);
+            result.normalize();
+
+            return result;
         }
 
         /**

+ 17 - 6
src/Engine/babylon.engine.ts

@@ -3450,7 +3450,13 @@
             var attributesNamesOrOptions = ParticleSystem._GetAttributeNamesOrOptions();
             var effectCreationOption = ParticleSystem._GetEffectCreationOptions();
 
-            defines += "\n#define BILLBOARD\n";
+            if (defines.indexOf(" BILLBOARD") === -1) {
+                defines += "\n#define BILLBOARD\n";
+            }
+
+            if (samplers.indexOf("diffuseSampler") === -1) {
+                samplers.push("diffuseSampler");
+            }
 
             return this.createEffect(
                 {
@@ -3459,7 +3465,7 @@
                 },
                 attributesNamesOrOptions,
                 effectCreationOption.concat(uniformsNames),
-                ["diffuseSampler"].concat(samplers), defines, fallbacks, onCompiled, onError);
+                samplers, defines, fallbacks, onCompiled, onError);
         }
 
         /**
@@ -5571,12 +5577,13 @@
          * @param createPolynomials if a polynomial sphere should be created for the cube texture
          * @param lodScale defines the scale applied to environment texture. This manages the range of LOD level used for IBL according to the roughness
          * @param lodOffset defines the offset applied to environment texture. This manages first LOD level used for IBL according to the roughness
+         * @param fallback defines texture to use while falling back when (compressed) texture file not found.
          * @returns the cube texture as an InternalTexture
          */
-        public createCubeTexture(rootUrl: string, scene: Nullable<Scene>, files: Nullable<string[]>, noMipmap?: boolean, onLoad: Nullable<(data?: any) => void> = null, onError: Nullable<(message?: string, exception?: any) => void> = null, format?: number, forcedExtension: any = null, createPolynomials = false, lodScale: number = 0, lodOffset: number = 0): InternalTexture {
+        public createCubeTexture(rootUrl: string, scene: Nullable<Scene>, files: Nullable<string[]>, noMipmap?: boolean, onLoad: Nullable<(data?: any) => void> = null, onError: Nullable<(message?: string, exception?: any) => void> = null, format?: number, forcedExtension: any = null, createPolynomials = false, lodScale: number = 0, lodOffset: number = 0, fallback: Nullable<InternalTexture> = null): InternalTexture {
             var gl = this._gl;
 
-            var texture = new InternalTexture(this, InternalTexture.DATASOURCE_CUBE);
+            var texture = fallback ? fallback : new InternalTexture(this, InternalTexture.DATASOURCE_CUBE);
             texture.isCube = true;
             texture.url = rootUrl;
             texture.generateMipMaps = !noMipmap;
@@ -5593,8 +5600,7 @@
             var isEnv = false;
             var lastDot = rootUrl.lastIndexOf('.');
             var extension = forcedExtension ? forcedExtension : (lastDot > -1 ? rootUrl.substring(lastDot).toLowerCase() : "");
-            if (this._textureFormatInUse) {
-                extension = this._textureFormatInUse;
+            if (this._textureFormatInUse && !fallback) {
                 rootUrl = (lastDot > -1 ? rootUrl.substring(0, lastDot) : rootUrl) + this._textureFormatInUse;
                 isKTX = true;
             } else {
@@ -5603,6 +5609,11 @@
             }
 
             let onerror = (request?: XMLHttpRequest, exception?: any) => {
+                if(isKTX){
+                    //remove the format appended to the rootUrl in the original createCubeTexture call.
+                    var exp = new RegExp("" + this._textureFormatInUse + "$");
+                    this.createCubeTexture(rootUrl.replace(exp, ""), scene, files, noMipmap, onLoad, onError, format, extension, createPolynomials, lodScale, lodOffset, texture);
+                }
                 if (onError && request) {
                     onError(request.status + " " + request.statusText, exception);
                 }

+ 32 - 6
src/Gizmos/babylon.axisDragGizmo.ts

@@ -6,6 +6,15 @@ module BABYLON {
         private _dragBehavior:PointerDragBehavior;
         private _pointerObserver:Nullable<Observer<PointerInfo>> = null;
         /**
+         * Drag distance in babylon units that the gizmo will snap to when dragged (Default: 0)
+         */
+        public snapDistance = 0;
+        /**
+         * Event that fires each time the gizmo snaps to a new location.
+         * * snapDistance is the the change in distance
+         */
+        public onSnapObservable = new Observable<{snapDistance:number}>();
+        /**
          * Creates an AxisDragGizmo
          * @param gizmoLayer The utility layer the gizmo will be added to
          * @param dragAxis The axis which the gizmo will be able to drag on
@@ -42,16 +51,30 @@ module BABYLON {
 
             this._rootMesh.addChild(arrow)
 
+            var currentSnapDragDistance = 0;
+            var tmpVector = new Vector3();
+            var tmpSnapEvent = {snapDistance: 0};
             // Add drag behavior to handle events when the gizmo is dragged
             this._dragBehavior = new PointerDragBehavior({dragAxis: dragAxis});
             this._dragBehavior.moveAttached = false;
             this._rootMesh.addBehavior(this._dragBehavior);
             this._dragBehavior.onDragObservable.add((event)=>{
-                if(!this.interactionsEnabled){
-                    return;
-                }
                 if(this.attachedMesh){
-                    this.attachedMesh.position.addInPlace(event.delta);
+                    // Snapping logic
+                    if(this.snapDistance == 0){
+                        this.attachedMesh.position.addInPlace(event.delta);
+                    }else{
+                        currentSnapDragDistance+=event.dragDistance
+                        if(Math.abs(currentSnapDragDistance)>this.snapDistance){
+                            var dragSteps = Math.floor(Math.abs(currentSnapDragDistance)/this.snapDistance);
+                            currentSnapDragDistance = currentSnapDragDistance % this.snapDistance;
+                            event.delta.normalizeToRef(tmpVector);
+                            tmpVector.scaleInPlace(this.snapDistance*dragSteps);
+                            this.attachedMesh.position.addInPlace(tmpVector);
+                            tmpSnapEvent.snapDistance = this.snapDistance*dragSteps;
+                            this.onSnapObservable.notifyObservers(tmpSnapEvent);
+                        }
+                    }
                 }
             })
 
@@ -67,13 +90,16 @@ module BABYLON {
                 }
             });
         }
-        protected _onInteractionsEnabledChanged(value:boolean){
-            this._dragBehavior.enabled = value;
+        protected _attachedMeshChanged(value:Nullable<AbstractMesh>){
+            if(this._dragBehavior){
+                this._dragBehavior.enabled = value?true:false;
+            }
         }
         /**
          * Disposes of the gizmo
          */
         public dispose(){
+            this.onSnapObservable.clear();
             this.gizmoLayer.utilityLayerScene.onPointerObservable.remove(this._pointerObserver);
             this._dragBehavior.detach();
             super.dispose();

+ 39 - 7
src/Gizmos/babylon.axisScaleGizmo.ts

@@ -6,6 +6,15 @@ module BABYLON {
         private _dragBehavior:PointerDragBehavior;
         private _pointerObserver:Nullable<Observer<PointerInfo>> = null;
         /**
+         * Scale distance in babylon units that the gizmo will snap to when dragged (Default: 0)
+         */
+        public snapDistance = 0;
+        /**
+         * Event that fires each time the gizmo snaps to a new location.
+         * * snapDistance is the the change in distance
+         */
+        public onSnapObservable = new Observable<{snapDistance:number}>();
+        /**
          * Creates an AxisScaleGizmo
          * @param gizmoLayer The utility layer the gizmo will be added to
          * @param dragAxis The axis which the gizmo will be able to scale on
@@ -46,13 +55,28 @@ module BABYLON {
             this._dragBehavior.moveAttached = false;
             this._rootMesh.addBehavior(this._dragBehavior);
 
+            var currentSnapDragDistance = 0;
             var tmpVector = new Vector3();
-            this._dragBehavior.onDragObservable.add((event)=>{
-                if(!this.interactionsEnabled){
-                    return;
-                }
+            var tmpSnapEvent = {snapDistance: 0};
+            this._dragBehavior.onDragObservable.add((event)=>{                
                 if(this.attachedMesh){
-                    dragAxis.scaleToRef(event.dragDistance, tmpVector);
+                    // Snapping logic
+                    var snapped = false;
+                    var dragSteps = 0;
+                    if(this.snapDistance == 0){
+                        dragAxis.scaleToRef(event.dragDistance, tmpVector);
+                    }else{
+                        currentSnapDragDistance+=event.dragDistance;
+                        if(Math.abs(currentSnapDragDistance)>this.snapDistance){
+                            dragSteps = Math.floor(currentSnapDragDistance/this.snapDistance);
+                            currentSnapDragDistance = currentSnapDragDistance % this.snapDistance;
+                            dragAxis.scaleToRef(this.snapDistance*dragSteps, tmpVector);
+                            snapped = true;
+                        }else{
+                            tmpVector.scaleInPlace(0);
+                        }
+                    }
+                    
                     var invertCount = 0;
                     if(this.attachedMesh.scaling["x"] < 0){
                         invertCount++;
@@ -68,6 +92,11 @@ module BABYLON {
                     }else{
                         this.attachedMesh.scaling.subtractInPlace(tmpVector);
                     }
+
+                    if(snapped){
+                        tmpSnapEvent.snapDistance = this.snapDistance*dragSteps;
+                        this.onSnapObservable.notifyObservers(tmpSnapEvent);
+                    }
                 }
             })
 
@@ -84,14 +113,17 @@ module BABYLON {
             });
         }
         
-        protected _onInteractionsEnabledChanged(value:boolean){
-            this._dragBehavior.enabled = value;
+        protected _attachedMeshChanged(value:Nullable<AbstractMesh>){
+            if(this._dragBehavior){
+                this._dragBehavior.enabled = value ? true : false;
+            }
         }
         
         /**
          * Disposes of the gizmo
          */
         public dispose(){
+            this.onSnapObservable.clear();
             this.gizmoLayer.utilityLayerScene.onPointerObservable.remove(this._pointerObserver);
             this._dragBehavior.detach();
             super.dispose();

+ 16 - 0
src/Gizmos/babylon.boundingBoxGizmo.ts

@@ -248,6 +248,22 @@ module BABYLON {
         }
 
         /**
+         * Enables rotation on the specified axis and disables rotation on the others
+         * @param axis The list of axis that should be enabled (eg. "xy" or "xyz")
+         */
+        public setEnabledRotationAxis(axis:string){
+            this._rotateSpheresParent.getChildMeshes().forEach((m,i)=>{
+                if(i<4){
+                    m.setEnabled(axis.indexOf("x")!=-1);
+                }else if(i<8){
+                    m.setEnabled(axis.indexOf("y")!=-1);
+                }else{
+                    m.setEnabled(axis.indexOf("z")!=-1);
+                }
+            })
+        }
+
+        /**
          * Disposes of the gizmo
          */
         public dispose(){

+ 12 - 13
src/Gizmos/babylon.gizmo.ts

@@ -7,10 +7,19 @@ module BABYLON {
          * The root mesh of the gizmo
          */
         protected _rootMesh:Mesh;
+        private _attachedMesh:Nullable<AbstractMesh>;
         /**
          * Mesh that the gizmo will be attached to. (eg. on a drag gizmo the mesh that will be dragged)
+         * * When set, interactions will be enabled
          */
-        public attachedMesh:Nullable<AbstractMesh>;
+        public get attachedMesh(){
+            return this._attachedMesh;
+        }
+        public set attachedMesh(value){
+            this._attachedMesh = value;
+            this._rootMesh.setEnabled(value?true:false);
+            this._attachedMeshChanged(value);
+        }
         /**
          * If set the gizmo's rotation will be updated to match the attached mesh each frame (Default: true)
          */
@@ -24,18 +33,7 @@ module BABYLON {
          */
         protected _updateScale = true;
         protected _interactionsEnabled = true;
-        protected _onInteractionsEnabledChanged(value:boolean){
-        }
-
-        /**
-         * If interactions are enabled with this gizmo. (eg. dragging/rotation)
-         */
-        public set interactionsEnabled(value:boolean){
-            this._interactionsEnabled = value;
-            this._onInteractionsEnabledChanged(value);
-        }
-        public get interactionsEnabled(){
-            return this._interactionsEnabled;
+        protected _attachedMeshChanged(value:Nullable<AbstractMesh>){
         }
 
         private _beforeRenderObserver:Nullable<Observer<Scene>>;
@@ -63,6 +61,7 @@ module BABYLON {
                     }
                 }
             })
+            this.attachedMesh = null;
         }
         /**
          * Disposes of the gizmo

+ 43 - 14
src/Gizmos/babylon.planeRotationGizmo.ts

@@ -5,6 +5,17 @@ module BABYLON {
     export class PlaneRotationGizmo extends Gizmo {
         private _dragBehavior:PointerDragBehavior;
         private _pointerObserver:Nullable<Observer<PointerInfo>> = null;
+        
+        /**
+         * Rotation distance in radians that the gizmo will snap to (Default: 0)
+         */
+        public snapDistance = 0;
+        /**
+         * Event that fires each time the gizmo snaps to a new location.
+         * * snapDistance is the the change in distance
+         */
+        public onSnapObservable = new Observable<{snapDistance:number}>();
+
         /**
          * Creates a PlaneRotationGizmo
          * @param gizmoLayer The utility layer the gizmo will be added to
@@ -43,19 +54,18 @@ module BABYLON {
             var lastDragPosition:Nullable<Vector3> = null;
 
             this._dragBehavior.onDragStartObservable.add((e)=>{
-                if(!this.interactionsEnabled){
-                    return;
+                if(this.attachedMesh){
+                    lastDragPosition = e.dragPlanePoint;
                 }
-                lastDragPosition = e.dragPlanePoint;
             })
 
             var rotationMatrix = new Matrix();
             var planeNormalTowardsCamera = new Vector3();
             var localPlaneNormalTowardsCamera = new Vector3();
+
+            var tmpSnapEvent = {snapDistance: 0};
+            var currentSnapDragDistance = 0;
             this._dragBehavior.onDragObservable.add((event)=>{
-                if(!this.interactionsEnabled){
-                    return;
-                }
                 if(this.attachedMesh && lastDragPosition){
                     if(!this.attachedMesh.rotationQuaternion){
                         this.attachedMesh.rotationQuaternion = new BABYLON.Quaternion();
@@ -83,15 +93,31 @@ module BABYLON {
                     var halfCircleSide = Vector3.Dot(localPlaneNormalTowardsCamera, cross) > 0.0;
                     if (halfCircleSide) angle = -angle;
                     
+                    // Snapping logic
+                    var snapped = false;
+                    if(this.snapDistance != 0){
+                        currentSnapDragDistance+=angle
+                        if(Math.abs(currentSnapDragDistance)>this.snapDistance){
+                            var dragSteps = Math.floor(currentSnapDragDistance/this.snapDistance);
+                            currentSnapDragDistance = currentSnapDragDistance % this.snapDistance;
+                            angle = this.snapDistance*dragSteps;
+                            snapped = true;
+                        }else{
+                            angle = 0;
+                        }
+                    }
+                     // Convert angle and axis to quaternion (http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm)
+                     var quaternionCoefficient = Math.sin(angle/2)
+                     var amountToRotate = new BABYLON.Quaternion(planeNormalTowardsCamera.x*quaternionCoefficient,planeNormalTowardsCamera.y*quaternionCoefficient,planeNormalTowardsCamera.z*quaternionCoefficient,Math.cos(angle/2));
 
-                    // Convert angle and axis to quaternion (http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm)
-                    var quaternionCoefficient = Math.sin(angle/2)
-                    var amountToRotate = new BABYLON.Quaternion(planeNormalTowardsCamera.x*quaternionCoefficient,planeNormalTowardsCamera.y*quaternionCoefficient,planeNormalTowardsCamera.z*quaternionCoefficient,Math.cos(angle/2));
-
-                    // Rotate selected mesh quaternion over fixed axis
-                    this.attachedMesh.rotationQuaternion.multiplyToRef(amountToRotate,this.attachedMesh.rotationQuaternion);
+                     // Rotate selected mesh quaternion over fixed axis
+                     this.attachedMesh.rotationQuaternion.multiplyToRef(amountToRotate,this.attachedMesh.rotationQuaternion);
 
                     lastDragPosition = event.dragPlanePoint;
+                    if(snapped){
+                        tmpSnapEvent.snapDistance = angle;
+                        this.onSnapObservable.notifyObservers(tmpSnapEvent);
+                    }
                 }
             })
 
@@ -108,14 +134,17 @@ module BABYLON {
             });
         }
 
-        protected _onInteractionsEnabledChanged(value:boolean){
-            this._dragBehavior.enabled = value;
+        protected _attachedMeshChanged(value:Nullable<AbstractMesh>){
+            if(this._dragBehavior){
+                this._dragBehavior.enabled = value ? true : false;
+            }
         }
 
         /**
          * Disposes of the gizmo
          */
         public dispose(){
+            this.onSnapObservable.clear();
             this.gizmoLayer.utilityLayerScene.onPointerObservable.remove(this._pointerObserver);
             this._dragBehavior.detach();
             super.dispose();

+ 7 - 10
src/Gizmos/babylon.positionGizmo.ts

@@ -8,11 +8,13 @@ module BABYLON {
         private _zDrag:AxisDragGizmo;
 
         public set attachedMesh(mesh:Nullable<AbstractMesh>){
-            this._xDrag.attachedMesh = mesh;
-            this._yDrag.attachedMesh = mesh;
-            this._zDrag.attachedMesh = mesh;
+            if(this._xDrag){
+                this._xDrag.attachedMesh = mesh;
+                this._yDrag.attachedMesh = mesh;
+                this._zDrag.attachedMesh = mesh;
+            }
         }
-        /**
+    /**
          * Creates a PositionGizmo
          * @param gizmoLayer The utility layer the gizmo will be added to
          */
@@ -21,12 +23,7 @@ module BABYLON {
             this._xDrag = new AxisDragGizmo(gizmoLayer, new Vector3(1,0,0), BABYLON.Color3.Green().scale(0.5));
             this._yDrag = new AxisDragGizmo(gizmoLayer, new Vector3(0,1,0), BABYLON.Color3.Red().scale(0.5));
             this._zDrag = new AxisDragGizmo(gizmoLayer, new Vector3(0,0,1), BABYLON.Color3.Blue().scale(0.5));
-        }
-
-        protected _onInteractionsEnabledChanged(value:boolean){
-            this._xDrag.interactionsEnabled = value
-            this._yDrag.interactionsEnabled = value
-            this._zDrag.interactionsEnabled = value
+            this.attachedMesh = null;
         }
 
         public set updateGizmoRotationToMatchAttachedMesh(value:boolean){

+ 6 - 9
src/Gizmos/babylon.rotationGizmo.ts

@@ -8,9 +8,11 @@ module BABYLON {
         private _zDrag:PlaneRotationGizmo;
 
         public set attachedMesh(mesh:Nullable<AbstractMesh>){
-            this._xDrag.attachedMesh = mesh;
-            this._yDrag.attachedMesh = mesh;
-            this._zDrag.attachedMesh = mesh;
+            if(this._xDrag){
+                this._xDrag.attachedMesh = mesh;
+                this._yDrag.attachedMesh = mesh;
+                this._zDrag.attachedMesh = mesh;
+            }
         }
         /**
          * Creates a RotationGizmo
@@ -21,12 +23,7 @@ module BABYLON {
             this._xDrag = new PlaneRotationGizmo(gizmoLayer, new Vector3(1,0,0), BABYLON.Color3.Green().scale(0.5));
             this._yDrag = new PlaneRotationGizmo(gizmoLayer, new Vector3(0,1,0), BABYLON.Color3.Red().scale(0.5));
             this._zDrag = new PlaneRotationGizmo(gizmoLayer, new Vector3(0,0,1), BABYLON.Color3.Blue().scale(0.5));
-        }
-
-        protected _onInteractionsEnabledChanged(value:boolean){
-            this._xDrag.interactionsEnabled = value
-            this._yDrag.interactionsEnabled = value
-            this._zDrag.interactionsEnabled = value
+            this.attachedMesh = null;
         }
 
         public set updateGizmoRotationToMatchAttachedMesh(value:boolean){

+ 6 - 9
src/Gizmos/babylon.scaleGizmo.ts

@@ -8,9 +8,11 @@ module BABYLON {
         private _zDrag:AxisScaleGizmo;
 
         public set attachedMesh(mesh:Nullable<AbstractMesh>){
-            this._xDrag.attachedMesh = mesh;
-            this._yDrag.attachedMesh = mesh;
-            this._zDrag.attachedMesh = mesh;
+            if(this._xDrag){
+                this._xDrag.attachedMesh = mesh;
+                this._yDrag.attachedMesh = mesh;
+                this._zDrag.attachedMesh = mesh;
+            }
         }
         /**
          * Creates a ScaleGizmo
@@ -21,12 +23,7 @@ module BABYLON {
             this._xDrag = new AxisScaleGizmo(gizmoLayer, new Vector3(1,0,0), BABYLON.Color3.Green().scale(0.5));
             this._yDrag = new AxisScaleGizmo(gizmoLayer, new Vector3(0,1,0), BABYLON.Color3.Red().scale(0.5));
             this._zDrag = new AxisScaleGizmo(gizmoLayer, new Vector3(0,0,1), BABYLON.Color3.Blue().scale(0.5));
-        }
-
-        protected _onInteractionsEnabledChanged(value:boolean){
-            this._xDrag.interactionsEnabled = value
-            this._yDrag.interactionsEnabled = value
-            this._zDrag.interactionsEnabled = value
+            this.attachedMesh = null;
         }
 
         public set updateGizmoRotationToMatchAttachedMesh(value:boolean){

+ 3 - 1
src/Materials/Textures/babylon.renderTargetTexture.ts

@@ -172,8 +172,9 @@
          * @param generateDepthBuffer True to generate a depth buffer
          * @param generateStencilBuffer True to generate a stencil buffer
          * @param isMulti True if multiple textures need to be created (Draw Buffers)
+         * @param format The internal format of the buffer in the RTT (RED, RG, RGB, RGBA, ALPHA...)
          */
-        constructor(name: string, size: number | {width: number, height: number} | {ratio: number}, scene: Nullable<Scene>, generateMipMaps?: boolean, doNotChangeAspectRatio: boolean = true, type: number = Engine.TEXTURETYPE_UNSIGNED_INT, public isCube = false, samplingMode = Texture.TRILINEAR_SAMPLINGMODE, generateDepthBuffer = true, generateStencilBuffer = false, isMulti = false) {
+        constructor(name: string, size: number | {width: number, height: number} | {ratio: number}, scene: Nullable<Scene>, generateMipMaps?: boolean, doNotChangeAspectRatio: boolean = true, type: number = Engine.TEXTURETYPE_UNSIGNED_INT, public isCube = false, samplingMode = Texture.TRILINEAR_SAMPLINGMODE, generateDepthBuffer = true, generateStencilBuffer = false, isMulti = false, format = Engine.TEXTUREFORMAT_RGBA) {
             super(null, scene, !generateMipMaps);
             scene = this.getScene();
 
@@ -204,6 +205,7 @@
             this._renderTargetOptions = {
                 generateMipMaps: generateMipMaps,
                 type: type,
+                format: format,
                 samplingMode: samplingMode,
                 generateDepthBuffer: generateDepthBuffer,
                 generateStencilBuffer: generateStencilBuffer

+ 9 - 0
src/Mesh/babylon.mesh.vertexData.ts

@@ -326,6 +326,7 @@
          * @returns the VertexData 
          */
         public transform(matrix: Matrix): VertexData {
+            var flip = matrix.m[0] * matrix.m[5] * matrix.m[10] < 0;
             var transformed = Vector3.Zero();
             var index: number;
             if (this.positions) {
@@ -369,6 +370,14 @@
                 }
             }
 
+            if (flip && this.indices) {
+                for (index = 0; index < this.indices!.length; index += 3) {
+                    let tmp = this.indices[index + 1];
+                    this.indices[index + 1] = this.indices[index + 2];
+                    this.indices[index + 2] = tmp;
+                }
+            }
+
             return this;
         }
 

+ 7 - 2
src/Particles/babylon.particleSystem.ts

@@ -1329,6 +1329,8 @@
                 program = this.customShader;
                 var defines: string = (program.shaderOptions.defines.length > 0) ? program.shaderOptions.defines.join("\n") : "";
                 custom = this._scene.getEngine().createEffectForParticles(program.shaderPath.fragmentElement, program.shaderOptions.uniforms, program.shaderOptions.samplers, defines);
+            } else if (this._customEffect) {
+                custom = this._customEffect;
             }
             var result = new ParticleSystem(name, this._capacity, this._scene, custom);
             result.customShader = program;
@@ -1537,8 +1539,8 @@
             }       
             
             // Emitter
+            let emitterType: IParticleEmitterType;
             if (parsedParticleSystem.particleEmitterType) {
-                let emitterType: IParticleEmitterType;
                 switch (parsedParticleSystem.particleEmitterType.type) {
                     case "SphereEmitter":
                         emitterType = new SphereParticleEmitter();
@@ -1556,8 +1558,11 @@
                 }
 
                 emitterType.parse(parsedParticleSystem.particleEmitterType);
-                particleSystem.particleEmitterType = emitterType;
+            } else {
+                emitterType = new BoxParticleEmitter();
+                emitterType.parse(parsedParticleSystem);
             }
+            particleSystem.particleEmitterType = emitterType;
         }
 
         /**

+ 3 - 3
src/Tools/babylon.khronosTextureContainer.ts

@@ -125,13 +125,13 @@ module BABYLON {
             var mipmapCount = loadMipmaps ? this.numberOfMipmapLevels : 1;
             for (var level = 0; level < mipmapCount; level++) {
                 var imageSize = new Int32Array(this.arrayBuffer, dataOffset, 1)[0]; // size per face, since not supporting array cubemaps
-
+                dataOffset += 4;//image data starts from next multiple of 4 offset. Each face refers to same imagesize field above.
                 for (var face = 0; face < this.numberOfFaces; face++) {
                     var sampler = this.numberOfFaces === 1 ? gl.TEXTURE_2D : (gl.TEXTURE_CUBE_MAP_POSITIVE_X + face);
-                    var byteArray = new Uint8Array(this.arrayBuffer, dataOffset + 4, imageSize);
+                    var byteArray = new Uint8Array(this.arrayBuffer, dataOffset, imageSize);
                     gl.compressedTexImage2D(sampler, level, this.glInternalFormat, width, height, 0, byteArray);
 
-                    dataOffset += imageSize + 4; // size of the image + 4 for the imageSize field
+                    dataOffset += imageSize; // add size of the image for the next face/mipmap
                     dataOffset += 3 - ((imageSize + 3) % 4); // add padding for odd sized image
                 }
                 width = Math.max(1.0, width * 0.5);

+ 4 - 56
tests/unit/babylon/serializers/babylon.glTFSerializer.tests.ts

@@ -35,29 +35,6 @@ describe('Babylon glTF Serializer', () => {
      * This tests the glTF serializer help functions 
      */
     describe('#GLTF', () => {
-        // it('should get alpha mode from Babylon metallic roughness', () => {
-        //     let alphaMode: string;
-
-        //     const scene = new BABYLON.Scene(subject);
-        //     const babylonMaterial = new BABYLON.PBRMetallicRoughnessMaterial("metallicroughness", scene);
-        //     babylonMaterial.transparencyMode = BABYLON.PBRMaterial.PBRMATERIAL_OPAQUE;
-
-        //     alphaMode = BABYLON.GLTF2._GLTFMaterial._GetAlphaMode(babylonMaterial);
-        //     alphaMode.should.be.equal('OPAQUE');
-
-        //     babylonMaterial.transparencyMode = BABYLON.PBRMaterial.PBRMATERIAL_ALPHABLEND;
-        //     alphaMode = BABYLON.GLTF2._GLTFMaterial._GetAlphaMode(babylonMaterial);
-        //     alphaMode.should.be.equal('BLEND');
-
-        //     babylonMaterial.transparencyMode = BABYLON.PBRMaterial.PBRMATERIAL_ALPHATESTANDBLEND;
-        //     alphaMode = BABYLON.GLTF2._GLTFMaterial._GetAlphaMode(babylonMaterial);
-        //     alphaMode.should.be.equal('BLEND');
-
-        //     babylonMaterial.transparencyMode = BABYLON.PBRMaterial.PBRMATERIAL_ALPHATEST;
-        //     alphaMode = BABYLON.GLTF2._GLTFMaterial._GetAlphaMode(babylonMaterial);
-        //     alphaMode.should.be.equal('MASK');
-        // });
-
         it('should convert Babylon standard material to metallic roughness', () => {
             const scene = new BABYLON.Scene(subject);
             const babylonStandardMaterial = new BABYLON.StandardMaterial("specGloss", scene);
@@ -65,8 +42,9 @@ describe('Babylon glTF Serializer', () => {
             babylonStandardMaterial.specularColor = BABYLON.Color3.Black();
             babylonStandardMaterial.specularPower = 64;
             babylonStandardMaterial.alpha = 1;
+            const materialExporter = new BABYLON.GLTF2._GLTFMaterialExporter(new BABYLON.GLTF2._Exporter(scene));
 
-            const metalRough = BABYLON.GLTF2._GLTFMaterial._ConvertToGLTFPBRMetallicRoughness(babylonStandardMaterial);
+            const metalRough = materialExporter._convertToGLTFPBRMetallicRoughness(babylonStandardMaterial);
 
             metalRough.baseColorFactor.should.deep.equal([0.5, 0.5, 0.5, 1]);
 
@@ -74,12 +52,10 @@ describe('Babylon glTF Serializer', () => {
 
             metalRough.roughnessFactor.should.be.approximately(0.328809, 1e-6);
         });
-
         it('should solve for metallic', () => {
-            BABYLON.GLTF2._GLTFMaterial._SolveMetallic(1.0, 0.0, 1.0).should.be.equal(0);
-            BABYLON.GLTF2._GLTFMaterial._SolveMetallic(0.0, 1.0, 1.0).should.be.approximately(1, 1e-6);
+            BABYLON.GLTF2._GLTFMaterialExporter._SolveMetallic(1.0, 0.0, 1.0).should.be.equal(0);
+            BABYLON.GLTF2._GLTFMaterialExporter._SolveMetallic(0.0, 1.0, 1.0).should.be.approximately(1, 1e-6);
         });
-
         it('should serialize empty Babylon scene to glTF with only asset property', () => {
             const scene = new BABYLON.Scene(subject);
 
@@ -92,7 +68,6 @@ describe('Babylon glTF Serializer', () => {
                 jsonData.asset.generator.should.be.equal("BabylonJS");
             });
         });
-
         it('should serialize sphere geometry in scene to glTF', () => {
             const scene = new BABYLON.Scene(subject);
             BABYLON.Mesh.CreateSphere('sphere', 16, 2, scene);
@@ -125,33 +100,6 @@ describe('Babylon glTF Serializer', () => {
                     jsonData.scene.should.be.equal(0);
                 });
         });
-
-        // it('should serialize alpha mode and cutoff', () => {
-        //     const scene = new BABYLON.Scene(subject);
-
-        //     const plane = BABYLON.Mesh.CreatePlane('plane', 120, scene);
-        //     const babylonPBRMetalRoughMaterial = new BABYLON.PBRMetallicRoughnessMaterial('metalRoughMat', scene);
-        //     babylonPBRMetalRoughMaterial.transparencyMode = BABYLON.PBRMaterial.PBRMATERIAL_ALPHATEST;
-        //     const alphaCutoff = 0.8;
-        //     babylonPBRMetalRoughMaterial.alphaCutOff = alphaCutoff;
-
-        //     plane.material = babylonPBRMetalRoughMaterial;
-
-
-        //     return BABYLON.GLTF2Export.GLTFAsync(scene, 'test').then(glTFData => {
-        //         const jsonString = glTFData.glTFFiles['test.gltf'] as string;
-        //         const jsonData = JSON.parse(jsonString);
-
-        //         // accessors, asset, buffers, bufferViews, meshes, nodes, scene, scenes, materials
-        //         Object.keys(jsonData).length.should.be.equal(9);
-
-        //         jsonData.materials.length.should.be.equal(2);
-
-        //         jsonData.materials[0].alphaMode.should.be.equal('MASK');
-
-        //         jsonData.materials[0].alphaCutoff.should.be.equal(alphaCutoff);
-        //     });
-        // });
         it('should serialize single component translation animation to glTF', () => {
             const scene = new BABYLON.Scene(subject);
             const box = BABYLON.Mesh.CreateBox('box', 1, scene);