Jelajahi Sumber

Merge remote-tracking branch 'upstream/master' into glTFFileLoader

Gary Hsu 8 tahun lalu
induk
melakukan
151e040697
78 mengubah file dengan 17161 tambahan dan 7004 penghapusan
  1. 31 12
      Playground/debug.html
  2. 31 13
      Playground/index-local.html
  3. 1 0
      Playground/index.html
  4. 36 38
      Playground/index2_5.html
  5. 54 20
      Playground/js/index.js
  6. 10 0
      Playground/js/v2.5/babylon.2.5.canvas2d.js
  7. 38 0
      Playground/js/v2.5/babylon.2.5.js
  8. 20 0
      Playground/textures/DemageFont.fnt
  9. TEMPAT SAMPAH
      Playground/textures/DemageFont.png
  10. 4916 0
      Playground/textures/HorrorBlue.3dl
  11. 4916 0
      Playground/textures/LateSunset.3dl
  12. TEMPAT SAMPAH
      Playground/textures/Logo.png
  13. TEMPAT SAMPAH
      Playground/textures/SunDiffuse.png
  14. TEMPAT SAMPAH
      Playground/textures/big_buck_bunny.mp4
  15. TEMPAT SAMPAH
      Playground/textures/candleopacity.png
  16. TEMPAT SAMPAH
      Playground/textures/co.png
  17. TEMPAT SAMPAH
      Playground/textures/country.hdr
  18. TEMPAT SAMPAH
      Playground/textures/distortion.png
  19. TEMPAT SAMPAH
      Playground/textures/environment.babylon.hdr
  20. TEMPAT SAMPAH
      Playground/textures/fire.png
  21. TEMPAT SAMPAH
      Playground/textures/floor.png
  22. TEMPAT SAMPAH
      Playground/textures/floor_bump.PNG
  23. TEMPAT SAMPAH
      Playground/textures/forest.hdr
  24. TEMPAT SAMPAH
      Playground/textures/fur.jpg
  25. TEMPAT SAMPAH
      Playground/textures/grass.png
  26. TEMPAT SAMPAH
      Playground/textures/grassn.png
  27. TEMPAT SAMPAH
      Playground/textures/heightMapTriPlanar.png
  28. TEMPAT SAMPAH
      Playground/textures/invmask.png
  29. TEMPAT SAMPAH
      Playground/textures/lensdirt.jpg
  30. TEMPAT SAMPAH
      Playground/textures/leopard_fur.JPG
  31. TEMPAT SAMPAH
      Playground/textures/mixMap.png
  32. TEMPAT SAMPAH
      Playground/textures/nba.png
  33. TEMPAT SAMPAH
      Playground/textures/night.hdr
  34. TEMPAT SAMPAH
      Playground/textures/parking.hdr
  35. TEMPAT SAMPAH
      Playground/textures/rock.png
  36. TEMPAT SAMPAH
      Playground/textures/rockn.png
  37. TEMPAT SAMPAH
      Playground/textures/roundMask.png
  38. TEMPAT SAMPAH
      Playground/textures/sand.jpg
  39. TEMPAT SAMPAH
      Playground/textures/speckles.jpg
  40. TEMPAT SAMPAH
      Playground/textures/walk.png
  41. 0 31
      dist/preview release/babylon.core.js
  42. 3189 3183
      dist/preview release/babylon.d.ts
  43. 23 23
      dist/preview release/babylon.js
  44. 65 20
      dist/preview release/babylon.max.js
  45. 3189 3183
      dist/preview release/babylon.module.d.ts
  46. 0 41
      dist/preview release/babylon.noworker.js
  47. 23 23
      dist/preview release/babylon.worker.js
  48. 249 249
      dist/preview release/inspector/babylon.inspector.bundle.js
  49. 36 36
      dist/preview release/inspector/babylon.inspector.d.ts
  50. 1 1
      dist/preview release/inspector/babylon.inspector.min.js
  51. 2 2
      dist/preview release/loaders/babylon.glTF1FileLoader.min.js
  52. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  53. 2 2
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  54. 9 3
      dist/preview release/loaders/babylon.stlFileLoader.js
  55. 1 1
      dist/preview release/loaders/babylon.stlFileLoader.min.js
  56. 1 0
      dist/preview release/what's new.md
  57. 11 3
      loaders/src/STL/babylon.stlFileLoader.ts
  58. 80 7
      loaders/src/glTF/2.0/babylon.glTFLoader.ts
  59. 1 1
      loaders/src/glTF/2.0/babylon.glTFLoaderInterfaces.ts
  60. 52 31
      serializers/src/OBJ/babylon.objSerializer.ts
  61. 27 3
      src/Cameras/VR/babylon.webVRCamera.ts
  62. 30 18
      src/Cameras/babylon.arcRotateCamera.ts
  63. 4 0
      src/Materials/babylon.effect.ts
  64. 7 0
      src/Materials/babylon.materialHelper.ts
  65. 2 0
      src/Materials/babylon.pbrMaterial.ts
  66. 1 0
      src/Materials/babylon.standardMaterial.ts
  67. 2 0
      src/Materials/babylon.uniformBuffer.ts
  68. 42 52
      src/Mesh/babylon.abstractMesh.ts
  69. 1 1
      src/Mesh/babylon.geometry.ts
  70. 7 0
      src/Mesh/babylon.mesh.ts
  71. 22 0
      src/Morph/babylon.morphTarget.ts
  72. 7 0
      src/Morph/babylon.morphTargetManager.ts
  73. 3 3
      src/Shaders/ShadersInclude/bumpVertex.fx
  74. 5 1
      src/Shaders/ShadersInclude/morphTargetsVertex.fx
  75. 4 0
      src/Shaders/ShadersInclude/morphTargetsVertexDeclaration.fx
  76. 3 0
      src/Shaders/default.vertex.fx
  77. 4 1
      src/Shaders/pbr.vertex.fx
  78. 2 1
      src/Tools/babylon.extendedGamepad.ts

+ 31 - 12
Playground/debug.html

@@ -58,7 +58,7 @@
 </head>
 
 <body>
-    <div class="navbar">
+     <div class="navbar">
         <div class="title">
             Babylon.js Playground
         </div>
@@ -73,17 +73,18 @@
 
         <div class="category">
             <div class="button" id="newButton">New<i class="fa fa-file" aria-hidden="true"></i></div>
-            <div class="button" id="clearButton">Clear<i class="fa fa-trash" aria-hidden="true"></i></div>
+            <div class="button removeOnPhone" id="clearButton">Clear<i class="fa fa-trash" aria-hidden="true"></i></div>
         </div>
 
         <div class="category">
             <div class="button" id="saveButton">Save <i class="fa fa-floppy-o" aria-hidden="true"></i></div>
-            <div class="button" id="zipButton">Zip<i class="fa fa-download" aria-hidden="true"></i></div>
+            <div class="button removeOnPhone" id="zipButton">Zip<i class="fa fa-download" aria-hidden="true"></i></div>
         </div>
 
 
-        <div class="category desktopOnly">
-            <div class="button select"><span id="currentFontSize">Font: 14</span>
+        <!--<div class="category desktopOnly">-->
+
+        <!--<div class="button select"><span id="currentFontSize">Font: 14</span>
                 <div class="toDisplay">
                     <div class="option" onclick="setFontSize(12);">12</div>
                     <div class="option" onclick="setFontSize(14);">14</div>
@@ -92,26 +93,44 @@
                     <div class="option" onclick="setFontSize(20);">20</div>
                     <div class="option" onclick="setFontSize(22);">22</div>
                 </div>
-            </div>
-            <div class="button select">Theme
+            </div>-->
+
+        <!--<div class="button select">Theme
                 <div class="toDisplay">
                     <div class="option" id="darkTheme">Dark</div>
                     <div class="option" id="lightTheme">Light</div>
                 </div>
-            </div>
-        </div>
+            </div>-->
+        <!--</div>-->
         <div class="category desktopTabletOnly">
             <div class="button select">Settings
                 <div class="toDisplay">
+                    <div class="option subSelect">Theme <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                        <div class="toDisplaySub">
+                            <div class="option" id="darkTheme">Dark</div>
+                            <div class="option" id="lightTheme">Light</div>
+                        </div>
+                    </div>
+                    <div class="option subSelect"><span id="currentFontSize">Font: 14</span><i class="fa fa-chevron-right" aria-hidden="true"></i>
+                        <div class="toDisplaySub">
+                            <div class="option" onclick="setFontSize(12);">12</div>
+                            <div class="option" onclick="setFontSize(14);">14</div>
+                            <div class="option" onclick="setFontSize(16);">16</div>
+                            <div class="option" onclick="setFontSize(18);">18</div>
+                            <div class="option" onclick="setFontSize(20);">20</div>
+                            <div class="option" onclick="setFontSize(22);">22</div>
+                        </div>
+                    </div>
                     <div class="option" id='safemodeToggle'>Safe mode <i class="fa fa-square-o" aria-hidden="true"></i></div>
                     <div class="option checked" id="editorButton">Editor <i class="fa fa-check-square" aria-hidden="true"></i>
                     </div>
                     <div class="option" id="fullscreenButton">Fullscreen</div>
-                    <div class="option" id="metadataButton">Metadata</div>
+                    <div class="option" id="formatButton">Format code</div>
                 </div>
             </div>
 
             <div class="button check uncheck" id="debugButton">Debug layer</div>
+            <div class="button" id="metadataButton">Metadata</div>
         </div>
 
 
@@ -150,11 +169,11 @@
     <div class="navbarBottom">
         <div id="statusBar"></div>
         <div class="links">
+            <div class='link'><a target='_new' href="https://www.netlify.com/">Deployed by Netlify</a></div>
             <div class='link'> <a target='_new' href="http://www.html5gamedevs.com/forum/16-babylonjs/">Forum</a></div>
             <div class='link'><a target='_new' href="https://www.babylonjs.com/sandbox">Sandbox</a></div>
-            <div class='link'><a target='_new' href="https://github.com/BabylonJS/Babylon.js/wiki">Wiki</a></div>
             <div class='link'><a target='_new' href="https://doc.babylonjs.com">Documentation</a></div>
-            <div class='link'><a target='_new' href="https://doc.babylonjs.com/playground">Playground Search</a></div>
+            <div class='link'><a target='_new' href="https://doc.babylonjs.com/playground">Search</a></div>
         </div>
     </div>
 

+ 31 - 13
Playground/index-local.html

@@ -24,7 +24,7 @@
 </head>
 
 <body>
-    <div class="navbar">
+   <div class="navbar">
         <div class="title">
             Babylon.js Playground
         </div>
@@ -39,17 +39,18 @@
 
         <div class="category">
             <div class="button" id="newButton">New<i class="fa fa-file" aria-hidden="true"></i></div>
-            <div class="button" id="clearButton">Clear<i class="fa fa-trash" aria-hidden="true"></i></div>
+            <div class="button removeOnPhone" id="clearButton">Clear<i class="fa fa-trash" aria-hidden="true"></i></div>
         </div>
 
         <div class="category">
             <div class="button" id="saveButton">Save <i class="fa fa-floppy-o" aria-hidden="true"></i></div>
-            <div class="button" id="zipButton">Zip<i class="fa fa-download" aria-hidden="true"></i></div>
+            <div class="button removeOnPhone" id="zipButton">Zip<i class="fa fa-download" aria-hidden="true"></i></div>
         </div>
 
 
-        <div class="category desktopOnly">
-            <div class="button select"><span id="currentFontSize">Font: 14</span>
+        <!--<div class="category desktopOnly">-->
+
+        <!--<div class="button select"><span id="currentFontSize">Font: 14</span>
                 <div class="toDisplay">
                     <div class="option" onclick="setFontSize(12);">12</div>
                     <div class="option" onclick="setFontSize(14);">14</div>
@@ -58,26 +59,44 @@
                     <div class="option" onclick="setFontSize(20);">20</div>
                     <div class="option" onclick="setFontSize(22);">22</div>
                 </div>
-            </div>
-            <div class="button select">Theme
+            </div>-->
+
+        <!--<div class="button select">Theme
                 <div class="toDisplay">
                     <div class="option" id="darkTheme">Dark</div>
                     <div class="option" id="lightTheme">Light</div>
                 </div>
-            </div>
-        </div>
+            </div>-->
+        <!--</div>-->
         <div class="category desktopTabletOnly">
             <div class="button select">Settings
                 <div class="toDisplay">
+                    <div class="option subSelect">Theme <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                        <div class="toDisplaySub">
+                            <div class="option" id="darkTheme">Dark</div>
+                            <div class="option" id="lightTheme">Light</div>
+                        </div>
+                    </div>
+                    <div class="option subSelect"><span id="currentFontSize">Font: 14</span><i class="fa fa-chevron-right" aria-hidden="true"></i>
+                        <div class="toDisplaySub">
+                            <div class="option" onclick="setFontSize(12);">12</div>
+                            <div class="option" onclick="setFontSize(14);">14</div>
+                            <div class="option" onclick="setFontSize(16);">16</div>
+                            <div class="option" onclick="setFontSize(18);">18</div>
+                            <div class="option" onclick="setFontSize(20);">20</div>
+                            <div class="option" onclick="setFontSize(22);">22</div>
+                        </div>
+                    </div>
                     <div class="option" id='safemodeToggle'>Safe mode <i class="fa fa-square-o" aria-hidden="true"></i></div>
                     <div class="option checked" id="editorButton">Editor <i class="fa fa-check-square" aria-hidden="true"></i>
                     </div>
                     <div class="option" id="fullscreenButton">Fullscreen</div>
-                    <div class="option" id="metadataButton">Metadata</div>
+                    <div class="option" id="formatButton">Format code</div>
                 </div>
             </div>
 
             <div class="button check uncheck" id="debugButton">Debug layer</div>
+            <div class="button" id="metadataButton">Metadata</div>
         </div>
 
 
@@ -116,11 +135,11 @@
     <div class="navbarBottom">
         <div id="statusBar"></div>
         <div class="links">
+            <div class='link'><a target='_new' href="https://www.netlify.com/">Deployed by Netlify</a></div>
             <div class='link'> <a target='_new' href="http://www.html5gamedevs.com/forum/16-babylonjs/">Forum</a></div>
             <div class='link'><a target='_new' href="https://www.babylonjs.com/sandbox">Sandbox</a></div>
-            <div class='link'><a target='_new' href="https://github.com/BabylonJS/Babylon.js/wiki">Wiki</a></div>
             <div class='link'><a target='_new' href="https://doc.babylonjs.com">Documentation</a></div>
-            <div class='link'><a target='_new' href="https://doc.babylonjs.com/playground">Playground Search</a></div>
+            <div class='link'><a target='_new' href="https://doc.babylonjs.com/playground">Search</a></div>
         </div>
     </div>
 
@@ -145,7 +164,6 @@
             </div>
         </div>
     </div>
-
     <script src="https://code.jquery.com/jquery.js"></script>
 
     <script src="js/actions.js"></script>

+ 1 - 0
Playground/index.html

@@ -124,6 +124,7 @@
                     <div class="option checked" id="editorButton">Editor <i class="fa fa-check-square" aria-hidden="true"></i>
                     </div>
                     <div class="option" id="fullscreenButton">Fullscreen</div>
+                    <div class="option" id="formatButton">Format code</div>
                 </div>
             </div>
 

+ 36 - 38
Playground/index2_5.html

@@ -18,34 +18,10 @@
     <!-- Babylon.js -->
     <script src="https://www.babylonjs.com/cannon.js"></script>
     <script src="https://www.babylonjs.com/Oimo.js"></script>
-    <script src="https://www.babylonjs.com/versions/babylon.2.5.js"></script>
-    <script src="https://www.babylonjs.com/versions/babylon.2.5.canvas2d.js"></script>
+    <script src="js/v2.5/babylon.2.5.js"></script>
+    <script src="js/v2.5/babylon.2.5.canvas2d.js"></script>
     <script src="https://www.babylonjs.com/babylon.inspector.bundle.js"></script>
 
-    <script src="https://www.babylonjs.com/lib/babylon.fireMaterial.min.js"></script>
-    <script src="https://www.babylonjs.com/lib/babylon.waterMaterial.min.js"></script>
-    <script src="https://www.babylonjs.com/lib/babylon.lavaMaterial.min.js"></script>
-    <script src="https://www.babylonjs.com/lib/babylon.normalMaterial.min.js"></script>
-    <script src="https://www.babylonjs.com/lib/babylon.skyMaterial.min.js"></script>
-    <script src="https://www.babylonjs.com/lib/babylon.triPlanarMaterial.min.js"></script>
-    <script src="https://www.babylonjs.com/lib/babylon.terrainMaterial.min.js"></script>
-    <script src="https://www.babylonjs.com/lib/babylon.gradientMaterial.min.js"></script>
-    <script src="https://www.babylonjs.com/lib/babylon.furMaterial.min.js"></script>
-    <script src="https://www.babylonjs.com/lib/babylon.gridMaterial.min.js"></script>
-    <script src="https://www.babylonjs.com/lib/babylon.shadowOnlyMaterial.min.js"></script>
-
-    <script src="https://www.babylonjs.com/lib/babylon.brickProceduralTexture.min.js"></script>
-    <script src="https://www.babylonjs.com/lib/babylon.cloudProceduralTexture.min.js"></script>
-    <script src="https://www.babylonjs.com/lib/babylon.fireProceduralTexture.min.js"></script>
-    <script src="https://www.babylonjs.com/lib/babylon.grassProceduralTexture.min.js"></script>
-    <script src="https://www.babylonjs.com/lib/babylon.marbleProceduralTexture.min.js"></script>
-    <script src="https://www.babylonjs.com/lib/babylon.roadProceduralTexture.min.js"></script>
-    <script src="https://www.babylonjs.com/lib/babylon.starfieldProceduralTexture.min.js"></script>
-    <script src="https://www.babylonjs.com/lib/babylon.woodProceduralTexture.min.js"></script>
-
-    <script src="https://www.babylonjs.com/lib/babylon.asciiArtPostProcess.min.js"></script>
-    <script src="https://www.babylonjs.com/lib/babylon.digitalRainPostProcess.min.js"></script>
-
     <script src="https://www.babylonjs.com/lib/babylon.glTFFileLoader.js"></script>
     <script src="https://www.babylonjs.com/lib/babylon.objFileLoader.js"></script>
     <script src="https://www.babylonjs.com/lib/babylon.stlFileLoader.js"></script>
@@ -55,7 +31,7 @@
 </head>
 
 <body>
-    <div class="navbar">
+      <div class="navbar">
         <div class="title">
             Babylon.js Playground
         </div>
@@ -70,17 +46,18 @@
 
         <div class="category">
             <div class="button" id="newButton">New<i class="fa fa-file" aria-hidden="true"></i></div>
-            <div class="button" id="clearButton">Clear<i class="fa fa-trash" aria-hidden="true"></i></div>
+            <div class="button removeOnPhone" id="clearButton">Clear<i class="fa fa-trash" aria-hidden="true"></i></div>
         </div>
 
         <div class="category">
             <div class="button" id="saveButton">Save <i class="fa fa-floppy-o" aria-hidden="true"></i></div>
-            <div class="button" id="zipButton">Zip<i class="fa fa-download" aria-hidden="true"></i></div>
+            <div class="button removeOnPhone" id="zipButton">Zip<i class="fa fa-download" aria-hidden="true"></i></div>
         </div>
 
 
-        <div class="category desktopOnly">
-            <div class="button select"><span id="currentFontSize">Font: 14</span>
+        <!--<div class="category desktopOnly">-->
+
+        <!--<div class="button select"><span id="currentFontSize">Font: 14</span>
                 <div class="toDisplay">
                     <div class="option" onclick="setFontSize(12);">12</div>
                     <div class="option" onclick="setFontSize(14);">14</div>
@@ -89,26 +66,44 @@
                     <div class="option" onclick="setFontSize(20);">20</div>
                     <div class="option" onclick="setFontSize(22);">22</div>
                 </div>
-            </div>
-            <div class="button select">Theme
+            </div>-->
+
+        <!--<div class="button select">Theme
                 <div class="toDisplay">
                     <div class="option" id="darkTheme">Dark</div>
                     <div class="option" id="lightTheme">Light</div>
                 </div>
-            </div>
-        </div>
+            </div>-->
+        <!--</div>-->
         <div class="category desktopTabletOnly">
             <div class="button select">Settings
                 <div class="toDisplay">
+                    <div class="option subSelect">Theme <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                        <div class="toDisplaySub">
+                            <div class="option" id="darkTheme">Dark</div>
+                            <div class="option" id="lightTheme">Light</div>
+                        </div>
+                    </div>
+                    <div class="option subSelect"><span id="currentFontSize">Font: 14</span><i class="fa fa-chevron-right" aria-hidden="true"></i>
+                        <div class="toDisplaySub">
+                            <div class="option" onclick="setFontSize(12);">12</div>
+                            <div class="option" onclick="setFontSize(14);">14</div>
+                            <div class="option" onclick="setFontSize(16);">16</div>
+                            <div class="option" onclick="setFontSize(18);">18</div>
+                            <div class="option" onclick="setFontSize(20);">20</div>
+                            <div class="option" onclick="setFontSize(22);">22</div>
+                        </div>
+                    </div>
                     <div class="option" id='safemodeToggle'>Safe mode <i class="fa fa-square-o" aria-hidden="true"></i></div>
                     <div class="option checked" id="editorButton">Editor <i class="fa fa-check-square" aria-hidden="true"></i>
                     </div>
                     <div class="option" id="fullscreenButton">Fullscreen</div>
-                    <div class="option" id="metadataButton">Metadata</div>
+                    <div class="option" id="formatButton">Format code</div>
                 </div>
             </div>
 
             <div class="button check uncheck" id="debugButton">Debug layer</div>
+            <div class="button" id="metadataButton">Metadata</div>
         </div>
 
 
@@ -147,11 +142,11 @@
     <div class="navbarBottom">
         <div id="statusBar"></div>
         <div class="links">
+            <div class='link'><a target='_new' href="https://www.netlify.com/">Deployed by Netlify</a></div>
             <div class='link'> <a target='_new' href="http://www.html5gamedevs.com/forum/16-babylonjs/">Forum</a></div>
             <div class='link'><a target='_new' href="https://www.babylonjs.com/sandbox">Sandbox</a></div>
-            <div class='link'><a target='_new' href="https://github.com/BabylonJS/Babylon.js/wiki">Wiki</a></div>
             <div class='link'><a target='_new' href="https://doc.babylonjs.com">Documentation</a></div>
-            <div class='link'><a target='_new' href="https://doc.babylonjs.com/playground">Playground Search</a></div>
+            <div class='link'><a target='_new' href="https://doc.babylonjs.com/playground">Search</a></div>
         </div>
     </div>
 
@@ -160,12 +155,15 @@
             <label for="saveFormTitle">TITLE</label>
             <div class="separator"></div>
             <input type="text" maxlength="120" id="saveFormTitle" class="save-form-title">
+
             <label for="saveFormDescription">DESCRIPTION</label>
             <div class="separator"></div>
             <textarea id="saveFormDescription" rows="4" cols="10"></textarea>
+
             <label for="saveFormTags">TAGS (separated by comma)</label>
             <div class="separator"></div>
             <textarea id="saveFormTags" rows="4" cols="10"></textarea>
+
             <div class="save-form-buttons" id="saveFormButtons">
 
                 <div id="saveFormButtonOk" class="button">OK</div>

+ 54 - 20
Playground/js/index.js

@@ -19,16 +19,19 @@
     var run = function () {
         var blockEditorChange = false;
 
-        jsEditor.onKeyDown(function (evt) {
-        });
-
-        jsEditor.onKeyUp(function (evt) {
+        var markDirty = function() {
             if (blockEditorChange) {
                 return;
             }
 
             document.getElementById("currentScript").innerHTML = "Custom";
             document.getElementById('safemodeToggle').classList.add('checked');
+
+            document.getElementById('safemodeToggle').innerHTML = 'Safe mode <i class="fa fa-check-square" aria-hidden="true"></i>';
+        }
+
+        jsEditor.onKeyUp(function (evt) {
+            markDirty();
         });
 
         var snippetUrl = "https://babylonjs-api2.azurewebsites.net/snippets";
@@ -207,12 +210,30 @@
         }
 
         var showNoMetadata = function () {
-            document.getElementById("saveFormTitle").value = '';
-            document.getElementById("saveFormTitle").readOnly = false;
-            document.getElementById("saveFormDescription").value = '';
-            document.getElementById("saveFormDescription").readOnly = false;
-            document.getElementById("saveFormTags").value = '';
-            document.getElementById("saveFormTags").readOnly = false;
+            if (currentSnippetTitle) {
+                document.getElementById("saveFormTitle").value = currentSnippetTitle;
+                document.getElementById("saveFormTitle").readOnly = true;
+            }
+            else {
+                document.getElementById("saveFormTitle").value = '';
+                document.getElementById("saveFormTitle").readOnly = false;
+            }
+            if (currentSnippetDescription) {
+                document.getElementById("saveFormDescription").value = currentSnippetDescription;
+                document.getElementById("saveFormDescription").readOnly = true;
+            }
+            else {
+                document.getElementById("saveFormDescription").value = '';
+                document.getElementById("saveFormDescription").readOnly = false;
+            }
+            if (currentSnippetTags) {
+                document.getElementById("saveFormTags").value = currentSnippetTags;
+                document.getElementById("saveFormTags").readOnly = true;
+            }
+            else {
+                document.getElementById("saveFormTags").value = '';
+                document.getElementById("saveFormTags").readOnly = false;
+            }
             document.getElementById("saveFormButtons").style.display = "block";
             document.getElementById("saveFormButtonOk").style.display = "inline-block";
             document.getElementById("saveMessage").style.display = "block";
@@ -563,6 +584,10 @@
             jsEditor.setValue(oldCode);
             setFontSize(fontSize);
 
+            jsEditor.onKeyUp(function (evt) {
+                markDirty();
+            });
+
             for (var index = 0; index < elementToTheme.length; index++) {
                 var obj = elementToTheme[index];
                 let domObjArr = document.querySelectorAll(obj);
@@ -598,6 +623,10 @@
             document.getElementById("saveLayer").style.display = "block";
         }
 
+        var formatCode = function () {
+            jsEditor.getAction('editor.action.format').run();
+        }
+
         // UI
         document.getElementById("runButton").addEventListener("click", compileAndRun);
         document.getElementById("zipButton").addEventListener("click", getZip);
@@ -609,6 +638,7 @@
         document.getElementById("metadataButton").addEventListener("click", toggleMetadata);
         document.getElementById("darkTheme").addEventListener("click", toggleTheme.bind(this, 'dark'));
         document.getElementById("lightTheme").addEventListener("click", toggleTheme.bind(this, 'light'));
+        document.getElementById("formatButton").addEventListener("click", formatCode);
 
         // Restore theme
         var theme = localStorage.getItem("bjs-playground-theme") || 'light';
@@ -678,8 +708,8 @@
 
         document.getElementById("saveButton").addEventListener("click", function () {
             if (currentSnippetTitle == null
-                && currentSnippetDescription == null
-                && currentSnippetTags == null) {
+                || currentSnippetDescription == null
+                || currentSnippetTags == null) {
 
                 document.getElementById("saveLayer").style.display = "block";
             }
@@ -729,15 +759,23 @@
                                     jsEditor.setValue(JSON.parse(snippet.jsonPayload).code.toString());
 
                                     // Check if title / descr / tags are already set
-                                    if ((snippet.name != null && snippet.name != "")
-                                        || (snippet.description != null && snippet.description != "")
-                                        || (snippet.tags != null && snippet.tags != "")) {
+                                    if (snippet.name != null && snippet.name != "") {
                                         currentSnippetTitle = snippet.name;
+                                    }
+                                    else currentSnippetTitle = null;
+
+                                    if (snippet.description != null && snippet.description != "") {
                                         currentSnippetDescription = snippet.description;
+                                    }
+                                    else currentSnippetDescription = null;
+
+                                    if (snippet.tags != null && snippet.tags != "") {
                                         currentSnippetTags = snippet.tags;
+                                    }
+                                    else currentSnippetTags = null;
 
+                                    if (currentSnippetTitle != null && currentSnippetTags != null && currentSnippetDescription) {
                                         if (document.getElementById("saveLayer")) {
-                                            var elem = document.getElementById("saveLayer");
 
                                             document.getElementById("saveFormTitle").value = currentSnippetTitle;
                                             document.getElementById("saveFormDescription").value = currentSnippetDescription;
@@ -747,10 +785,6 @@
                                         }
                                     }
                                     else {
-                                        currentSnippetTitle = null;
-                                        currentSnippetDescription = null;
-                                        currentSnippetTags = null;
-
                                         showNoMetadata();
                                     }
 

File diff ditekan karena terlalu besar
+ 10 - 0
Playground/js/v2.5/babylon.2.5.canvas2d.js


File diff ditekan karena terlalu besar
+ 38 - 0
Playground/js/v2.5/babylon.2.5.js


+ 20 - 0
Playground/textures/DemageFont.fnt

@@ -0,0 +1,20 @@
+info face="Arial" size=32 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0
+common lineHeight=32 base=26 scaleW=128 scaleH=128 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0
+page id=0 file="DemageFont.png"
+chars count=16
+char id=45   x=62    y=93    width=28    height=30    xoffset=0     yoffset=0     xadvance=28    page=0  chnl=15
+char id=48   x=0     y=0     width=30    height=30    xoffset=0     yoffset=0     xadvance=30    page=0  chnl=15
+char id=49   x=91    y=93    width=22    height=30    xoffset=0     yoffset=0     xadvance=22    page=0  chnl=15
+char id=50   x=31    y=0     width=30    height=30    xoffset=0     yoffset=0     xadvance=30    page=0  chnl=15
+char id=51   x=62    y=0     width=30    height=30    xoffset=0     yoffset=0     xadvance=30    page=0  chnl=15
+char id=52   x=93    y=0     width=30    height=30    xoffset=0     yoffset=0     xadvance=30    page=0  chnl=15
+char id=53   x=0     y=31    width=30    height=30    xoffset=0     yoffset=0     xadvance=30    page=0  chnl=15
+char id=54   x=31    y=31    width=30    height=30    xoffset=0     yoffset=0     xadvance=30    page=0  chnl=15
+char id=55   x=62    y=31    width=30    height=30    xoffset=0     yoffset=0     xadvance=30    page=0  chnl=15
+char id=56   x=93    y=31    width=30    height=30    xoffset=0     yoffset=0     xadvance=30    page=0  chnl=15
+char id=57   x=0     y=62    width=30    height=30    xoffset=0     yoffset=0     xadvance=30    page=0  chnl=15
+char id=68   x=31    y=62    width=30    height=30    xoffset=0     yoffset=0     xadvance=30    page=0  chnl=15
+char id=69   x=62    y=62    width=30    height=30    xoffset=0     yoffset=0     xadvance=30    page=0  chnl=15
+char id=70   x=93    y=62    width=30    height=30    xoffset=0     yoffset=0     xadvance=30    page=0  chnl=15
+char id=71   x=0     y=93    width=30    height=30    xoffset=0     yoffset=0     xadvance=30    page=0  chnl=15
+char id=74   x=31    y=93    width=30    height=30    xoffset=0     yoffset=0     xadvance=30    page=0  chnl=15

TEMPAT SAMPAH
Playground/textures/DemageFont.png


File diff ditekan karena terlalu besar
+ 4916 - 0
Playground/textures/HorrorBlue.3dl


File diff ditekan karena terlalu besar
+ 4916 - 0
Playground/textures/LateSunset.3dl


TEMPAT SAMPAH
Playground/textures/Logo.png


TEMPAT SAMPAH
Playground/textures/SunDiffuse.png


TEMPAT SAMPAH
Playground/textures/big_buck_bunny.mp4


TEMPAT SAMPAH
Playground/textures/candleopacity.png


TEMPAT SAMPAH
Playground/textures/co.png


TEMPAT SAMPAH
Playground/textures/country.hdr


TEMPAT SAMPAH
Playground/textures/distortion.png


TEMPAT SAMPAH
Playground/textures/environment.babylon.hdr


TEMPAT SAMPAH
Playground/textures/fire.png


TEMPAT SAMPAH
Playground/textures/floor.png


TEMPAT SAMPAH
Playground/textures/floor_bump.PNG


TEMPAT SAMPAH
Playground/textures/forest.hdr


TEMPAT SAMPAH
Playground/textures/fur.jpg


TEMPAT SAMPAH
Playground/textures/grass.png


TEMPAT SAMPAH
Playground/textures/grassn.png


TEMPAT SAMPAH
Playground/textures/heightMapTriPlanar.png


TEMPAT SAMPAH
Playground/textures/invmask.png


TEMPAT SAMPAH
Playground/textures/lensdirt.jpg


TEMPAT SAMPAH
Playground/textures/leopard_fur.JPG


TEMPAT SAMPAH
Playground/textures/mixMap.png


TEMPAT SAMPAH
Playground/textures/nba.png


TEMPAT SAMPAH
Playground/textures/night.hdr


TEMPAT SAMPAH
Playground/textures/parking.hdr


TEMPAT SAMPAH
Playground/textures/rock.png


TEMPAT SAMPAH
Playground/textures/rockn.png


TEMPAT SAMPAH
Playground/textures/roundMask.png


TEMPAT SAMPAH
Playground/textures/sand.jpg


TEMPAT SAMPAH
Playground/textures/speckles.jpg


TEMPAT SAMPAH
Playground/textures/walk.png


File diff ditekan karena terlalu besar
+ 0 - 31
dist/preview release/babylon.core.js


File diff ditekan karena terlalu besar
+ 3189 - 3183
dist/preview release/babylon.d.ts


File diff ditekan karena terlalu besar
+ 23 - 23
dist/preview release/babylon.js


+ 65 - 20
dist/preview release/babylon.max.js

@@ -22032,6 +22032,9 @@ var BABYLON;
             return this;
         };
         Effect.prototype.setMatrices = function (uniformName, matrices) {
+            if (!matrices) {
+                return;
+            }
             this._valueCache[uniformName] = null;
             this._engine.setMatrices(this.getUniform(uniformName), matrices);
             return this;
@@ -23387,6 +23390,8 @@ var BABYLON;
             if (this._buffer) {
                 return; // nothing to do
             }
+            // See spec, alignment must be filled as a vec4
+            this._fillAlignment(4);
             this._bufferData = new Float32Array(this._data);
             if (this._dynamic) {
                 this._buffer = this._engine.createDynamicUniformBuffer(this._bufferData);
@@ -26075,7 +26080,7 @@ var BABYLON;
             return this._indexBuffer;
         };
         Geometry.prototype._releaseVertexArrayObject = function (effect) {
-            if (!effect) {
+            if (!effect || !this._vertexArrayObjects) {
                 return;
             }
             if (this._vertexArrayObjects[effect.key]) {
@@ -31189,10 +31194,10 @@ var BABYLON;
                 _this._collisionTriggered = false;
             };
             if (!target) {
-                _this.target = BABYLON.Vector3.Zero();
+                _this._target = BABYLON.Vector3.Zero();
             }
             else {
-                _this.target = target;
+                _this._target = target;
             }
             _this.alpha = alpha;
             _this.beta = beta;
@@ -31202,6 +31207,16 @@ var BABYLON;
             _this.inputs.addKeyboard().addMouseWheel().addPointers();
             return _this;
         }
+        Object.defineProperty(ArcRotateCamera.prototype, "target", {
+            get: function () {
+                return this._target;
+            },
+            set: function (value) {
+                this.setTarget(value);
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(ArcRotateCamera.prototype, "angularSensibilityX", {
             //-- begin properties for backward compatibility for inputs       
             get: function () {
@@ -31336,7 +31351,7 @@ var BABYLON;
         // Cache
         ArcRotateCamera.prototype._initCache = function () {
             _super.prototype._initCache.call(this);
-            this._cache.target = new BABYLON.Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
+            this._cache._target = new BABYLON.Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
             this._cache.alpha = undefined;
             this._cache.beta = undefined;
             this._cache.radius = undefined;
@@ -31346,7 +31361,7 @@ var BABYLON;
             if (!ignoreParentClass) {
                 _super.prototype._updateCache.call(this);
             }
-            this._cache.target.copyFrom(this._getTargetPosition());
+            this._cache._target.copyFrom(this._getTargetPosition());
             this._cache.alpha = this.alpha;
             this._cache.beta = this.beta;
             this._cache.radius = this.radius;
@@ -31355,15 +31370,20 @@ var BABYLON;
         ArcRotateCamera.prototype._getTargetPosition = function () {
             if (this._targetHost && this._targetHost.getAbsolutePosition) {
                 var pos = this._targetHost.getAbsolutePosition();
-                return this._targetBoundingCenter ? pos.add(this._targetBoundingCenter) : pos;
+                if (this._targetBoundingCenter) {
+                    pos.addToRef(this._targetBoundingCenter, this._target);
+                }
+                else {
+                    this._target.copyFrom(pos);
+                }
             }
-            return this.target;
+            return this._target;
         };
         // Synchronized
         ArcRotateCamera.prototype._isSynchronizedViewMatrix = function () {
             if (!_super.prototype._isSynchronizedViewMatrix.call(this))
                 return false;
-            return this._cache.target.equals(this.target)
+            return this._cache._target.equals(this._target)
                 && this._cache.alpha === this.alpha
                 && this._cache.beta === this.beta
                 && this._cache.radius === this.radius
@@ -31435,8 +31455,8 @@ var BABYLON;
                 if (!this.panningAxis.y) {
                     this._transformedDirection.y = 0;
                 }
-                if (!this.target.getAbsolutePosition) {
-                    this.target.addInPlace(this._transformedDirection);
+                if (!this._targetHost) {
+                    this._target.addInPlace(this._transformedDirection);
                 }
             }
             // Limits
@@ -31507,14 +31527,15 @@ var BABYLON;
                     this._targetBoundingCenter = null;
                 }
                 this._targetHost = target;
-                this.target = this._getTargetPosition();
+                this._target = this._getTargetPosition();
             }
             else {
                 var newTarget = target;
-                if (!allowSamePosition && this._getTargetPosition().equals(newTarget)) {
+                var currentTarget = this._getTargetPosition();
+                if (currentTarget && !allowSamePosition && currentTarget.equals(newTarget)) {
                     return;
                 }
-                this.target = newTarget;
+                this._target = newTarget;
                 this._targetBoundingCenter = null;
             }
             this.rebuildAnglesAndRadius();
@@ -31579,7 +31600,7 @@ var BABYLON;
                 meshesOrMinMaxVector = meshesOrMinMaxVectorAndDistance;
                 distance = meshesOrMinMaxVectorAndDistance.distance;
             }
-            this.target = BABYLON.Mesh.Center(meshesOrMinMaxVector);
+            this._target = BABYLON.Mesh.Center(meshesOrMinMaxVector);
             if (!doNotUpdateMaxZ) {
                 this.maxZ = distance * 2;
             }
@@ -31601,7 +31622,7 @@ var BABYLON;
                     alphaShift = this._cameraRigParams.stereoHalfAngle * (cameraIndex === 0 ? -1 : 1);
                     break;
             }
-            var rigCam = new ArcRotateCamera(name, this.alpha + alphaShift, this.beta, this.radius, this.target, this.getScene());
+            var rigCam = new ArcRotateCamera(name, this.alpha + alphaShift, this.beta, this.radius, this._target, this.getScene());
             rigCam._cameraRigParams = {};
             return rigCam;
         };
@@ -31648,8 +31669,8 @@ var BABYLON;
         BABYLON.serialize()
     ], ArcRotateCamera.prototype, "radius", void 0);
     __decorate([
-        BABYLON.serializeAsVector3()
-    ], ArcRotateCamera.prototype, "target", void 0);
+        BABYLON.serializeAsVector3("target")
+    ], ArcRotateCamera.prototype, "_target", void 0);
     __decorate([
         BABYLON.serialize()
     ], ArcRotateCamera.prototype, "inertialAlphaOffset", void 0);
@@ -46185,6 +46206,7 @@ var BABYLON;
         */
         OculusTouchController.prototype.handleButtonChange = function (buttonIdx, state, changes) {
             var notifyObject = state; //{ state: state, changes: changes };
+            var triggerDirection = this.hand === 'right' ? -1 : 1;
             switch (buttonIdx) {
                 case 0:
                     this.onPadStateChangedObservable.notifyObservers(notifyObject);
@@ -46199,7 +46221,7 @@ var BABYLON;
                     return;
                 case 2:
                     if (this._defaultModel) {
-                        (this._defaultModel.getChildren()[4]).position.x = notifyObject.value * 0.0035;
+                        (this._defaultModel.getChildren()[4]).position.x = triggerDirection * notifyObject.value * 0.0035;
                     }
                     this.onSecondaryTriggerStateChangedObservable.notifyObservers(notifyObject);
                     return;
@@ -58739,6 +58761,29 @@ var BABYLON;
             });
             return _this;
         }
+        Object.defineProperty(WebVRFreeCamera.prototype, "onControllersAttached", {
+            set: function (callback) {
+                this._onControllersAttached = callback;
+                // after setting - if the controllers are already set, execute the callback.
+                if (this.controllers.length >= 2) {
+                    callback(this.controllers);
+                }
+            },
+            enumerable: true,
+            configurable: true
+        });
+        WebVRFreeCamera.prototype.getLeftCamera = function () {
+            return this._rigCameras[0];
+        };
+        WebVRFreeCamera.prototype.getRightCamera = function () {
+            return this._rigCameras[1];
+        };
+        WebVRFreeCamera.prototype.getLeftTarget = function () {
+            return this._rigCameras[0].getTarget();
+        };
+        WebVRFreeCamera.prototype.getRightTarget = function () {
+            return this._rigCameras[1].getTarget();
+        };
         WebVRFreeCamera.prototype._checkInputs = function () {
             if (this._vrEnabled) {
                 if (this._specsVersion === 1.1) {
@@ -58910,8 +58955,8 @@ var BABYLON;
                         //add to the controllers array
                         _this.controllers.push(webVrController);
                         //did we find enough controllers? Great! let the developer know.
-                        if (_this.onControllersAttached && _this.controllers.length === 2) {
-                            _this.onControllersAttached(_this.controllers);
+                        if (_this._onControllersAttached && _this.controllers.length >= 2) {
+                            _this._onControllersAttached(_this.controllers);
                         }
                     }
                 }

File diff ditekan karena terlalu besar
+ 3189 - 3183
dist/preview release/babylon.module.d.ts


File diff ditekan karena terlalu besar
+ 0 - 41
dist/preview release/babylon.noworker.js


File diff ditekan karena terlalu besar
+ 23 - 23
dist/preview release/babylon.worker.js


File diff ditekan karena terlalu besar
+ 249 - 249
dist/preview release/inspector/babylon.inspector.bundle.js


+ 36 - 36
dist/preview release/inspector/babylon.inspector.d.ts

@@ -113,7 +113,7 @@ declare module INSPECTOR {
             type: typeof BABYLON.BaseTexture;
         };
         'FontTexture': {
-            type: typeof BABYLON.FontTexture;
+            type: any;
         };
         'Sound': {
             type: typeof BABYLON.Sound;
@@ -142,23 +142,23 @@ declare module INSPECTOR {
             format: (mat: BABYLON.StandardMaterial) => string;
         };
         'PrimitiveAlignment': {
-            type: typeof BABYLON.PrimitiveAlignment;
+            type: any;
             properties: string[];
         };
         'PrimitiveThickness': {
-            type: typeof BABYLON.PrimitiveThickness;
+            type: any;
             properties: string[];
         };
         'BoundingInfo2D': {
-            type: typeof BABYLON.BoundingInfo2D;
+            type: any;
             properties: string[];
         };
         'SolidColorBrush2D': {
-            type: typeof BABYLON.SolidColorBrush2D;
+            type: any;
             properties: string[];
         };
         'GradientColorBrush2D': {
-            type: typeof BABYLON.GradientColorBrush2D;
+            type: any;
             properties: string[];
         };
         'PBRMaterial': {
@@ -166,94 +166,94 @@ declare module INSPECTOR {
             properties: string[];
         };
         'Canvas2D': {
-            type: typeof BABYLON.Canvas2D;
+            type: any;
         };
         'Canvas2DEngineBoundData': {
-            type: typeof BABYLON.Canvas2DEngineBoundData;
+            type: any;
         };
         'Ellipse2D': {
-            type: typeof BABYLON.Ellipse2D;
+            type: any;
         };
         'Ellipse2DInstanceData': {
-            type: typeof BABYLON.Ellipse2DInstanceData;
+            type: any;
         };
         'Ellipse2DRenderCache': {
-            type: typeof BABYLON.Ellipse2DRenderCache;
+            type: any;
         };
         'Group2D': {
-            type: typeof BABYLON.Group2D;
+            type: any;
         };
         'IntersectInfo2D': {
-            type: typeof BABYLON.IntersectInfo2D;
+            type: any;
         };
         'Lines2D': {
-            type: typeof BABYLON.Lines2D;
+            type: any;
         };
         'Lines2DInstanceData': {
-            type: typeof BABYLON.Lines2DInstanceData;
+            type: any;
         };
         'Lines2DRenderCache': {
-            type: typeof BABYLON.Lines2DRenderCache;
+            type: any;
         };
         'PrepareRender2DContext': {
-            type: typeof BABYLON.PrepareRender2DContext;
+            type: any;
         };
         'Prim2DBase': {
-            type: typeof BABYLON.Prim2DBase;
+            type: any;
         };
         'Prim2DClassInfo': {
-            type: typeof BABYLON.Prim2DClassInfo;
+            type: any;
         };
         'Prim2DPropInfo': {
-            type: typeof BABYLON.Prim2DPropInfo;
+            type: any;
         };
         'Rectangle2D': {
-            type: typeof BABYLON.Rectangle2D;
+            type: any;
         };
         'Rectangle2DInstanceData': {
-            type: typeof BABYLON.Rectangle2DInstanceData;
+            type: any;
         };
         'Rectangle2DRenderCache': {
-            type: typeof BABYLON.Rectangle2DRenderCache;
+            type: any;
         };
         'Render2DContext': {
-            type: typeof BABYLON.Render2DContext;
+            type: any;
         };
         'RenderablePrim2D': {
-            type: typeof BABYLON.RenderablePrim2D;
+            type: any;
         };
         'ScreenSpaceCanvas2D': {
-            type: typeof BABYLON.ScreenSpaceCanvas2D;
+            type: any;
         };
         'Shape2D': {
-            type: typeof BABYLON.Shape2D;
+            type: any;
         };
         'Shape2DInstanceData': {
-            type: typeof BABYLON.Shape2DInstanceData;
+            type: any;
         };
         'Sprite2D': {
-            type: typeof BABYLON.Sprite2D;
+            type: any;
         };
         'Sprite2DInstanceData': {
-            type: typeof BABYLON.Sprite2DInstanceData;
+            type: any;
         };
         'Sprite2DRenderCache': {
-            type: typeof BABYLON.Sprite2DRenderCache;
+            type: any;
         };
         'Text2D': {
-            type: typeof BABYLON.Text2D;
+            type: any;
         };
         'Text2DInstanceData': {
-            type: typeof BABYLON.Text2DInstanceData;
+            type: any;
         };
         'Text2DRenderCache': {
-            type: typeof BABYLON.Text2DRenderCache;
+            type: any;
         };
         'WorldSpaceCanvas2D': {
-            type: typeof BABYLON.WorldSpaceCanvas2D;
+            type: any;
         };
         'WorldSpaceCanvas2DNode': {
-            type: typeof BABYLON.WorldSpaceCanvas2DNode;
+            type: any;
         };
     };
 }

File diff ditekan karena terlalu besar
+ 1 - 1
dist/preview release/inspector/babylon.inspector.min.js


File diff ditekan karena terlalu besar
+ 2 - 2
dist/preview release/loaders/babylon.glTF1FileLoader.min.js


File diff ditekan karena terlalu besar
+ 1 - 1
dist/preview release/loaders/babylon.glTF2FileLoader.min.js


File diff ditekan karena terlalu besar
+ 2 - 2
dist/preview release/loaders/babylon.glTFFileLoader.min.js


+ 9 - 3
dist/preview release/loaders/babylon.stlFileLoader.js

@@ -11,13 +11,18 @@ var BABYLON;
         }
         STLFileLoader.prototype.importMesh = function (meshesNames, scene, data, rootUrl, meshes, particleSystems, skeletons) {
             var matches;
+            if (typeof data !== "string") {
+                BABYLON.Tools.Error("STL format not recognized. Ensure it's ASCII formatted");
+                return false;
+            }
             while (matches = this.solidPattern.exec(data)) {
                 var meshName = matches[1];
                 var meshNameFromEnd = matches[3];
                 if (meshName != meshNameFromEnd) {
-                    console.log("error in stl, solid name != endsolid name");
+                    BABYLON.Tools.Error("Error in STL, solid name != endsolid name");
+                    return false;
                 }
-                //check meshesNames
+                // check meshesNames
                 if (meshesNames && meshName) {
                     if (meshesNames instanceof Array) {
                         if (!meshesNames.indexOf(meshName)) {
@@ -30,10 +35,11 @@ var BABYLON;
                         }
                     }
                 }
-                //stl mesh name can be empty as well
+                // stl mesh name can be empty as well
                 meshName = meshName || "stlmesh";
                 var babylonMesh = new BABYLON.Mesh(meshName, scene);
                 this.parseSolid(babylonMesh, matches[2]);
+                meshes.push(babylonMesh);
             }
             return true;
         };

File diff ditekan karena terlalu besar
+ 1 - 1
dist/preview release/loaders/babylon.stlFileLoader.min.js


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

@@ -8,6 +8,7 @@
  - Support for Morph Targets. [More info here](http://doc.babylonjs.com/tutorials/how_to_use_morphtargets) ([deltakosh](https://github.com/deltakosh))
  - Added support for Exponential Shadow maps to replace Variance Shadow maps. [more info here](http://www.babylonjs-playground.com/debug.html#1CXNXC#3) - [Demo](http://www.babylonjs.com/Demos/AdvancedShadows/) - [Demo](http://www.babylonjs-playground.com/#1CXNXC#4) ([deltakosh](https://github.com/deltakosh))
  - Support for [Vertex Array Objects](https://www.opengl.org/registry/specs/ARB/vertex_array_object.txt) ([deltakosh](https://github.com/deltakosh))
+ - Support for [Uniform Buffer Objects](https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.16) ([CraigFeldspar](https://github.com/CraigFeldspar))
  - Support for multisample render targets. [Demo](http://www.babylonjs-playground.com/#12MKMN) ([deltakosh](https://github.com/deltakosh))
  - New Unity 5 Editor Toolkit. Complete pipeline integration [Doc](TODO) - ([MackeyK24](https://github.com/MackeyK24))
  - New DebugLayer. [Doc](TODO) - ([temechon](https://github.com/temechon))

+ 11 - 3
loaders/src/STL/babylon.stlFileLoader.ts

@@ -14,14 +14,20 @@ module BABYLON {
         public importMesh(meshesNames: any, scene: Scene, data: any, rootUrl: string, meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]): boolean {
             var matches;
 
+            if (typeof data !== "string") {
+                Tools.Error("STL format not recognized. Ensure it's ASCII formatted");
+                return false;
+            }
+
             while (matches = this.solidPattern.exec(data)) {
                 var meshName = matches[1];
                 var meshNameFromEnd = matches[3];
                 if (meshName != meshNameFromEnd) {
-                    console.log("error in stl, solid name != endsolid name");
+                    Tools.Error("Error in STL, solid name != endsolid name");
+                    return false;
                 }
 
-                //check meshesNames
+                // check meshesNames
                 if (meshesNames && meshName) {
                     if (meshesNames instanceof Array) {
                         if (!meshesNames.indexOf(meshName)) {
@@ -34,10 +40,12 @@ module BABYLON {
                     }
                 }
 
-                //stl mesh name can be empty as well
+                // stl mesh name can be empty as well
                 meshName = meshName || "stlmesh";
                 var babylonMesh = new Mesh(meshName, scene);
                 this.parseSolid(babylonMesh, matches[2]);
+
+                meshes.push(babylonMesh);
             }
 
             return true;

+ 80 - 7
loaders/src/glTF/2.0/babylon.glTFLoader.ts

@@ -508,12 +508,14 @@ module BABYLON.GLTF2 {
         var indexStarts = [];
         var indexCounts = [];
 
+        var morphTargetManager = new BABYLON.MorphTargetManager();
+
         // Positions, normals and UVs
-        for (var index = 0; index < mesh.primitives.length; index++) {
+        for (var primitiveIndex = 0; primitiveIndex < mesh.primitives.length; primitiveIndex++) {
             // Temporary vertex data
             var tempVertexData = new VertexData();
 
-            var primitive = mesh.primitives[index];
+            var primitive = mesh.primitives[primitiveIndex];
             if (primitive.mode !== EMeshPrimitiveMode.TRIANGLES) {
                 // continue;
             }
@@ -579,8 +581,8 @@ module BABYLON.GLTF2 {
             else {
                 // Set indices on the fly
                 var indices: number[] = [];
-                for (var j = 0; j < tempVertexData.positions.length / 3; j++) {
-                    indices.push(j);
+                for (var index = 0; index < tempVertexData.positions.length / 3; index++) {
+                    indices.push(index);
                 }
 
                 tempVertexData.indices = new Int32Array(indices);
@@ -594,6 +596,72 @@ module BABYLON.GLTF2 {
             var material = getMaterial(runtime, primitive.material);
             multiMat.subMaterials.push(material);
 
+            // Morph Targets
+            if (primitive.targets !== undefined) {
+                for (var targetsIndex = 0; targetsIndex < primitive.targets.length; targetsIndex++) {
+                    var target = primitive.targets[targetsIndex];
+
+                    var weight = 0.0;
+                    if (node.weights !== undefined) {
+                        weight = node.weights[targetsIndex];
+                    }
+                    else if (mesh.weights !== undefined) {
+                        weight = mesh.weights[targetsIndex];
+                    }
+
+                    var morph = new BABYLON.MorphTarget("morph" + targetsIndex, weight);
+
+                    for (var semantic in target) {
+                        // Link accessor and buffer view
+                        accessor = runtime.gltf.accessors[target[semantic]];
+                        buffer = GLTFUtils.GetBufferFromAccessor(runtime, accessor);
+
+                        if (accessor.name !== undefined) {
+                            morph.name = accessor.name;
+                        }
+
+                        // glTF stores morph target information as deltas
+                        // while babylon.js expects the final data.
+                        // As a result we have to add the original data to the delta to calculate
+                        // the final data.
+                        if (semantic === "NORMAL") {
+                            for (var bufferIndex = 0; bufferIndex < buffer.length; bufferIndex++) {
+                                buffer[bufferIndex] += (<Float32Array>vertexData.normals)[bufferIndex];
+                            }
+                            morph.setNormals(buffer);
+                        }
+                        else if (semantic === "POSITION") {
+                            for (var bufferIndex = 0; bufferIndex < buffer.length; bufferIndex++) {
+                                buffer[bufferIndex] += (<Float32Array>vertexData.positions)[bufferIndex];
+                            }
+                            morph.setPositions(buffer);
+                        }
+                        else if (semantic === "TANGENT") {
+                            // Tangent data for morph targets is stored as xyz delta.
+                            // The vertexData.tangent is stored as xyzw.
+                            // So we need to skip every fourth vertexData.tangent.
+                            for (var bufferIndex = 0, tangentsIndex = 0; bufferIndex < buffer.length; bufferIndex++, tangentsIndex++) {
+                                buffer[bufferIndex] += (<Float32Array>vertexData.tangents)[tangentsIndex];
+                                if ((bufferIndex + 1) % 3 == 0) {
+                                    tangentsIndex++;
+                                }
+                            }
+                            morph.setTangents(buffer);
+                        }
+                        else {
+                            Tools.Warn("Ignoring unrecognized semantic '" + semantic + "'");
+                        }
+                    }
+                    
+                    if (morph.getPositions() !== undefined) {
+                        morphTargetManager.addTarget(morph);
+                    }
+                    else {
+                        Tools.Warn("Not adding morph target '" + morph.name + "' because it has no position data");
+                    }
+                }
+            }
+
             // Update vertices start and index start
             verticesStarts.push(verticesStarts.length === 0 ? 0 : verticesStarts[verticesStarts.length - 1] + verticesCounts[verticesCounts.length - 2]);
             indexStarts.push(indexStarts.length === 0 ? 0 : indexStarts[indexStarts.length - 1] + indexCounts[indexCounts.length - 2]);
@@ -603,14 +671,19 @@ module BABYLON.GLTF2 {
         geometry.setAllVerticesData(vertexData, false);
         babylonMesh.computeWorldMatrix(true);
 
+        // Set morph target manager after all vertices data has been processed
+        if (morphTargetManager !== undefined && morphTargetManager.numInfluencers > 0) {
+            babylonMesh.morphTargetManager = morphTargetManager;
+        }
+
         // Apply submeshes
         babylonMesh.subMeshes = [];
-        for (var index = 0; index < mesh.primitives.length; index++) {
-            if (mesh.primitives[index].mode !== EMeshPrimitiveMode.TRIANGLES) {
+        for (var primitiveIndex = 0; primitiveIndex < mesh.primitives.length; primitiveIndex++) {
+            if (mesh.primitives[primitiveIndex].mode !== EMeshPrimitiveMode.TRIANGLES) {
                 //continue;
             }
 
-            var subMesh = new SubMesh(index, verticesStarts[index], verticesCounts[index], indexStarts[index], indexCounts[index], babylonMesh, babylonMesh, true);
+            var subMesh = new SubMesh(primitiveIndex, verticesStarts[primitiveIndex], verticesCounts[primitiveIndex], indexStarts[primitiveIndex], indexCounts[primitiveIndex], babylonMesh, babylonMesh, true);
         }
 
         // Finish

+ 1 - 1
loaders/src/glTF/2.0/babylon.glTFLoaderInterfaces.ts

@@ -193,7 +193,7 @@ module BABYLON.GLTF2 {
         indices?: number;
         material?: number;
         mode?: EMeshPrimitiveMode;
-        targets?: number[];
+        targets?: [ { [name: string]: number } ];
     }
 
     export interface IGLTFMesh extends IGLTFChildRootProperty {

+ 52 - 31
serializers/src/OBJ/babylon.objSerializer.ts

@@ -1,50 +1,71 @@
 /// <reference path="../../../dist/preview release/babylon.d.ts"/>
 
 module BABYLON {
- export class OBJExport {
-        //Exports the geometry of a Mesh in .OBJ file format (text)
-        public static OBJ(mesh: Mesh, materials?: boolean, matlibname?: string): string {
+    export class OBJExport {
+        //Exports the geometrys of a Mesh array in .OBJ file format (text)
+        public static OBJ(mesh: Mesh[], materials?: boolean, matlibname?: string, globalposition?: boolean): string {
             var output = [];
-            var g = mesh.geometry;
-            var trunkVerts = g.getVerticesData('position');
-            var trunkNormals = g.getVerticesData('normal');
-            var trunkUV = g.getVerticesData('uv');
-            var trunkFaces = g.getIndices();
+            var v = 1;
             if (materials) {
                 if (!matlibname) {
                     matlibname = 'mat';
                 }
                 output.push("mtllib " + matlibname + ".mtl");
             }
-            for (var i = 0; i < trunkVerts.length; i += 3) {
-                output.push("v " + trunkVerts[i] + " " + trunkVerts[i + 1] + " " + trunkVerts[i + 2]);
-            }
-            for (i = 0; i < trunkNormals.length; i += 3) {
-                output.push("vn " + trunkNormals[i] + " " + trunkNormals[i + 1] + " " + trunkNormals[i + 2]);
-            }
-            for (i = 0; i < trunkUV.length; i += 2) {
-                output.push("vt " + trunkUV[i] + " " + trunkUV[i + 1]);
-            }
+            for (var j = 0; j < mesh.length; j++) {
+                output.push("g object" + j);
+                output.push("o object_" + j);
 
-            //TODO: submeshes (groups)
-            //TODO: smoothing groups (s 1, s off)
+                //Uses the position of the item in the scene, to the file (this back to normal in the end)
+                if (globalposition) {
+                    var newMatrix = BABYLON.Matrix.Translation(mesh[j].position.x, mesh[j].position.y, mesh[j].position.z);
+                    var lastMatrix = BABYLON.Matrix.Translation(-(mesh[j].position.x), -(mesh[j].position.y), -(mesh[j].position.z));
+                    mesh[j].bakeTransformIntoVertices(newMatrix);
+                }
 
-            output.push("g gr1");
-            if (materials) {
-                output.push("usemtl mat1");
-            }
-            for (i = 0; i < trunkFaces.length; i += 3) {
-                output.push(
-                    "f " + (trunkFaces[i + 2] + 1) + "/" + (trunkFaces[i + 2] + 1) + "/" + (trunkFaces[i + 2] + 1) +
-                    " " + (trunkFaces[i + 1] + 1) + "/" + (trunkFaces[i + 1] + 1) + "/" + (trunkFaces[i + 1] + 1) +
-                    " " + (trunkFaces[i] + 1) + "/" + (trunkFaces[i] + 1) + "/" + (trunkFaces[i] + 1)
-                );
+                //TODO: submeshes (groups)
+                //TODO: smoothing groups (s 1, s off);
+                if (materials) {
+                    output.push("usemtl " + mesh[j].material.id);
+                }
+                var g = mesh[j].geometry;
+                var trunkVerts = g.getVerticesData('position');
+                var trunkNormals = g.getVerticesData('normal');
+                var trunkUV = g.getVerticesData('uv');
+                var trunkFaces = g.getIndices();
+                var curV = 0;
+
+                for (var i = 0; i < trunkVerts.length; i += 3) {
+                    output.push("v " + trunkVerts[i] + " " + trunkVerts[i + 1] + " " + trunkVerts[i + 2]);
+                    curV++;
+                }
+
+                for (i = 0; i < trunkNormals.length; i += 3) {
+                    output.push("vn " + trunkNormals[i] + " " + trunkNormals[i + 1] + " " + trunkNormals[i + 2]);
+                }
+
+                for (i = 0; i < trunkUV.length; i += 2) {
+                    output.push("vt " + trunkUV[i] + " " + trunkUV[i + 1]);
+                }
+
+                for (i = 0; i < trunkFaces.length; i += 3) {
+                    output.push(
+                        "f " + (trunkFaces[i + 2] + v) + "/" + (trunkFaces[i + 2] + v) + "/" + (trunkFaces[i + 2] + v) +
+                        " " + (trunkFaces[i + 1] + v) + "/" + (trunkFaces[i + 1] + v) + "/" + (trunkFaces[i + 1] + v) +
+                        " " + (trunkFaces[i] + v) + "/" + (trunkFaces[i] + v) + "/" + (trunkFaces[i] + v)
+                    );
+                }
+                //back de previous matrix, to not change the original mesh in the scene
+                if (globalposition) {
+                    mesh[j].bakeTransformIntoVertices(lastMatrix);
+                }
+                v += curV;
             }
             var text = output.join("\n");
             return (text);
         }
-
         //Exports the material(s) of a mesh in .MTL file format (text)
+        //TODO: Export the materials of mesh array
         public static MTL(mesh: Mesh): string {
             var output = [];
             var m = <StandardMaterial>mesh.material;
@@ -100,4 +121,4 @@ module BABYLON {
             return (text);
         }
     }
-}
+}

+ 27 - 3
src/Cameras/VR/babylon.webVRCamera.ts

@@ -61,7 +61,7 @@ module BABYLON {
         public deviceScaleFactor: number = 1;
 
         public controllers: Array<WebVRController> = [];
-        public onControllersAttached: (controllers: Array<WebVRController>) => void;
+        private _onControllersAttached: (controllers: Array<WebVRController>) => void;
 
         public rigParenting: boolean = true; // should the rig cameras be used as parent instead of this camera.
 
@@ -178,6 +178,30 @@ module BABYLON {
             });
         }
 
+        public set onControllersAttached(callback: (controllers: Array<WebVRController>) => void) {
+            this._onControllersAttached = callback;
+            // after setting - if the controllers are already set, execute the callback.
+            if (this.controllers.length >= 2) {
+                callback(this.controllers);
+            }
+        }
+
+        public getLeftCamera() {
+            return (<FreeCamera>this._rigCameras[0]);
+        }
+
+        public getRightCamera() {
+            return (<FreeCamera>this._rigCameras[1]);
+        }
+
+        public getLeftTarget() {
+            return (<TargetCamera>this._rigCameras[0]).getTarget();
+        }
+
+        public getRightTarget() {
+            return (<TargetCamera>this._rigCameras[1]).getTarget();
+        }
+
         public _checkInputs(): void {
             if (this._vrEnabled) {
                 if (this._specsVersion === 1.1) {
@@ -377,8 +401,8 @@ module BABYLON {
                         this.controllers.push(webVrController);
 
                         //did we find enough controllers? Great! let the developer know.
-                        if (this.onControllersAttached && this.controllers.length === 2) {
-                            this.onControllersAttached(this.controllers);
+                        if (this._onControllersAttached && this.controllers.length >= 2) {
+                            this._onControllersAttached(this.controllers);
                         }
                     }
                 }

+ 30 - 18
src/Cameras/babylon.arcRotateCamera.ts

@@ -12,10 +12,17 @@ module BABYLON {
         @serialize()
         public radius: number;
 
-        @serializeAsVector3()
-        public target: Vector3;
+        @serializeAsVector3("target")
+        private _target: Vector3;
         private _targetHost: AbstractMesh;
 
+        public get target(): Vector3 {
+            return this._target;
+        }
+        public set target(value: Vector3) {
+            this.setTarget(value);
+        }
+
         @serialize()
         public inertialAlphaOffset = 0;
 
@@ -204,9 +211,9 @@ module BABYLON {
             super(name, Vector3.Zero(), scene);
 
             if (!target) {
-                this.target = Vector3.Zero();
+                this._target = Vector3.Zero();
             } else {
-                this.target = target;
+                this._target = target;
             }
 
             this.alpha = alpha;
@@ -221,7 +228,7 @@ module BABYLON {
         // Cache
         public _initCache(): void {
             super._initCache();
-            this._cache.target = new Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
+            this._cache._target = new Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
             this._cache.alpha = undefined;
             this._cache.beta = undefined;
             this._cache.radius = undefined;
@@ -233,7 +240,7 @@ module BABYLON {
                 super._updateCache();
             }
 
-            this._cache.target.copyFrom(this._getTargetPosition());
+            this._cache._target.copyFrom(this._getTargetPosition());
             this._cache.alpha = this.alpha;
             this._cache.beta = this.beta;
             this._cache.radius = this.radius;
@@ -241,12 +248,16 @@ module BABYLON {
         }
 
         private _getTargetPosition(): Vector3 {
-            if (this._targetHost && (<any>this._targetHost).getAbsolutePosition) {
-                var pos : Vector3 = (<any>this._targetHost).getAbsolutePosition();
-                return this._targetBoundingCenter ? pos.add(this._targetBoundingCenter) : pos;
+            if (this._targetHost && this._targetHost.getAbsolutePosition) {
+                var pos : Vector3 = this._targetHost.getAbsolutePosition();
+                if (this._targetBoundingCenter) {
+                    pos.addToRef(this._targetBoundingCenter, this._target);
+                } else {
+                    this._target.copyFrom(pos);
+                }
             }
 
-            return this.target;
+            return this._target;
         }
 
         // Synchronized
@@ -254,7 +265,7 @@ module BABYLON {
             if (!super._isSynchronizedViewMatrix())
                 return false;
 
-            return this._cache.target.equals(this.target)
+            return this._cache._target.equals(this._target)
                 && this._cache.alpha === this.alpha
                 && this._cache.beta === this.beta
                 && this._cache.radius === this.radius
@@ -337,8 +348,8 @@ module BABYLON {
                     this._transformedDirection.y = 0;
                 }
 
-                if (!(<any>this.target).getAbsolutePosition) {
-                    this.target.addInPlace(this._transformedDirection);
+                if (!this._targetHost) {
+                    this._target.addInPlace(this._transformedDirection);
                 }                
             }
 
@@ -419,13 +430,14 @@ module BABYLON {
                     this._targetBoundingCenter = null;
                 }
                 this._targetHost = <AbstractMesh>target;
-                this.target = this._getTargetPosition();
+                this._target = this._getTargetPosition();
             } else {
                 var newTarget = <Vector3>target;
-                if (!allowSamePosition && this._getTargetPosition().equals(newTarget)) {
+                var currentTarget = this._getTargetPosition();
+                if (currentTarget && !allowSamePosition && currentTarget.equals(newTarget)) {
                    return;
                 }
-                this.target = newTarget;
+                this._target = newTarget;
                 this._targetBoundingCenter = null;
             }
 
@@ -542,7 +554,7 @@ module BABYLON {
                 distance = meshesOrMinMaxVectorAndDistance.distance;
             }
 
-            this.target = Mesh.Center(meshesOrMinMaxVector);
+            this._target = Mesh.Center(meshesOrMinMaxVector);
 
             if (!doNotUpdateMaxZ) {
                 this.maxZ = distance * 2;
@@ -566,7 +578,7 @@ module BABYLON {
                     alphaShift = this._cameraRigParams.stereoHalfAngle * (cameraIndex === 0 ? -1 : 1);
                     break;
            }
-            var rigCam = new ArcRotateCamera(name, this.alpha + alphaShift, this.beta, this.radius, this.target, this.getScene());
+            var rigCam = new ArcRotateCamera(name, this.alpha + alphaShift, this.beta, this.radius, this._target, this.getScene());
             rigCam._cameraRigParams = {};
             return rigCam;
         }

+ 4 - 0
src/Materials/babylon.effect.ts

@@ -752,6 +752,10 @@
         }
 
         public setMatrices(uniformName: string, matrices: Float32Array): Effect {
+            if (!matrices) {
+                return;
+            }
+
             this._valueCache[uniformName] = null;
             this._engine.setMatrices(this.getUniform(uniformName), matrices);
 

+ 7 - 0
src/Materials/babylon.materialHelper.ts

@@ -72,10 +72,12 @@
             if (useMorphTargets) {
                 if ((<any>mesh).morphTargetManager) {
                     var manager = (<Mesh>mesh).morphTargetManager;
+                    defines["MORPHTARGETS_TANGENT"] = manager.supportsTangents && defines["TANGENT"];
                     defines["MORPHTARGETS_NORMAL"] = manager.supportsNormals && defines["NORMAL"] ;
                     defines["MORPHTARGETS"] = (manager.numInfluencers > 0);
                     defines["NUM_MORPH_INFLUENCERS"] = manager.numInfluencers;
                 } else {
+                    defines["MORPHTARGETS_TANGENT"] = false;
                     defines["MORPHTARGETS_NORMAL"] = false;
                     defines["MORPHTARGETS"] = false;
                     defines["NUM_MORPH_INFLUENCERS"] = 0;
@@ -266,6 +268,7 @@
                 var maxAttributesCount = Engine.LastCreatedEngine.getCaps().maxVertexAttribs;
                 var manager = (<Mesh>mesh).morphTargetManager;
                 var normal = manager.supportsNormals && defines["NORMAL"];
+                var tangent = manager.supportsTangents && defines["TANGENT"];
                 for (var index = 0; index < influencers; index++) {
                     attribs.push(VertexBuffer.PositionKind + index);
 
@@ -273,6 +276,10 @@
                         attribs.push(VertexBuffer.NormalKind + index);
                     }
 
+                    if (tangent) {
+                        attribs.push(VertexBuffer.TangentKind + index);
+                    }
+
                     if (attribs.length > maxAttributesCount) {
                         Tools.Error("Cannot add more vertex attributes for mesh " + mesh.name);
                     }

+ 2 - 0
src/Materials/babylon.pbrMaterial.ts

@@ -79,6 +79,7 @@
 
         public MORPHTARGETS = false;
         public MORPHTARGETS_NORMAL = false;
+        public MORPHTARGETS_TANGENT = false;
         public NUM_MORPH_INFLUENCERS = 0;
 
         constructor() {
@@ -1033,6 +1034,7 @@
 
                if ((<any>mesh).morphTargetManager) {
                     var manager = (<Mesh>mesh).morphTargetManager;
+                    this._defines.MORPHTARGETS_TANGENT = manager.supportsTangents && this._defines.TANGENT;
                     this._defines.MORPHTARGETS_NORMAL = manager.supportsNormals && this._defines.NORMAL;
                     this._defines.MORPHTARGETS = (manager.numInfluencers > 0);
                     this._defines.NUM_MORPH_INFLUENCERS = manager.numInfluencers;

+ 1 - 0
src/Materials/babylon.standardMaterial.ts

@@ -61,6 +61,7 @@ module BABYLON {
         public CAMERACOLORCURVES = false;
         public MORPHTARGETS = false;
         public MORPHTARGETS_NORMAL = false;
+        public MORPHTARGETS_TANGENT = false;
         public NUM_MORPH_INFLUENCERS = 0;
 
         constructor() {

+ 2 - 0
src/Materials/babylon.uniformBuffer.ts

@@ -366,6 +366,8 @@ module BABYLON {
                 return; // nothing to do
             }
 
+            // See spec, alignment must be filled as a vec4
+            this._fillAlignment(4);
             this._bufferData = new Float32Array(this._data);
 
             if (this._dynamic) {

+ 42 - 52
src/Mesh/babylon.abstractMesh.ts

@@ -1822,76 +1822,67 @@
 
         /**
          * Defines the passed mesh as the parent of the current mesh.  
-         * If keepWorldPositionRotation is set to `true` (default `false`), the current mesh position and rotation are kept.
          * Returns the AbstractMesh.  
          */
-        public setParent(mesh:AbstractMesh, keepWorldPositionRotation = false): AbstractMesh {
-
+        public setParent(mesh:AbstractMesh): AbstractMesh {
+            
             var child = this;
             var parent = mesh;
 
             if(mesh == null){
 
-                if(child.parent && keepWorldPositionRotation){
-                  
-                    var rotation = Tmp.Quaternion[0];
-                    var position = Tmp.Vector3[0];
-                    var scale = Tmp.Vector3[1];
+                var rotation = Tmp.Quaternion[0];
+                var position = Tmp.Vector3[0];
+                var scale = Tmp.Vector3[1];
 
-                    child.getWorldMatrix().decompose(scale, rotation, position);
-
-                    if (child.rotationQuaternion) {
-                        child.rotationQuaternion.copyFrom(rotation);
-                    } else {
-                        rotation.toEulerAnglesToRef(child.rotation);
-                    }
+                child.getWorldMatrix().decompose(scale, rotation, position);
 
-                    child.position.x = position.x;
-                    child.position.y = position.y;
-                    child.position.z = position.z;
+                if (child.rotationQuaternion) {
+                    child.rotationQuaternion.copyFrom(rotation);
+                } else {
+                    rotation.toEulerAnglesToRef(child.rotation);
+                }
 
-               }
+                child.position.x = position.x;
+                child.position.y = position.y;
+                child.position.z = position.z;
 
             } else {
+  
+                var rotation = Tmp.Quaternion[0];
+                var position = Tmp.Vector3[0];
+                var scale = Tmp.Vector3[1];
+                var m1 = Tmp.Matrix[0];
+                var m2 = Tmp.Matrix[1];
 
-                if(keepWorldPositionRotation){
-                    
-                    var rotation = Tmp.Quaternion[0];
-                    var position = Tmp.Vector3[0];
-                    var scale = Tmp.Vector3[1];
-                    var m1 = Tmp.Matrix[0];
-                    var m2 = Tmp.Matrix[1];
+                parent.getWorldMatrix().decompose(scale, rotation, position);
 
-                    parent.getWorldMatrix().decompose(scale, rotation, position);
+                rotation.toRotationMatrix(m1);
+                m2.setTranslation(position);
 
-                    rotation.toRotationMatrix(m1);
-                    m2.setTranslation(position);
+                m2.multiplyToRef(m1, m1);
 
-                    m2.multiplyToRef(m1, m1);
+                var invParentMatrix = Matrix.Invert(m1);
 
-                    var invParentMatrix = Matrix.Invert(m1);
+                var m = child.getWorldMatrix().multiply(invParentMatrix);
 
-                    var m = child.getWorldMatrix().multiply(invParentMatrix);
+                m.decompose(scale, rotation, position);
 
-                    m.decompose(scale, rotation, position);
-
-                    if (child.rotationQuaternion) {
-                        child.rotationQuaternion.copyFrom(rotation);
-                    } else {
-                        rotation.toEulerAnglesToRef(child.rotation);
-                    }
-
-                    invParentMatrix = Matrix.Invert(parent.getWorldMatrix());
+                if (child.rotationQuaternion) {
+                    child.rotationQuaternion.copyFrom(rotation);
+                } else {
+                    rotation.toEulerAnglesToRef(child.rotation);
+                }
 
-                    var m = child.getWorldMatrix().multiply(invParentMatrix);
+                invParentMatrix = Matrix.Invert(parent.getWorldMatrix());
 
-                    m.decompose(scale, rotation, position);
+                var m = child.getWorldMatrix().multiply(invParentMatrix);
 
-                    child.position.x = position.x;
-                    child.position.y = position.y;
-                    child.position.z = position.z;
+                m.decompose(scale, rotation, position);
 
-                }
+                child.position.x = position.x;
+                child.position.y = position.y;
+                child.position.z = position.z;
 
             }
             child.parent = parent;
@@ -1900,11 +1891,10 @@
 
         /**
          * Adds the passed mesh as a child to the current mesh.  
-         * If keepWorldPositionRotation is set to `true` (default `false`), the child world position and rotation are kept.  
          * Returns the AbstractMesh.  
          */
-        public addChild(mesh:AbstractMesh, keepWorldPositionRotation = false): AbstractMesh {
-            mesh.setParent(this, keepWorldPositionRotation);
+        public addChild(mesh:AbstractMesh): AbstractMesh {
+            mesh.setParent(this);
             return this;
         }
 
@@ -1912,8 +1902,8 @@
          * Removes the passed mesh from the current mesh children list.  
          * Returns the AbstractMesh.  
          */
-        public removeChild(mesh:AbstractMesh, keepWorldPositionRotation = false): AbstractMesh {
-            mesh.setParent(null, keepWorldPositionRotation);
+        public removeChild(mesh:AbstractMesh): AbstractMesh {
+            mesh.setParent(null);
             return this;
         }
 

+ 1 - 1
src/Mesh/babylon.geometry.ts

@@ -349,7 +349,7 @@
         }
 
         public _releaseVertexArrayObject(effect: Effect) {
-            if (!effect) {
+            if (!effect || !this._vertexArrayObjects) {
                 return;
             }
             

+ 7 - 0
src/Mesh/babylon.mesh.ts

@@ -2021,6 +2021,9 @@
                     if (morphTarget.hasNormals) {
                         this.geometry.setVerticesData(VertexBuffer.NormalKind + index, morphTarget.getNormals(), false, 3);
                     }
+                    if (morphTarget.hasTangents) {
+                        this.geometry.setVerticesData(VertexBuffer.TangentKind + index, morphTarget.getTangents(), false, 3);
+                    }
                 }
             } else {
                 var index = 0;
@@ -2034,6 +2037,10 @@
                     {
                         this.geometry.removeVerticesData(VertexBuffer.NormalKind + index);
                     }
+                    if (this.geometry.isVerticesDataPresent(VertexBuffer.TangentKind + index))
+                    {
+                        this.geometry.removeVerticesData(VertexBuffer.TangentKind + index);
+                    }
                     index++;
                 }    
             }

+ 22 - 0
src/Morph/babylon.morphTarget.ts

@@ -2,6 +2,7 @@ module BABYLON {
     export class MorphTarget {
         private _positions: Float32Array;
         private _normals: Float32Array;
+        private _tangents: Float32Array;
         private _influence: number;
 
         public onInfluenceChanged = new Observable<boolean>();
@@ -31,6 +32,10 @@ module BABYLON {
             return this._normals !== undefined;
         }
 
+        public get hasTangents(): boolean {
+            return this._tangents !== undefined;
+        }
+
         public setPositions(data: Float32Array | number[]) {
             this._positions = new Float32Array(data);
         }
@@ -47,6 +52,14 @@ module BABYLON {
             return this._normals;
         }
 
+        public setTangents(data: Float32Array | number[]) {
+            this._tangents = new Float32Array(data);
+        }
+
+        public getTangents(): Float32Array {
+            return this._tangents;
+        }
+
         /**
          * Serializes the current target into a Serialization object.  
          * Returns the serialized object.  
@@ -61,6 +74,9 @@ module BABYLON {
             if (this.hasNormals) {
                 serializationObject.normals = Array.prototype.slice.call(this.getNormals());
             }
+            if (this.hasTangents) {
+                serializationObject.tangents = Array.prototype.slice.call(this.getTangents());
+            }
 
             return serializationObject;
         }
@@ -74,6 +90,9 @@ module BABYLON {
             if (serializationObject.normals) {
                 result.setNormals(serializationObject.normals);
             }
+            if (serializationObject.tangents) {
+                result.setTangents(serializationObject.tangents);
+            }
 
             return result;
         }
@@ -90,6 +109,9 @@ module BABYLON {
             if (mesh.isVerticesDataPresent(VertexBuffer.NormalKind)) {
                 result.setNormals(mesh.getVerticesData(VertexBuffer.NormalKind));
             }
+            if (mesh.isVerticesDataPresent(VertexBuffer.TangentKind)) {
+                result.setTangents(mesh.getVerticesData(VertexBuffer.TangentKind));
+            }
 
             return result;
         }

+ 7 - 0
src/Morph/babylon.morphTargetManager.ts

@@ -6,6 +6,7 @@ module BABYLON {
         private _scene: Scene;
         private _influences: Float32Array;
         private _supportsNormals = false;
+        private _supportsTangents = false;
         private _vertexCount = 0;
         private _uniqueId = 0;
 
@@ -33,6 +34,10 @@ module BABYLON {
             return this._supportsNormals;
         }
 
+        public get supportsTangents(): boolean {
+            return this._supportsTangents;
+        }
+
         public get numInfluencers(): number {
             return this._activeTargets.length;
         }
@@ -96,12 +101,14 @@ module BABYLON {
             this._activeTargets.reset();
             var tempInfluences = [];
             this._supportsNormals = true;
+            this._supportsTangents = true;
             for (var target of this._targets) {
                 if (target.influence > 0) {
                     this._activeTargets.push(target);
                     tempInfluences.push(target.influence);
 
                     this._supportsNormals = this._supportsNormals && target.hasNormals;
+                    this._supportsTangents = this._supportsTangents && target.hasTangents;
 
                     if (this._vertexCount === 0) {
                         this._vertexCount = target.getPositions().length / 3;

+ 3 - 3
src/Shaders/ShadersInclude/bumpVertex.fx

@@ -1,8 +1,8 @@
 #if defined(BUMP) || defined(PARALLAX)
 	#if defined(TANGENT) && defined(NORMAL)
-		vec3 normalW = normalize(vec3(finalWorld * vec4(normal, 0.0)));
-		vec3 tangentW = normalize(vec3(finalWorld * vec4(tangent.xyz, 0.0)));
-		vec3 bitangentW = cross(normalW, tangentW) * tangent.w;
+		vec3 normalW = normalize(vec3(finalWorld * vec4(normalUpdated, 0.0)));
+		vec3 tangentW = normalize(vec3(finalWorld * vec4(tangentUpdated.xyz, 0.0)));
+		vec3 bitangentW = cross(normalW, tangentW) * tangentUpdated.w;
 		vTBN = mat3(tangentW, bitangentW, normalW);
 	#endif
 #endif

+ 5 - 1
src/Shaders/ShadersInclude/morphTargetsVertex.fx

@@ -3,5 +3,9 @@
 	
 	#ifdef MORPHTARGETS_NORMAL
 	normalUpdated += (normal{X} - normal) * morphTargetInfluences[{X}];
-	#endif	
+	#endif
+
+	#ifdef MORPHTARGETS_TANGENT
+	tangentUpdated.xyz += (tangent{X} - tangent.xyz) * morphTargetInfluences[{X}];
+	#endif
 #endif

+ 4 - 0
src/Shaders/ShadersInclude/morphTargetsVertexDeclaration.fx

@@ -4,4 +4,8 @@
 	#ifdef MORPHTARGETS_NORMAL
 	attribute vec3 normal{X};
 	#endif
+
+	#ifdef MORPHTARGETS_TANGENT
+	attribute vec3 tangent{X};
+	#endif
 #endif

+ 3 - 0
src/Shaders/default.vertex.fx

@@ -86,6 +86,9 @@ void main(void) {
 #ifdef NORMAL	
 	vec3 normalUpdated = normal;
 #endif
+#ifdef TANGENT
+	vec4 tangentUpdated = tangent;
+#endif
 
 #include<morphTargetsVertex>[0..maxSimultaneousMorphTargets]
 

+ 4 - 1
src/Shaders/pbr.vertex.fx

@@ -87,9 +87,12 @@ varying vec3 vDirectionW;
 
 void main(void) {
 	vec3 positionUpdated = position;
-#ifdef NORMAL	
+#ifdef NORMAL
 	vec3 normalUpdated = normal;
 #endif
+#ifdef TANGENT
+    vec4 tangentUpdated = tangent;
+#endif
 
 #include<morphTargetsVertex>[0..maxSimultaneousMorphTargets]
 

+ 2 - 1
src/Tools/babylon.extendedGamepad.ts

@@ -293,6 +293,7 @@ module BABYLON {
         */
         protected handleButtonChange(buttonIdx: number, state: ExtendedGamepadButton, changes: GamepadButtonChanges) {
             let notifyObject = state; //{ state: state, changes: changes };
+            let triggerDirection = this.hand === 'right' ? -1 : 1;
             switch (buttonIdx) {
                 case 0:
                     this.onPadStateChangedObservable.notifyObservers(notifyObject);
@@ -307,7 +308,7 @@ module BABYLON {
                     return;
                 case 2:  // secondary trigger
                     if (this._defaultModel) {
-                        (<AbstractMesh>(this._defaultModel.getChildren()[4])).position.x = notifyObject.value * 0.0035;
+                        (<AbstractMesh>(this._defaultModel.getChildren()[4])).position.x = triggerDirection * notifyObject.value * 0.0035;
                     }
                     this.onSecondaryTriggerStateChangedObservable.notifyObservers(notifyObject);
                     return;