Ver código fonte

Merge branch 'master' of https://github.com/BabylonJS/Babylon.js into c2d

Adam Bowman 8 anos atrás
pai
commit
5c93d02360
41 arquivos alterados com 5870 adições e 5531 exclusões
  1. 46 0
      canvas2D/features.md
  2. 12 1
      canvas2D/readme.md
  3. 44 9
      canvas2D/src/Engine/babylon.canvas2d.ts
  4. 13 3
      canvas2D/src/Engine/babylon.canvas2dLayoutEngine.ts
  5. 1 1
      canvas2D/src/Engine/babylon.ellipse2d.ts
  6. 2 0
      canvas2D/src/Engine/babylon.fontTexture.ts
  7. 6 2
      canvas2D/src/Engine/babylon.group2d.ts
  8. 41 9
      canvas2D/src/Engine/babylon.prim2dBase.ts
  9. 6 2
      canvas2D/src/Engine/babylon.rectangle2d.ts
  10. 5 0
      canvas2D/src/Engine/babylon.smartPropertyPrim.ts
  11. 17 5
      canvas2D/src/Engine/babylon.sprite2d.ts
  12. 11 7
      canvas2D/src/Engine/babylon.text2d.ts
  13. 5 1
      canvas2D/src/Engine/babylon.wireFrame2d.ts
  14. 1 1
      canvas2D/src/shaders/text2d.fragment.fx
  15. 24 24
      dist/preview release/babylon.core.js
  16. 4651 4650
      dist/preview release/babylon.d.ts
  17. 34 34
      dist/preview release/babylon.js
  18. 340 326
      dist/preview release/babylon.max.js
  19. 33 33
      dist/preview release/babylon.noworker.js
  20. 7 1
      dist/preview release/canvas2D/babylon.canvas2d.d.ts
  21. 198 65
      dist/preview release/canvas2D/babylon.canvas2d.js
  22. 11 11
      dist/preview release/canvas2D/babylon.canvas2d.min.js
  23. 1 1
      dist/preview release/proceduralTexturesLibrary/babylon.brickProceduralTexture.js
  24. 1 1
      dist/preview release/proceduralTexturesLibrary/babylon.brickProceduralTexture.min.js
  25. 1 1
      dist/preview release/proceduralTexturesLibrary/babylon.marbleProceduralTexture.js
  26. 1 1
      dist/preview release/proceduralTexturesLibrary/babylon.marbleProceduralTexture.min.js
  27. 3 3
      proceduralTexturesLibrary/src/brick/brickProceduralTexture.fragment.fx
  28. 3 3
      proceduralTexturesLibrary/src/marble/marbleProceduralTexture.fragment.fx
  29. 1 1
      src/Collisions/babylon.collider.ts
  30. 2 2
      src/Collisions/babylon.collisionCoordinator.ts
  31. 6 3
      src/Materials/Textures/Procedurals/babylon.proceduralTexture.ts
  32. 299 1
      src/Mesh/babylon.abstractMesh.ts
  33. 4 4
      src/Mesh/babylon.geometry.ts
  34. 1 1
      src/Mesh/babylon.instancedMesh.ts
  35. 4 301
      src/Mesh/babylon.mesh.ts
  36. 9 6
      src/Mesh/babylon.mesh.vertexData.ts
  37. 1 1
      src/Mesh/babylon.meshBuilder.ts
  38. 2 2
      src/Mesh/babylon.subMesh.ts
  39. 1 1
      src/Physics/babylon.physicsImpostor.ts
  40. 1 3
      src/Tools/babylon.tools.ts
  41. 21 10
      src/babylon.engine.ts

+ 46 - 0
canvas2D/features.md

@@ -1,3 +1,49 @@
 Canvas2D: features list
 ====================
 
+## Features soup
+
+Here is some features, in no particular order. To get a clearer picture of what is where, keep reading this document.
+
+ - Rendering is **WebGL** based, powered by Babylon.js core architecture.
+ - Draw Calls are **minimized** due to a rendering architecture using (when available) the [ANGLE_instanced_arrays](https://www.khronos.org/registry/webgl/extensions/ANGLE_instanced_arrays) extension.
+   - All non transparent instances of the Ellipse2D, Rectangl2D are drawn in one draw call per primitive type whatever the Ellipse/Rectangle width, height, roundRadius, subdivision, fill/border brush are.
+   - All non transparent instances of Sprite2D using the same Texture are rendered into a single draw call.
+   - All instances of [Text2D](http://doc.babylonjs.com/overviews/Canvas2D_Text2D) using the same fontName in Signed Distance Field mode are rendered into a single draw call. Non SDF Text follow the Transparent rendering rules.
+   - All transparent primitives applying to the rules above can be rendered into a single call if there are consecutive in the depth order. Transparent Primitives must be rendered **back to front** no matter what, it's packed into Instanced Arrays when it can, otherwise single draw calls are made.
+ - All the rendering engine's architecture is based on dirty/update caches to compute the data only when needed to **avoid computation when nothing changes**.
+ - Part of the content of a Canvas (or the whole) can be **cached** into a big texture in order to avoid a render every frame, in order to maximize performance by rendering just once static content. [More info](http://doc.babylonjs.com/overviews/Canvas2D_Rendering).
+ - You can create on screen Canvas, called **ScreenSpaceCanvas** (SSC) that are displayed on the top of the 3D Scene (or below, in between, in the depth layer you want...)
+ - You can create a Canvas that is displayed in the 3D Scene on a Rectangle, this a **WorldSpaceCanvas** (WSC), some features:
+   - The rendering quality of a WSC is **adaptive**, the closer your WSC is the bigger is the surface when its content is rendered to, avoiding you to see pixelized content everything is adaptive, **even text**.
+   
+     - Without ![before](http://www.html5gamedevs.com/uploads/monthly_2016_06/57641896ccee5_c6o7BdT1.png.57ad694cf4cb86f884cfebb0ffa29fc1.png)
+     - With ![after](http://www.html5gamedevs.com/uploads/monthly_2016_06/576419dc5794d_Pastedimageat2016_06_1715_35.thumb.png.47a928c707526926198401132a049b50.png)
+   - A WSC can **track** a 3D Scene Node, and optionally always face the screen, [example](http://babylonjs-playground.com/#1KYG17#1).
+   - By default a WSC is rendered on a Plane, but you can render it on pretty much every **surface you want**, [example](http://babylonjs-playground.com/#EPFQG#4).
+ - A Canvas can rely on a **Design Size** for the user to work with a Fixed Size Surface and position its primitives accordingly, the rendered size of the Canvas adapting to the rendering device, scaling the content for proportions to be kept, [more info](http://doc.babylonjs.com/overviews/Canvas2D_DesignSize).
+ - You can create custom frame of reference or containers, called **Group2D**, [more info](http://doc.babylonjs.com/overviews/Canvas2D_Group2D). A Group2D's content can be **cached** into a big texture in order to avoid rendering of its content every frame, as stated above.
+ - An **Interaction Engine** support the HTML PointerEvent, which is replicated at the level of a primitive, you can now when the pointer is entering/leaving a primitive's surface, when there's a touch/click, etc. [more info](http://doc.babylonjs.com/overviews/Canvas2D_Interaction). Interaction works for both WSC and SSC.
+ - A **Collision Engine** at the Canvas level detect all the primitives intersecting each others or against the Canvas' borders, [more info](http://doc.babylonjs.com/overviews/Canvas2D_PCM)
+ - Every primitive can be **animated** using the Babylon.js [animation framework](http://doc.babylonjs.com/tutorials/animations), [example](http://babylonjs-playground.com/#FFTQL#3).
+ - Primitives can be positioned manually using the **Absolute Positioning** ([more info](http://doc.babylonjs.com/overviews/Canvas2D_PosTransHierarchy)) or arranged by a **Layout Engine** and the **Positioning Engine** using Margin, Margin Alignment, Padding properties, [more info](http://doc.babylonjs.com/overviews/Canvas2D_Prim_Positioning).
+ - Primitives can be manually sized or be auto-size based on their content and/or the area taken by their children.
+ - Multiple Layout Engines can be developed through time, for now only the default one (Canvas Positioning) and a StackPanel are implemented. Grid Layout and Radial Layout will come soon.
+ - The Primitive types implemented so far:
+   - [Shape based](http://doc.babylonjs.com/overviews/Canvas2D_Shape2D):
+     - [Rectangle2D](http://doc.babylonjs.com/overviews/Canvas2D_Rectangle2D): a simple rectangle with a width and a height and an optional roundedRadius to have rounded corners.
+     - [Ellipse2D](http://doc.babylonjs.com/overviews/Canvas2D_Ellipse2D): an ellipse (so also a circle) with a width, height and a subdivision count for its rendering.
+     - [Lines2D](http://doc.babylonjs.com/overviews/Canvas2D_Lines2D): to render opened or closed line path from a list of points, with a given thickness and for opened Lines2D optional starting and ending caps (RoundCap, TriangleCap, SquaredAnchorCap, etc.)
+   - [Text2D](http://doc.babylonjs.com/overviews/Canvas2D_Text2D): render a text using either:
+     - A generated font using a given CSS-style fontName, in this mode the text can be rendered using three techniques: standard quality, super sample quality, signed distance field algorithm.
+     - A BitmapFontTexture to render more game/fancy character.
+     - This primitive also support Text Word Wrapping and Text Alignment (both horizontally and vertically).
+   - [Sprite2D](http://doc.babylonjs.com/overviews/Canvas2D_Sprite2D): render a sprite from a texture, sprite frame is supported for sprite animation, the sprite can be stored in an [AtlasPicture](http://doc.babylonjs.com/overviews/Canvas2D_AtlasPicture) and/or be rendered using the [Scale9Sprite](http://doc.babylonjs.com/overviews/Canvas2D_Sprite2D#scale9Sprite-feature) algorithm.
+   - [WireFrame2D](http://doc.babylonjs.com/overviews/Canvas2D_WireFrame2D): to render many wire lines.
+
+## Class diagram
+
+You can get a high level view of the implemented classes with this class diagram:
+
+![ClassDiagram](http://imgur.com/qclw4cI.png)
+

+ 12 - 1
canvas2D/readme.md

@@ -4,7 +4,7 @@ Canvas2D, a 100% WebGL based 2D Engine
 ## Table of Content
 
 - [Introduction](#introduction)
-- [Documentation](#documentation)
+- [Documentation, want to give feedback, report a bug or need help?](#documentation)
 - [Releases](#releases)
 - [Features list](features.md) (separated page)
 - [How to build it](#how-to-build-babyloncanvas2djs-with-gulp)
@@ -33,6 +33,17 @@ This overview page has many links to other documentation pages (organized like a
 #### Reference
 The reference documentation is available [here](http://doc.babylonjs.com/classes/), most of the Canvas2D classes are suffixed by `2D` so you can use it in the filter box like this:![2D classes](http://i.imgur.com/hx4Llmi.png)
 
+#### Using the Forum
+
+If you need help, want to give feedback, report a bug or be aware of the latest development: you have to use the **[Babylon.js forum](http://www.html5gamedevs.com/forum/16-babylonjs/)**.
+
+ - Questions are to be posted [here](http://www.html5gamedevs.com/forum/28-questions-answers/)
+ - Bugs reports must be made [there](http://www.html5gamedevs.com/forum/30-bugs/)
+ - Check [this post](http://www.html5gamedevs.com/topic/22552-canvas2d-main-post/) to be aware of all the improvements/fixes made during the alpha/beta development of the library. You can check the first post as I update it each time there's new stuff or I simply encourage you to follow the thread to get notified. **Please** don't ask question or report bugs in this thread, create a dedicated one, thanks!
+ - [Another post](http://www.html5gamedevs.com/topic/25275-the-gui-lib-of-babylonjs/) was created to track the progress on the GUI Library, same rules and observations as above.
+
+**Important** when you post something you better mentioned me using `@nockawa`, I'm **not** checking the forum everyday but some other users does and ping me if needed, but still: mentioning me is the best way to get my attention.
+
 ## Releases
 
 You want to use an existing build, that's simple, you can grab either the latest official release or the latest build of the current developing version.

+ 44 - 9
canvas2D/src/Engine/babylon.canvas2d.ts

@@ -1052,6 +1052,10 @@
             return this._designUseHorizAxis;
         }
 
+        public set designSizeUseHorizeAxis(value: boolean) {
+            this._designUseHorizAxis = value;
+        }
+
         /**
          * Return 
          */
@@ -1336,6 +1340,8 @@
                     if (scale) {
                         wsn.scaling = scale;
                     }
+                } else {
+                    throw new Error("Can't Track another Scene Node Type than AbstractMesh right now, call me lazy!");
                 }
             }
         }
@@ -1838,15 +1844,9 @@
             //    throw new Error("CACHESTRATEGY_DONTCACHE cache Strategy can't be used for WorldSpace Canvas");
             //}
 
-            if (settings.trackNode != null) {
-                this._trackNode = settings.trackNode;
-                this._trackNodeOffset = (settings.trackNodeOffset != null) ? settings.trackNodeOffset : Vector3.Zero();
-                this._trackNodeBillboard = (settings.trackNodeBillboard != null) ? settings.trackNodeBillboard : false;
-            } else {
-                this._trackNode = null;
-                this._trackNodeOffset = null;
-                this._trackNodeBillboard = false;
-            }
+            this._trackNode          = (settings.trackNode != null)          ? settings.trackNode          : null;
+            this._trackNodeOffset    = (settings.trackNodeOffset != null)    ? settings.trackNodeOffset    : Vector3.Zero();
+            this._trackNodeBillboard = (settings.trackNodeBillboard != null) ? settings.trackNodeBillboard : true;
 
             let createWorldSpaceNode = !settings || (settings.customWorldSpaceNode == null);
             this._customWorldSpaceNode = !createWorldSpaceNode;
@@ -1890,6 +1890,9 @@
             }
 
             this.propertyChanged.add((e, st) => {
+                if (e.propertyName !== "isVisible") {
+                    return;
+                }
                 let mesh = this._worldSpaceNode as AbstractMesh;
                 if (mesh) {
                     mesh.isVisible = e.newValue;
@@ -1908,6 +1911,38 @@
             }
         }
 
+        public get trackNode(): Node {
+            return this._trackNode;
+        }
+
+        public set trackNode(value: Node) {
+            if (this._trackNode === value) {
+                return;
+            }
+
+            this._trackNode = value;
+        }
+
+        public get trackNodeOffset(): Vector3 {
+            return this._trackNodeOffset;
+        }
+
+        public set trackNodeOffset(value: Vector3) {
+            if (!this._trackNodeOffset) {
+                this._trackNodeOffset = value.clone();
+            } else {
+                this._trackNodeOffset.copyFrom(value);
+            }
+        }
+
+        public get trackNodeBillboard(): boolean {
+            return this._trackNodeBillboard;
+        }
+
+        public set trackNodeBillboard(value: boolean) {
+            this._trackNodeBillboard = value;
+        }
+
         private _customWorldSpaceNode: boolean;
     }
 

+ 13 - 3
canvas2D/src/Engine/babylon.canvas2dLayoutEngine.ts

@@ -49,7 +49,18 @@
      * This layout must be used as a Singleton through the CanvasLayoutEngine.Singleton property.
      */
     export class CanvasLayoutEngine extends LayoutEngineBase {
-        public static Singleton: CanvasLayoutEngine = new CanvasLayoutEngine();
+        private  static _singleton: CanvasLayoutEngine = null;
+        public static get Singleton(): CanvasLayoutEngine {
+            if (!CanvasLayoutEngine._singleton) {
+                CanvasLayoutEngine._singleton = new CanvasLayoutEngine();
+            }
+            return CanvasLayoutEngine._singleton;
+        } 
+
+        constructor() {
+            super();
+            this.layoutDirtyOnPropertyChangedMask = Prim2DBase.sizeProperty.flagId | Prim2DBase.actualSizeProperty.flagId;
+        }
 
         // A very simple (no) layout computing...
         // The Canvas and its direct children gets the Canvas' size as Layout Area
@@ -58,7 +69,6 @@
 
             // If this prim is layoutDiry we update  its layoutArea and also the one of its direct children
             if (prim._isFlagSet(SmartPropertyPrim.flagLayoutDirty)) {
-
                 for (let child of prim.children) {
                     this._doUpdate(child);
                 }
@@ -98,7 +108,7 @@
     export class StackPanelLayoutEngine extends LayoutEngineBase {
         constructor() {
             super();
-            this.layoutDirtyOnPropertyChangedMask = Prim2DBase.sizeProperty.flagId;
+            this.layoutDirtyOnPropertyChangedMask = Prim2DBase.sizeProperty.flagId | Prim2DBase.actualSizeProperty.flagId;
         }
 
         public static get Horizontal(): StackPanelLayoutEngine {

+ 1 - 1
canvas2D/src/Engine/babylon.ellipse2d.ts

@@ -38,7 +38,7 @@
                 engine.setDepthFunctionToLessOrEqual();
             }
 
-            let curAlphaMode = engine.getAlphaMode();
+            var curAlphaMode = engine.getAlphaMode();
 
             if (this.effectFill) {
                 let partIndex = instanceInfo.partIndexFromId.get(Shape2D.SHAPE2D_FILLPARTID.toString());

+ 2 - 0
canvas2D/src/Engine/babylon.fontTexture.ts

@@ -712,6 +712,8 @@
         // More info here: https://videlais.com/2014/03/16/the-many-and-varied-problems-with-measuring-font-height-for-html5-canvas/
         private getFontHeight(font: string): {height: number, offset: number} {
             var fontDraw = document.createElement("canvas");
+            fontDraw.width = 600;
+            fontDraw.height = 600;
             var ctx = fontDraw.getContext('2d');
             ctx.fillRect(0, 0, fontDraw.width, fontDraw.height);
             ctx.textBaseline = 'top';

+ 6 - 2
canvas2D/src/Engine/babylon.group2d.ts

@@ -253,7 +253,7 @@
          * BEWARE: if the Group is a RenderableGroup and its content is cache the texture will be resized each time the group is getting bigger. For performance reason the opposite won't be true: the texture won't shrink if the group does.
          */
         public set size(val: Size) {
-            this._size = val;
+            this.internalSetSize(val);
         }
 
         public get viewportSize(): ISize {
@@ -295,7 +295,11 @@
         }
 
         public set actualSize(value: Size) {
-            this._actualSize = value;
+            if (!this._actualSize) {
+                this._actualSize = value.clone();
+            } else {
+                this._actualSize.copyFrom(value);
+            }
         }
 
 

+ 41 - 9
canvas2D/src/Engine/babylon.prim2dBase.ts

@@ -1866,7 +1866,11 @@
          * DO NOT INVOKE for internal purpose only
          */
         public set actualPosition(val: Vector2) {
-            this._actualPosition = val;
+            if (!this._actualPosition) {
+                this._actualPosition = val.clone();
+            } else {
+                this._actualPosition.copyFrom(val);
+            }
         }
 
         /**
@@ -1913,7 +1917,11 @@
             if (!this._checkPositionChange()) {
                 return;
             }
-            this._position = value;
+            if (!this._position) {
+                this._position = value.clone();
+            } else {
+                this._position.copyFrom(value);
+            }
             this._triggerPropertyChanged(Prim2DBase.actualPositionProperty, value);
         }
 
@@ -2013,7 +2021,11 @@
         }
 
         protected internalSetSize(value: Size) {
-            this._size = value;
+            if (!this._size) {
+                this._size = (value != null) ? value.clone() : null;
+            } else {
+                this._size.copyFrom(value);
+            }
         }
 
         /**
@@ -2115,7 +2127,11 @@
                 return;
             }
 
-            this._actualSize = value;
+            if (!this._actualSize) {
+                this._actualSize = value.clone();
+            } else {
+                this._actualSize.copyFrom(value);
+            }
         }
 
         /**
@@ -2168,7 +2184,11 @@
                 return;
             }
 
-            this._minSize = value;
+            if (!this._minSize) {
+                this._minSize = value.clone();
+            } else {
+                this._minSize.copyFrom(value);
+            }
             this._parentLayoutDirty();
         }
 
@@ -2186,7 +2206,11 @@
                 return;
             }
 
-            this._maxSize = value;
+            if (!this._maxSize) {
+                this._maxSize = value.clone();
+            } else {
+                this._maxSize.copyFrom(value);
+            }
             this._parentLayoutDirty();
         }
 
@@ -2205,7 +2229,11 @@
         }
 
         public set origin(value: Vector2) {
-            this._origin = value;
+            if (!this._origin) {
+                this._origin = value.clone();
+            } else {
+                this._origin.copyFrom(value);
+            }
         }
 
         @dynamicLevelProperty(SmartPropertyPrim.SMARTPROPERTYPRIM_PROPCOUNT + 15, pi => Prim2DBase.levelVisibleProperty = pi)
@@ -2482,7 +2510,7 @@
             if (this.parent) {
                 this.parent._setFlags(SmartPropertyPrim.flagLayoutBoundingInfoDirty | SmartPropertyPrim.flagGlobalTransformDirty);
             }
-            this._layoutArea = val;
+            this._layoutArea.copyFrom(val);
         }
 
         /**
@@ -2504,7 +2532,11 @@
                 this.parent._setFlags(SmartPropertyPrim.flagLayoutBoundingInfoDirty | SmartPropertyPrim.flagGlobalTransformDirty);
             }
             this._positioningDirty();
-            this._layoutAreaPos = val;
+            if (!this._layoutAreaPos) {
+                this._layoutAreaPos = val.clone();
+            } else {
+                this._layoutAreaPos.copyFrom(val);
+            }
         }
 
         /**

+ 6 - 2
canvas2D/src/Engine/babylon.rectangle2d.ts

@@ -28,6 +28,7 @@
                 }
                 this.effectsReady = true;
             }
+
             let canvas = instanceInfo.owner.owner;
             var engine = canvas.engine;
 
@@ -40,7 +41,6 @@
             var curAlphaMode = engine.getAlphaMode();
 
             if (this.effectFill) {
-
                 let partIndex = instanceInfo.partIndexFromId.get(Shape2D.SHAPE2D_FILLPARTID.toString());
                 let pid = context.groupInfoPartData[partIndex];
 
@@ -182,7 +182,11 @@
         }
 
         public set actualSize(value: Size) {
-            this._actualSize = value;
+            if (!this._actualSize) {
+                this._actualSize = value.clone();
+            } else {
+                this._actualSize.copyFrom(value);
+            }
         }
 
         @modelLevelProperty(Shape2D.SHAPE2D_PROPCOUNT + 2, pi => Rectangle2D.notRoundedProperty = pi)

+ 5 - 0
canvas2D/src/Engine/babylon.smartPropertyPrim.ts

@@ -1151,6 +1151,11 @@
                 if (p != null && p.layoutEngine && (p.layoutEngine.layoutDirtyOnPropertyChangedMask & propInfo.flagId) !== 0) {
                     p._setLayoutDirty();
                 }
+
+                let that = this as Prim2DBase;
+                if (that.layoutEngine && (that.layoutEngine.layoutDirtyOnPropertyChangedMask & propInfo.flagId) !== 0) {
+                    (<any>this)._setLayoutDirty();
+                }
             }
 
             // For type level compare, if there's a change of type it's a change of model, otherwise we issue an instance change

+ 17 - 5
canvas2D/src/Engine/babylon.sprite2d.ts

@@ -157,7 +157,11 @@
         }
 
         public set actualSize(value: Size) {
-            this._actualSize = value;
+            if (!this._actualSize) {
+                this._actualSize = value.clone();
+            } else {
+                this._actualSize.copyFrom(value);
+            }
         }
 
         @instanceLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 4, pi => Sprite2D.spriteSizeProperty = pi)
@@ -169,7 +173,11 @@
         }
 
         public set spriteSize(value: Size) {
-            this._spriteSize = value;
+            if (!this._spriteSize) {
+                this._spriteSize = value.clone();
+            } else {
+                this._spriteSize.copyFrom(value);
+            }
             this._updateSpriteScaleFactor();
         }
 
@@ -182,7 +190,11 @@
         }
 
         public set spriteLocation(value: Vector2) {
-            this._spriteLocation = value;
+            if (!this._spriteLocation) {
+                this._spriteLocation = value.clone();
+            } else {
+                this._spriteLocation.copyFrom(value);
+            }
         }
 
         @instanceLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 6, pi => Sprite2D.spriteFrameProperty = pi)
@@ -364,8 +376,8 @@
             this.texture.wrapU = Texture.CLAMP_ADDRESSMODE;
             this.texture.wrapV = Texture.CLAMP_ADDRESSMODE;
             this._useSize = false;
-            this.spriteSize = (settings.spriteSize!=null) ? settings.spriteSize.clone() : null;
-            this.spriteLocation = (settings.spriteLocation!=null) ? settings.spriteLocation.clone() : new Vector2(0, 0);
+            this._spriteSize = (settings.spriteSize!=null) ? settings.spriteSize.clone() : null;
+            this._spriteLocation = (settings.spriteLocation!=null) ? settings.spriteLocation.clone() : new Vector2(0, 0);
             if (settings.size != null) {
                 this.size = settings.size;
             }

+ 11 - 7
canvas2D/src/Engine/babylon.text2d.ts

@@ -204,7 +204,11 @@
         }
 
         public set defaultFontColor(value: Color4) {
-            this._defaultFontColor = value;
+            if (!this._defaultFontColor) {
+                this._defaultFontColor = value.clone();
+            } else {
+                this._defaultFontColor.copyFrom(value);
+            }
         }
 
         @instanceLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 3, pi => Text2D.textProperty = pi, false, true)
@@ -242,7 +246,7 @@
         }
 
         public set size(value: Size) {
-            this._size = value;
+            this.internalSetSize(value);
         }
 
         @modelLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 5, pi => Text2D.fontSuperSampleProperty = pi, false, false)
@@ -456,7 +460,7 @@
                 this._fontSuperSample= (settings.fontSuperSample!=null && settings.fontSuperSample);
                 this._fontSDF        = (settings.fontSignedDistanceField!=null && settings.fontSignedDistanceField);
             }
-            this.defaultFontColor    = (settings.defaultFontColor==null) ? new Color4(1,1,1,1) : settings.defaultFontColor;
+            this._defaultFontColor   = (settings.defaultFontColor==null) ? new Color4(1,1,1,1) : settings.defaultFontColor.clone();
             this._tabulationSize     = (settings.tabulationSize == null) ? 4 : settings.tabulationSize;
             this._textSize           = null;
             this.text                = text;
@@ -715,10 +719,8 @@
                         let char = text[charNum];
                         let charWidth = charWidths[charNum];
 
-                        this.updateInstanceDataPart(d, offset);
-                        offset.x += charWidth;
-
-                        if (!this._isWhiteSpaceCharHoriz(char)) {
+                        if(!this._isWhiteSpaceCharHoriz(char) && !this._isWhiteSpaceCharVert(char)){ 
+                            this.updateInstanceDataPart(d, offset);
                             let ci = texture.getChar(char);
                             d.topLeftUV = ci.topLeftUV;
                             let suv = ci.bottomRightUV.subtract(ci.topLeftUV);
@@ -728,6 +730,8 @@
                             d.superSampleFactor = superSampleFactor;
                             ++d.curElement;
                         }
+
+                        offset.x += charWidth;
                         charNum++;
                     }
 

+ 5 - 1
canvas2D/src/Engine/babylon.wireFrame2d.ts

@@ -245,7 +245,11 @@
         }
 
         public set actualSize(value: Size) {
-            this._actualSize = value;
+            if (!this._actualSize) {
+                this._actualSize.clone();
+            } else {
+                this._actualSize.copyFrom(value);
+            }
         }
 
         protected updateLevelBoundingInfo(): boolean {

+ 1 - 1
canvas2D/src/shaders/text2d.fragment.fx

@@ -19,7 +19,7 @@ void main(void) {
 	//float opacity = dist * smoothstep(edgeDistance - edgeWidth, edgeDistance + edgeWidth, dist);
 
 	//float opacity = smoothstep(0.25, 0.75, dist);
-	gl_FragColor = vec4(vColor.xyz*dist, 1.0);
+	gl_FragColor = vec4(vColor.xyz*dist, vColor.a);
 #else
 	vec4 color = texture2D(diffuseSampler, vUV);
 	gl_FragColor = color*vColor;

Diferenças do arquivo suprimidas por serem muito extensas
+ 24 - 24
dist/preview release/babylon.core.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 4651 - 4650
dist/preview release/babylon.d.ts


Diferenças do arquivo suprimidas por serem muito extensas
+ 34 - 34
dist/preview release/babylon.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 340 - 326
dist/preview release/babylon.max.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 33 - 33
dist/preview release/babylon.noworker.js


+ 7 - 1
dist/preview release/canvas2D/babylon.canvas2d.d.ts

@@ -884,7 +884,9 @@ declare module BABYLON {
         private _isLocked;
     }
     class CanvasLayoutEngine extends LayoutEngineBase {
-        static Singleton: CanvasLayoutEngine;
+        private static _singleton;
+        static readonly Singleton: CanvasLayoutEngine;
+        constructor();
         updateLayout(prim: Prim2DBase): void;
         private _doUpdate(prim);
         readonly isChildPositionAllowed: boolean;
@@ -4194,6 +4196,7 @@ declare module BABYLON {
         readonly fitRenderingDevice: boolean;
         readonly designSize: Size;
         readonly designSizeUseHorizAxis: boolean;
+        designSizeUseHorizeAxis: boolean;
         /**
          * Return
          */
@@ -4411,6 +4414,9 @@ declare module BABYLON {
             padding?: string;
         });
         dispose(): boolean;
+        trackNode: Node;
+        trackNodeOffset: Vector3;
+        trackNodeBillboard: boolean;
         private _customWorldSpaceNode;
     }
     class ScreenSpaceCanvas2D extends Canvas2D {

Diferenças do arquivo suprimidas por serem muito extensas
+ 198 - 65
dist/preview release/canvas2D/babylon.canvas2d.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 11 - 11
dist/preview release/canvas2D/babylon.canvas2d.min.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 1 - 1
dist/preview release/proceduralTexturesLibrary/babylon.brickProceduralTexture.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 1 - 1
dist/preview release/proceduralTexturesLibrary/babylon.brickProceduralTexture.min.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 1 - 1
dist/preview release/proceduralTexturesLibrary/babylon.marbleProceduralTexture.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 1 - 1
dist/preview release/proceduralTexturesLibrary/babylon.marbleProceduralTexture.min.js


+ 3 - 3
proceduralTexturesLibrary/src/brick/brickProceduralTexture.fragment.fx

@@ -28,7 +28,7 @@ float fbm(vec2 n) {
 	return total;
 }
 
-float round(float number){
+float roundF(float number){
 	return sign(number)*floor(abs(number) + 0.5);
 }
 
@@ -40,14 +40,14 @@ void main(void)
 	float jointHPercentage = 0.05;
 	vec3 color = brickColor;
 	float yi = vUV.y / brickH;
-	float nyi = round(yi);
+	float nyi = roundF(yi);
 	float xi = vUV.x / brickW;
 
 	if (mod(floor(yi), 2.0) == 0.0){
 		xi = xi - 0.5;
 	}
 
-	float nxi = round(xi);
+	float nxi = roundF(xi);
 	vec2 brickvUV = vec2((xi - floor(xi)) / brickH, (yi - floor(yi)) /  brickW);
 
 	if (yi < nyi + jointHPercentage && yi > nyi - jointHPercentage){

+ 3 - 3
proceduralTexturesLibrary/src/marble/marbleProceduralTexture.fragment.fx

@@ -34,7 +34,7 @@ float turbulence(vec2 P)
 	return val;
 }
 
-float round(float number){
+float roundF(float number){
 	return sign(number)*floor(abs(number) + 0.5);
 }
 
@@ -58,14 +58,14 @@ void main()
 	float jointHPercentage = 0.01;
 	vec3 color = marbleColor;
 	float yi = vUV.y / brickH;
-	float nyi = round(yi);
+	float nyi = roundF(yi);
 	float xi = vUV.x / brickW;
 
 	if (mod(floor(yi), 2.0) == 0.0){
 		xi = xi - 0.5;
 	}
 
-	float nxi = round(xi);
+	float nxi = roundF(xi);
 	vec2 brickvUV = vec2((xi - floor(xi)) / brickH, (yi - floor(yi)) / brickW);
 
 	if (yi < nyi + jointHPercentage && yi > nyi - jointHPercentage){

+ 1 - 1
src/Collisions/babylon.collider.ts

@@ -319,7 +319,7 @@
             }
         }
 
-        public _collide(trianglePlaneArray: Array<Plane>, pts: Vector3[], indices: number[] | Int32Array, indexStart: number, indexEnd: number, decal: number, hasMaterial: boolean): void {
+        public _collide(trianglePlaneArray: Array<Plane>, pts: Vector3[], indices: IndicesArray, indexStart: number, indexEnd: number, decal: number, hasMaterial: boolean): void {
             for (var i = indexStart; i < indexEnd; i += 3) {
                 var p1 = pts[indices[i] - decal];
                 var p2 = pts[indices[i + 1] - decal];

+ 2 - 2
src/Collisions/babylon.collisionCoordinator.ts

@@ -47,7 +47,7 @@ module BABYLON {
     export interface SerializedGeometry {
         id: string;
         positions: Float32Array;
-        indices: Int32Array;
+        indices: Uint32Array;
         normals: Float32Array;
         //uvs?: Float32Array;
     }
@@ -181,7 +181,7 @@ module BABYLON {
                 id: geometry.id,
                 positions: new Float32Array(geometry.getVerticesData(VertexBuffer.PositionKind) || []),
                 normals: new Float32Array(geometry.getVerticesData(VertexBuffer.NormalKind) || []),
-                indices: new Int32Array(geometry.getIndices() || []),
+                indices: new Uint32Array(geometry.getIndices() || []),
                 //uvs: new Float32Array(geometry.getVerticesData(VertexBuffer.UVKind) || [])
             }
         }

+ 6 - 3
src/Materials/Textures/Procedurals/babylon.proceduralTexture.ts

@@ -289,13 +289,13 @@
                 this._effect.setMatrix(name, this._matrices[name]);
             }            
 
-            // VBOs
-            engine.bindBuffers(this._vertexBuffers, this._indexBuffer, this._effect);
-
             if (this.isCube) {
                 for (var face = 0; face < 6; face++) {
                     engine.bindFramebuffer(this._texture, face);
 
+                    // VBOs
+                    engine.bindBuffers(this._vertexBuffers, this._indexBuffer, this._effect);
+
                     this._effect.setFloat("face", face);
 
                     // Clear
@@ -312,6 +312,9 @@
             } else {
                 engine.bindFramebuffer(this._texture);
 
+                // VBOs
+                engine.bindBuffers(this._vertexBuffers, this._indexBuffer, this._effect);
+
                 // Clear
                 engine.clear(scene.clearColor, true, true, true);
 

+ 299 - 1
src/Mesh/babylon.abstractMesh.ts

@@ -27,6 +27,55 @@
             return AbstractMesh._BILLBOARDMODE_ALL;
         }
 
+        // facetData private properties
+        private _facetPositions: Vector3[];             // facet local positions
+        private _facetNormals: Vector3[];               // facet local normals
+        private _facetPartitioning: number[][];           // partitioning array of facet index arrays
+        private _facetNb: number = 0;                   // facet number
+        private _partitioningSubdivisions: number = 10; // number of subdivisions per axis in the partioning space  
+        private _partitioningBBoxRatio: number = 1.01;  // the partioning array space is by default 1% bigger than the bounding box
+        private _facetDataEnabled: boolean = false;     // is the facet data feature enabled on this mesh ?
+        private _facetParameters: any = {};                  // keep a reference to the object parameters to avoid memory re-allocation
+        private _bbSize: Vector3 = Vector3.Zero();      // bbox size approximated for facet data
+        private _subDiv = {                         // actual number of subdivisions per axis for ComputeNormals()
+            max: 1,
+            X: 1,
+            Y: 1,
+            Z: 1
+        };
+        /**
+         * Read-only : the number of facets in the mesh
+         */
+        public get facetNb(): number {
+            return this._facetNb;
+        }
+        /**
+         * The number of subdivisions per axis in the partioning space
+         */
+        public get partitioningSubdivisions(): number {
+            return this._partitioningSubdivisions;
+        }
+        public set partitioningSubdivisions(nb: number) {
+            this._partitioningSubdivisions = nb;
+        } 
+        /**
+         * The ratio to apply to the bouding box size to set to the partioning space.  
+         * Ex : 1.01 (default) the partioning space is 1% bigger than the bounding box.
+         */
+        public get partitioningBBoxRatio(): number {
+            return this._partitioningBBoxRatio;
+        }
+        public set partitioningBBoxRatio(ratio: number) {
+            this._partitioningBBoxRatio = ratio;
+        }
+        /**
+         * Read-only : is the feature facetData enabled ?
+         */
+        public get isFacetDataEnabled(): boolean {
+            return this._facetDataEnabled;
+        }
+
+
         // Events
 
         /**
@@ -280,7 +329,7 @@
             return 0;
         }
 
-        public getIndices(): number[] | Int32Array {
+        public getIndices(): IndicesArray {
             return null;
         }
 
@@ -1204,6 +1253,11 @@
                 }
             }
 
+            // facet data
+            if (this._facetDataEnabled) {
+                this.disableFacetData();
+            }
+
             this.onAfterWorldMatrixUpdateObservable.clear();
             this.onCollideObservable.clear();
             this.onCollisionPositionChangeObservable.clear();
@@ -1375,5 +1429,249 @@
 
         }
 
+       // Facet data
+        /** 
+         *  Initialize the facet data arrays : facetNormals, facetPositions and facetPartitioning
+         */
+        private _initFacetData(): AbstractMesh {
+            if (!this._facetNormals) {
+                this._facetNormals = new Array<Vector3>();
+            }
+            if (!this._facetPositions) {
+                this._facetPositions = new Array<Vector3>();
+            }
+            if (!this._facetPartitioning) {
+                this._facetPartitioning = new Array<number[]>();
+            }
+            this._facetNb = this.getIndices().length / 3;
+            this._partitioningSubdivisions = (this._partitioningSubdivisions) ? this._partitioningSubdivisions : 10;   // default nb of partitioning subdivisions = 10
+            this._partitioningBBoxRatio = (this._partitioningBBoxRatio) ? this._partitioningBBoxRatio : 1.01;          // default ratio 1.01 = the partitioning is 1% bigger than the bounding box
+            for (var f = 0; f < this._facetNb; f++) {
+                this._facetNormals[f] = Vector3.Zero();
+                this._facetPositions[f] = Vector3.Zero();
+            }
+            this._facetDataEnabled = true;           
+            return this;
+        }
+
+        /**
+         * Updates the mesh facetData arrays and the internal partitioning when the mesh is morphed or updated.  
+         * This method can be called within the render loop.  
+         * You don't need to call this method by yourself in the render loop when you update/morph a mesh with the methods CreateXXX() as they automatically manage this computation.  
+         */
+        public updateFacetData(): AbstractMesh {
+            if (!this._facetDataEnabled) {
+                this._initFacetData();
+            }
+            var positions = this.getVerticesData(VertexBuffer.PositionKind);
+            var indices = this.getIndices();
+            var normals = this.getVerticesData(VertexBuffer.NormalKind);
+            var bInfo = this.getBoundingInfo();
+            this._bbSize.x = (bInfo.maximum.x - bInfo.minimum.x > Epsilon) ? bInfo.maximum.x - bInfo.minimum.x : Epsilon;
+            this._bbSize.y = (bInfo.maximum.y - bInfo.minimum.y > Epsilon) ? bInfo.maximum.y - bInfo.minimum.y : Epsilon;
+            this._bbSize.z = (bInfo.maximum.z - bInfo.minimum.z > Epsilon) ? bInfo.maximum.z - bInfo.minimum.z : Epsilon;
+            var bbSizeMax = (this._bbSize.x > this._bbSize.y) ? this._bbSize.x : this._bbSize.y;
+            bbSizeMax = (bbSizeMax > this._bbSize.z) ? bbSizeMax : this._bbSize.z;
+            this._subDiv.max = this._partitioningSubdivisions;
+            this._subDiv.X = Math.floor(this._subDiv.max * this._bbSize.x / bbSizeMax);   // adjust the number of subdivisions per axis
+            this._subDiv.Y = Math.floor(this._subDiv.max * this._bbSize.y / bbSizeMax);   // according to each bbox size per axis
+            this._subDiv.Z = Math.floor(this._subDiv.max * this._bbSize.z / bbSizeMax);
+            this._subDiv.X = this._subDiv.X < 1 ? 1 : this._subDiv.X;                     // at least one subdivision
+            this._subDiv.Y = this._subDiv.Y < 1 ? 1 : this._subDiv.Y;
+            this._subDiv.Z = this._subDiv.Z < 1 ? 1 : this._subDiv.Z;
+            // set the parameters for ComputeNormals()
+            this._facetParameters.facetNormals = this.getFacetLocalNormals(); 
+            this._facetParameters.facetPositions = this.getFacetLocalPositions();
+            this._facetParameters.facetPartitioning = this.getFacetLocalPartitioning();
+            this._facetParameters.bInfo = bInfo;
+            this._facetParameters.bbSize = this._bbSize;
+            this._facetParameters.subDiv = this._subDiv;
+            this._facetParameters.ratio = this.partitioningBBoxRatio;
+            VertexData.ComputeNormals(positions, indices, normals, this._facetParameters);
+            return this;
+        }
+        /**
+         * Returns the facetLocalNormals array.  
+         * The normals are expressed in the mesh local space.  
+         */
+        public getFacetLocalNormals(): Vector3[] {
+            if (!this._facetNormals) {
+                this.updateFacetData();
+            }
+            return this._facetNormals;
+        }
+        /**
+         * Returns the facetLocalPositions array.  
+         * The facet positions are expressed in the mesh local space.  
+         */
+        public getFacetLocalPositions(): Vector3[] {
+            if (!this._facetPositions) {
+                this.updateFacetData();
+            }
+            return this._facetPositions;           
+        }
+        /**
+         * Returns the facetLocalPartioning array
+         */
+        public getFacetLocalPartitioning(): number[][] {
+            if (!this._facetPartitioning) {
+                this.updateFacetData();
+            }
+            return this._facetPartitioning;
+        }
+        /**
+         * Returns the i-th facet position in the world system.  
+         * This method allocates a new Vector3 per call.  
+         */
+        public getFacetPosition(i: number): Vector3 {
+            var pos = Vector3.Zero();
+            this.getFacetPositionToRef(i, pos);
+            return pos;
+        }
+        /**
+         * Sets the reference Vector3 with the i-th facet position in the world system.  
+         * Returns the mesh.  
+         */
+        public getFacetPositionToRef(i: number, ref: Vector3): AbstractMesh {
+            var localPos = (this.getFacetLocalPositions())[i];
+            var world = this.getWorldMatrix();
+            Vector3.TransformCoordinatesToRef(localPos, world, ref);
+            return this;
+        }
+        /**
+         * Returns the i-th facet normal in the world system.  
+         * This method allocates a new Vector3 per call.  
+         */
+        public getFacetNormal(i: number): Vector3 {
+            var norm = Vector3.Zero();
+            this.getFacetNormalToRef(i, norm);
+            return norm;
+        }
+        /**
+         * Sets the reference Vector3 with the i-th facet normal in the world system.  
+         * Returns the mesh.  
+         */
+        public getFacetNormalToRef(i: number, ref: Vector3) {
+            var localNorm = (this.getFacetLocalNormals())[i];
+            Vector3.TransformNormalToRef(localNorm, this.getWorldMatrix(), ref);
+            return this;
+        }
+        /** 
+         * Returns the facets (in an array) in the same partitioning block than the one the passed coordinates are located (expressed in the mesh local system).
+         */
+        public getFacetsAtLocalCoordinates(x: number, y: number, z: number): number[] {
+            var bInfo = this.getBoundingInfo();
+            var ox = Math.floor((x - bInfo.minimum.x * this._partitioningBBoxRatio) * this._subDiv.X * this._partitioningBBoxRatio / this._bbSize.x);
+            var oy = Math.floor((y - bInfo.minimum.y * this._partitioningBBoxRatio) * this._subDiv.Y * this._partitioningBBoxRatio / this._bbSize.y);
+            var oz = Math.floor((z - bInfo.minimum.z * this._partitioningBBoxRatio) * this._subDiv.Z * this._partitioningBBoxRatio / this._bbSize.z);
+            if (ox < 0 || ox > this._subDiv.max || oy < 0 || oy > this._subDiv.max || oz < 0 || oz > this._subDiv.max) {
+                return null;
+            }
+            return this._facetPartitioning[ox + this._subDiv.max * oy + this._subDiv.max * this._subDiv.max * oz];
+        }
+        /** 
+         * Returns the closest mesh facet index at (x,y,z) World coordinates, null if not found.  
+         * If the parameter projected (vector3) is passed, it is set as the (x,y,z) World projection on the facet.  
+         * If checkFace is true (default false), only the facet "facing" to (x,y,z) or only the ones "turning their backs", according to the parameter "facing" are returned.
+         * If facing and checkFace are true, only the facet "facing" to (x, y, z) are returned : positive dot (x, y, z) * facet position.
+         * If facing si false and checkFace is true, only the facet "turning their backs" to (x, y, z) are returned : negative dot (x, y, z) * facet position. 
+         */
+        public getClosestFacetAtCoordinates(x: number, y: number, z: number, projected?: Vector3, checkFace: boolean = false, facing: boolean = true): number {
+            var world = this.getWorldMatrix();
+            var invMat = Tmp.Matrix[5];
+            world.invertToRef(invMat);
+            var invVect = Tmp.Vector3[8];
+            var closest = null;
+            Vector3.TransformCoordinatesFromFloatsToRef(x, y, z, invMat, invVect);  // transform (x,y,z) to coordinates in the mesh local space
+            closest = this.getClosestFacetAtLocalCoordinates(invVect.x, invVect.y, invVect.z, projected, checkFace, facing);
+            if (projected) {
+                // tranform the local computed projected vector to world coordinates
+                Vector3.TransformCoordinatesFromFloatsToRef(projected.x, projected.y, projected.z, world, projected);
+            }
+            return closest;
+        }
+        /** 
+         * Returns the closest mesh facet index at (x,y,z) local coordinates, null if not found.   
+         * If the parameter projected (vector3) is passed, it is set as the (x,y,z) local projection on the facet.  
+         * If checkFace is true (default false), only the facet "facing" to (x,y,z) or only the ones "turning their backs", according to the parameter "facing" are returned.
+         * If facing and checkFace are true, only the facet "facing" to (x, y, z) are returned : positive dot (x, y, z) * facet position.
+         * If facing si false and checkFace is true, only the facet "turning their backs"  to (x, y, z) are returned : negative dot (x, y, z) * facet position.
+         */
+        public getClosestFacetAtLocalCoordinates(x: number, y: number, z: number, projected?: Vector3, checkFace: boolean = false, facing: boolean = true): number {
+            var closest = null;
+            var tmpx = 0.0;         
+            var tmpy = 0.0;
+            var tmpz = 0.0;
+            var d = 0.0;            // tmp dot facet normal * facet position
+            var t0 = 0.0;
+            var projx = 0.0;
+            var projy = 0.0;
+            var projz = 0.0;
+            // Get all the facets in the same partitioning block than (x, y, z)
+            var facetPositions = this.getFacetLocalPositions();
+            var facetNormals = this.getFacetLocalNormals();
+            var facetsInBlock = this.getFacetsAtLocalCoordinates(x, y, z);
+            if (!facetsInBlock) {
+                return null;
+            }
+            // Get the closest facet to (x, y, z)
+            var shortest = Number.MAX_VALUE;            // init distance vars
+            var tmpDistance = shortest;
+            var fib;                                    // current facet in the block
+            var norm;                                   // current facet normal
+            var p0;                                     // current facet barycenter position
+            // loop on all the facets in the current partitioning block
+            for (var idx = 0; idx < facetsInBlock.length; idx++) {
+                fib = facetsInBlock[idx];           
+                norm = facetNormals[fib];
+                p0 = facetPositions[fib];
+
+                d = (x - p0.x) * norm.x + (y - p0.y) * norm.y + (z - p0.z) * norm.z;
+                if ( !checkFace || (checkFace && facing && d >= 0.0) || (checkFace && !facing && d <= 0.0) ) {
+                    // compute (x,y,z) projection on the facet = (projx, projy, projz)
+                    d = norm.x * p0.x + norm.y * p0.y + norm.z * p0.z; 
+                    t0 = -(norm.x * x + norm.y * y + norm.z * z - d) / (norm.x * norm.x + norm.y * norm.y + norm.z * norm.z);
+                    projx = x + norm.x * t0;
+                    projy = y + norm.y * t0;
+                    projz = z + norm.z * t0;
+
+                    tmpx = projx - x;
+                    tmpy = projy - y;
+                    tmpz = projz - z;
+                    tmpDistance = tmpx * tmpx + tmpy * tmpy + tmpz * tmpz;             // compute length between (x, y, z) and its projection on the facet
+                    if (tmpDistance < shortest) {                                      // just keep the closest facet to (x, y, z)
+                        shortest = tmpDistance;
+                        closest = fib; 
+                        if (projected) {
+                            projected.x = projx;
+                            projected.y = projy;
+                            projected.z = projz;
+                        }
+                    }
+                }
+            }
+            return closest;
+        }
+        /**
+         * Returns the object "parameter" set with all the expected parameters for facetData computation by ComputeNormals()  
+         */
+        public getFacetDataParameters(): any {
+            return this._facetParameters;
+        }
+        /** 
+         * Disables the feature FacetData and frees the related memory.  
+         * Returns the mesh.  
+         */
+        public disableFacetData(): AbstractMesh {
+            if (this._facetDataEnabled) {
+                this._facetDataEnabled = false;
+                this._facetPositions = null;
+                this._facetNormals = null;
+                this._facetPartitioning = null;
+                this._facetParameters = null;
+            }
+            return this;
+        } 
+
     }
 }

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

@@ -11,7 +11,7 @@
         private _engine: Engine;
         private _meshes: Mesh[];
         private _totalVertices = 0;
-        private _indices: number[] | Int32Array;
+        private _indices: IndicesArray;
         private _vertexBuffers: { [key: string]: VertexBuffer; };
         private _isDisposed = false;
         private _extend: { minimum: Vector3, maximum: Vector3 };
@@ -285,7 +285,7 @@
             return result;
         }
 
-        public setIndices(indices: number[] | Int32Array, totalVertices?: number): void {
+        public setIndices(indices: IndicesArray, totalVertices?: number): void {
             if (this._indexBuffer) {
                 this._engine._releaseBuffer(this._indexBuffer);
             }
@@ -317,7 +317,7 @@
             return this._indices.length;
         }
 
-        public getIndices(copyWhenShared?: boolean): number[] | Int32Array {
+        public getIndices(copyWhenShared?: boolean): IndicesArray {
             if (!this.isReady()) {
                 return null;
             }
@@ -1017,7 +1017,7 @@
                 super.setAllVerticesData(vertexData, false);
             }
 
-            public setVerticesData(kind: string, data: number[] | Int32Array | Float32Array, updatable?: boolean): void {
+            public setVerticesData(kind: string, data: number[] | Float32Array, updatable?: boolean): void {
                 if (!this._beingRegenerated) {
                     return;
                 }

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

@@ -71,7 +71,7 @@
             return this._sourceMesh.isVerticesDataPresent(kind);
         }
 
-        public getIndices(): number[] | Int32Array {
+        public getIndices(): IndicesArray {
             return this._sourceMesh.getIndices();
         }
 

+ 4 - 301
src/Mesh/babylon.mesh.ts

@@ -121,53 +121,6 @@
         private _sourcePositions: Float32Array; // Will be used to save original positions when using software skinning
         private _sourceNormals: Float32Array;   // Will be used to save original normals when using software skinning
 
-        private _facetPositions: Vector3[];             // facet local positions
-        private _facetNormals: Vector3[];               // facet local normals
-        private _facetPartitioning: number[][];           // partitioning array of facet index arrays
-        private _facetNb: number = 0;                   // facet number
-        private _partitioningSubdivisions: number = 10; // number of subdivisions per axis in the partioning space  
-        private _partitioningBBoxRatio: number = 1.01;  // the partioning array space is by default 1% bigger than the bounding box
-        private _facetDataEnabled: boolean = false;     // is the facet data feature enabled on this mesh ?
-        private _facetParameters: any = {};                  // keep a reference to the object parameters to avoid memory re-allocation
-        private _bbSize: Vector3 = Vector3.Zero();      // bbox size approximated for facet data
-        private _subDiv = {                         // actual number of subdivisions per axis for ComputeNormals()
-            max: 1,
-            X: 1,
-            Y: 1,
-            Z: 1
-        };
-        /**
-         * Read-only : the number of facets in the mesh
-         */
-        public get facetNb(): number {
-            return this._facetNb;
-        }
-        /**
-         * The number of subdivisions per axis in the partioning space
-         */
-        public get partitioningSubdivisions(): number {
-            return this._partitioningSubdivisions;
-        }
-        public set partitioningSubdivisions(nb: number) {
-            this._partitioningSubdivisions = nb;
-        } 
-        /**
-         * The ratio to apply to the bouding box size to set to the partioning space.  
-         * Ex : 1.01 (default) the partioning space is 1% bigger than the bounding box.
-         */
-        public get partitioningBBoxRatio(): number {
-            return this._partitioningBBoxRatio;
-        }
-        public set partitioningBBoxRatio(ratio: number) {
-            this._partitioningBBoxRatio = ratio;
-        }
-        /**
-         * Read-only : is the feature facetData enabled ?
-         */
-        public get isFacetDataEnabled(): boolean {
-            return this._facetDataEnabled;
-        }
-
         // Will be used to save a source mesh reference, If any
         private _source: BABYLON.Mesh = null; 
         public get source(): BABYLON.Mesh {
@@ -524,11 +477,11 @@
         }
 
         /**
-         * Returns an array of integers or a Int32Array populated with the mesh indices.  
+         * Returns an array of integers or a typed array (Int32Array, Uint32Array, Uint16Array) populated with the mesh indices.  
          * If the parameter `copyWhenShared` is true (default false) and and if the mesh geometry is shared among some other meshes, the returned array is a copy of the internal one.
          * Returns an empty array if the mesh has no geometry.
          */
-        public getIndices(copyWhenShared?: boolean): number[] | Int32Array {
+        public getIndices(copyWhenShared?: boolean): IndicesArray {
 
             if (!this._geometry) {
                 return [];
@@ -829,11 +782,11 @@
 
         /**
          * Sets the mesh indices.  
-         * Expects an array populated with integers or a Int32Array.
+         * Expects an array populated with integers or a typed array (Int32Array, Uint32Array, Uint16Array).
          * If the mesh has no geometry, a new Geometry object is created and set to the mesh. 
          * This method creates a new index buffer each call.
          */
-        public setIndices(indices: number[] | Int32Array, totalVertices?: number): void {
+        public setIndices(indices: IndicesArray, totalVertices?: number): void {
             if (!this._geometry) {
                 var vertexData = new VertexData();
                 vertexData.indices = indices;
@@ -1423,12 +1376,6 @@
                     highlightLayer.removeExcludedMesh(this);
                 }
             }
-
-            // facet data
-            if (this._facetDataEnabled) {
-                this.disableFacetData();
-            }
-
             super.dispose(doNotRecurse);
         }
 
@@ -1813,250 +1760,6 @@
             });
         }
 
-        // Facet data
-        /** 
-         *  Initialize the facet data arrays : facetNormals, facetPositions and facetPartitioning
-         */
-        private _initFacetData(): Mesh {
-            if (!this._facetNormals) {
-                this._facetNormals = new Array<Vector3>();
-            }
-            if (!this._facetPositions) {
-                this._facetPositions = new Array<Vector3>();
-            }
-            if (!this._facetPartitioning) {
-                this._facetPartitioning = new Array<number[]>();
-            }
-            this._facetNb = this.getIndices().length / 3;
-            this._partitioningSubdivisions = (this._partitioningSubdivisions) ? this._partitioningSubdivisions : 10;   // default nb of partitioning subdivisions = 10
-            this._partitioningBBoxRatio = (this._partitioningBBoxRatio) ? this._partitioningBBoxRatio : 1.01;          // default ratio 1.01 = the partitioning is 1% bigger than the bounding box
-            for (var f = 0; f < this._facetNb; f++) {
-                this._facetNormals[f] = Vector3.Zero();
-                this._facetPositions[f] = Vector3.Zero();
-            }
-            this._facetDataEnabled = true;           
-            return this;
-        }
-
-        /**
-         * Updates the mesh facetData arrays and the internal partitioning when the mesh is morphed or updated.  
-         * This method can be called within the render loop.  
-         * You don't need to call this method by yourself in the render loop when you update/morph a mesh with the methods CreateXXX() as they automatically manage this computation.  
-         */
-        public updateFacetData(): Mesh {
-            if (!this._facetDataEnabled) {
-                this._initFacetData();
-            }
-            var positions = this.getVerticesData(VertexBuffer.PositionKind);
-            var indices = this.getIndices();
-            var normals = this.getVerticesData(VertexBuffer.NormalKind);
-            var bInfo = this.getBoundingInfo();
-            this._bbSize.x = (bInfo.maximum.x - bInfo.minimum.x > Epsilon) ? bInfo.maximum.x - bInfo.minimum.x : Epsilon;
-            this._bbSize.y = (bInfo.maximum.y - bInfo.minimum.y > Epsilon) ? bInfo.maximum.y - bInfo.minimum.y : Epsilon;
-            this._bbSize.z = (bInfo.maximum.z - bInfo.minimum.z > Epsilon) ? bInfo.maximum.z - bInfo.minimum.z : Epsilon;
-            var bbSizeMax = (this._bbSize.x > this._bbSize.y) ? this._bbSize.x : this._bbSize.y;
-            bbSizeMax = (bbSizeMax > this._bbSize.z) ? bbSizeMax : this._bbSize.z;
-            this._subDiv.max = this._partitioningSubdivisions;
-            this._subDiv.X = Math.floor(this._subDiv.max * this._bbSize.x / bbSizeMax);   // adjust the number of subdivisions per axis
-            this._subDiv.Y = Math.floor(this._subDiv.max * this._bbSize.y / bbSizeMax);   // according to each bbox size per axis
-            this._subDiv.Z = Math.floor(this._subDiv.max * this._bbSize.z / bbSizeMax);
-            this._subDiv.X = this._subDiv.X < 1 ? 1 : this._subDiv.X;                     // at least one subdivision
-            this._subDiv.Y = this._subDiv.Y < 1 ? 1 : this._subDiv.Y;
-            this._subDiv.Z = this._subDiv.Z < 1 ? 1 : this._subDiv.Z;
-            // set the parameters for ComputeNormals()
-            this._facetParameters.facetNormals = this.getFacetLocalNormals(); 
-            this._facetParameters.facetPositions = this.getFacetLocalPositions();
-            this._facetParameters.facetPartitioning = this.getFacetLocalPartitioning();
-            this._facetParameters.bInfo = bInfo;
-            this._facetParameters.bbSize = this._bbSize;
-            this._facetParameters.subDiv = this._subDiv;
-            this._facetParameters.ratio = this.partitioningBBoxRatio;
-            VertexData.ComputeNormals(positions, indices, normals, this._facetParameters);
-            return this;
-        }
-        /**
-         * Returns the facetLocalNormals array.  
-         * The normals are expressed in the mesh local space.  
-         */
-        public getFacetLocalNormals(): Vector3[] {
-            if (!this._facetNormals) {
-                this.updateFacetData();
-            }
-            return this._facetNormals;
-        }
-        /**
-         * Returns the facetLocalPositions array.  
-         * The facet positions are expressed in the mesh local space.  
-         */
-        public getFacetLocalPositions(): Vector3[] {
-            if (!this._facetPositions) {
-                this.updateFacetData();
-            }
-            return this._facetPositions;           
-        }
-        /**
-         * Returns the facetLocalPartioning array
-         */
-        public getFacetLocalPartitioning(): number[][] {
-            if (!this._facetPartitioning) {
-                this.updateFacetData();
-            }
-            return this._facetPartitioning;
-        }
-        /**
-         * Returns the i-th facet position in the world system.  
-         * This method allocates a new Vector3 per call.  
-         */
-        public getFacetPosition(i: number): Vector3 {
-            var pos = Vector3.Zero();
-            this.getFacetPositionToRef(i, pos);
-            return pos;
-        }
-        /**
-         * Sets the reference Vector3 with the i-th facet position in the world system.  
-         * Returns the mesh.  
-         */
-        public getFacetPositionToRef(i: number, ref: Vector3): Mesh {
-            var localPos = (this.getFacetLocalPositions())[i];
-            var world = this.getWorldMatrix();
-            Vector3.TransformCoordinatesToRef(localPos, world, ref);
-            return this;
-        }
-        /**
-         * Returns the i-th facet normal in the world system.  
-         * This method allocates a new Vector3 per call.  
-         */
-        public getFacetNormal(i: number): Vector3 {
-            var norm = Vector3.Zero();
-            this.getFacetNormalToRef(i, norm);
-            return norm;
-        }
-        /**
-         * Sets the reference Vector3 with the i-th facet normal in the world system.  
-         * Returns the mesh.  
-         */
-        public getFacetNormalToRef(i: number, ref: Vector3) {
-            var localNorm = (this.getFacetLocalNormals())[i];
-            Vector3.TransformNormalToRef(localNorm, this.getWorldMatrix(), ref);
-            return this;
-        }
-        /** 
-         * Returns the facets (in an array) in the same partitioning block than the one the passed coordinates are located (expressed in the mesh local system).
-         */
-        public getFacetsAtLocalCoordinates(x: number, y: number, z: number): number[] {
-            var bInfo = this.getBoundingInfo();
-            var ox = Math.floor((x - bInfo.minimum.x * this._partitioningBBoxRatio) * this._subDiv.X * this._partitioningBBoxRatio / this._bbSize.x);
-            var oy = Math.floor((y - bInfo.minimum.y * this._partitioningBBoxRatio) * this._subDiv.Y * this._partitioningBBoxRatio / this._bbSize.y);
-            var oz = Math.floor((z - bInfo.minimum.z * this._partitioningBBoxRatio) * this._subDiv.Z * this._partitioningBBoxRatio / this._bbSize.z);
-            if (ox < 0 || ox > this._subDiv.max || oy < 0 || oy > this._subDiv.max || oz < 0 || oz > this._subDiv.max) {
-                return null;
-            }
-            return this._facetPartitioning[ox + this._subDiv.max * oy + this._subDiv.max * this._subDiv.max * oz];
-        }
-        /** 
-         * Returns the closest mesh facet index at (x,y,z) World coordinates, null if not found.  
-         * If the parameter projected (vector3) is passed, it is set as the (x,y,z) World projection on the facet.  
-         * If checkFace is true (default false), only the facet "facing" to (x,y,z) or only the ones "turning their backs", according to the parameter "facing" are returned.
-         * If facing and checkFace are true, only the facet "facing" to (x, y, z) are returned : positive dot (x, y, z) * facet position.
-         * If facing si false and checkFace is true, only the facet "turning their backs" to (x, y, z) are returned : negative dot (x, y, z) * facet position. 
-         */
-        public getClosestFacetAtCoordinates(x: number, y: number, z: number, projected?: Vector3, checkFace: boolean = false, facing: boolean = true): number {
-            var world = this.getWorldMatrix();
-            var invMat = Tmp.Matrix[5];
-            world.invertToRef(invMat);
-            var invVect = Tmp.Vector3[8];
-            var closest = null;
-            Vector3.TransformCoordinatesFromFloatsToRef(x, y, z, invMat, invVect);  // transform (x,y,z) to coordinates in the mesh local space
-            closest = this.getClosestFacetAtLocalCoordinates(invVect.x, invVect.y, invVect.z, projected, checkFace, facing);
-            if (projected) {
-                // tranform the local computed projected vector to world coordinates
-                Vector3.TransformCoordinatesFromFloatsToRef(projected.x, projected.y, projected.z, world, projected);
-            }
-            return closest;
-        }
-        /** 
-         * Returns the closest mesh facet index at (x,y,z) local coordinates, null if not found.   
-         * If the parameter projected (vector3) is passed, it is set as the (x,y,z) local projection on the facet.  
-         * If checkFace is true (default false), only the facet "facing" to (x,y,z) or only the ones "turning their backs", according to the parameter "facing" are returned.
-         * If facing and checkFace are true, only the facet "facing" to (x, y, z) are returned : positive dot (x, y, z) * facet position.
-         * If facing si false and checkFace is true, only the facet "turning their backs"  to (x, y, z) are returned : negative dot (x, y, z) * facet position.
-         */
-        public getClosestFacetAtLocalCoordinates(x: number, y: number, z: number, projected?: Vector3, checkFace: boolean = false, facing: boolean = true) {
-            var closest = null;
-            var tmpx = 0.0;         
-            var tmpy = 0.0;
-            var tmpz = 0.0;
-            var d = 0.0;            // tmp dot facet normal * facet position
-            var t0 = 0.0;
-            var projx = 0.0;
-            var projy = 0.0;
-            var projz = 0.0;
-            // Get all the facets in the same partitioning block than (x, y, z)
-            var facetPositions = this.getFacetLocalPositions();
-            var facetNormals = this.getFacetLocalNormals();
-            var facetsInBlock = this.getFacetsAtLocalCoordinates(x, y, z);
-            if (!facetsInBlock) {
-                return null;
-            }
-            // Get the closest facet to (x, y, z)
-            var shortest = Number.MAX_VALUE;            // init distance vars
-            var tmpDistance = shortest;
-            var fib;                                    // current facet in the block
-            var norm;                                   // current facet normal
-            var p0;                                     // current facet barycenter position
-            // loop on all the facets in the current partitioning block
-            for (var idx = 0; idx < facetsInBlock.length; idx++) {
-                fib = facetsInBlock[idx];           
-                norm = facetNormals[fib];
-                p0 = facetPositions[fib];
-
-                d = (x - p0.x) * norm.x + (y - p0.y) * norm.y + (z - p0.z) * norm.z;
-                if ( !checkFace || (checkFace && facing && d >= 0.0) || (checkFace && !facing && d <= 0.0) ) {
-                    // compute (x,y,z) projection on the facet = (projx, projy, projz)
-                    d = norm.x * p0.x + norm.y * p0.y + norm.z * p0.z; 
-                    t0 = -(norm.x * x + norm.y * y + norm.z * z - d) / (norm.x * norm.x + norm.y * norm.y + norm.z * norm.z);
-                    projx = x + norm.x * t0;
-                    projy = y + norm.y * t0;
-                    projz = z + norm.z * t0;
-
-                    tmpx = projx - x;
-                    tmpy = projy - y;
-                    tmpz = projz - z;
-                    tmpDistance = tmpx * tmpx + tmpy * tmpy + tmpz * tmpz;             // compute length between (x, y, z) and its projection on the facet
-                    if (tmpDistance < shortest) {                                      // just keep the closest facet to (x, y, z)
-                        shortest = tmpDistance;
-                        closest = fib; 
-                        if (projected) {
-                            projected.x = projx;
-                            projected.y = projy;
-                            projected.z = projz;
-                        }
-                    }
-                }
-            }
-            return closest;
-        }
-        /**
-         * Returns the object "parameter" set with all the expected parameters for facetData computation by ComputeNormals()  
-         */
-        public getFacetDataParameters(): any {
-            return this._facetParameters;
-        }
-        /** 
-         * Disables the feature FacetData and frees the related memory.  
-         * Returns the mesh.  
-         */
-        public disableFacetData(): Mesh {
-            if (this._facetDataEnabled) {
-                this._facetDataEnabled = false;
-                this._facetPositions = null;
-                this._facetNormals = null;
-                this._facetPartitioning = null;
-                this._facetParameters = null;
-            }
-            return this;
-        }
-
         // Statics
         /**
          * Returns a new Mesh object what is a deep copy of the passed mesh.   

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

@@ -1,11 +1,14 @@
 module BABYLON {
-    export interface IGetSetVerticesData {
+    export type IndicesArray = number[] | Int32Array | Uint32Array | Uint16Array;
+
+    export interface IGetSetVerticesData
+    {
         isVerticesDataPresent(kind: string): boolean;
-        getVerticesData(kind: string, copyWhenShared?: boolean): number[] | Int32Array | Float32Array;
-        getIndices(copyWhenShared?: boolean): number[] | Int32Array;
+        getVerticesData(kind: string, copyWhenShared?: boolean): number[] | Float32Array;
+        getIndices(copyWhenShared?: boolean): IndicesArray;
         setVerticesData(kind: string, data: number[] | Float32Array, updatable?: boolean): void;
         updateVerticesData(kind: string, data: number[] | Float32Array, updateExtends?: boolean, makeItUnique?: boolean): void;
-        setIndices(indices: number[] | Int32Array): void;
+        setIndices(indices: IndicesArray): void;
     }
 
     export class VertexData {
@@ -22,7 +25,7 @@
         public matricesWeights: number[] | Float32Array;
         public matricesIndicesExtra: number[] | Float32Array;
         public matricesWeightsExtra: number[] | Float32Array;
-        public indices: number[] | Int32Array;
+        public indices: IndicesArray;
 
         public set(data: number[] | Float32Array, kind: string) {
             switch (kind) {
@@ -238,7 +241,7 @@
 
                 var offset = this.positions ? this.positions.length / 3 : 0;
                 for (var index = 0; index < other.indices.length; index++) {
-                    //TODO check type - if Int32Array!
+                    //TODO check type - if Int32Array | Uint32Array | Uint16Array!
                     (<number[]>this.indices).push(other.indices[index] + offset);
                 }
             }

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

@@ -1093,7 +1093,7 @@
                 for (var vIndex = 0; vIndex < faceVertices.length; vIndex++) {
                     var vertex = faceVertices[vIndex];
 
-                    //TODO check for Int32Array
+                    //TODO check for Int32Array | Uint32Array | Uint16Array
                     (<number[]>vertexData.indices).push(currentVertexDataIndex);
                     vertex.position.toArray(vertexData.positions, currentVertexDataIndex * 3);
                     vertex.normal.toArray(vertexData.normals, currentVertexDataIndex * 3);

+ 2 - 2
src/Mesh/babylon.subMesh.ts

@@ -119,7 +119,7 @@
             this._renderingMesh.render(this, enableAlphaMode);
         }
 
-        public getLinesIndexBuffer(indices: number[] | Int32Array, engine: Engine): WebGLBuffer {
+        public getLinesIndexBuffer(indices: IndicesArray, engine: Engine): WebGLBuffer {
             if (!this._linesIndexBuffer) {
                 var linesIndices = [];
 
@@ -139,7 +139,7 @@
             return ray.intersectsBox(this.getBoundingInfo().boundingBox);
         }
 
-        public intersects(ray: Ray, positions: Vector3[], indices: number[] | Int32Array, fastCheck?: boolean): IntersectionInfo {
+        public intersects(ray: Ray, positions: Vector3[], indices: IndicesArray, fastCheck?: boolean): IntersectionInfo {
             var intersectInfo: IntersectionInfo = null;
 
             // LineMesh first as it's also a Mesh...

+ 1 - 1
src/Physics/babylon.physicsImpostor.ts

@@ -17,7 +17,7 @@ module BABYLON {
         computeWorldMatrix?(force: boolean): void;
         getChildMeshes?(): Array<AbstractMesh>;
         getVerticesData?(kind: string): Array<number> | Float32Array;
-        getIndices?(): Array<number> | Int32Array;
+        getIndices?(): IndicesArray;
         getScene?(): Scene;
     }
 

+ 1 - 3
src/Tools/babylon.tools.ts

@@ -135,7 +135,7 @@
             return "data:image/png;base64," + output;
         }
 
-        public static ExtractMinAndMaxIndexed(positions: number[] | Float32Array, indices: number[] | Int32Array, indexStart: number, indexCount: number, bias: Vector2 = null): { minimum: Vector3; maximum: Vector3 } {
+        public static ExtractMinAndMaxIndexed(positions: number[] | Float32Array, indices: IndicesArray, indexStart: number, indexCount: number, bias: Vector2 = null): { minimum: Vector3; maximum: Vector3 } {
             var minimum = new Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
             var maximum = new Vector3(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
 
@@ -740,8 +740,6 @@
             var offsetX = Math.max(0, width - newWidth) / 2;
             var offsetY = Math.max(0, height - newHeight) / 2;
 
-            renderContext.fillStyle = camera.getScene().clearColor.toHexString();
-            renderContext.fillRect(0, 0, width, height);
             renderContext.drawImage(engine.getRenderingCanvas(), offsetX, offsetY, newWidth, newHeight);
 
             Tools.EncodeScreenshotCanvasData(successCallback, mimeType);

+ 21 - 10
src/babylon.engine.ts

@@ -1308,7 +1308,7 @@
             this._cachedIndexBuffer = null;
         }
 
-        public createIndexBuffer(indices: number[] | Int32Array): WebGLBuffer {
+        public createIndexBuffer(indices: IndicesArray): WebGLBuffer {
             var vbo = this._gl.createBuffer();
             this.bindIndexBuffer(vbo);
 
@@ -1316,18 +1316,29 @@
             var arrayBuffer;
             var need32Bits = false;
 
-            if (this._caps.uintIndices) {
-
-                for (var index = 0; index < indices.length; index++) {
-                    if (indices[index] > 65535) {
+            if (indices instanceof Uint16Array) {
+                arrayBuffer = indices;
+            } else {
+                //check 32 bit support
+                if (this._caps.uintIndices) {
+                    if (indices instanceof Uint32Array) {
+                        arrayBuffer = indices;
                         need32Bits = true;
-                        break;
+                    } else {
+                        //number[] or Int32Array, check if 32 bit is necessary
+                        for (var index = 0; index < indices.length; index++) {
+                            if (indices[index] > 65535) {
+                                need32Bits = true;
+                                break;
+                            }
+                        }
+
+                        arrayBuffer = need32Bits ? new Uint32Array(indices) : new Uint16Array(indices);
                     }
+                } else {
+                    //no 32 bit support, force conversion to 16 bit (values greater 16 bit are lost)
+                    arrayBuffer = new Uint16Array(indices);
                 }
-
-                arrayBuffer = need32Bits ? new Uint32Array(indices) : new Uint16Array(indices);
-            } else {
-                arrayBuffer = new Uint16Array(indices);
             }
 
             this._gl.bufferData(this._gl.ELEMENT_ARRAY_BUFFER, arrayBuffer, this._gl.STATIC_DRAW);