Преглед изворни кода

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

sevan пре 8 година
родитељ
комит
30ffbf4cab
95 измењених фајлова са 130582 додато и 58747 уклоњено
  1. 0 1
      .vscode/settings.json
  2. BIN
      Exporters/Blender/Blender2Babylon-5.3.zip
  3. 14 0
      Exporters/Blender/src/babylon-js/json_exporter.py
  4. 1 1
      Exporters/Blender/src/babylon-js/material.py
  5. 18 13
      Exporters/Blender/src/babylon-js/mesh.py
  6. 104 0
      Exporters/Blender/src/babylon-js/shape_key_group.py
  7. 2 0
      Playground/debug.html
  8. 2 0
      Playground/frame.html
  9. 2 0
      Playground/index.html
  10. 34 5
      Tools/Gulp/config.json
  11. 75 60
      Tools/Gulp/gulpfile.js
  12. 42 43
      Tools/Npm/babylon.js
  13. 52955 50759
      Tools/Npm/babylon.max.js
  14. 1 1
      Tools/Npm/package.json
  15. BIN
      assets/meshes/0.jpg
  16. 1 0
      assets/meshes/Rabbit.babylon.manifest
  17. 445 425
      dist/preview release/babylon.d.ts
  18. 40 40
      dist/preview release/babylon.js
  19. 548 403
      dist/preview release/babylon.max.js
  20. 445 425
      dist/preview release/babylon.module.d.ts
  21. 41 41
      dist/preview release/babylon.worker.js
  22. 1 1
      dist/preview release/canvas2D/babylon.canvas2d.js
  23. 11 11
      dist/preview release/canvas2D/babylon.canvas2d.min.js
  24. 17380 0
      dist/preview release/customConfigurations/minimalViewer/babylon.d.ts
  25. 23 0
      dist/preview release/customConfigurations/minimalViewer/babylon.js
  26. 37186 0
      dist/preview release/customConfigurations/minimalViewer/babylon.max.js
  27. 17382 0
      dist/preview release/customConfigurations/minimalViewer/babylon.module.d.ts
  28. 61 2
      dist/preview release/gui/babylon.gui.d.ts
  29. 328 18
      dist/preview release/gui/babylon.gui.js
  30. 1 1
      dist/preview release/gui/babylon.gui.min.js
  31. 17 17
      dist/preview release/inspector/babylon.inspector.bundle.js
  32. 3 6
      dist/preview release/inspector/babylon.inspector.js
  33. 3 3
      dist/preview release/inspector/babylon.inspector.min.js
  34. 2 2
      dist/preview release/loaders/babylon.glTF1FileLoader.min.js
  35. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.d.ts
  36. 167 235
      dist/preview release/loaders/babylon.glTF2FileLoader.js
  37. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  38. 1 1
      dist/preview release/loaders/babylon.glTFFileLoader.d.ts
  39. 167 235
      dist/preview release/loaders/babylon.glTFFileLoader.js
  40. 2 2
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  41. 1 1
      dist/preview release/loaders/babylon.objFileLoader.min.js
  42. 28 0
      dist/preview release/materialsLibrary/babylon.cellMaterial.d.ts
  43. 276 0
      dist/preview release/materialsLibrary/babylon.cellMaterial.js
  44. 1 0
      dist/preview release/materialsLibrary/babylon.cellMaterial.min.js
  45. 47 8
      dist/preview release/materialsLibrary/babylon.customMaterial.d.ts
  46. 647 12
      dist/preview release/materialsLibrary/babylon.customMaterial.js
  47. 1 1
      dist/preview release/materialsLibrary/babylon.customMaterial.min.js
  48. 1 1
      dist/preview release/materialsLibrary/babylon.waterMaterial.min.js
  49. 1 1
      dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.min.js
  50. 1 1
      dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js
  51. 2 0
      dist/preview release/what's new.md
  52. 16 3
      gui/src/advancedDynamicTexture.ts
  53. 42 1
      gui/src/controls/button.ts
  54. 10 2
      gui/src/controls/container.ts
  55. 189 12
      gui/src/controls/control.ts
  56. 1 1
      gui/src/controls/image.ts
  57. 1 1
      gui/src/controls/textBlock.ts
  58. 96 0
      gui/src/math2D.ts
  59. 7 10
      inspector/src/adapters/MeshAdapter.ts
  60. 15 0
      loaders/src/glTF/README.md
  61. 0 145
      localDev/captureMenu.css
  62. BIN
      localDev/localDev.zip
  63. 0 245
      localDev/resultView.css
  64. 0 5360
      localDev/spector.js
  65. 9 0
      localDev/template/index.js
  66. 8 2
      materialsLibrary/index.html
  67. 296 0
      materialsLibrary/src/cell/babylon.cellMaterial.ts
  68. 144 0
      materialsLibrary/src/cell/cell.fragment.fx
  69. 101 0
      materialsLibrary/src/cell/cell.vertex.fx
  70. 0 1
      materialsLibrary/src/custom/Babylon.CustomMaterial.js.map
  71. 0 38
      materialsLibrary/src/custom/babylon.customMaterial.js
  72. 700 22
      materialsLibrary/src/custom/babylon.customMaterial.ts
  73. 110 0
      materialsLibrary/src/custom/readme.md
  74. 1 1
      materialsLibrary/src/fur/readme.md
  75. 22 0
      materialsLibrary/test/addCell.js
  76. 1 1
      materialsLibrary/test/addfur.js
  77. 1 1
      materialsLibrary/test/addterrain.js
  78. 4 4
      src/Audio/babylon.sound.ts
  79. 24 25
      src/Cameras/babylon.arcRotateCamera.ts
  80. 5 5
      src/Cameras/babylon.targetCamera.ts
  81. 13 21
      src/Debug/babylon.axesViewer.ts
  82. 3 1
      src/Materials/Textures/babylon.baseTexture.ts
  83. 12 7
      src/Materials/Textures/babylon.renderTargetTexture.ts
  84. 1 1
      src/Materials/babylon.effect.ts
  85. 8 7
      src/Materials/babylon.standardMaterial.ts
  86. 2 2
      src/Mesh/babylon.mesh.ts
  87. 4 2
      src/PostProcess/babylon.postProcess.ts
  88. 86 8
      src/PostProcess/babylon.standardRenderingPipeline.ts
  89. 10 3
      src/Rendering/babylon.renderingManager.ts
  90. 6 1
      src/Shaders/ShadersInclude/lightFragment.fx
  91. 17 0
      src/Shaders/ShadersInclude/lightsFragmentFunctions.fx
  92. 40 0
      src/Shaders/standard.fragment.fx
  93. 6 5
      src/Tools/babylon.tools.ts
  94. 14 5
      src/babylon.engine.ts
  95. 44 26
      src/babylon.scene.ts

+ 0 - 1
.vscode/settings.json

@@ -9,7 +9,6 @@
         "**/.vs": true,        
         "**/.tempChromeProfileForDebug": true,
         "**/node_modules": true,
-        "**/dist": true,
         "**/temp": true,
         "**/.temp": true,
         "**/*.d.ts": true,

BIN
Exporters/Blender/Blender2Babylon-5.3.zip


+ 14 - 0
Exporters/Blender/src/babylon-js/json_exporter.py

@@ -62,6 +62,7 @@ class JsonExporter:
             self.skeletons = []
             skeletonId = 0
             self.meshesAndNodes = []
+            self.morphTargetMngrs = []
             self.materials = []
             self.multiMaterials = []
             self.sounds = []
@@ -106,6 +107,8 @@ class JsonExporter:
                         
                         if hasattr(mesh, 'instances'):
                             self.meshesAndNodes.append(mesh)
+                            if hasattr(mesh, 'morphTargetManagerId'):
+                                self.morphTargetMngrs.append(mesh)
                         else:
                             break
 
@@ -209,6 +212,17 @@ class JsonExporter:
             mesh.to_scene_file(file_handler)
         file_handler.write(']')
 
+        # Morph targets
+        file_handler.write(',\n"morphTargetManagers":[')
+        first = True
+        for mesh in self.morphTargetMngrs:
+            if first != True:
+                file_handler.write(',')
+
+            first = False
+            mesh.write_morphing_file(file_handler)
+        file_handler.write(']')
+
         # Cameras
         file_handler.write(',\n"cameras":[')
         first = True

+ 1 - 1
Exporters/Blender/src/babylon-js/material.py

@@ -187,7 +187,7 @@ class BakingRecipe:
 
         # accumulators set by Blender Game
         self.backFaceCulling = True  # used only when baking
-        self.isBillboard = len(mesh.material_slots) == 1 and mesh.material_slots[0].material.game_settings.face_orientation == 'BILLBOARD'
+        self.isBillboard = len(mesh.material_slots) == 1 and mesh.material_slots[0] is not None and mesh.material_slots[0].material.game_settings.face_orientation == 'BILLBOARD'
 
         # Cycles specific, need to get the node trees of each material
         self.nodeTrees = []

+ 18 - 13
Exporters/Blender/src/babylon-js/mesh.py

@@ -9,6 +9,7 @@ from .shape_key_group import *
 import bpy
 import math
 from mathutils import Vector
+from random import randint
 import shutil
 
 # output related constants
@@ -435,6 +436,7 @@ class Mesh(FCurveAnimatable):
         if hasShapeKeys:
             Mesh.sort(keyOrderMap)
             self.rawShapeKeys = []
+            self.morphTargetManagerId = randint(0, 1000000) # not used for TOB implementation
             groupNames = []
             Logger.log('Shape Keys:', 2)
 
@@ -675,24 +677,27 @@ class Mesh(FCurveAnimatable):
         file_handler.write(']')
         
         # Shape Keys
-        if hasattr(self, 'rawShapeKeys'):
-            first = True
-            file_handler.write('\n,"MorphTargetManager":{')
-            write_string(file_handler, 'id', self.name, True)
-            file_handler.write('\n,"targets":[')
-            for key in self.rawShapeKeys:
-                if first == False:
-                    file_handler.write(',')
-
-                key.to_scene_file(file_handler)
-
-                first = False
-            file_handler.write(']}')
+        if hasattr(self, 'morphTargetManagerId'):
+            write_int(file_handler, 'morphTargetManagerId', self.morphTargetManagerId)
 
         # Close mesh
         file_handler.write('}\n')
         self.alreadyExported = True
 #===============================================================================
+    def write_morphing_file(self, file_handler):
+        first = True
+        file_handler.write('{')
+        write_int(file_handler, 'id', self.morphTargetManagerId, True)
+        file_handler.write('\n,"targets":[')
+        for key in self.rawShapeKeys:
+            if first == False:
+                file_handler.write(',')
+
+            key.to_scene_file(file_handler)
+
+            first = False
+        file_handler.write(']}')
+#===============================================================================
 class MeshInstance:
      def __init__(self, instancedMesh, rotation, rotationQuaternion):
         self.name = instancedMesh.name

+ 104 - 0
Exporters/Blender/src/babylon-js/shape_key_group.py

@@ -0,0 +1,104 @@
+from .logger import *
+from .package_level import *
+
+import bpy
+#===============================================================================
+# extract data in Mesh order, no optimization from group analysis yet; mapped into a copy of position
+# 
+class RawShapeKey:
+    def __init__(self, keyBlock, group, state, keyOrderMap, basis):
+        self.group = group
+        self.state = state
+        self.vertices = []
+
+        retSz = len(keyOrderMap)
+        for i in range(retSz):
+            self.vertices.append(None)
+
+        nDifferent = 0
+        for i in range(retSz):
+            pair = keyOrderMap[i]
+            value = keyBlock.data[pair[0]].co
+            self.vertices[pair[1]] = value
+            if not similar_vertex(value, basis.data[pair[0]].co):
+                nDifferent += 1
+
+        # only log when groups / allowVertReduction
+        if state != 'BASIS' and group is not None:
+            Logger.log('shape key "' + group + '-' + state + '":  n verts different from basis: ' + str(nDifferent), 3)
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+    def to_scene_file(self, file_handler):
+        file_handler.write('{')
+        write_string(file_handler, 'name', self.state, True)
+        write_vector_array(file_handler, 'positions', self.vertices)
+        write_int(file_handler, 'influence', 0)
+        file_handler.write('}')
+#===============================================================================
+class ShapeKeyGroup:
+    def __init__(self, group, rawShapeKeys, basisVerts):
+        self.group = group
+        self.basisVerts = basisVerts
+        self.stateNames = []
+        self.stateVertices = []
+        self.affectedIndices = []
+
+        nRawKeys = len(rawShapeKeys)
+        nSize = len(self.basisVerts)
+
+        sameForAll = []
+        for i in range(nSize):
+            sameForAll.append(True)
+
+        # first pass to determine which vertices are not the same across all members of a group & also Basis
+        for i in range(nSize):
+            for key in rawShapeKeys:
+                # no need for more checking once 1 difference is found
+                if not sameForAll[i]:
+                    break;
+
+                # skip key if not member of the current group being processed
+                if group != key.group:
+                    continue;
+
+                # check vertex not different from Basis
+                if not similar_vertex(key.vertices[i],  self.basisVerts[i]):
+                    sameForAll[i] = False
+                    break;
+
+        affectedWholeVertices = []
+
+        # pass to convert sameForAll into self.affectedIndices, build 'BASIS' state at the same time
+        for i in range(nSize):
+            if not sameForAll[i]:
+                affectedWholeVertices.append(i)
+                self.affectedIndices.append(i * 3 + 0)
+                self.affectedIndices.append(i * 3 + 1)
+                self.affectedIndices.append(i * 3 + 2)
+
+        Logger.log('Shape-key group, ' + group + ', # of affected vertices: '+ str(len(affectedWholeVertices)) + ', out of ' + str(nSize), 2)
+
+        # pass to convert rawShapeKeys in this group, to stateVertices of only affected indices
+        for key in rawShapeKeys:
+            if group != key.group:
+                continue;
+
+            affectedVertices = []
+            for idx in affectedWholeVertices:
+                # clone vert, so key can be deleted in pass 1, and not affect pass2
+                # encode as a difference to basis, so more compact
+                vert = key.vertices[idx].copy()
+                vert.x -= self.basisVerts[idx].x
+                vert.y -= self.basisVerts[idx].y
+                vert.z -= self.basisVerts[idx].z
+                affectedVertices.append(vert)
+
+            self.stateNames.append(key.state)
+            self.stateVertices.append(affectedVertices)
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+    def to_script_file(self, file_handler, var, indent):
+        writeInt32Array(file_handler, '_i', indent, self.affectedIndices, True)
+        file_handler.write(indent  + 'shapeKeyGroup = new QI.ShapeKeyGroup(' + var + ', "' + self.group + '", _i);\n')
+
+        for state_idx in range(len(self.stateVertices)):
+            writeFloat32Array(file_handler, '_i', indent, self.stateVertices[state_idx], True)
+            file_handler.write(indent  + 'shapeKeyGroup._addShapeKey("' + self.stateNames[state_idx] + '", true, _i);\n')

+ 2 - 0
Playground/debug.html

@@ -33,6 +33,8 @@
     <script src="https://preview.babylonjs.com/materialsLibrary/babylon.furMaterial.min.js"></script>
     <script src="https://preview.babylonjs.com/materialsLibrary/babylon.gridMaterial.min.js"></script>
     <script src="https://preview.babylonjs.com/materialsLibrary/babylon.shadowOnlyMaterial.min.js"></script>
+    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.customMaterial.min.js"></script>
+    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.cellMaterial.min.js"></script>
 
     <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.brickProceduralTexture.min.js"></script>
     <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.cloudProceduralTexture.min.js"></script>

+ 2 - 0
Playground/frame.html

@@ -22,6 +22,8 @@
     <script src="https://preview.babylonjs.com/materialsLibrary/babylon.furMaterial.min.js"></script>
     <script src="https://preview.babylonjs.com/materialsLibrary/babylon.gridMaterial.min.js"></script>
     <script src="https://preview.babylonjs.com/materialsLibrary/babylon.shadowOnlyMaterial.min.js"></script>
+    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.customMaterial.min.js"></script>
+    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.cellMaterial.min.js"></script>
 
     <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.brickProceduralTexture.min.js"></script>
     <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.cloudProceduralTexture.min.js"></script>

+ 2 - 0
Playground/index.html

@@ -33,6 +33,8 @@
     <script src="https://preview.babylonjs.com/materialsLibrary/babylon.furMaterial.min.js"></script>
     <script src="https://preview.babylonjs.com/materialsLibrary/babylon.gridMaterial.min.js"></script>
     <script src="https://preview.babylonjs.com/materialsLibrary/babylon.shadowOnlyMaterial.min.js"></script>
+    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.customMaterial.min.js"></script>
+    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.cellMaterial.min.js"></script>
 
     <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.brickProceduralTexture.min.js"></script>
     <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.cloudProceduralTexture.min.js"></script>

+ 34 - 5
Tools/Gulp/config.json

@@ -6,6 +6,7 @@
         "declarationFilename": "babylon.d.ts",
         "declarationModuleFilename": "babylon.module.d.ts",
         "outputDirectory": "../../dist/preview release",
+        "outputCustomConfigurationsDirectory": "../../dist/preview release/customConfigurations",
         "srcOutputDirectory": "../../src/",
         "currentConfig": "all"
     },
@@ -21,7 +22,12 @@
                 "mapTexture", "dynamicFloatArray", "serialization", "probes", "layer"
         ],
         "minimal": ["standardMaterial", "freeCamera", "hemisphericLight"],
-        "minimalWithBuilder": ["meshBuilder", "standardMaterial", "freeCamera", "hemisphericLight"]
+        "minimalWithBuilder": ["meshBuilder", "standardMaterial", "freeCamera", "hemisphericLight"],
+        "minimalViewer": [
+                "meshBuilder", "animations", "arcRotateCamera", "additionalTextures", "textureFormats", "debug",
+                "multiMaterial"
+        ],
+        "distributed": ["minimalViewer"]
     },
     "workloads" :
     {
@@ -412,15 +418,23 @@
                 "core"
             ]
         },
+        "stringDictionary" : 
+        {
+            "files": [
+                "../../src/Tools/babylon.stringDictionary.js"
+            ],
+            "dependUpon" : [
+                "core"
+            ]
+        },
         "userData" : 
         {
             "files": [
-                "../../src/Tools/babylon.stringDictionary.js",
                 "../../src/Tools/babylon.tags.js",
                 "../../src/Tools/babylon.andOrNotEvaluator.js"
             ],
             "dependUpon" : [
-                "core"
+                "core", "stringDictionary"
             ]
         },
         "offline" : 
@@ -688,7 +702,11 @@
             ],
             "dependUpon" : [
                 "shaderMaterial",
-                "additionalMeshes"
+                "additionalMeshes",
+                "standardMaterial", 
+                "stringDictionary", 
+                "dynamicFloatArray",
+                "actions"
             ],
             "shaders" : [
                 "color.vertex",
@@ -1015,6 +1033,16 @@
                     "../../materialsLibrary/src/custom/babylon.customMaterial.ts"
                 ], 
                 "output": "babylon.customMaterial.js"
+            },
+            {
+                "files": [
+                    "../../materialsLibrary/src/cell/babylon.cellMaterial.ts"
+                ],
+                "shaderFiles": [
+                    "../../materialsLibrary/src/cell/cell.vertex.fx",
+                    "../../materialsLibrary/src/cell/cell.fragment.fx"
+                ],
+                "output": "babylon.cellMaterial.js"
             }
         ],
         "build": {
@@ -1217,6 +1245,7 @@
                 "files": [
                     "../../gui/src/advancedDynamicTexture.ts",
                     "../../gui/src/measure.ts",
+                    "../../gui/src/math2D.ts",
                     "../../gui/src/valueAndUnit.ts",
                     "../../gui/src/controls/control.ts",
                     "../../gui/src/controls/container.ts",
@@ -1238,7 +1267,7 @@
             {
                 "files": [
                     "../../canvas2D/src/Tools/babylon.math2D.ts",
-                    "../../canvas2D/src/Tools/babylon.iPropertyChanged.ts",
+                    "../../canvas2D/src/Tools/babylon.IPropertyChanged.ts",
                     "../../canvas2D/src/Tools/babylon.c2dlogging.ts",
                     "../../canvas2D/src/Tools/babylon.observableArray.ts",
                     "../../canvas2D/src/Tools/babylon.observableStringDictionary.ts",

+ 75 - 60
Tools/Gulp/gulpfile.js

@@ -59,7 +59,7 @@ var externalTsConfig = {
 
 function processDependency(kind, dependency, filesToLoad) {
     if (dependency.dependUpon) {
-        for (var i = 0; i < dependency.dependUpon.length; i++ ) {
+        for (var i = 0; i < dependency.dependUpon.length; i++) {
             var dependencyName = dependency.dependUpon[i];
             var parent = config.workloads[dependencyName];
             processDependency(kind, parent, filesToLoad);
@@ -71,7 +71,7 @@ function processDependency(kind, dependency, filesToLoad) {
         return;
     }
 
-    for (var i = 0; i< content.length; i++) {
+    for (var i = 0; i < content.length; i++) {
         var file = content[i];
 
         if (filesToLoad.indexOf(file) === -1) {
@@ -129,18 +129,18 @@ gulp.task("includeShaders", function (cb) {
         pipe(uncommentShader()).
         pipe(srcToVariable({
             variableName: "BABYLON.Effect.IncludesShadersStore", asMap: true, namingCallback: includeShadersName
-    }));
+        }));
     cb();
 });
 
 gulp.task("shaders", ["includeShaders"], function (cb) {
     var filesToProcess = determineFilesToProcess("shaders");
     shadersStream = gulp.src(filesToProcess).
-        pipe(expect.real({ errorOnFailure: true}, filesToProcess)).
+        pipe(expect.real({ errorOnFailure: true }, filesToProcess)).
         pipe(uncommentShader()).
         pipe(srcToVariable({
             variableName: "BABYLON.Effect.ShadersStore", asMap: true, namingCallback: shadersName
-    }));
+        }));
     cb();
 });
 
@@ -162,12 +162,12 @@ gulp.task("workers", function (cb) {
 gulp.task("buildWorker", ["workers", "shaders"], function () {
     var filesToProcess = determineFilesToProcess("files");
     return merge2(
-        gulp.src(filesToProcess).        
+        gulp.src(filesToProcess).
             pipe(expect.real({ errorOnFailure: true }, filesToProcess)),
         shadersStream,
         includeShadersStream,
         workersStream
-        )
+    )
         .pipe(concat(config.build.minWorkerFilename))
         .pipe(cleants())
         .pipe(replace(extendsSearchRegex, ""))
@@ -181,11 +181,11 @@ gulp.task("buildWorker", ["workers", "shaders"], function () {
 gulp.task("build", ["shaders"], function () {
     var filesToProcess = determineFilesToProcess("files");
     return merge2(
-        gulp.src(filesToProcess).        
+        gulp.src(filesToProcess).
             pipe(expect.real({ errorOnFailure: true }, filesToProcess)),
         shadersStream,
         includeShadersStream
-        )
+    )
         .pipe(concat(config.build.filename))
         .pipe(cleants())
         .pipe(replace(extendsSearchRegex, ""))
@@ -228,11 +228,11 @@ gulp.task('typescript-compile', function () {
             .pipe(addDtsExport("BABYLON"))
             .pipe(gulp.dest(config.build.outputDirectory)),
         tsResult.js
-            .pipe(sourcemaps.write("./", 
+            .pipe(sourcemaps.write("./",
                 {
-                    includeContent:false, 
+                    includeContent: false,
                     sourceRoot: (filePath) => {
-                        return ''; 
+                        return '';
                     }
                 }))
             .pipe(gulp.dest(config.build.srcOutputDirectory))
@@ -242,31 +242,31 @@ gulp.task('typescript-compile', function () {
 /**
  * Helper methods to build external library (mat, post processes, ...).
  */
-var buildExternalLibraries = function(settings) {
+var buildExternalLibraries = function (settings) {
     var tasks = settings.libraries.map(function (library) {
-        return buildExternalLibrary(library, settings, false); 
+        return buildExternalLibrary(library, settings, false);
     });
 
     return merge2(tasks);
 }
 
-var buildExternalLibrary= function(library, settings, watch) {
-    var tsProcess = gulp.src(library.files, {base: settings.build.srcOutputDirectory})
+var buildExternalLibrary = function (library, settings, watch) {
+    var tsProcess = gulp.src(library.files, { base: settings.build.srcOutputDirectory })
         .pipe(sourcemaps.init())
         .pipe(typescript(externalTsConfig));
 
-    var shader = gulp.src(library.shaderFiles || [], {base: settings.build.srcOutputDirectory} )
-            .pipe(uncommentShader())            
-            .pipe(appendSrcToVariable("BABYLON.Effect.ShadersStore", shadersName, library.output + '.fx'))
-            .pipe(gulp.dest(settings.build.srcOutputDirectory));
+    var shader = gulp.src(library.shaderFiles || [], { base: settings.build.srcOutputDirectory })
+        .pipe(uncommentShader())
+        .pipe(appendSrcToVariable("BABYLON.Effect.ShadersStore", shadersName, library.output + '.fx'))
+        .pipe(gulp.dest(settings.build.srcOutputDirectory));
 
     var dev = tsProcess.js.pipe(sourcemaps.write("./", {
-        includeContent:false, 
+        includeContent: false,
         sourceRoot: (filePath) => {
-            return ''; 
+            return '';
         }
     }))
-    .pipe(gulp.dest(settings.build.srcOutputDirectory));
+        .pipe(gulp.dest(settings.build.srcOutputDirectory));
 
     var outputDirectory = config.build.outputDirectory + settings.build.distOutputDirectory;
     var css = gulp.src(library.sassFiles || [])
@@ -275,29 +275,29 @@ var buildExternalLibrary= function(library, settings, watch) {
         .pipe(gulp.dest(outputDirectory));
 
     if (watch) {
-        return merge2([shader, dev, css]);    
+        return merge2([shader, dev, css]);
     }
     else {
         var code = merge2([tsProcess.js, shader])
-                .pipe(concat(library.output))
-                .pipe(gulp.dest(outputDirectory))
-                .pipe(cleants())
-                .pipe(replace(extendsSearchRegex, ""))
-                .pipe(replace(decorateSearchRegex, ""))
-                .pipe(rename({extname: ".min.js"}))
-                .pipe(uglify())
-                .pipe(optimisejs())
-                .pipe(gulp.dest(outputDirectory));
-        
+            .pipe(concat(library.output))
+            .pipe(gulp.dest(outputDirectory))
+            .pipe(cleants())
+            .pipe(replace(extendsSearchRegex, ""))
+            .pipe(replace(decorateSearchRegex, ""))
+            .pipe(rename({ extname: ".min.js" }))
+            .pipe(uglify())
+            .pipe(optimisejs())
+            .pipe(gulp.dest(outputDirectory));
+
         var dts = tsProcess.dts
-                .pipe(concat(library.output))
-                .pipe(rename({extname: ".d.ts"}))
-                .pipe(gulp.dest(outputDirectory));
+            .pipe(concat(library.output))
+            .pipe(rename({ extname: ".d.ts" }))
+            .pipe(gulp.dest(outputDirectory));
 
-        var waitAll =  merge2([dev, code, css, dts]);
+        var waitAll = merge2([dev, code, css, dts]);
 
         if (library.webpack) {
-            return waitAll.on('end', function() {
+            return waitAll.on('end', function () {
                 webpack(require(library.webpack))
                     .pipe(rename(library.output.replace(".js", ".bundle.js")))
                     .pipe(gulp.dest(outputDirectory))
@@ -312,7 +312,7 @@ var buildExternalLibrary= function(library, settings, watch) {
 /**
  * The default task, concat and min the main BJS files.
  */
-gulp.task('default', function (cb) {
+gulp.task("default", function (cb) {
     runSequence("buildWorker", "build", cb);
 });
 
@@ -336,6 +336,21 @@ gulp.task("typescript-libraries", config.modules, function () {
 });
 
 /**
+ * Dynamic custom configurations.
+ */
+config.buildConfigurations.distributed.map(function (customConfiguration) {
+    gulp.task(customConfiguration, function (cb) {
+        config.build.currentConfig = customConfiguration;
+        config.build.outputDirectory = config.build.outputCustomConfigurationsDirectory + "/" + customConfiguration;
+        runSequence("typescript-compile", "build", cb);
+    });
+});
+
+gulp.task("typescript-customConfigurations", function (cb) {
+    runSequence(config.buildConfigurations.distributed, cb);
+});
+
+/**
  * Do it all.
  */
 gulp.task("typescript-all", function (cb) {
@@ -348,26 +363,26 @@ gulp.task("typescript-all", function (cb) {
 gulp.task('watch', [], function () {
     var tasks = [gulp.watch(config.typescript, ['typescript-compile'])];
 
-    config.modules.map(function (module) { 
-        config[module].libraries.map(function (library) {            
-            tasks.push(gulp.watch(library.files, function() { 
+    config.modules.map(function (module) {
+        config[module].libraries.map(function (library) {
+            tasks.push(gulp.watch(library.files, function () {
                 console.log(library.output);
                 return buildExternalLibrary(library, config[module], true)
-                .pipe(debug()); 
+                    .pipe(debug());
             }));
-            tasks.push(gulp.watch(library.shaderFiles, function() { 
+            tasks.push(gulp.watch(library.shaderFiles, function () {
                 console.log(library.output);
                 return buildExternalLibrary(library, config[module], true)
-                .pipe(debug()) 
+                    .pipe(debug())
             }));
-            tasks.push(gulp.watch(library.sassFiles, function() { 
+            tasks.push(gulp.watch(library.sassFiles, function () {
                 console.log(library.output);
                 return buildExternalLibrary(library, config[module], true)
-                .pipe(debug()) 
+                    .pipe(debug())
             }));
-        }); 
+        });
     });
-    
+
     return tasks;
 });
 
@@ -384,9 +399,9 @@ gulp.task('deployLocalDev', function () {
  */
 gulp.task('webserver', function () {
     gulp.src('../../.').pipe(webserver({
-      port: 1338,
-      livereload: false
-    }));
+        port: 1338,
+        livereload: false
+        }));
 });
 
 /**
@@ -396,14 +411,14 @@ gulp.task('run', ['watch', 'webserver'], function () {
 });
 
 
-gulp.task("zip-blender" , function() {
+gulp.task("zip-blender", function () {
     return gulp.src('../../Exporters/Blender/src/**')
-    .pipe(zip('Blender2Babylon-5.3.zip'))
-    .pipe(gulp.dest('../../Exporters/Blender'));
+        .pipe(zip('Blender2Babylon-5.3.zip'))
+        .pipe(gulp.dest('../../Exporters/Blender'));
 });
 
 gulp.task('clean-JS-MAP', function () {
-	  return del([
-		  '../../src/**/*.js.map','../../src/**/*.js'
-	  ], {force: true});
-	});
+    return del([
+        '../../src/**/*.js.map', '../../src/**/*.js'
+    ], { force: true });
+});

Разлика између датотеке није приказан због своје велике величине
+ 42 - 43
Tools/Npm/babylon.js


Разлика између датотеке није приказан због своје велике величине
+ 52955 - 50759
Tools/Npm/babylon.max.js


+ 1 - 1
Tools/Npm/package.json

@@ -7,7 +7,7 @@
   ],
   "name": "babylonjs",
   "description": "Babylon.js is a JavaScript 3D engine based on webgl.",
-  "version": "3.0.0-alpha",
+  "version": "3.0.1-alpha",
   "repository": {
     "type": "git",
     "url": "https://github.com/BabylonJS/Babylon.js.git"

BIN
assets/meshes/0.jpg


+ 1 - 0
assets/meshes/Rabbit.babylon.manifest

@@ -0,0 +1 @@
+{"version" : 1,    "enableSceneOffline" : true,    "enableTexturesOffline" : true}

Разлика између датотеке није приказан због своје велике величине
+ 445 - 425
dist/preview release/babylon.d.ts


Разлика између датотеке није приказан због своје велике величине
+ 40 - 40
dist/preview release/babylon.js


Разлика између датотеке није приказан због своје велике величине
+ 548 - 403
dist/preview release/babylon.max.js


Разлика између датотеке није приказан због своје велике величине
+ 445 - 425
dist/preview release/babylon.module.d.ts


Разлика између датотеке није приказан због своје велике величине
+ 41 - 41
dist/preview release/babylon.worker.js


+ 1 - 1
dist/preview release/canvas2D/babylon.canvas2d.js

@@ -604,7 +604,7 @@ var BABYLON;
     BABYLON.PropertyChangedBase = PropertyChangedBase;
 })(BABYLON || (BABYLON = {}));
 
-//# sourceMappingURL=babylon.iPropertyChanged.js.map
+//# sourceMappingURL=babylon.IPropertyChanged.js.map
 
 var BABYLON;
 (function (BABYLON) {

Разлика између датотеке није приказан због своје велике величине
+ 11 - 11
dist/preview release/canvas2D/babylon.canvas2d.min.js


Разлика између датотеке није приказан због своје велике величине
+ 17380 - 0
dist/preview release/customConfigurations/minimalViewer/babylon.d.ts


Разлика између датотеке није приказан због своје велике величине
+ 23 - 0
dist/preview release/customConfigurations/minimalViewer/babylon.js


Разлика између датотеке није приказан због своје велике величине
+ 37186 - 0
dist/preview release/customConfigurations/minimalViewer/babylon.max.js


Разлика између датотеке није приказан због своје велике величине
+ 17382 - 0
dist/preview release/customConfigurations/minimalViewer/babylon.module.d.ts


+ 61 - 2
dist/preview release/gui/babylon.gui.d.ts

@@ -8,6 +8,9 @@ declare module BABYLON.GUI {
         private _background;
         private _rootContainer;
         _lastControlOver: Control;
+        _lastControlDown: Control;
+        _shouldBlockPointer: boolean;
+        _toDispose: IDisposable;
         background: string;
         constructor(name: string, width: number, height: number, scene: Scene, generateMipMaps?: boolean, samplingMode?: number);
         markAsDirty(): void;
@@ -40,6 +43,27 @@ declare module BABYLON.GUI {
 
 /// <reference path="../../dist/preview release/babylon.d.ts" />
 declare module BABYLON.GUI {
+    class Matrix2D {
+        m: Float32Array;
+        constructor(m00: number, m01: number, m10: number, m11: number, m20: number, m21: number);
+        fromValues(m00: number, m01: number, m10: number, m11: number, m20: number, m21: number): Matrix2D;
+        determinant(): number;
+        invertToRef(result: Matrix2D): Matrix2D;
+        multiplyToRef(other: Matrix2D, result: Matrix2D): Matrix2D;
+        static Identity(): Matrix2D;
+        static TranslationToRef(x: number, y: number, result: Matrix2D): void;
+        static ScalingToRef(x: number, y: number, result: Matrix2D): void;
+        static RotationToRef(angle: number, result: Matrix2D): void;
+        private static _TempPreTranslationMatrix;
+        private static _TempPostTranslationMatrix;
+        private static _TempRotationMatrix;
+        private static _TempScalingMatrix;
+        static ComposeToRef(tx: number, ty: number, angle: number, scaleX: number, scaleY: number, parentMatrix: Matrix2D, result: Matrix2D): void;
+    }
+}
+
+/// <reference path="../../dist/preview release/babylon.d.ts" />
+declare module BABYLON.GUI {
     class ValueAndUnit {
         value: number;
         unit: number;
@@ -87,6 +111,18 @@ declare module BABYLON.GUI {
         private _marginBottom;
         private _left;
         private _top;
+        private _scaleX;
+        private _scaleY;
+        private _rotation;
+        private _transformCenterX;
+        private _transformCenterY;
+        private _transformMatrix;
+        private _invertTransformMatrix;
+        private _isMatrixDirty;
+        private _cachedOffsetX;
+        private _cachedOffsetY;
+        isHitTestVisible: boolean;
+        isPointerBlocker: boolean;
         /**
         * An event triggered when the pointer move over the control.
         * @type {BABYLON.Observable}
@@ -107,6 +143,16 @@ declare module BABYLON.GUI {
         * @type {BABYLON.Observable}
         */
         onPointerUpObservable: Observable<Control>;
+        /**
+        * An event triggered when pointer enters the control
+        * @type {BABYLON.Observable}
+        */
+        onPointerEnterObservable: Observable<Control>;
+        scaleX: number;
+        scaleY: number;
+        rotation: number;
+        transformCenterY: number;
+        transformCenterX: number;
         horizontalAlignment: number;
         verticalAlignment: number;
         width: string;
@@ -125,15 +171,21 @@ declare module BABYLON.GUI {
         constructor(name: string);
         protected _markAsDirty(): void;
         _link(root: Container, host: AdvancedDynamicTexture): void;
-        protected applyStates(context: CanvasRenderingContext2D): void;
+        protected _transform(context: CanvasRenderingContext2D): void;
+        protected _applyStates(context: CanvasRenderingContext2D): void;
         protected _processMeasures(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         protected _clip(context: CanvasRenderingContext2D): void;
         protected _measure(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         protected _computeAlignment(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
-        protected _contains(x: number, y: number): boolean;
+        contains(x: number, y: number): boolean;
         _processPicking(x: number, y: number, type: number): boolean;
+        protected _onPointerMove(): void;
+        protected _onPointerEnter(): void;
+        protected _onPointerOut(): void;
+        protected _onPointerDown(): void;
+        protected _onPointerUp(): void;
         protected _processObservables(type: number): boolean;
         private _prepareFont();
         private static _HORIZONTAL_ALIGNMENT_LEFT;
@@ -168,6 +220,7 @@ declare module BABYLON.GUI {
         removeControl(control: Control): Container;
         _reOrderControl(control: Control): void;
         protected _localDraw(context: CanvasRenderingContext2D): void;
+        _link(root: Container, host: AdvancedDynamicTexture): void;
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         _processPicking(x: number, y: number, type: number): boolean;
         protected _clipForChildren(context: CanvasRenderingContext2D): void;
@@ -243,6 +296,12 @@ declare module BABYLON.GUI {
     class Button extends Rectangle {
         name: string;
         constructor(name: string);
+        _processPicking(x: number, y: number, type: number): boolean;
+        protected _onPointerEnter(): void;
+        protected _onPointerOut(): void;
+        protected _onPointerDown(): void;
+        protected _onPointerUp(): void;
         static CreateImageButton(name: string, text: string, imageUrl: string): Button;
+        static CreateSimpleButton(name: string, text: string): Button;
     }
 }

+ 328 - 18
dist/preview release/gui/babylon.gui.js

@@ -63,7 +63,11 @@ var BABYLON;
                     this.getScene().getEngine().onResizeObservable.remove(this._resizeObserver);
                 }
                 if (this._pointerMoveObserver) {
-                    this.getScene().onPointerObservable.remove(this._pointerMoveObserver);
+                    this.getScene().onPrePointerObservable.remove(this._pointerMoveObserver);
+                }
+                if (this._toDispose) {
+                    this._toDispose.dispose();
+                    this._toDispose = null;
                 }
                 _super.prototype.dispose.call(this);
             };
@@ -116,13 +120,15 @@ var BABYLON;
             AdvancedDynamicTexture.prototype.attach = function () {
                 var _this = this;
                 var scene = this.getScene();
-                this._pointerMoveObserver = scene.onPointerObservable.add(function (pi, state) {
+                this._pointerMoveObserver = scene.onPrePointerObservable.add(function (pi, state) {
                     if (pi.type !== BABYLON.PointerEventTypes.POINTERMOVE
                         && pi.type !== BABYLON.PointerEventTypes.POINTERUP
                         && pi.type !== BABYLON.PointerEventTypes.POINTERDOWN) {
                         return;
                     }
+                    _this._shouldBlockPointer = false;
                     _this._doPicking(scene.pointerX, scene.pointerY, pi.type);
+                    pi.skipOnPointerObservable = _this._shouldBlockPointer;
                 });
             };
             // Statics
@@ -143,6 +149,7 @@ var BABYLON;
                 // Display
                 var layer = new BABYLON.Layer(name + "_layer", null, scene, !foreground);
                 layer.texture = result;
+                result._toDispose = layer;
                 // Attach
                 result.attach();
                 return result;
@@ -204,6 +211,104 @@ var BABYLON;
 (function (BABYLON) {
     var GUI;
     (function (GUI) {
+        var Matrix2D = (function () {
+            function Matrix2D(m00, m01, m10, m11, m20, m21) {
+                this.m = new Float32Array(6);
+                this.fromValues(m00, m01, m10, m11, m20, m21);
+            }
+            Matrix2D.prototype.fromValues = function (m00, m01, m10, m11, m20, m21) {
+                this.m[0] = m00;
+                this.m[1] = m01;
+                this.m[2] = m10;
+                this.m[3] = m11;
+                this.m[4] = m20;
+                this.m[5] = m21;
+                return this;
+            };
+            Matrix2D.prototype.determinant = function () {
+                return this.m[0] * this.m[3] - this.m[1] * this.m[2];
+            };
+            Matrix2D.prototype.invertToRef = function (result) {
+                var l0 = this.m[0];
+                var l1 = this.m[1];
+                var l2 = this.m[2];
+                var l3 = this.m[3];
+                var l4 = this.m[4];
+                var l5 = this.m[5];
+                var det = this.determinant();
+                if (det < (BABYLON.Epsilon * BABYLON.Epsilon)) {
+                    throw new Error("Can't invert matrix, near null determinant");
+                }
+                var detDiv = 1 / det;
+                var det4 = l2 * l5 - l3 * l4;
+                var det5 = l1 * l4 - l0 * l5;
+                result.m[0] = l3 * detDiv;
+                result.m[1] = -l1 * detDiv;
+                result.m[2] = -l2 * detDiv;
+                result.m[3] = l0 * detDiv;
+                result.m[4] = det4 * detDiv;
+                result.m[5] = det5 * detDiv;
+                return this;
+            };
+            Matrix2D.prototype.multiplyToRef = function (other, result) {
+                var l0 = this.m[0];
+                var l1 = this.m[1];
+                var l2 = this.m[2];
+                var l3 = this.m[3];
+                var l4 = this.m[4];
+                var l5 = this.m[5];
+                var r0 = other.m[0];
+                var r1 = other.m[1];
+                var r2 = other.m[2];
+                var r3 = other.m[3];
+                var r4 = other.m[4];
+                var r5 = other.m[5];
+                result.m[0] = l0 * r0 + l1 * r2;
+                result.m[1] = l0 * r1 + l1 * r3;
+                result.m[2] = l2 * r0 + l3 * r2;
+                result.m[3] = l2 * r1 + l3 * r3;
+                result.m[4] = l4 * r0 + l5 * r2 + r4;
+                result.m[5] = l4 * r1 + l5 * r3 + r5;
+                return this;
+            };
+            // Statics
+            Matrix2D.Identity = function () {
+                return new Matrix2D(1, 0, 0, 1, 0, 0);
+            };
+            Matrix2D.TranslationToRef = function (x, y, result) {
+                result.fromValues(1, 0, 0, 1, x, y);
+            };
+            Matrix2D.ScalingToRef = function (x, y, result) {
+                result.fromValues(x, 0, 0, y, 0, 0);
+            };
+            Matrix2D.RotationToRef = function (angle, result) {
+                var s = Math.sin(angle);
+                var c = Math.cos(angle);
+                result.fromValues(c, s, -s, c, 0, 0);
+            };
+            Matrix2D.ComposeToRef = function (tx, ty, angle, scaleX, scaleY, parentMatrix, result) {
+                Matrix2D.TranslationToRef(tx, ty, Matrix2D._TempPreTranslationMatrix);
+                Matrix2D.ScalingToRef(scaleX, scaleY, Matrix2D._TempScalingMatrix);
+                Matrix2D.RotationToRef(angle, Matrix2D._TempRotationMatrix);
+                Matrix2D.TranslationToRef(-tx, -ty, Matrix2D._TempPostTranslationMatrix);
+            };
+            return Matrix2D;
+        }());
+        Matrix2D._TempPreTranslationMatrix = Matrix2D.Identity();
+        Matrix2D._TempPostTranslationMatrix = Matrix2D.Identity();
+        Matrix2D._TempRotationMatrix = Matrix2D.Identity();
+        Matrix2D._TempScalingMatrix = Matrix2D.Identity();
+        GUI.Matrix2D = Matrix2D;
+    })(GUI = BABYLON.GUI || (BABYLON.GUI = {}));
+})(BABYLON || (BABYLON = {}));
+
+//# sourceMappingURL=math2D.js.map
+
+/// <reference path="../../dist/preview release/babylon.d.ts"/>
+var BABYLON;
+(function (BABYLON) {
+    var GUI;
+    (function (GUI) {
         var ValueAndUnit = (function () {
             function ValueAndUnit(value, unit, negativeValueAllowed) {
                 if (value === void 0) { value = 1; }
@@ -316,6 +421,16 @@ var BABYLON;
                 this._marginBottom = new GUI.ValueAndUnit(0);
                 this._left = new GUI.ValueAndUnit(0);
                 this._top = new GUI.ValueAndUnit(0);
+                this._scaleX = 1.0;
+                this._scaleY = 1.0;
+                this._rotation = 0;
+                this._transformCenterX = 0.5;
+                this._transformCenterY = 0.5;
+                this._transformMatrix = GUI.Matrix2D.Identity();
+                this._invertTransformMatrix = GUI.Matrix2D.Identity();
+                this._isMatrixDirty = true;
+                this.isHitTestVisible = true;
+                this.isPointerBlocker = false;
                 // Properties
                 /**
                 * An event triggered when the pointer move over the control.
@@ -337,8 +452,88 @@ var BABYLON;
                 * @type {BABYLON.Observable}
                 */
                 this.onPointerUpObservable = new BABYLON.Observable();
+                /**
+                * An event triggered when pointer enters the control
+                * @type {BABYLON.Observable}
+                */
+                this.onPointerEnterObservable = new BABYLON.Observable();
                 this.fontFamily = "Arial";
             }
+            Object.defineProperty(Control.prototype, "scaleX", {
+                get: function () {
+                    return this._scaleX;
+                },
+                set: function (value) {
+                    if (this._scaleX === value) {
+                        return;
+                    }
+                    this._scaleX = value;
+                    this._markAsDirty();
+                    this._isMatrixDirty = true;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(Control.prototype, "scaleY", {
+                get: function () {
+                    return this._scaleY;
+                },
+                set: function (value) {
+                    if (this._scaleY === value) {
+                        return;
+                    }
+                    this._scaleY = value;
+                    this._markAsDirty();
+                    this._isMatrixDirty = true;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(Control.prototype, "rotation", {
+                get: function () {
+                    return this._rotation;
+                },
+                set: function (value) {
+                    if (this._rotation === value) {
+                        return;
+                    }
+                    this._rotation = value;
+                    this._markAsDirty();
+                    this._isMatrixDirty = true;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(Control.prototype, "transformCenterY", {
+                get: function () {
+                    return this._transformCenterY;
+                },
+                set: function (value) {
+                    if (this._transformCenterY === value) {
+                        return;
+                    }
+                    this._transformCenterY = value;
+                    this._markAsDirty();
+                    this._isMatrixDirty = true;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(Control.prototype, "transformCenterX", {
+                get: function () {
+                    return this._transformCenterX;
+                },
+                set: function (value) {
+                    if (this._transformCenterX === value) {
+                        return;
+                    }
+                    this._transformCenterX = value;
+                    this._markAsDirty();
+                    this._isMatrixDirty = true;
+                },
+                enumerable: true,
+                configurable: true
+            });
             Object.defineProperty(Control.prototype, "horizontalAlignment", {
                 get: function () {
                     return this._horizontalAlignment;
@@ -543,7 +738,30 @@ var BABYLON;
                 this._root = root;
                 this._host = host;
             };
-            Control.prototype.applyStates = function (context) {
+            Control.prototype._transform = function (context) {
+                if (this._scaleX === 1 && this._scaleY === 1 && this._rotation === 0) {
+                    return;
+                }
+                // preTranslate
+                var offsetX = this._currentMeasure.width * this._transformCenterX + this._currentMeasure.left;
+                var offsetY = this._currentMeasure.height * this._transformCenterY + this._currentMeasure.top;
+                context.translate(offsetX, offsetY);
+                // scale
+                context.scale(this._scaleX, this._scaleY);
+                // rotate
+                context.rotate(this._rotation);
+                // postTranslate
+                context.translate(-offsetX, -offsetY);
+                // Need to update matrices?
+                if (this._isMatrixDirty || this._cachedOffsetX !== offsetX || this._cachedOffsetY !== offsetY) {
+                    this._cachedOffsetX = offsetX;
+                    this._cachedOffsetY = offsetY;
+                    this._isMatrixDirty = false;
+                    GUI.Matrix2D.ComposeToRef(offsetX, offsetY, this._rotation, this._scaleX, this._scaleY, this._root ? this._root._transformMatrix : null, this._transformMatrix);
+                    this._transformMatrix.invertToRef(this._invertTransformMatrix);
+                }
+            };
+            Control.prototype._applyStates = function (context) {
                 if (this._font) {
                     context.font = this._font;
                 }
@@ -566,6 +784,8 @@ var BABYLON;
                     this._isDirty = false;
                     this._cachedParentMeasure.copyFrom(parentMeasure);
                 }
+                // Transform
+                this._transform(context);
                 // Clip
                 this._clip(context);
                 context.clip();
@@ -668,7 +888,11 @@ var BABYLON;
             Control.prototype._draw = function (parentMeasure, context) {
                 // Do nothing
             };
-            Control.prototype._contains = function (x, y) {
+            Control.prototype.contains = function (x, y) {
+                // Invert transform
+                if (this._scaleX !== 1 || this._scaleY !== 1 || this.rotation !== 0) {
+                }
+                // Check
                 if (x < this._currentMeasure.left) {
                     return false;
                 }
@@ -681,30 +905,70 @@ var BABYLON;
                 if (y > this._currentMeasure.top + this._currentMeasure.height) {
                     return false;
                 }
+                if (this.isPointerBlocker) {
+                    this._host._shouldBlockPointer = true;
+                }
                 return true;
             };
             Control.prototype._processPicking = function (x, y, type) {
-                if (!this._contains(x, y)) {
+                if (!this.contains(x, y)) {
                     return false;
                 }
-                return this._processObservables(type);
+                this._processObservables(type);
+                return true;
             };
-            Control.prototype._processObservables = function (type) {
-                if (type === BABYLON.PointerEventTypes.POINTERMOVE && this.onPointerMoveObservable.hasObservers()) {
+            Control.prototype._onPointerMove = function () {
+                if (this.onPointerMoveObservable.hasObservers()) {
                     this.onPointerMoveObservable.notifyObservers(this);
+                }
+            };
+            Control.prototype._onPointerEnter = function () {
+                if (this.onPointerEnterObservable.hasObservers()) {
+                    this.onPointerEnterObservable.notifyObservers(this);
+                }
+            };
+            Control.prototype._onPointerOut = function () {
+                if (this.onPointerOutObservable.hasObservers()) {
+                    this.onPointerOutObservable.notifyObservers(this);
+                }
+            };
+            Control.prototype._onPointerDown = function () {
+                if (this.onPointerDownObservable.hasObservers()) {
+                    this.onPointerDownObservable.notifyObservers(this);
+                }
+            };
+            Control.prototype._onPointerUp = function () {
+                if (this.onPointerUpObservable.hasObservers()) {
+                    this.onPointerUpObservable.notifyObservers(this);
+                }
+            };
+            Control.prototype._processObservables = function (type) {
+                if (!this.isHitTestVisible) {
+                    return false;
+                }
+                if (type === BABYLON.PointerEventTypes.POINTERMOVE) {
+                    this._onPointerMove();
                     var previousControlOver = this._host._lastControlOver;
-                    if (previousControlOver && previousControlOver !== this && previousControlOver.onPointerOutObservable.hasObservers()) {
-                        previousControlOver.onPointerOutObservable.notifyObservers(previousControlOver);
+                    if (previousControlOver && previousControlOver !== this) {
+                        previousControlOver._onPointerOut();
+                    }
+                    if (previousControlOver !== this) {
+                        this._onPointerEnter();
                     }
                     this._host._lastControlOver = this;
                     return true;
                 }
-                if (type === BABYLON.PointerEventTypes.POINTERDOWN && this.onPointerDownObservable.hasObservers()) {
-                    this.onPointerDownObservable.notifyObservers(this);
+                if (type === BABYLON.PointerEventTypes.POINTERDOWN) {
+                    this._onPointerDown();
+                    this._host._lastControlDown = this;
                     return true;
                 }
-                if (type === BABYLON.PointerEventTypes.POINTERUP && this.onPointerUpObservable.hasObservers()) {
-                    this.onPointerUpObservable.notifyObservers(this);
+                if (type === BABYLON.PointerEventTypes.POINTERUP) {
+                    this._onPointerUp();
+                    if (this._host._lastControlDown !== this) {
+                        this._host._lastControlDown._onPointerUp();
+                        this._host._lastControlDown = null;
+                    }
                     return true;
                 }
                 return false;
@@ -862,10 +1126,17 @@ var BABYLON;
             Container.prototype._localDraw = function (context) {
                 // Implemented by child to be injected inside main draw
             };
+            Container.prototype._link = function (root, host) {
+                _super.prototype._link.call(this, root, host);
+                for (var _i = 0, _a = this._children; _i < _a.length; _i++) {
+                    var child = _a[_i];
+                    child._link(root, host);
+                }
+            };
             Container.prototype._draw = function (parentMeasure, context) {
                 context.save();
                 _super.prototype._processMeasures.call(this, parentMeasure, context);
-                this.applyStates(context);
+                this._applyStates(context);
                 this._localDraw(context);
                 this._clipForChildren(context);
                 for (var _i = 0, _a = this._children; _i < _a.length; _i++) {
@@ -875,7 +1146,7 @@ var BABYLON;
                 context.restore();
             };
             Container.prototype._processPicking = function (x, y, type) {
-                if (!_super.prototype._contains.call(this, x, y)) {
+                if (!_super.prototype.contains.call(this, x, y)) {
                     return false;
                 }
                 // Checking backwards to pick closest first
@@ -1138,7 +1409,7 @@ var BABYLON;
             };
             TextBlock.prototype._draw = function (parentMeasure, context) {
                 context.save();
-                this.applyStates(context);
+                this._applyStates(context);
                 _super.prototype._processMeasures.call(this, parentMeasure, context);
                 // Render lines
                 this._renderLines(context);
@@ -1253,7 +1524,7 @@ var BABYLON;
             });
             Image.prototype._draw = function (parentMeasure, context) {
                 context.save();
-                this.applyStates(context);
+                this._applyStates(context);
                 _super.prototype._processMeasures.call(this, parentMeasure, context);
                 if (this._loaded) {
                     switch (this._stretch) {
@@ -1328,8 +1599,38 @@ var BABYLON;
             function Button(name) {
                 var _this = _super.call(this, name) || this;
                 _this.name = name;
+                _this.thickness = 1;
+                _this.isPointerBlocker = true;
                 return _this;
             }
+            // While being a container, the button behaves like a control.
+            Button.prototype._processPicking = function (x, y, type) {
+                if (!this.contains(x, y)) {
+                    return false;
+                }
+                this._processObservables(type);
+                return true;
+            };
+            Button.prototype._onPointerEnter = function () {
+                this.scaleX += 0.01;
+                this.scaleY += 0.01;
+                _super.prototype._onPointerEnter.call(this);
+            };
+            Button.prototype._onPointerOut = function () {
+                this.scaleX -= 0.01;
+                this.scaleY -= 0.01;
+                _super.prototype._onPointerOut.call(this);
+            };
+            Button.prototype._onPointerDown = function () {
+                this.scaleX -= 0.05;
+                this.scaleY -= 0.05;
+                _super.prototype._onPointerDown.call(this);
+            };
+            Button.prototype._onPointerUp = function () {
+                this.scaleX += 0.05;
+                this.scaleY += 0.05;
+                _super.prototype._onPointerUp.call(this);
+            };
             // Statics
             Button.CreateImageButton = function (name, text, imageUrl) {
                 var result = new Button(name);
@@ -1347,6 +1648,15 @@ var BABYLON;
                 result.addControl(iconImage);
                 return result;
             };
+            Button.CreateSimpleButton = function (name, text) {
+                var result = new Button(name);
+                // Adding text
+                var textBlock = new BABYLON.GUI.TextBlock(name + "_button", text);
+                textBlock.textWrapping = true;
+                textBlock.textHorizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_CENTER;
+                result.addControl(textBlock);
+                return result;
+            };
             return Button;
         }(GUI.Rectangle));
         GUI.Button = Button;

Разлика између датотеке није приказан због своје велике величине
+ 1 - 1
dist/preview release/gui/babylon.gui.min.js


Разлика између датотеке није приказан због своје велике величине
+ 17 - 17
dist/preview release/inspector/babylon.inspector.bundle.js


+ 3 - 6
dist/preview release/inspector/babylon.inspector.js

@@ -1299,19 +1299,16 @@ var INSPECTOR;
                 return axis;
             };
             // X axis
-            var xAxis = _drawAxis(BABYLON.Color3.Red(), this._obj.getAbsolutePosition(), BABYLON.Vector3.TransformCoordinates(x, m));
-            xAxis.position.subtractInPlace(this._obj.position);
+            var xAxis = _drawAxis(BABYLON.Color3.Red(), BABYLON.Vector3.Zero(), x);
             xAxis.parent = this._obj;
             this._axis.push(xAxis);
             // Y axis        
-            var yAxis = _drawAxis(BABYLON.Color3.Green(), this._obj.getAbsolutePosition(), BABYLON.Vector3.TransformCoordinates(y, m));
+            var yAxis = _drawAxis(BABYLON.Color3.Green(), BABYLON.Vector3.Zero(), y);
             yAxis.parent = this._obj;
-            yAxis.position.subtractInPlace(this._obj.position);
             this._axis.push(yAxis);
             // Z axis
-            var zAxis = _drawAxis(BABYLON.Color3.Blue(), this._obj.getAbsolutePosition(), BABYLON.Vector3.TransformCoordinates(z, m));
+            var zAxis = _drawAxis(BABYLON.Color3.Blue(), BABYLON.Vector3.Zero(), z);
             zAxis.parent = this._obj;
-            zAxis.position.subtractInPlace(this._obj.position);
             this._axis.push(zAxis);
         };
         return MeshAdapter;

Разлика између датотеке није приказан због своје велике величине
+ 3 - 3
dist/preview release/inspector/babylon.inspector.min.js


Разлика између датотеке није приказан због своје велике величине
+ 2 - 2
dist/preview release/loaders/babylon.glTF1FileLoader.min.js


+ 1 - 1
dist/preview release/loaders/babylon.glTF2FileLoader.d.ts

@@ -347,7 +347,7 @@ declare module BABYLON.GLTF2 {
          * @param runtime: the GLTF runtime
          * @param accessor: the GLTF accessor
          */
-        static GetBufferFromAccessor(runtime: IGLTFRuntime, accessor: IGLTFAccessor): any;
+        static GetBufferFromAccessor(runtime: IGLTFRuntime, accessor: IGLTFAccessor): ArrayBufferView;
         /**
          * Decodes a buffer view into a string
          * @param view: the buffer view

+ 167 - 235
dist/preview release/loaders/babylon.glTF2FileLoader.js

@@ -284,203 +284,146 @@ var BABYLON;
 (function (BABYLON) {
     var GLTF2;
     (function (GLTF2) {
-        /**
-        * Values
-        */
-        var glTFAnimationPaths = ["translation", "rotation", "scale", "weights"];
-        var babylonAnimationPaths = ["position", "rotationQuaternion", "scaling", "influence"];
-        /**
-        * Utils
-        */
-        var normalizeUVs = function (buffer) {
-            if (!buffer) {
-                return;
-            }
-            for (var i = 0; i < buffer.length / 2; i++) {
-                buffer[i * 2 + 1] = 1.0 - buffer[i * 2 + 1];
-            }
-        };
-        var createStringId = function (index) {
+        var getNodeID = function (index) {
             return "node" + index;
         };
-        /**
-        * Returns the animation path (glTF -> Babylon)
-        */
-        var getAnimationPath = function (path) {
-            var index = glTFAnimationPaths.indexOf(path);
-            if (index !== -1) {
-                return babylonAnimationPaths[index];
+        var loadAnimation = function (runtime, animation, animationIndex) {
+            for (var channelIndex = 0; channelIndex < animation.channels.length; channelIndex++) {
+                var channel = animation.channels[channelIndex];
+                if (!channel) {
+                    BABYLON.Tools.Warn("[Animation " + animationIndex + "] Channel " + channelIndex + " does not exist");
+                    continue;
+                }
+                var samplerIndex = channel.sampler;
+                if (samplerIndex === undefined) {
+                    BABYLON.Tools.Warn("[Animation " + animationIndex + ", Channel + " + samplerIndex + "] Sampler is not defined");
+                    continue;
+                }
+                var sampler = animation.samplers[samplerIndex];
+                if (!sampler) {
+                    BABYLON.Tools.Warn("[Animation " + animationIndex + ", Channel + " + channelIndex + "] Sampler " + samplerIndex + " does not exist");
+                    continue;
+                }
+                if (!channel.target) {
+                    BABYLON.Tools.Warn("[Animation " + animationIndex + ", Channel + " + channelIndex + "] Target does not exist");
+                    continue;
+                }
+                var targetNode = runtime.babylonScene.getNodeByID(getNodeID(channel.target.node));
+                if (!targetNode) {
+                    BABYLON.Tools.Warn("[Animation " + animationIndex + ", Channel + " + channelIndex + "] Target node " + channel.target.node + " does not exist");
+                    continue;
+                }
+                var targetPath = {
+                    "translation": "position",
+                    "rotation": "rotationQuaternion",
+                    "scale": "scaling",
+                    "weights": "influence"
+                }[channel.target.path];
+                if (!targetPath) {
+                    BABYLON.Tools.Warn("[Animation " + animationIndex + ", Channel + " + channelIndex + "] Target path " + channel.target.path + " is invalid");
+                    continue;
+                }
+                var inputBuffer = GLTF2.GLTFUtils.GetBufferFromAccessor(runtime, runtime.gltf.accessors[sampler.input]);
+                var outputBuffer = GLTF2.GLTFUtils.GetBufferFromAccessor(runtime, runtime.gltf.accessors[sampler.output]);
+                var outputBufferOffset = 0;
+                var animationType = {
+                    "position": BABYLON.Animation.ANIMATIONTYPE_VECTOR3,
+                    "rotationQuaternion": BABYLON.Animation.ANIMATIONTYPE_QUATERNION,
+                    "scale": BABYLON.Animation.ANIMATIONTYPE_VECTOR3,
+                    "influence": BABYLON.Animation.ANIMATIONTYPE_FLOAT,
+                }[targetPath];
+                var getNextOutputValue = {
+                    "position": function () {
+                        var value = BABYLON.Vector3.FromArray(outputBuffer, outputBufferOffset);
+                        outputBufferOffset += 3;
+                        return value;
+                    },
+                    "rotationQuaternion": function () {
+                        var value = BABYLON.Quaternion.FromArray(outputBuffer, outputBufferOffset);
+                        outputBufferOffset += 4;
+                        return value;
+                    },
+                    "scale": function () {
+                        var value = BABYLON.Vector3.FromArray(outputBuffer, outputBufferOffset);
+                        outputBufferOffset += 3;
+                        return value;
+                    },
+                    "influence": function () {
+                        var numTargets = targetNode.morphTargetManager.numTargets;
+                        var value = new Array(numTargets);
+                        for (var i = 0; i < numTargets; i++) {
+                            value[i] = outputBuffer[outputBufferOffset++];
+                        }
+                        return value;
+                    },
+                }[targetPath];
+                var getNextKey = {
+                    "LINEAR": function (frameIndex) { return ({
+                        frame: inputBuffer[frameIndex],
+                        value: getNextOutputValue()
+                    }); },
+                    "CUBICSPLINE": function (frameIndex) { return ({
+                        frame: inputBuffer[frameIndex],
+                        inTangent: getNextOutputValue(),
+                        value: getNextOutputValue(),
+                        outTangent: getNextOutputValue()
+                    }); },
+                }[sampler.interpolation];
+                if (!getNextKey) {
+                    BABYLON.Tools.Warn("[Animation " + animationIndex + ", Channel + " + channelIndex + "] Sampler interpolation '" + sampler.interpolation + "' is invalid");
+                    continue;
+                }
+                var keys = new Array(inputBuffer.length);
+                for (var frameIndex = 0; frameIndex < inputBuffer.length; frameIndex++) {
+                    keys[frameIndex] = getNextKey(frameIndex);
+                }
+                if (targetPath === "influence") {
+                    var targetMesh = targetNode;
+                    for (var targetIndex = 0; targetIndex < targetMesh.morphTargetManager.numTargets; targetIndex++) {
+                        var morphTarget = targetMesh.morphTargetManager.getTarget(targetIndex);
+                        var animationName = (animation.name || "anim" + animationIndex) + "_" + targetIndex;
+                        var babylonAnimation = new BABYLON.Animation(animationName, targetPath, 1, animationType);
+                        babylonAnimation.setKeys(keys.map(function (key) { return ({
+                            frame: key.frame,
+                            inTangent: key.inTangent ? key.inTangent[targetIndex] : undefined,
+                            value: key.value[targetIndex],
+                            outTangent: key.outTangent ? key.outTangent[targetIndex] : undefined
+                        }); }));
+                        morphTarget.animations.push(babylonAnimation);
+                        runtime.babylonScene.beginAnimation(morphTarget, 0, inputBuffer[inputBuffer.length - 1], true);
+                    }
+                }
+                else {
+                    var animationName = animation.name || "anim" + animationIndex;
+                    var babylonAnimation = new BABYLON.Animation(animationName, targetPath, 1, animationType);
+                    babylonAnimation.setKeys(keys);
+                    targetNode.animations.push(babylonAnimation);
+                    runtime.babylonScene.beginAnimation(targetNode, 0, inputBuffer[inputBuffer.length - 1], true);
+                }
             }
-            return path;
         };
         /**
         * Loads and creates animations
         */
         var loadAnimations = function (runtime) {
             var animations = runtime.gltf.animations;
-            if (!animations) {
+            if (!animations || animations.length === 0) {
                 return;
             }
             for (var animationIndex = 0; animationIndex < animations.length; animationIndex++) {
                 var animation = animations[animationIndex];
-                if (!animation || !animation.channels || !animation.samplers) {
+                if (!animation) {
+                    BABYLON.Tools.Warn("Animation " + animationIndex + " not found");
                     continue;
                 }
-                var lastAnimation = null;
-                for (var channelIndex = 0; channelIndex < animation.channels.length; channelIndex++) {
-                    var channel = animation.channels[channelIndex];
-                    if (!channel) {
-                        continue;
-                    }
-                    var sampler = animation.samplers[channel.sampler];
-                    if (!sampler) {
-                        continue;
-                    }
-                    var inputData = sampler.input;
-                    var outputData = sampler.output;
-                    var bufferInput = GLTF2.GLTFUtils.GetBufferFromAccessor(runtime, runtime.gltf.accessors[inputData]);
-                    var bufferOutput = GLTF2.GLTFUtils.GetBufferFromAccessor(runtime, runtime.gltf.accessors[outputData]);
-                    var targetID = channel.target.node;
-                    var targetNode = runtime.babylonScene.getNodeByID(createStringId(targetID));
-                    if (targetNode === null) {
-                        BABYLON.Tools.Warn("Creating animation index " + animationIndex + " but cannot find node index " + targetID + " to attach to");
-                        continue;
-                    }
-                    var isBone = targetNode instanceof BABYLON.Bone;
-                    var numTargets = 0;
-                    // Get target path (position, rotation, scaling, or weights)
-                    var targetPath = channel.target.path;
-                    var targetPathIndex = glTFAnimationPaths.indexOf(targetPath);
-                    if (targetPathIndex !== -1) {
-                        targetPath = babylonAnimationPaths[targetPathIndex];
-                    }
-                    var isMorph = targetPath === "influence";
-                    // Determine animation type
-                    var animationType = BABYLON.Animation.ANIMATIONTYPE_MATRIX;
-                    if (!isBone) {
-                        if (targetPath === "rotationQuaternion") {
-                            animationType = BABYLON.Animation.ANIMATIONTYPE_QUATERNION;
-                            targetNode.rotationQuaternion = new BABYLON.Quaternion();
-                        }
-                        else if (isMorph) {
-                            animationType = BABYLON.Animation.ANIMATIONTYPE_FLOAT;
-                            numTargets = targetNode.morphTargetManager.numTargets;
-                        }
-                        else {
-                            animationType = BABYLON.Animation.ANIMATIONTYPE_VECTOR3;
-                        }
-                    }
-                    // Create animation and key frames
-                    var babylonAnimation = null;
-                    var keys = [];
-                    var arrayOffset = 0;
-                    var modifyKey = false;
-                    if (isBone && lastAnimation && lastAnimation.getKeys().length === bufferInput.length) {
-                        babylonAnimation = lastAnimation;
-                        modifyKey = true;
-                    }
-                    // Each morph animation may have more than one more, so we need a
-                    // multi dimensional array.
-                    if (isMorph) {
-                        for (var influence = 0; influence < numTargets; influence++) {
-                            keys[influence] = [];
-                        }
-                    }
-                    // For each frame
-                    for (var frameIndex = 0; frameIndex < bufferInput.length; frameIndex++) {
-                        var value = null;
-                        if (targetPath === "rotationQuaternion") {
-                            value = BABYLON.Quaternion.FromArray([bufferOutput[arrayOffset], bufferOutput[arrayOffset + 1], bufferOutput[arrayOffset + 2], bufferOutput[arrayOffset + 3]]);
-                            arrayOffset += 4;
-                        }
-                        else if (isMorph) {
-                            value = [];
-                            // There is 1 value for each morph target for each frame
-                            for (var influence = 0; influence < numTargets; influence++) {
-                                value.push(bufferOutput[arrayOffset + influence]);
-                            }
-                            arrayOffset += numTargets;
-                        }
-                        else {
-                            value = BABYLON.Vector3.FromArray([bufferOutput[arrayOffset], bufferOutput[arrayOffset + 1], bufferOutput[arrayOffset + 2]]);
-                            arrayOffset += 3;
-                        }
-                        if (isBone) {
-                            var bone = targetNode;
-                            var translation = BABYLON.Vector3.Zero();
-                            var rotationQuaternion = new BABYLON.Quaternion();
-                            var scaling = BABYLON.Vector3.Zero();
-                            // Warning on decompose
-                            var mat = bone.getBaseMatrix();
-                            if (modifyKey) {
-                                mat = lastAnimation.getKeys()[frameIndex].value;
-                            }
-                            mat.decompose(scaling, rotationQuaternion, translation);
-                            if (targetPath === "position") {
-                                translation = value;
-                            }
-                            else if (targetPath === "rotationQuaternion") {
-                                rotationQuaternion = value;
-                            }
-                            else {
-                                scaling = value;
-                            }
-                            value = BABYLON.Matrix.Compose(scaling, rotationQuaternion, translation);
-                        }
-                        if (!modifyKey) {
-                            if (isMorph) {
-                                for (var influence = 0; influence < numTargets; influence++) {
-                                    keys[influence].push({
-                                        frame: bufferInput[frameIndex],
-                                        value: value[influence]
-                                    });
-                                }
-                            }
-                            else {
-                                keys.push({
-                                    frame: bufferInput[frameIndex],
-                                    value: value
-                                });
-                            }
-                        }
-                        else {
-                            lastAnimation.getKeys()[frameIndex].value = value;
-                        }
-                    }
-                    // Finish
-                    if (!modifyKey) {
-                        if (isMorph) {
-                            for (var influence = 0; influence < numTargets; influence++) {
-                                var morphTarget = targetNode.morphTargetManager.getTarget(influence);
-                                if (morphTarget.animations === undefined) {
-                                    morphTarget.animations = [];
-                                }
-                                var animationName = (animation.name || "anim" + animationIndex) + "_" + influence;
-                                babylonAnimation = new BABYLON.Animation(animationName, targetPath, 1, animationType, BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE);
-                                babylonAnimation.setKeys(keys[influence]);
-                                morphTarget.animations.push(babylonAnimation);
-                            }
-                        }
-                        else {
-                            var animationName = animation.name || "anim" + animationIndex;
-                            babylonAnimation = new BABYLON.Animation(animationName, isBone ? "_matrix" : targetPath, 1, animationType, BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE);
-                            babylonAnimation.setKeys(keys);
-                            targetNode.animations.push(babylonAnimation);
-                        }
-                    }
-                    lastAnimation = babylonAnimation;
-                    if (isMorph) {
-                        for (var influence = 0; influence < numTargets; influence++) {
-                            var morph = targetNode.morphTargetManager.getTarget(influence);
-                            runtime.babylonScene.stopAnimation(morph);
-                            runtime.babylonScene.beginAnimation(morph, 0, bufferInput[bufferInput.length - 1], true, 1.0);
-                        }
-                    }
-                    else {
-                        runtime.babylonScene.stopAnimation(targetNode);
-                        runtime.babylonScene.beginAnimation(targetNode, 0, bufferInput[bufferInput.length - 1], true, 1.0);
-                    }
+                if (!animation.channels || animation.channels.length === 0) {
+                    BABYLON.Tools.Warn("Animation " + animationIndex + " has no channels");
                 }
+                if (!animation.samplers || animation.samplers.length === 0) {
+                    BABYLON.Tools.Warn("Animation " + animationIndex + " has no samplers");
+                    continue;
+                }
+                loadAnimation(runtime, animation, animationIndex);
             }
         };
         /**
@@ -504,7 +447,7 @@ var BABYLON;
         */
         var getParentBone = function (runtime, skin, index, newSkeleton) {
             // Try to find
-            var nodeStringID = createStringId(index);
+            var nodeStringID = getNodeID(index);
             for (var i = 0; i < newSkeleton.bones.length; i++) {
                 if (newSkeleton.bones[i].id === nodeStringID) {
                     return newSkeleton.bones[i].getParent();
@@ -524,8 +467,8 @@ var BABYLON;
                     }
                     if (childID === index) {
                         var mat = configureBoneTransformation(parent);
-                        var bone = new BABYLON.Bone(parent.name || createStringId(parentID), newSkeleton, getParentBone(runtime, skin, parentID, newSkeleton), mat);
-                        bone.id = createStringId(parentID);
+                        var bone = new BABYLON.Bone(parent.name || getNodeID(parentID), newSkeleton, getParentBone(runtime, skin, parentID, newSkeleton), mat);
+                        bone.id = getNodeID(parentID);
                         return bone;
                     }
                 }
@@ -585,8 +528,8 @@ var BABYLON;
                 }
                 // Create node to root bone
                 var mat = configureBoneTransformation(node);
-                var bone = new BABYLON.Bone(node.name || createStringId(i), newSkeleton, null, mat);
-                bone.id = createStringId(i);
+                var bone = new BABYLON.Bone(node.name || getNodeID(i), newSkeleton, null, mat);
+                bone.id = getNodeID(i);
                 nodesToRoot.push({ bone: bone, node: node, index: i });
             }
             // Parenting
@@ -639,7 +582,7 @@ var BABYLON;
                     continue;
                 }
                 var index = jointNode.index;
-                var stringID = createStringId(index);
+                var stringID = getNodeID(index);
                 // Optimize, if the bone already exists...
                 var existingBone = runtime.babylonScene.getBoneByID(stringID);
                 if (existingBone) {
@@ -689,7 +632,7 @@ var BABYLON;
                 if (!jointNode) {
                     continue;
                 }
-                var jointNodeStringId = createStringId(jointNode.index);
+                var jointNodeStringId = getNodeID(jointNode.index);
                 for (var j = 0; j < bones.length; j++) {
                     if (bones[j].id === jointNodeStringId) {
                         babylonSkeleton.bones.push(bones[j]);
@@ -744,7 +687,7 @@ var BABYLON;
             var verticesCounts = [];
             var indexStarts = [];
             var indexCounts = [];
-            var morphTargetManager = new BABYLON.MorphTargetManager();
+            var morphTargetManager;
             // Positions, normals and UVs
             for (var primitiveIndex = 0; primitiveIndex < mesh.primitives.length; primitiveIndex++) {
                 // Temporary vertex data
@@ -762,37 +705,28 @@ var BABYLON;
                     accessor = runtime.gltf.accessors[attributes[semantic]];
                     buffer = GLTF2.GLTFUtils.GetBufferFromAccessor(runtime, accessor);
                     if (semantic === "NORMAL") {
-                        tempVertexData.normals = new Float32Array(buffer.length);
-                        tempVertexData.normals.set(buffer);
+                        tempVertexData.normals = buffer;
                     }
                     else if (semantic === "POSITION") {
-                        tempVertexData.positions = new Float32Array(buffer.length);
-                        tempVertexData.positions.set(buffer);
+                        tempVertexData.positions = buffer;
                         verticesCounts.push(tempVertexData.positions.length);
                     }
                     else if (semantic === "TANGENT") {
-                        tempVertexData.tangents = new Float32Array(buffer.length);
-                        tempVertexData.tangents.set(buffer);
+                        tempVertexData.tangents = buffer;
                     }
                     else if (semantic.indexOf("TEXCOORD_") !== -1) {
                         var channel = Number(semantic.split("_")[1]);
                         var uvKind = BABYLON.VertexBuffer.UVKind + (channel === 0 ? "" : (channel + 1));
-                        var uvs = new Float32Array(buffer.length);
-                        uvs.set(buffer);
-                        normalizeUVs(uvs);
-                        tempVertexData.set(uvs, uvKind);
+                        tempVertexData.set(buffer, uvKind);
                     }
                     else if (semantic === "JOINT") {
-                        tempVertexData.matricesIndices = new Float32Array(buffer.length);
-                        tempVertexData.matricesIndices.set(buffer);
+                        tempVertexData.matricesIndices = buffer;
                     }
                     else if (semantic === "WEIGHT") {
-                        tempVertexData.matricesWeights = new Float32Array(buffer.length);
-                        tempVertexData.matricesWeights.set(buffer);
+                        tempVertexData.matricesWeights = buffer;
                     }
                     else if (semantic === "COLOR_0") {
-                        tempVertexData.colors = new Float32Array(buffer.length);
-                        tempVertexData.colors.set(buffer);
+                        tempVertexData.colors = buffer;
                     }
                     else {
                         BABYLON.Tools.Warn("Ignoring unrecognized semantic '" + semantic + "'");
@@ -802,17 +736,15 @@ var BABYLON;
                 accessor = runtime.gltf.accessors[primitive.indices];
                 if (accessor) {
                     buffer = GLTF2.GLTFUtils.GetBufferFromAccessor(runtime, accessor);
-                    tempVertexData.indices = new Int32Array(buffer.length);
-                    tempVertexData.indices.set(buffer);
+                    tempVertexData.indices = buffer;
                     indexCounts.push(tempVertexData.indices.length);
                 }
                 else {
                     // Set indices on the fly
-                    var indices = [];
-                    for (var index = 0; index < tempVertexData.positions.length / 3; index++) {
-                        indices.push(index);
+                    tempVertexData.indices = new Uint32Array(tempVertexData.positions.length / 3);
+                    for (var index = 0; index < tempVertexData.indices.length; index++) {
+                        tempVertexData.indices[index] = index;
                     }
-                    tempVertexData.indices = new Int32Array(indices);
                     indexCounts.push(tempVertexData.indices.length);
                 }
                 vertexData.merge(tempVertexData);
@@ -821,22 +753,22 @@ var BABYLON;
                 var material = getMaterial(runtime, primitive.material);
                 multiMat.subMaterials.push(material);
                 // Morph Targets
-                if (primitive.targets !== undefined) {
+                if (primitive.targets) {
                     for (var targetsIndex = 0; targetsIndex < primitive.targets.length; targetsIndex++) {
                         var target = primitive.targets[targetsIndex];
                         var weight = 0.0;
-                        if (node.weights !== undefined) {
+                        if (node.weights) {
                             weight = node.weights[targetsIndex];
                         }
-                        else if (mesh.weights !== undefined) {
+                        else if (mesh.weights) {
                             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 = GLTF2.GLTFUtils.GetBufferFromAccessor(runtime, accessor);
-                            if (accessor.name !== undefined) {
+                            var values = GLTF2.GLTFUtils.GetBufferFromAccessor(runtime, accessor);
+                            if (accessor.name) {
                                 morph.name = accessor.name;
                             }
                             // glTF stores morph target information as deltas
@@ -844,34 +776,38 @@ var BABYLON;
                             // 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] += vertexData.normals[bufferIndex];
+                                for (var i = 0; i < values.length; i++) {
+                                    values[i] += vertexData.normals[i];
                                 }
-                                morph.setNormals(buffer);
+                                morph.setNormals(values);
                             }
                             else if (semantic === "POSITION") {
-                                for (var bufferIndex = 0; bufferIndex < buffer.length; bufferIndex++) {
-                                    buffer[bufferIndex] += vertexData.positions[bufferIndex];
+                                for (var i = 0; i < values.length; i++) {
+                                    values[i] += vertexData.positions[i];
                                 }
-                                morph.setPositions(buffer);
+                                morph.setPositions(values);
                             }
                             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] += vertexData.tangents[tangentsIndex];
-                                    if ((bufferIndex + 1) % 3 == 0) {
-                                        tangentsIndex++;
+                                for (var i = 0, j = 0; i < values.length; i++, j++) {
+                                    values[i] += vertexData.tangents[j];
+                                    if ((i + 1) % 3 == 0) {
+                                        j++;
                                     }
                                 }
-                                morph.setTangents(buffer);
+                                morph.setTangents(values);
                             }
                             else {
                                 BABYLON.Tools.Warn("Ignoring unrecognized semantic '" + semantic + "'");
                             }
                         }
-                        if (morph.getPositions() !== undefined) {
+                        if (morph.getPositions()) {
+                            if (!morphTargetManager) {
+                                morphTargetManager = new BABYLON.MorphTargetManager();
+                                babylonMesh.morphTargetManager = morphTargetManager;
+                            }
                             morphTargetManager.addTarget(morph);
                         }
                         else {
@@ -886,10 +822,6 @@ var BABYLON;
             // Apply geometry
             geometry.setAllVerticesData(vertexData, false);
             babylonMesh.computeWorldMatrix(true);
-            // Set morph target manager after all vertices data has been processed
-            if (morphTargetManager !== undefined && morphTargetManager.numTargets > 0) {
-                babylonMesh.morphTargetManager = morphTargetManager;
-            }
             // Apply submeshes
             babylonMesh.subMeshes = [];
             for (var primitiveIndex = 0; primitiveIndex < mesh.primitives.length; primitiveIndex++) {
@@ -1017,7 +949,7 @@ var BABYLON;
             if (meshIncluded) {
                 newNode = importNode(runtime, node);
                 if (newNode !== null) {
-                    newNode.id = createStringId(index);
+                    newNode.id = getNodeID(index);
                     newNode.parent = parent;
                 }
             }
@@ -1288,7 +1220,7 @@ var BABYLON;
                 var sampler = (texture.sampler === undefined ? {} : runtime.gltf.samplers[texture.sampler]);
                 var noMipMaps = (sampler.minFilter === GLTF2.ETextureMinFilter.NEAREST || sampler.minFilter === GLTF2.ETextureMinFilter.LINEAR);
                 var samplingMode = GLTF2.GLTFUtils.GetTextureFilterMode(sampler.minFilter);
-                var babylonTexture = new BABYLON.Texture(url, runtime.babylonScene, noMipMaps, true, samplingMode, function () {
+                var babylonTexture = new BABYLON.Texture(url, runtime.babylonScene, noMipMaps, false, samplingMode, function () {
                     onSuccess(babylonTexture);
                 }, onError);
                 babylonTexture.coordinatesIndex = texCoord;
@@ -1405,7 +1337,7 @@ var BABYLON;
             };
             GLTFLoader._loadMaterialsAsync = function (runtime, onSuccess, onError) {
                 var materials = runtime.gltf.materials;
-                if (!materials) {
+                if (!materials || materials.length === 0) {
                     onSuccess();
                     return;
                 }

Разлика између датотеке није приказан због своје велике величине
+ 1 - 1
dist/preview release/loaders/babylon.glTF2FileLoader.min.js


+ 1 - 1
dist/preview release/loaders/babylon.glTFFileLoader.d.ts

@@ -842,7 +842,7 @@ declare module BABYLON.GLTF2 {
          * @param runtime: the GLTF runtime
          * @param accessor: the GLTF accessor
          */
-        static GetBufferFromAccessor(runtime: IGLTFRuntime, accessor: IGLTFAccessor): any;
+        static GetBufferFromAccessor(runtime: IGLTFRuntime, accessor: IGLTFAccessor): ArrayBufferView;
         /**
          * Decodes a buffer view into a string
          * @param view: the buffer view

+ 167 - 235
dist/preview release/loaders/babylon.glTFFileLoader.js

@@ -2434,203 +2434,146 @@ var BABYLON;
 (function (BABYLON) {
     var GLTF2;
     (function (GLTF2) {
-        /**
-        * Values
-        */
-        var glTFAnimationPaths = ["translation", "rotation", "scale", "weights"];
-        var babylonAnimationPaths = ["position", "rotationQuaternion", "scaling", "influence"];
-        /**
-        * Utils
-        */
-        var normalizeUVs = function (buffer) {
-            if (!buffer) {
-                return;
-            }
-            for (var i = 0; i < buffer.length / 2; i++) {
-                buffer[i * 2 + 1] = 1.0 - buffer[i * 2 + 1];
-            }
-        };
-        var createStringId = function (index) {
+        var getNodeID = function (index) {
             return "node" + index;
         };
-        /**
-        * Returns the animation path (glTF -> Babylon)
-        */
-        var getAnimationPath = function (path) {
-            var index = glTFAnimationPaths.indexOf(path);
-            if (index !== -1) {
-                return babylonAnimationPaths[index];
+        var loadAnimation = function (runtime, animation, animationIndex) {
+            for (var channelIndex = 0; channelIndex < animation.channels.length; channelIndex++) {
+                var channel = animation.channels[channelIndex];
+                if (!channel) {
+                    BABYLON.Tools.Warn("[Animation " + animationIndex + "] Channel " + channelIndex + " does not exist");
+                    continue;
+                }
+                var samplerIndex = channel.sampler;
+                if (samplerIndex === undefined) {
+                    BABYLON.Tools.Warn("[Animation " + animationIndex + ", Channel + " + samplerIndex + "] Sampler is not defined");
+                    continue;
+                }
+                var sampler = animation.samplers[samplerIndex];
+                if (!sampler) {
+                    BABYLON.Tools.Warn("[Animation " + animationIndex + ", Channel + " + channelIndex + "] Sampler " + samplerIndex + " does not exist");
+                    continue;
+                }
+                if (!channel.target) {
+                    BABYLON.Tools.Warn("[Animation " + animationIndex + ", Channel + " + channelIndex + "] Target does not exist");
+                    continue;
+                }
+                var targetNode = runtime.babylonScene.getNodeByID(getNodeID(channel.target.node));
+                if (!targetNode) {
+                    BABYLON.Tools.Warn("[Animation " + animationIndex + ", Channel + " + channelIndex + "] Target node " + channel.target.node + " does not exist");
+                    continue;
+                }
+                var targetPath = {
+                    "translation": "position",
+                    "rotation": "rotationQuaternion",
+                    "scale": "scaling",
+                    "weights": "influence"
+                }[channel.target.path];
+                if (!targetPath) {
+                    BABYLON.Tools.Warn("[Animation " + animationIndex + ", Channel + " + channelIndex + "] Target path " + channel.target.path + " is invalid");
+                    continue;
+                }
+                var inputBuffer = GLTF2.GLTFUtils.GetBufferFromAccessor(runtime, runtime.gltf.accessors[sampler.input]);
+                var outputBuffer = GLTF2.GLTFUtils.GetBufferFromAccessor(runtime, runtime.gltf.accessors[sampler.output]);
+                var outputBufferOffset = 0;
+                var animationType = {
+                    "position": BABYLON.Animation.ANIMATIONTYPE_VECTOR3,
+                    "rotationQuaternion": BABYLON.Animation.ANIMATIONTYPE_QUATERNION,
+                    "scale": BABYLON.Animation.ANIMATIONTYPE_VECTOR3,
+                    "influence": BABYLON.Animation.ANIMATIONTYPE_FLOAT,
+                }[targetPath];
+                var getNextOutputValue = {
+                    "position": function () {
+                        var value = BABYLON.Vector3.FromArray(outputBuffer, outputBufferOffset);
+                        outputBufferOffset += 3;
+                        return value;
+                    },
+                    "rotationQuaternion": function () {
+                        var value = BABYLON.Quaternion.FromArray(outputBuffer, outputBufferOffset);
+                        outputBufferOffset += 4;
+                        return value;
+                    },
+                    "scale": function () {
+                        var value = BABYLON.Vector3.FromArray(outputBuffer, outputBufferOffset);
+                        outputBufferOffset += 3;
+                        return value;
+                    },
+                    "influence": function () {
+                        var numTargets = targetNode.morphTargetManager.numTargets;
+                        var value = new Array(numTargets);
+                        for (var i = 0; i < numTargets; i++) {
+                            value[i] = outputBuffer[outputBufferOffset++];
+                        }
+                        return value;
+                    },
+                }[targetPath];
+                var getNextKey = {
+                    "LINEAR": function (frameIndex) { return ({
+                        frame: inputBuffer[frameIndex],
+                        value: getNextOutputValue()
+                    }); },
+                    "CUBICSPLINE": function (frameIndex) { return ({
+                        frame: inputBuffer[frameIndex],
+                        inTangent: getNextOutputValue(),
+                        value: getNextOutputValue(),
+                        outTangent: getNextOutputValue()
+                    }); },
+                }[sampler.interpolation];
+                if (!getNextKey) {
+                    BABYLON.Tools.Warn("[Animation " + animationIndex + ", Channel + " + channelIndex + "] Sampler interpolation '" + sampler.interpolation + "' is invalid");
+                    continue;
+                }
+                var keys = new Array(inputBuffer.length);
+                for (var frameIndex = 0; frameIndex < inputBuffer.length; frameIndex++) {
+                    keys[frameIndex] = getNextKey(frameIndex);
+                }
+                if (targetPath === "influence") {
+                    var targetMesh = targetNode;
+                    for (var targetIndex = 0; targetIndex < targetMesh.morphTargetManager.numTargets; targetIndex++) {
+                        var morphTarget = targetMesh.morphTargetManager.getTarget(targetIndex);
+                        var animationName = (animation.name || "anim" + animationIndex) + "_" + targetIndex;
+                        var babylonAnimation = new BABYLON.Animation(animationName, targetPath, 1, animationType);
+                        babylonAnimation.setKeys(keys.map(function (key) { return ({
+                            frame: key.frame,
+                            inTangent: key.inTangent ? key.inTangent[targetIndex] : undefined,
+                            value: key.value[targetIndex],
+                            outTangent: key.outTangent ? key.outTangent[targetIndex] : undefined
+                        }); }));
+                        morphTarget.animations.push(babylonAnimation);
+                        runtime.babylonScene.beginAnimation(morphTarget, 0, inputBuffer[inputBuffer.length - 1], true);
+                    }
+                }
+                else {
+                    var animationName = animation.name || "anim" + animationIndex;
+                    var babylonAnimation = new BABYLON.Animation(animationName, targetPath, 1, animationType);
+                    babylonAnimation.setKeys(keys);
+                    targetNode.animations.push(babylonAnimation);
+                    runtime.babylonScene.beginAnimation(targetNode, 0, inputBuffer[inputBuffer.length - 1], true);
+                }
             }
-            return path;
         };
         /**
         * Loads and creates animations
         */
         var loadAnimations = function (runtime) {
             var animations = runtime.gltf.animations;
-            if (!animations) {
+            if (!animations || animations.length === 0) {
                 return;
             }
             for (var animationIndex = 0; animationIndex < animations.length; animationIndex++) {
                 var animation = animations[animationIndex];
-                if (!animation || !animation.channels || !animation.samplers) {
+                if (!animation) {
+                    BABYLON.Tools.Warn("Animation " + animationIndex + " not found");
                     continue;
                 }
-                var lastAnimation = null;
-                for (var channelIndex = 0; channelIndex < animation.channels.length; channelIndex++) {
-                    var channel = animation.channels[channelIndex];
-                    if (!channel) {
-                        continue;
-                    }
-                    var sampler = animation.samplers[channel.sampler];
-                    if (!sampler) {
-                        continue;
-                    }
-                    var inputData = sampler.input;
-                    var outputData = sampler.output;
-                    var bufferInput = GLTF2.GLTFUtils.GetBufferFromAccessor(runtime, runtime.gltf.accessors[inputData]);
-                    var bufferOutput = GLTF2.GLTFUtils.GetBufferFromAccessor(runtime, runtime.gltf.accessors[outputData]);
-                    var targetID = channel.target.node;
-                    var targetNode = runtime.babylonScene.getNodeByID(createStringId(targetID));
-                    if (targetNode === null) {
-                        BABYLON.Tools.Warn("Creating animation index " + animationIndex + " but cannot find node index " + targetID + " to attach to");
-                        continue;
-                    }
-                    var isBone = targetNode instanceof BABYLON.Bone;
-                    var numTargets = 0;
-                    // Get target path (position, rotation, scaling, or weights)
-                    var targetPath = channel.target.path;
-                    var targetPathIndex = glTFAnimationPaths.indexOf(targetPath);
-                    if (targetPathIndex !== -1) {
-                        targetPath = babylonAnimationPaths[targetPathIndex];
-                    }
-                    var isMorph = targetPath === "influence";
-                    // Determine animation type
-                    var animationType = BABYLON.Animation.ANIMATIONTYPE_MATRIX;
-                    if (!isBone) {
-                        if (targetPath === "rotationQuaternion") {
-                            animationType = BABYLON.Animation.ANIMATIONTYPE_QUATERNION;
-                            targetNode.rotationQuaternion = new BABYLON.Quaternion();
-                        }
-                        else if (isMorph) {
-                            animationType = BABYLON.Animation.ANIMATIONTYPE_FLOAT;
-                            numTargets = targetNode.morphTargetManager.numTargets;
-                        }
-                        else {
-                            animationType = BABYLON.Animation.ANIMATIONTYPE_VECTOR3;
-                        }
-                    }
-                    // Create animation and key frames
-                    var babylonAnimation = null;
-                    var keys = [];
-                    var arrayOffset = 0;
-                    var modifyKey = false;
-                    if (isBone && lastAnimation && lastAnimation.getKeys().length === bufferInput.length) {
-                        babylonAnimation = lastAnimation;
-                        modifyKey = true;
-                    }
-                    // Each morph animation may have more than one more, so we need a
-                    // multi dimensional array.
-                    if (isMorph) {
-                        for (var influence = 0; influence < numTargets; influence++) {
-                            keys[influence] = [];
-                        }
-                    }
-                    // For each frame
-                    for (var frameIndex = 0; frameIndex < bufferInput.length; frameIndex++) {
-                        var value = null;
-                        if (targetPath === "rotationQuaternion") {
-                            value = BABYLON.Quaternion.FromArray([bufferOutput[arrayOffset], bufferOutput[arrayOffset + 1], bufferOutput[arrayOffset + 2], bufferOutput[arrayOffset + 3]]);
-                            arrayOffset += 4;
-                        }
-                        else if (isMorph) {
-                            value = [];
-                            // There is 1 value for each morph target for each frame
-                            for (var influence = 0; influence < numTargets; influence++) {
-                                value.push(bufferOutput[arrayOffset + influence]);
-                            }
-                            arrayOffset += numTargets;
-                        }
-                        else {
-                            value = BABYLON.Vector3.FromArray([bufferOutput[arrayOffset], bufferOutput[arrayOffset + 1], bufferOutput[arrayOffset + 2]]);
-                            arrayOffset += 3;
-                        }
-                        if (isBone) {
-                            var bone = targetNode;
-                            var translation = BABYLON.Vector3.Zero();
-                            var rotationQuaternion = new BABYLON.Quaternion();
-                            var scaling = BABYLON.Vector3.Zero();
-                            // Warning on decompose
-                            var mat = bone.getBaseMatrix();
-                            if (modifyKey) {
-                                mat = lastAnimation.getKeys()[frameIndex].value;
-                            }
-                            mat.decompose(scaling, rotationQuaternion, translation);
-                            if (targetPath === "position") {
-                                translation = value;
-                            }
-                            else if (targetPath === "rotationQuaternion") {
-                                rotationQuaternion = value;
-                            }
-                            else {
-                                scaling = value;
-                            }
-                            value = BABYLON.Matrix.Compose(scaling, rotationQuaternion, translation);
-                        }
-                        if (!modifyKey) {
-                            if (isMorph) {
-                                for (var influence = 0; influence < numTargets; influence++) {
-                                    keys[influence].push({
-                                        frame: bufferInput[frameIndex],
-                                        value: value[influence]
-                                    });
-                                }
-                            }
-                            else {
-                                keys.push({
-                                    frame: bufferInput[frameIndex],
-                                    value: value
-                                });
-                            }
-                        }
-                        else {
-                            lastAnimation.getKeys()[frameIndex].value = value;
-                        }
-                    }
-                    // Finish
-                    if (!modifyKey) {
-                        if (isMorph) {
-                            for (var influence = 0; influence < numTargets; influence++) {
-                                var morphTarget = targetNode.morphTargetManager.getTarget(influence);
-                                if (morphTarget.animations === undefined) {
-                                    morphTarget.animations = [];
-                                }
-                                var animationName = (animation.name || "anim" + animationIndex) + "_" + influence;
-                                babylonAnimation = new BABYLON.Animation(animationName, targetPath, 1, animationType, BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE);
-                                babylonAnimation.setKeys(keys[influence]);
-                                morphTarget.animations.push(babylonAnimation);
-                            }
-                        }
-                        else {
-                            var animationName = animation.name || "anim" + animationIndex;
-                            babylonAnimation = new BABYLON.Animation(animationName, isBone ? "_matrix" : targetPath, 1, animationType, BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE);
-                            babylonAnimation.setKeys(keys);
-                            targetNode.animations.push(babylonAnimation);
-                        }
-                    }
-                    lastAnimation = babylonAnimation;
-                    if (isMorph) {
-                        for (var influence = 0; influence < numTargets; influence++) {
-                            var morph = targetNode.morphTargetManager.getTarget(influence);
-                            runtime.babylonScene.stopAnimation(morph);
-                            runtime.babylonScene.beginAnimation(morph, 0, bufferInput[bufferInput.length - 1], true, 1.0);
-                        }
-                    }
-                    else {
-                        runtime.babylonScene.stopAnimation(targetNode);
-                        runtime.babylonScene.beginAnimation(targetNode, 0, bufferInput[bufferInput.length - 1], true, 1.0);
-                    }
+                if (!animation.channels || animation.channels.length === 0) {
+                    BABYLON.Tools.Warn("Animation " + animationIndex + " has no channels");
                 }
+                if (!animation.samplers || animation.samplers.length === 0) {
+                    BABYLON.Tools.Warn("Animation " + animationIndex + " has no samplers");
+                    continue;
+                }
+                loadAnimation(runtime, animation, animationIndex);
             }
         };
         /**
@@ -2654,7 +2597,7 @@ var BABYLON;
         */
         var getParentBone = function (runtime, skin, index, newSkeleton) {
             // Try to find
-            var nodeStringID = createStringId(index);
+            var nodeStringID = getNodeID(index);
             for (var i = 0; i < newSkeleton.bones.length; i++) {
                 if (newSkeleton.bones[i].id === nodeStringID) {
                     return newSkeleton.bones[i].getParent();
@@ -2674,8 +2617,8 @@ var BABYLON;
                     }
                     if (childID === index) {
                         var mat = configureBoneTransformation(parent);
-                        var bone = new BABYLON.Bone(parent.name || createStringId(parentID), newSkeleton, getParentBone(runtime, skin, parentID, newSkeleton), mat);
-                        bone.id = createStringId(parentID);
+                        var bone = new BABYLON.Bone(parent.name || getNodeID(parentID), newSkeleton, getParentBone(runtime, skin, parentID, newSkeleton), mat);
+                        bone.id = getNodeID(parentID);
                         return bone;
                     }
                 }
@@ -2735,8 +2678,8 @@ var BABYLON;
                 }
                 // Create node to root bone
                 var mat = configureBoneTransformation(node);
-                var bone = new BABYLON.Bone(node.name || createStringId(i), newSkeleton, null, mat);
-                bone.id = createStringId(i);
+                var bone = new BABYLON.Bone(node.name || getNodeID(i), newSkeleton, null, mat);
+                bone.id = getNodeID(i);
                 nodesToRoot.push({ bone: bone, node: node, index: i });
             }
             // Parenting
@@ -2789,7 +2732,7 @@ var BABYLON;
                     continue;
                 }
                 var index = jointNode.index;
-                var stringID = createStringId(index);
+                var stringID = getNodeID(index);
                 // Optimize, if the bone already exists...
                 var existingBone = runtime.babylonScene.getBoneByID(stringID);
                 if (existingBone) {
@@ -2839,7 +2782,7 @@ var BABYLON;
                 if (!jointNode) {
                     continue;
                 }
-                var jointNodeStringId = createStringId(jointNode.index);
+                var jointNodeStringId = getNodeID(jointNode.index);
                 for (var j = 0; j < bones.length; j++) {
                     if (bones[j].id === jointNodeStringId) {
                         babylonSkeleton.bones.push(bones[j]);
@@ -2894,7 +2837,7 @@ var BABYLON;
             var verticesCounts = [];
             var indexStarts = [];
             var indexCounts = [];
-            var morphTargetManager = new BABYLON.MorphTargetManager();
+            var morphTargetManager;
             // Positions, normals and UVs
             for (var primitiveIndex = 0; primitiveIndex < mesh.primitives.length; primitiveIndex++) {
                 // Temporary vertex data
@@ -2912,37 +2855,28 @@ var BABYLON;
                     accessor = runtime.gltf.accessors[attributes[semantic]];
                     buffer = GLTF2.GLTFUtils.GetBufferFromAccessor(runtime, accessor);
                     if (semantic === "NORMAL") {
-                        tempVertexData.normals = new Float32Array(buffer.length);
-                        tempVertexData.normals.set(buffer);
+                        tempVertexData.normals = buffer;
                     }
                     else if (semantic === "POSITION") {
-                        tempVertexData.positions = new Float32Array(buffer.length);
-                        tempVertexData.positions.set(buffer);
+                        tempVertexData.positions = buffer;
                         verticesCounts.push(tempVertexData.positions.length);
                     }
                     else if (semantic === "TANGENT") {
-                        tempVertexData.tangents = new Float32Array(buffer.length);
-                        tempVertexData.tangents.set(buffer);
+                        tempVertexData.tangents = buffer;
                     }
                     else if (semantic.indexOf("TEXCOORD_") !== -1) {
                         var channel = Number(semantic.split("_")[1]);
                         var uvKind = BABYLON.VertexBuffer.UVKind + (channel === 0 ? "" : (channel + 1));
-                        var uvs = new Float32Array(buffer.length);
-                        uvs.set(buffer);
-                        normalizeUVs(uvs);
-                        tempVertexData.set(uvs, uvKind);
+                        tempVertexData.set(buffer, uvKind);
                     }
                     else if (semantic === "JOINT") {
-                        tempVertexData.matricesIndices = new Float32Array(buffer.length);
-                        tempVertexData.matricesIndices.set(buffer);
+                        tempVertexData.matricesIndices = buffer;
                     }
                     else if (semantic === "WEIGHT") {
-                        tempVertexData.matricesWeights = new Float32Array(buffer.length);
-                        tempVertexData.matricesWeights.set(buffer);
+                        tempVertexData.matricesWeights = buffer;
                     }
                     else if (semantic === "COLOR_0") {
-                        tempVertexData.colors = new Float32Array(buffer.length);
-                        tempVertexData.colors.set(buffer);
+                        tempVertexData.colors = buffer;
                     }
                     else {
                         BABYLON.Tools.Warn("Ignoring unrecognized semantic '" + semantic + "'");
@@ -2952,17 +2886,15 @@ var BABYLON;
                 accessor = runtime.gltf.accessors[primitive.indices];
                 if (accessor) {
                     buffer = GLTF2.GLTFUtils.GetBufferFromAccessor(runtime, accessor);
-                    tempVertexData.indices = new Int32Array(buffer.length);
-                    tempVertexData.indices.set(buffer);
+                    tempVertexData.indices = buffer;
                     indexCounts.push(tempVertexData.indices.length);
                 }
                 else {
                     // Set indices on the fly
-                    var indices = [];
-                    for (var index = 0; index < tempVertexData.positions.length / 3; index++) {
-                        indices.push(index);
+                    tempVertexData.indices = new Uint32Array(tempVertexData.positions.length / 3);
+                    for (var index = 0; index < tempVertexData.indices.length; index++) {
+                        tempVertexData.indices[index] = index;
                     }
-                    tempVertexData.indices = new Int32Array(indices);
                     indexCounts.push(tempVertexData.indices.length);
                 }
                 vertexData.merge(tempVertexData);
@@ -2971,22 +2903,22 @@ var BABYLON;
                 var material = getMaterial(runtime, primitive.material);
                 multiMat.subMaterials.push(material);
                 // Morph Targets
-                if (primitive.targets !== undefined) {
+                if (primitive.targets) {
                     for (var targetsIndex = 0; targetsIndex < primitive.targets.length; targetsIndex++) {
                         var target = primitive.targets[targetsIndex];
                         var weight = 0.0;
-                        if (node.weights !== undefined) {
+                        if (node.weights) {
                             weight = node.weights[targetsIndex];
                         }
-                        else if (mesh.weights !== undefined) {
+                        else if (mesh.weights) {
                             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 = GLTF2.GLTFUtils.GetBufferFromAccessor(runtime, accessor);
-                            if (accessor.name !== undefined) {
+                            var values = GLTF2.GLTFUtils.GetBufferFromAccessor(runtime, accessor);
+                            if (accessor.name) {
                                 morph.name = accessor.name;
                             }
                             // glTF stores morph target information as deltas
@@ -2994,34 +2926,38 @@ var BABYLON;
                             // 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] += vertexData.normals[bufferIndex];
+                                for (var i = 0; i < values.length; i++) {
+                                    values[i] += vertexData.normals[i];
                                 }
-                                morph.setNormals(buffer);
+                                morph.setNormals(values);
                             }
                             else if (semantic === "POSITION") {
-                                for (var bufferIndex = 0; bufferIndex < buffer.length; bufferIndex++) {
-                                    buffer[bufferIndex] += vertexData.positions[bufferIndex];
+                                for (var i = 0; i < values.length; i++) {
+                                    values[i] += vertexData.positions[i];
                                 }
-                                morph.setPositions(buffer);
+                                morph.setPositions(values);
                             }
                             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] += vertexData.tangents[tangentsIndex];
-                                    if ((bufferIndex + 1) % 3 == 0) {
-                                        tangentsIndex++;
+                                for (var i = 0, j = 0; i < values.length; i++, j++) {
+                                    values[i] += vertexData.tangents[j];
+                                    if ((i + 1) % 3 == 0) {
+                                        j++;
                                     }
                                 }
-                                morph.setTangents(buffer);
+                                morph.setTangents(values);
                             }
                             else {
                                 BABYLON.Tools.Warn("Ignoring unrecognized semantic '" + semantic + "'");
                             }
                         }
-                        if (morph.getPositions() !== undefined) {
+                        if (morph.getPositions()) {
+                            if (!morphTargetManager) {
+                                morphTargetManager = new BABYLON.MorphTargetManager();
+                                babylonMesh.morphTargetManager = morphTargetManager;
+                            }
                             morphTargetManager.addTarget(morph);
                         }
                         else {
@@ -3036,10 +2972,6 @@ var BABYLON;
             // Apply geometry
             geometry.setAllVerticesData(vertexData, false);
             babylonMesh.computeWorldMatrix(true);
-            // Set morph target manager after all vertices data has been processed
-            if (morphTargetManager !== undefined && morphTargetManager.numTargets > 0) {
-                babylonMesh.morphTargetManager = morphTargetManager;
-            }
             // Apply submeshes
             babylonMesh.subMeshes = [];
             for (var primitiveIndex = 0; primitiveIndex < mesh.primitives.length; primitiveIndex++) {
@@ -3167,7 +3099,7 @@ var BABYLON;
             if (meshIncluded) {
                 newNode = importNode(runtime, node);
                 if (newNode !== null) {
-                    newNode.id = createStringId(index);
+                    newNode.id = getNodeID(index);
                     newNode.parent = parent;
                 }
             }
@@ -3438,7 +3370,7 @@ var BABYLON;
                 var sampler = (texture.sampler === undefined ? {} : runtime.gltf.samplers[texture.sampler]);
                 var noMipMaps = (sampler.minFilter === GLTF2.ETextureMinFilter.NEAREST || sampler.minFilter === GLTF2.ETextureMinFilter.LINEAR);
                 var samplingMode = GLTF2.GLTFUtils.GetTextureFilterMode(sampler.minFilter);
-                var babylonTexture = new BABYLON.Texture(url, runtime.babylonScene, noMipMaps, true, samplingMode, function () {
+                var babylonTexture = new BABYLON.Texture(url, runtime.babylonScene, noMipMaps, false, samplingMode, function () {
                     onSuccess(babylonTexture);
                 }, onError);
                 babylonTexture.coordinatesIndex = texCoord;
@@ -3555,7 +3487,7 @@ var BABYLON;
             };
             GLTFLoader._loadMaterialsAsync = function (runtime, onSuccess, onError) {
                 var materials = runtime.gltf.materials;
-                if (!materials) {
+                if (!materials || materials.length === 0) {
                     onSuccess();
                     return;
                 }

Разлика између датотеке није приказан због своје велике величине
+ 2 - 2
dist/preview release/loaders/babylon.glTFFileLoader.min.js


Разлика између датотеке није приказан због своје велике величине
+ 1 - 1
dist/preview release/loaders/babylon.objFileLoader.min.js


+ 28 - 0
dist/preview release/materialsLibrary/babylon.cellMaterial.d.ts

@@ -0,0 +1,28 @@
+/// <reference path="../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON {
+    class CellMaterial extends PushMaterial {
+        private _diffuseTexture;
+        diffuseTexture: BaseTexture;
+        diffuseColor: Color3;
+        _computeHighLevel: boolean;
+        computeHighLevel: boolean;
+        private _disableLighting;
+        disableLighting: boolean;
+        private _maxSimultaneousLights;
+        maxSimultaneousLights: number;
+        private _worldViewProjectionMatrix;
+        private _scaledDiffuse;
+        private _renderId;
+        constructor(name: string, scene: Scene);
+        needAlphaBlending(): boolean;
+        needAlphaTesting(): boolean;
+        getAlphaTestTexture(): BaseTexture;
+        isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean;
+        bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void;
+        getAnimatables(): IAnimatable[];
+        dispose(forceDisposeEffect?: boolean): void;
+        clone(name: string): CellMaterial;
+        serialize(): any;
+        static Parse(source: any, scene: Scene, rootUrl: string): CellMaterial;
+    }
+}

Разлика између датотеке није приказан због своје велике величине
+ 276 - 0
dist/preview release/materialsLibrary/babylon.cellMaterial.js


Разлика између датотеке није приказан због своје велике величине
+ 1 - 0
dist/preview release/materialsLibrary/babylon.cellMaterial.min.js


+ 47 - 8
dist/preview release/materialsLibrary/babylon.customMaterial.d.ts

@@ -1,15 +1,54 @@
 /// <reference path="../../../dist/preview release/babylon.d.ts" />
 declare module BABYLON {
-    class CustomShaderHelper {
+    class CustomShaderStructure {
+        FragmentStore: string;
+        VertexStore: string;
+        constructor();
     }
-    interface ICustomMaterialBuilder {
-        (builder: CustomShaderHelper, name: string, mainPart: string, diffusePart: string, vertexPositionPart: string): string;
+    class ShaderSpecialParts {
+        constructor();
+        Fragment_Begin: string;
+        Fragment_Definations: string;
+        Fragment_MainBegin: string;
+        Fragment_Custom_Diffuse: string;
+        Fragment_Custom_Alpha: string;
+        Fragment_Before_FragColor: string;
+        Vertex_Begin: string;
+        Vertex_Definations: string;
+        Vertex_MainBegin: string;
+        Vertex_Before_PositionUpdated: string;
+        Vertex_Before_NormalUpdated: string;
+    }
+    class ShaderForVer3_0 extends CustomShaderStructure {
+        constructor();
+    }
+    class StandardShaderVersions {
+        static Ver3_0: any;
     }
     class CustomMaterial extends StandardMaterial {
-        builder: ICustomMaterialBuilder;
-        private _mainPart;
-        private _diffusePart;
-        private _vertexPositionPart;
-        constructor(name: string, builder: ICustomMaterialBuilder, scene: Scene);
+        static ShaderIndexer: number;
+        CustomParts: ShaderSpecialParts;
+        ShaderVersion: CustomShaderStructure;
+        _customUnifrom: string[];
+        _newUnifroms: string[];
+        _newUnifromInstances: any[];
+        _newSamplerInstances: Texture[];
+        AttachAfterBind(mesh: Mesh, effect: Effect): void;
+        ReviewUniform(name: string, arr: string[]): string[];
+        Builder(shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: StandardMaterialDefines): string;
+        SelectVersion(ver: string): void;
+        constructor(name: string, scene: Scene);
+        AddUniform(name: string, kind: string, param: any): CustomMaterial;
+        Fragment_Begin(shaderPart: string): CustomMaterial;
+        Fragment_Definations(shaderPart: string): CustomMaterial;
+        Fragment_MainBegin(shaderPart: string): CustomMaterial;
+        Fragment_Custom_Diffuse(shaderPart: string): CustomMaterial;
+        Fragment_Custom_Alpha(shaderPart: string): CustomMaterial;
+        Fragment_Before_FragColor(shaderPart: string): CustomMaterial;
+        Vertex_Begin(shaderPart: string): CustomMaterial;
+        Vertex_Definations(shaderPart: string): CustomMaterial;
+        Vertex_MainBegin(shaderPart: string): CustomMaterial;
+        Vertex_Before_PositionUpdated(shaderPart: string): CustomMaterial;
+        Vertex_Before_NormalUpdated(shaderPart: string): CustomMaterial;
     }
 }

+ 647 - 12
dist/preview release/materialsLibrary/babylon.customMaterial.js

@@ -11,27 +11,662 @@ var __extends = (this && this.__extends) || (function () {
 })();
 var BABYLON;
 (function (BABYLON) {
-    var CustomShaderHelper = (function () {
-        function CustomShaderHelper() {
+    var CustomShaderStructure = (function () {
+        function CustomShaderStructure() {
         }
-        return CustomShaderHelper;
+        return CustomShaderStructure;
     }());
-    BABYLON.CustomShaderHelper = CustomShaderHelper;
+    BABYLON.CustomShaderStructure = CustomShaderStructure;
+    var ShaderSpecialParts = (function () {
+        function ShaderSpecialParts() {
+        }
+        return ShaderSpecialParts;
+    }());
+    BABYLON.ShaderSpecialParts = ShaderSpecialParts;
+    var ShaderForVer3_0 = (function (_super) {
+        __extends(ShaderForVer3_0, _super);
+        function ShaderForVer3_0() {
+            var _this = _super.call(this) || this;
+            _this.VertexStore = "";
+            _this.FragmentStore = "#include<__decl__defaultFragment>\n\
+#[Fragment_Begin]\n\
+#ifdef BUMP\n\
+#extension GL_OES_standard_derivatives : enable\n\
+#endif\n\
+#ifdef LOGARITHMICDEPTH\n\
+#extension GL_EXT_frag_depth : enable\n\
+#endif\n\
+\n\
+#define RECIPROCAL_PI2 0.15915494\n\
+uniform vec3 vEyePosition;\n\
+uniform vec3 vAmbientColor;\n\
+\n\
+varying vec3 vPositionW;\n\
+#ifdef NORMAL\n\
+varying vec3 vNormalW;\n\
+#endif\n\
+#ifdef VERTEXCOLOR\n\
+varying vec4 vColor;\n\
+#endif\n\
+\n\
+#include<helperFunctions>\n\
+\n\
+#include<__decl__lightFragment>[0..maxSimultaneousLights]\n\
+#include<lightsFragmentFunctions>\n\
+#include<shadowsFragmentFunctions>\n\
+\n\
+#ifdef DIFFUSE\n\
+varying vec2 vDiffuseUV;\n\
+uniform sampler2D diffuseSampler;\n\
+#endif\n\
+#ifdef AMBIENT\n\
+varying vec2 vAmbientUV;\n\
+uniform sampler2D ambientSampler;\n\
+#endif\n\
+#ifdef OPACITY\n\
+varying vec2 vOpacityUV;\n\
+uniform sampler2D opacitySampler;\n\
+#endif\n\
+#ifdef EMISSIVE\n\
+varying vec2 vEmissiveUV;\n\
+uniform sampler2D emissiveSampler;\n\
+#endif\n\
+#ifdef LIGHTMAP\n\
+varying vec2 vLightmapUV;\n\
+uniform sampler2D lightmapSampler;\n\
+#endif\n\
+#ifdef REFRACTION\n\
+#ifdef REFRACTIONMAP_3D\n\
+uniform samplerCube refractionCubeSampler;\n\
+#else\n\
+uniform sampler2D refraction2DSampler;\n\
+#endif\n\
+#endif\n\
+#if defined(SPECULAR) && defined(SPECULARTERM)\n\
+varying vec2 vSpecularUV;\n\
+uniform sampler2D specularSampler;\n\
+#endif\n\
+\n\
+#include<fresnelFunction>\n\
+\n\
+#ifdef REFLECTION\n\
+#ifdef REFLECTIONMAP_3D\n\
+uniform samplerCube reflectionCubeSampler;\n\
+#else\n\
+uniform sampler2D reflection2DSampler;\n\
+#endif\n\
+#ifdef REFLECTIONMAP_SKYBOX\n\
+varying vec3 vPositionUVW;\n\
+#else\n\
+#if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED)\n\
+varying vec3 vDirectionW;\n\
+#endif\n\
+#endif\n\
+#include<reflectionFunction>\n\
+#endif\n\
+#ifdef CAMERACOLORGRADING\n\
+#include<colorGradingDefinition> \n\
+#include<colorGrading>\n\
+#endif\n\
+#ifdef CAMERACOLORCURVES\n\
+#include<colorCurvesDefinition>\n\
+#include<colorCurves>\n\
+#endif\n\
+#include<bumpFragmentFunctions>\n\
+#include<clipPlaneFragmentDeclaration>\n\
+#include<logDepthDeclaration>\n\
+#include<fogFragmentDeclaration>\n\
+\n\
+#[Fragment_Definations]\n\
+\n\
+void main(void) {\n\
+\n\
+#[Fragment_MainBegin]\n\
+\n\
+#include<clipPlaneFragment>\n\
+vec3 viewDirectionW=normalize(vEyePosition-vPositionW);\n\
+\n\
+vec4 baseColor=vec4(1.,1.,1.,1.);\n\
+vec3 diffuseColor=vDiffuseColor.rgb;\n\
+#[Fragment_Custom_Diffuse]\n\
+\n\
+float alpha=vDiffuseColor.a;\n\
+#[Fragment_Custom_Alpha]\n\
+\n\
+#ifdef NORMAL\n\
+vec3 normalW=normalize(vNormalW);\n\
+#else\n\
+vec3 normalW=vec3(1.0,1.0,1.0);\n\
+#endif\n\
+#include<bumpFragment>\n\
+#ifdef TWOSIDEDLIGHTING\n\
+normalW=gl_FrontFacing ? normalW : -normalW;\n\
+#endif\n\
+#ifdef DIFFUSE\n\
+baseColor=texture2D(diffuseSampler,vDiffuseUV+uvOffset);\n\
+#ifdef ALPHATEST\n\
+if (baseColor.a<0.4)\n\
+discard;\n\
+#endif\n\
+#ifdef ALPHAFROMDIFFUSE\n\
+alpha*=baseColor.a;\n\
+#endif\n\
+baseColor.rgb*=vDiffuseInfos.y;\n\
+#endif\n\
+#ifdef VERTEXCOLOR\n\
+baseColor.rgb*=vColor.rgb;\n\
+#endif\n\
+\n\
+vec3 baseAmbientColor=vec3(1.,1.,1.);\n\
+#ifdef AMBIENT\n\
+baseAmbientColor=texture2D(ambientSampler,vAmbientUV+uvOffset).rgb*vAmbientInfos.y;\n\
+#endif\n\
+\n\
+#ifdef SPECULARTERM\n\
+float glossiness=vSpecularColor.a;\n\
+vec3 specularColor=vSpecularColor.rgb;\n\
+#ifdef SPECULAR\n\
+vec4 specularMapColor=texture2D(specularSampler,vSpecularUV+uvOffset);\n\
+specularColor=specularMapColor.rgb;\n\
+#ifdef GLOSSINESS\n\
+glossiness=glossiness*specularMapColor.a;\n\
+#endif\n\
+#endif\n\
+#else\n\
+float glossiness=0.;\n\
+#endif\n\
+\n\
+vec3 diffuseBase=vec3(0.,0.,0.);\n\
+lightingInfo info;\n\
+#ifdef SPECULARTERM\n\
+vec3 specularBase=vec3(0.,0.,0.);\n\
+#endif\n\
+float shadow=1.;\n\
+#ifdef LIGHTMAP\n\
+vec3 lightmapColor=texture2D(lightmapSampler,vLightmapUV+uvOffset).rgb*vLightmapInfos.y;\n\
+#endif\n\
+#include<lightFragment>[0..maxSimultaneousLights]\n\
+\n\
+vec3 refractionColor=vec3(0.,0.,0.);\n\
+#ifdef REFRACTION\n\
+vec3 refractionVector=normalize(refract(-viewDirectionW,normalW,vRefractionInfos.y));\n\
+#ifdef REFRACTIONMAP_3D\n\
+refractionVector.y=refractionVector.y*vRefractionInfos.w;\n\
+if (dot(refractionVector,viewDirectionW)<1.0)\n\
+{\n\
+refractionColor=textureCube(refractionCubeSampler,refractionVector).rgb*vRefractionInfos.x;\n\
+}\n\
+#else\n\
+vec3 vRefractionUVW=vec3(refractionMatrix*(view*vec4(vPositionW+refractionVector*vRefractionInfos.z,1.0)));\n\
+vec2 refractionCoords=vRefractionUVW.xy/vRefractionUVW.z;\n\
+refractionCoords.y=1.0-refractionCoords.y;\n\
+refractionColor=texture2D(refraction2DSampler,refractionCoords).rgb*vRefractionInfos.x;\n\
+#endif\n\
+#endif\n\
+\n\
+vec3 reflectionColor=vec3(0.,0.,0.);\n\
+#ifdef REFLECTION\n\
+vec3 vReflectionUVW=computeReflectionCoords(vec4(vPositionW,1.0),normalW);\n\
+#ifdef REFLECTIONMAP_3D\n\
+#ifdef ROUGHNESS\n\
+float bias=vReflectionInfos.y;\n\
+#ifdef SPECULARTERM\n\
+#ifdef SPECULAR\n\
+#ifdef GLOSSINESS\n\
+bias*=(1.0-specularMapColor.a);\n\
+#endif\n\
+#endif\n\
+#endif\n\
+reflectionColor=textureCube(reflectionCubeSampler,vReflectionUVW,bias).rgb*vReflectionInfos.x;\n\
+#else\n\
+reflectionColor=textureCube(reflectionCubeSampler,vReflectionUVW).rgb*vReflectionInfos.x;\n\
+#endif\n\
+#else\n\
+vec2 coords=vReflectionUVW.xy;\n\
+#ifdef REFLECTIONMAP_PROJECTION\n\
+coords/=vReflectionUVW.z;\n\
+#endif\n\
+coords.y=1.0-coords.y;\n\
+reflectionColor=texture2D(reflection2DSampler,coords).rgb*vReflectionInfos.x;\n\
+#endif\n\
+#ifdef REFLECTIONFRESNEL\n\
+float reflectionFresnelTerm=computeFresnelTerm(viewDirectionW,normalW,reflectionRightColor.a,reflectionLeftColor.a);\n\
+#ifdef REFLECTIONFRESNELFROMSPECULAR\n\
+#ifdef SPECULARTERM\n\
+reflectionColor*=specularColor.rgb*(1.0-reflectionFresnelTerm)+reflectionFresnelTerm*reflectionRightColor.rgb;\n\
+#else\n\
+reflectionColor*=reflectionLeftColor.rgb*(1.0-reflectionFresnelTerm)+reflectionFresnelTerm*reflectionRightColor.rgb;\n\
+#endif\n\
+#else\n\
+reflectionColor*=reflectionLeftColor.rgb*(1.0-reflectionFresnelTerm)+reflectionFresnelTerm*reflectionRightColor.rgb;\n\
+#endif\n\
+#endif\n\
+#endif\n\
+#ifdef REFRACTIONFRESNEL\n\
+float refractionFresnelTerm=computeFresnelTerm(viewDirectionW,normalW,refractionRightColor.a,refractionLeftColor.a);\n\
+refractionColor*=refractionLeftColor.rgb*(1.0-refractionFresnelTerm)+refractionFresnelTerm*refractionRightColor.rgb;\n\
+#endif\n\
+#ifdef OPACITY\n\
+vec4 opacityMap=texture2D(opacitySampler,vOpacityUV+uvOffset);\n\
+#ifdef OPACITYRGB\n\
+opacityMap.rgb=opacityMap.rgb*vec3(0.3,0.59,0.11);\n\
+alpha*=(opacityMap.x+opacityMap.y+opacityMap.z)* vOpacityInfos.y;\n\
+#else\n\
+alpha*=opacityMap.a*vOpacityInfos.y;\n\
+#endif\n\
+#endif\n\
+#ifdef VERTEXALPHA\n\
+alpha*=vColor.a;\n\
+#endif\n\
+#ifdef OPACITYFRESNEL\n\
+float opacityFresnelTerm=computeFresnelTerm(viewDirectionW,normalW,opacityParts.z,opacityParts.w);\n\
+alpha+=opacityParts.x*(1.0-opacityFresnelTerm)+opacityFresnelTerm*opacityParts.y;\n\
+#endif\n\
+\n\
+vec3 emissiveColor=vEmissiveColor;\n\
+#ifdef EMISSIVE\n\
+emissiveColor+=texture2D(emissiveSampler,vEmissiveUV+uvOffset).rgb*vEmissiveInfos.y;\n\
+#endif\n\
+#ifdef EMISSIVEFRESNEL\n\
+float emissiveFresnelTerm=computeFresnelTerm(viewDirectionW,normalW,emissiveRightColor.a,emissiveLeftColor.a);\n\
+emissiveColor*=emissiveLeftColor.rgb*(1.0-emissiveFresnelTerm)+emissiveFresnelTerm*emissiveRightColor.rgb;\n\
+#endif\n\
+\n\
+#ifdef DIFFUSEFRESNEL\n\
+float diffuseFresnelTerm=computeFresnelTerm(viewDirectionW,normalW,diffuseRightColor.a,diffuseLeftColor.a);\n\
+diffuseBase*=diffuseLeftColor.rgb*(1.0-diffuseFresnelTerm)+diffuseFresnelTerm*diffuseRightColor.rgb;\n\
+#endif\n\
+\n\
+#ifdef EMISSIVEASILLUMINATION\n\
+vec3 finalDiffuse=clamp(diffuseBase*diffuseColor+vAmbientColor,0.0,1.0)*baseColor.rgb;\n\
+#else\n\
+#ifdef LINKEMISSIVEWITHDIFFUSE\n\
+vec3 finalDiffuse=clamp((diffuseBase+emissiveColor)*diffuseColor+vAmbientColor,0.0,1.0)*baseColor.rgb;\n\
+#else\n\
+vec3 finalDiffuse=clamp(diffuseBase*diffuseColor+emissiveColor+vAmbientColor,0.0,1.0)*baseColor.rgb;\n\
+#endif\n\
+#endif\n\
+#ifdef SPECULARTERM\n\
+vec3 finalSpecular=specularBase*specularColor;\n\
+#ifdef SPECULAROVERALPHA\n\
+alpha=clamp(alpha+dot(finalSpecular,vec3(0.3,0.59,0.11)),0.,1.);\n\
+#endif\n\
+#else\n\
+vec3 finalSpecular=vec3(0.0);\n\
+#endif\n\
+#ifdef REFLECTIONOVERALPHA\n\
+alpha=clamp(alpha+dot(reflectionColor,vec3(0.3,0.59,0.11)),0.,1.);\n\
+#endif\n\
+\n\
+#ifdef EMISSIVEASILLUMINATION\n\
+vec4 color=vec4(clamp(finalDiffuse*baseAmbientColor+finalSpecular+reflectionColor+emissiveColor+refractionColor,0.0,1.0),alpha);\n\
+#else\n\
+vec4 color=vec4(finalDiffuse*baseAmbientColor+finalSpecular+reflectionColor+refractionColor,alpha);\n\
+#endif\n\
+\n\
+#ifdef LIGHTMAP\n\
+#ifndef LIGHTMAPEXCLUDED\n\
+#ifdef USELIGHTMAPASSHADOWMAP\n\
+color.rgb*=lightmapColor;\n\
+#else\n\
+color.rgb+=lightmapColor;\n\
+#endif\n\
+#endif\n\
+#endif\n\
+#include<logDepthFragment>\n\
+#include<fogFragment>\n\
+#ifdef CAMERACOLORGRADING\n\
+color=colorGrades(color);\n\
+#endif\n\
+#ifdef CAMERACOLORCURVES\n\
+color.rgb=applyColorCurves(color.rgb);\n\
+#endif\n\
+#[Fragment_Before_FragColor]\n\
+gl_FragColor=color;\n\
+}";
+            _this.VertexStore = "#include<__decl__defaultVertex>\n\
+\n\
+#[Vertex_Begin]\n\
+\n\
+attribute vec3 position;\n\
+#ifdef NORMAL\n\
+attribute vec3 normal;\n\
+#endif\n\
+#ifdef TANGENT\n\
+attribute vec4 tangent;\n\
+#endif\n\
+#ifdef UV1\n\
+attribute vec2 uv;\n\
+#endif\n\
+#ifdef UV2\n\
+attribute vec2 uv2;\n\
+#endif\n\
+#ifdef VERTEXCOLOR\n\
+attribute vec4 color;\n\
+#endif\n\
+#include<bonesDeclaration>\n\
+\n\
+#include<instancesDeclaration>\n\
+#ifdef DIFFUSE\n\
+varying vec2 vDiffuseUV;\n\
+#endif\n\
+#ifdef AMBIENT\n\
+varying vec2 vAmbientUV;\n\
+#endif\n\
+#ifdef OPACITY\n\
+varying vec2 vOpacityUV;\n\
+#endif\n\
+#ifdef EMISSIVE\n\
+varying vec2 vEmissiveUV;\n\
+#endif\n\
+#ifdef LIGHTMAP\n\
+varying vec2 vLightmapUV;\n\
+#endif\n\
+#if defined(SPECULAR) && defined(SPECULARTERM)\n\
+varying vec2 vSpecularUV;\n\
+#endif\n\
+#ifdef BUMP\n\
+varying vec2 vBumpUV;\n\
+#endif\n\
+\n\
+varying vec3 vPositionW;\n\
+#ifdef NORMAL\n\
+varying vec3 vNormalW;\n\
+#endif\n\
+#ifdef VERTEXCOLOR\n\
+varying vec4 vColor;\n\
+#endif\n\
+#include<bumpVertexDeclaration>\n\
+#include<clipPlaneVertexDeclaration>\n\
+#include<fogVertexDeclaration>\n\
+#include<shadowsVertexDeclaration>[0..maxSimultaneousLights]\n\
+#include<morphTargetsVertexGlobalDeclaration>\n\
+#include<morphTargetsVertexDeclaration>[0..maxSimultaneousMorphTargets]\n\
+#ifdef REFLECTIONMAP_SKYBOX\n\
+varying vec3 vPositionUVW;\n\
+#endif\n\
+#if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED)\n\
+varying vec3 vDirectionW;\n\
+#endif\n\
+#include<logDepthDeclaration>\n\
+\n\
+#[Vertex_Definations]\n\
+\n\
+void main(void) {\n\
+    \n\
+    #[Vertex_MainBegin]\n\
+    \n\
+vec3 positionUpdated=position;\n\
+#ifdef NORMAL \n\
+vec3 normalUpdated=normal;\n\
+#endif\n\
+#ifdef TANGENT\n\
+vec4 tangentUpdated=tangent;\n\
+#endif\n\
+#include<morphTargetsVertex>[0..maxSimultaneousMorphTargets]\n\
+#ifdef REFLECTIONMAP_SKYBOX\n\
+vPositionUVW=positionUpdated;\n\
+#endif \n\
+#include<instancesVertex>\n\
+#include<bonesVertex>\n\
+\n\
+#[Vertex_Before_PositionUpdated]\n\
+\n\
+gl_Position=viewProjection*finalWorld*vec4(positionUpdated,1.0);\n\
+vec4 worldPos=finalWorld*vec4(positionUpdated,1.0);\n\
+vPositionW=vec3(worldPos);\n\
+#ifdef NORMAL\n\
+\n\
+#[Vertex_Before_NormalUpdated]\n\
+\n\
+vNormalW=normalize(vec3(finalWorld*vec4(normalUpdated,0.0)));\n\
+#endif\n\
+#if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED)\n\
+vDirectionW=normalize(vec3(finalWorld*vec4(positionUpdated,0.0)));\n\
+#endif\n\
+\n\
+#ifndef UV1\n\
+vec2 uv=vec2(0.,0.);\n\
+#endif\n\
+#ifndef UV2\n\
+vec2 uv2=vec2(0.,0.);\n\
+#endif\n\
+#ifdef DIFFUSE\n\
+if (vDiffuseInfos.x == 0.)\n\
+{\n\
+vDiffuseUV=vec2(diffuseMatrix*vec4(uv,1.0,0.0));\n\
+}\n\
+else\n\
+{\n\
+vDiffuseUV=vec2(diffuseMatrix*vec4(uv2,1.0,0.0));\n\
+}\n\
+#endif\n\
+#ifdef AMBIENT\n\
+if (vAmbientInfos.x == 0.)\n\
+{\n\
+vAmbientUV=vec2(ambientMatrix*vec4(uv,1.0,0.0));\n\
+}\n\
+else\n\
+{\n\
+vAmbientUV=vec2(ambientMatrix*vec4(uv2,1.0,0.0));\n\
+}\n\
+#endif\n\
+#ifdef OPACITY\n\
+if (vOpacityInfos.x == 0.)\n\
+{\n\
+vOpacityUV=vec2(opacityMatrix*vec4(uv,1.0,0.0));\n\
+}\n\
+else\n\
+{\n\
+vOpacityUV=vec2(opacityMatrix*vec4(uv2,1.0,0.0));\n\
+}\n\
+#endif\n\
+#ifdef EMISSIVE\n\
+if (vEmissiveInfos.x == 0.)\n\
+{\n\
+vEmissiveUV=vec2(emissiveMatrix*vec4(uv,1.0,0.0));\n\
+}\n\
+else\n\
+{\n\
+vEmissiveUV=vec2(emissiveMatrix*vec4(uv2,1.0,0.0));\n\
+}\n\
+#endif\n\
+#ifdef LIGHTMAP\n\
+if (vLightmapInfos.x == 0.)\n\
+{\n\
+vLightmapUV=vec2(lightmapMatrix*vec4(uv,1.0,0.0));\n\
+}\n\
+else\n\
+{\n\
+vLightmapUV=vec2(lightmapMatrix*vec4(uv2,1.0,0.0));\n\
+}\n\
+#endif\n\
+#if defined(SPECULAR) && defined(SPECULARTERM)\n\
+if (vSpecularInfos.x == 0.)\n\
+{\n\
+vSpecularUV=vec2(specularMatrix*vec4(uv,1.0,0.0));\n\
+}\n\
+else\n\
+{\n\
+vSpecularUV=vec2(specularMatrix*vec4(uv2,1.0,0.0));\n\
+}\n\
+#endif\n\
+#ifdef BUMP\n\
+if (vBumpInfos.x == 0.)\n\
+{\n\
+vBumpUV=vec2(bumpMatrix*vec4(uv,1.0,0.0));\n\
+}\n\
+else\n\
+{\n\
+vBumpUV=vec2(bumpMatrix*vec4(uv2,1.0,0.0));\n\
+}\n\
+#endif\n\
+#include<bumpVertex>\n\
+#include<clipPlaneVertex>\n\
+#include<fogVertex>\n\
+#include<shadowsVertex>[0..maxSimultaneousLights]\n\
+#ifdef VERTEXCOLOR\n\
+\n\
+vColor=color;\n\
+#endif\n\
+#include<pointCloudVertex>\n\
+#include<logDepthVertex>\n\
+}";
+            return _this;
+        }
+        return ShaderForVer3_0;
+    }(CustomShaderStructure));
+    BABYLON.ShaderForVer3_0 = ShaderForVer3_0;
+    var StandardShaderVersions = (function () {
+        function StandardShaderVersions() {
+        }
+        return StandardShaderVersions;
+    }());
+    BABYLON.StandardShaderVersions = StandardShaderVersions;
     var CustomMaterial = (function (_super) {
         __extends(CustomMaterial, _super);
-        function CustomMaterial(name, builder, scene) {
+        function CustomMaterial(name, scene) {
             var _this = _super.call(this, name, scene) || this;
-            _this._mainPart = 'void main(void) {';
-            _this._diffusePart = 'vec3 diffuseColor=vDiffuseColor.rgb;';
-            _this._vertexPositionPart = 'gl_Position=viewProjection*finalWorld*vec4(position,1.0);';
-            _this.builder = builder;
-            _this.customShaderNameResolve = function (shaderName) {
-                return _this.builder(new CustomShaderHelper(), shaderName, _this._mainPart, _this._diffusePart, _this._vertexPositionPart);
-            };
+            _this.CustomParts = new ShaderSpecialParts();
+            _this.customShaderNameResolve = _this.Builder;
+            _this.SelectVersion("3.0.0");
             return _this;
         }
+        CustomMaterial.prototype.AttachAfterBind = function (mesh, effect) {
+            for (var el in this._newUnifromInstances) {
+                var ea = el.toString().split('-');
+                if (ea[0] == 'vec2')
+                    effect.setVector2(ea[1], this._newUnifromInstances[el]);
+                else if (ea[0] == 'vec3')
+                    effect.setVector3(ea[1], this._newUnifromInstances[el]);
+                else if (ea[0] == 'vec4')
+                    effect.setVector4(ea[1], this._newUnifromInstances[el]);
+                else if (ea[0] == 'mat4')
+                    effect.setMatrix(ea[1], this._newUnifromInstances[el]);
+                else if (ea[0] == 'float')
+                    effect.setFloat(ea[1], this._newUnifromInstances[el]);
+            }
+            for (var el in this._newSamplerInstances) {
+                var ea = el.toString().split('-');
+                if (ea[0] == 'sampler2D' && this._newSamplerInstances[el].isReady && this._newSamplerInstances[el].isReady())
+                    effect.setTexture(ea[1], this._newSamplerInstances[el]);
+            }
+        };
+        CustomMaterial.prototype.ReviewUniform = function (name, arr) {
+            if (name == "uniform") {
+                for (var ind in this._newUnifroms)
+                    if (this._customUnifrom[ind].indexOf('sampler') == -1)
+                        arr.push(this._newUnifroms[ind]);
+            }
+            if (name == "sampler") {
+                for (var ind in this._newUnifroms)
+                    if (this._customUnifrom[ind].indexOf('sampler') != -1)
+                        arr.push(this._newUnifroms[ind]);
+            }
+            return arr;
+        };
+        CustomMaterial.prototype.Builder = function (shaderName, uniforms, uniformBuffers, samplers, defines) {
+            CustomMaterial.ShaderIndexer++;
+            var name = name + "custom_" + CustomMaterial.ShaderIndexer;
+            this.ReviewUniform("uniform", uniforms);
+            this.ReviewUniform("sampler", samplers);
+            var fn_afterBind = this._afterBind;
+            this._afterBind = function (m, e) {
+                this.AttachAfterBind(m, e);
+                try {
+                    fn_afterBind(m, e);
+                }
+                catch (e) { }
+                ;
+            };
+            BABYLON.Effect.ShadersStore[name + "VertexShader"] = this.ShaderVersion.VertexStore
+                .replace('#[Vertex_Begin]', (this.CustomParts.Vertex_Begin ? this.CustomParts.Vertex_Begin : ""))
+                .replace('#[Vertex_Definations]', (this._customUnifrom ? this._customUnifrom.join("\n") : "") + (this.CustomParts.Vertex_Definations ? this.CustomParts.Vertex_Definations : ""))
+                .replace('#[Vertex_MainBegin]', (this.CustomParts.Vertex_MainBegin ? this.CustomParts.Vertex_MainBegin : ""))
+                .replace('#[Vertex_Before_PositionUpdated]', (this.CustomParts.Vertex_Before_PositionUpdated ? this.CustomParts.Vertex_Before_PositionUpdated : ""))
+                .replace('#[Vertex_Before_NormalUpdated]', (this.CustomParts.Vertex_Before_NormalUpdated ? this.CustomParts.Vertex_Before_NormalUpdated : ""));
+            BABYLON.Effect.ShadersStore[name + "PixelShader"] = this.ShaderVersion.FragmentStore
+                .replace('#[Fragment_Begin]', (this.CustomParts.Fragment_Begin ? this.CustomParts.Fragment_Begin : ""))
+                .replace('#[Fragment_MainBegin]', (this.CustomParts.Fragment_MainBegin ? this.CustomParts.Fragment_MainBegin : ""))
+                .replace('#[Fragment_Definations]', (this._customUnifrom ? this._customUnifrom.join("\n") : "") + (this.CustomParts.Fragment_Definations ? this.CustomParts.Fragment_Definations : ""))
+                .replace('#[Fragment_Custom_Diffuse]', (this.CustomParts.Fragment_Custom_Diffuse ? this.CustomParts.Fragment_Custom_Diffuse : ""))
+                .replace('#[Fragment_Custom_Alpha]', (this.CustomParts.Fragment_Custom_Alpha ? this.CustomParts.Fragment_Custom_Alpha : ""))
+                .replace('#[Fragment_Before_FragColor]', (this.CustomParts.Fragment_Before_FragColor ? this.CustomParts.Fragment_Before_FragColor : ""));
+            return name;
+        };
+        CustomMaterial.prototype.SelectVersion = function (ver) {
+            switch (ver) {
+                case "3.0.0":
+                    this.ShaderVersion = new ShaderForVer3_0();
+                    break;
+            }
+        };
+        CustomMaterial.prototype.AddUniform = function (name, kind, param) {
+            if (!this._customUnifrom) {
+                this._customUnifrom = new Array();
+                this._newUnifroms = new Array();
+                this._newSamplerInstances = new Array();
+                this._newUnifromInstances = new Array();
+            }
+            if (param) {
+                if (kind.indexOf("sampler") == -1) {
+                    this._newUnifromInstances[kind + "-" + name] = param;
+                }
+                else {
+                    this._newSamplerInstances[kind + "-" + name] = param;
+                }
+            }
+            this._customUnifrom.push("uniform " + kind + " " + name + ";");
+            this._newUnifroms.push(name);
+            return this;
+        };
+        CustomMaterial.prototype.Fragment_Begin = function (shaderPart) {
+            this.CustomParts.Fragment_Begin = shaderPart;
+            return this;
+        };
+        CustomMaterial.prototype.Fragment_Definations = function (shaderPart) {
+            this.CustomParts.Fragment_Definations = shaderPart;
+            return this;
+        };
+        CustomMaterial.prototype.Fragment_MainBegin = function (shaderPart) {
+            this.CustomParts.Fragment_MainBegin = shaderPart;
+            return this;
+        };
+        CustomMaterial.prototype.Fragment_Custom_Diffuse = function (shaderPart) {
+            this.CustomParts.Fragment_Custom_Diffuse = shaderPart.replace("result", "diffuseColor");
+            return this;
+        };
+        CustomMaterial.prototype.Fragment_Custom_Alpha = function (shaderPart) {
+            this.CustomParts.Fragment_Custom_Alpha = shaderPart.replace("result", "alpha");
+            return this;
+        };
+        CustomMaterial.prototype.Fragment_Before_FragColor = function (shaderPart) {
+            this.CustomParts.Fragment_Before_FragColor = shaderPart.replace("result", "color");
+            return this;
+        };
+        CustomMaterial.prototype.Vertex_Begin = function (shaderPart) {
+            this.CustomParts.Vertex_Begin = shaderPart;
+            return this;
+        };
+        CustomMaterial.prototype.Vertex_Definations = function (shaderPart) {
+            this.CustomParts.Vertex_Definations = shaderPart;
+            return this;
+        };
+        CustomMaterial.prototype.Vertex_MainBegin = function (shaderPart) {
+            this.CustomParts.Vertex_MainBegin = shaderPart;
+            return this;
+        };
+        CustomMaterial.prototype.Vertex_Before_PositionUpdated = function (shaderPart) {
+            this.CustomParts.Vertex_Before_PositionUpdated = shaderPart.replace("result", "positionUpdated");
+            return this;
+        };
+        CustomMaterial.prototype.Vertex_Before_NormalUpdated = function (shaderPart) {
+            this.CustomParts.Vertex_Before_NormalUpdated = shaderPart.replace("result", "normalUpdated");
+            return this;
+        };
         return CustomMaterial;
     }(BABYLON.StandardMaterial));
+    CustomMaterial.ShaderIndexer = 1;
     BABYLON.CustomMaterial = CustomMaterial;
 })(BABYLON || (BABYLON = {}));
 

Разлика између датотеке није приказан због своје велике величине
+ 1 - 1
dist/preview release/materialsLibrary/babylon.customMaterial.min.js


Разлика између датотеке није приказан због своје велике величине
+ 1 - 1
dist/preview release/materialsLibrary/babylon.waterMaterial.min.js


Разлика између датотеке није приказан због своје велике величине
+ 1 - 1
dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.min.js


Разлика између датотеке није приказан због своје велике величине
+ 1 - 1
dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js


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

@@ -18,6 +18,7 @@
  - Multi-platform Compressed Textures for Desktops & Mobile Devices with fall back.  Batch (dos) scripts to convert entire directories of .jpg's & .png's [Doc](http://doc.babylonjs.com/tutorials/multi-platform_compressed_textures) ([jcpalmer](https://github.com/Palmer-JC))
  - All deprecated functions and properties were removed ([deltakosh](https://github.com/deltakosh))
  - New build system based on workloads. [More info here](http://doc.babylonjs.com/generals/how_to_start#custom-builds) ([deltakosh](https://github.com/deltakosh))
+ - New `Cell Shading` material added into `Materials Library` [Demo](http://www.babylonjs.com/Demos/CellShading/) - ([Julien Moreau-Mathis](https://github.com/julien-moreau))
 
 ### Updates
 - Added `FIXED_EQUIRECTANGULAR_MIRRORED_MODE` mode for reflection texture. [Demo here](http://www.babylonjs-playground.com/#11GAIH#22) ([deltakosh](https://github.com/deltakosh))
@@ -51,6 +52,7 @@
 - Added `material.twoSidedLighting` to PBRMaterial and StandardMaterial to enable flipping normals when backfaceCulling is false ([BeardedGnome](https://github.com/BeardedGnome), [bghgary](https://github.com/bghgary))
 - Added a [HTML page](https://github.com/BabylonJS/Babylon.js/blob/master/Tools/Gulp/profiling.html) with embedded directions to improve the custom build process. ([jcpalmer](https://github.com/Palmer-JC))
 - Added glTF 2.0 loader with versioning support ([bghgary](https://github.com/bghgary), thanks to [BeardedGnome](https://github.com/BeardedGnome) for animation updates)
+- New `Motion Blur` effect added into `StandardRenderingPipeline` [Demo](http://www.babylonjs.com/Demos/MotionBlur/) - ([Julien Moreau-Mathis](https://github.com/julien-moreau))
  
 ### Bug fixes
 - Fixed a bug with spotlight direction ([deltakosh](https://github.com/deltakosh)) 

+ 16 - 3
gui/src/advancedDynamicTexture.ts

@@ -5,10 +5,13 @@ module BABYLON.GUI {
         private _isDirty = false;
         private _renderObserver: Observer<Scene>;
         private _resizeObserver: Observer<Engine>;
-        private _pointerMoveObserver: Observer<PointerInfo>;
+        private _pointerMoveObserver: Observer<PointerInfoPre>;
         private _background: string;
         private _rootContainer = new Container("root");
         public _lastControlOver: Control;
+        public _lastControlDown: Control;
+        public _shouldBlockPointer: boolean;
+        public _toDispose: IDisposable;
 
         public get background(): string {
             return this._background;
@@ -61,7 +64,12 @@ module BABYLON.GUI {
             }
 
             if (this._pointerMoveObserver) {
-                this.getScene().onPointerObservable.remove(this._pointerMoveObserver);
+                this.getScene().onPrePointerObservable.remove(this._pointerMoveObserver);
+            }
+
+            if (this._toDispose) {
+                this._toDispose.dispose();
+                this._toDispose = null;
             }
 
             super.dispose();
@@ -125,14 +133,17 @@ module BABYLON.GUI {
 
         public attach(): void {
             var scene = this.getScene();
-            this._pointerMoveObserver = scene.onPointerObservable.add((pi, state) => {
+            this._pointerMoveObserver = scene.onPrePointerObservable.add((pi, state) => {
                 if (pi.type !== BABYLON.PointerEventTypes.POINTERMOVE 
                     && pi.type !== BABYLON.PointerEventTypes.POINTERUP
                     && pi.type !== BABYLON.PointerEventTypes.POINTERDOWN) {
                     return;
                 }
 
+                this._shouldBlockPointer = false;
                 this._doPicking(scene.pointerX, scene.pointerY, pi.type);
+
+                pi.skipOnPointerObservable = this._shouldBlockPointer;
             });
         }
 
@@ -157,6 +168,8 @@ module BABYLON.GUI {
             var layer = new BABYLON.Layer(name + "_layer", null, scene, !foreground);
             layer.texture = result;
 
+            result._toDispose = layer;
+
             // Attach
             result.attach();
 

+ 42 - 1
gui/src/controls/button.ts

@@ -4,11 +4,13 @@ module BABYLON.GUI {
     export class Button extends Rectangle {      
         constructor(public name: string) {
             super(name);
+            this.thickness = 1;
+            this.isPointerBlocker = true;
         }
 
         // While being a container, the button behaves like a control.
         public _processPicking(x: number, y: number, type: number): boolean {
-            if (!this._contains(x, y)) {
+            if (!this.contains(x, y)) {
                 return false;
             }
 
@@ -17,6 +19,33 @@ module BABYLON.GUI {
             return true;
         }
 
+        protected _onPointerEnter(): void {
+            this.scaleX += 0.01;
+            this.scaleY += 0.01;
+            super._onPointerEnter();
+        }
+
+        protected _onPointerOut(): void {
+            this.scaleX -= 0.01;
+            this.scaleY -= 0.01;
+
+            super._onPointerOut();
+        }
+
+        protected _onPointerDown(): void {
+            this.scaleX -= 0.05;
+            this.scaleY -= 0.05;
+
+            super._onPointerDown();
+        }
+
+        protected _onPointerUp (): void {
+            this.scaleX += 0.05;
+            this.scaleY += 0.05;
+
+            super._onPointerUp();
+        }        
+
         // Statics
         public static CreateImageButton(name: string, text: string, imageUrl: string): Button {
             var result = new Button(name);
@@ -37,5 +66,17 @@ module BABYLON.GUI {
 
             return result;
         }
+
+        public static CreateSimpleButton(name: string, text: string): Button {
+            var result = new Button(name);
+
+            // Adding text
+            var textBlock = new BABYLON.GUI.TextBlock(name + "_button", text);
+            textBlock.textWrapping = true;
+            textBlock.textHorizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_CENTER;
+            result.addControl(textBlock);           
+
+            return result;
+        }
     }    
 }

+ 10 - 2
gui/src/controls/container.ts

@@ -53,11 +53,19 @@ module BABYLON.GUI {
             // Implemented by child to be injected inside main draw
         }
 
+        public _link(root: Container, host: AdvancedDynamicTexture): void {
+            super._link(root, host);
+
+            for (var child of this._children) {
+                child._link(root, host);
+            }
+        }
+
         public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
             context.save();
             super._processMeasures(parentMeasure, context);
            
-            this.applyStates(context);
+            this._applyStates(context);
 
             this._localDraw(context);
 
@@ -69,7 +77,7 @@ module BABYLON.GUI {
         }
 
         public _processPicking(x: number, y: number, type: number): boolean {
-            if (!super._contains(x, y)) {
+            if (!super.contains(x, y)) {
                 return false;
             }
 

+ 189 - 12
gui/src/controls/control.ts

@@ -24,6 +24,19 @@ module BABYLON.GUI {
         private _marginBottom = new ValueAndUnit(0);        
         private _left = new ValueAndUnit(0);
         private _top = new ValueAndUnit(0);
+        private _scaleX = 1.0;
+        private _scaleY = 1.0;
+        private _rotation = 0;
+        private _transformCenterX = 0.5;
+        private _transformCenterY = 0.5;
+        private _transformMatrix = Matrix2D.Identity();
+        private _invertTransformMatrix = Matrix2D.Identity();
+        private _isMatrixDirty = true;
+        private _cachedOffsetX: number;
+        private _cachedOffsetY: number;
+
+        public isHitTestVisible = true;
+        public isPointerBlocker = false;
         
         // Properties
 
@@ -51,6 +64,82 @@ module BABYLON.GUI {
         */
         public onPointerUpObservable = new Observable<Control>();     
 
+        /**
+        * An event triggered when pointer enters the control
+        * @type {BABYLON.Observable}
+        */
+        public onPointerEnterObservable = new Observable<Control>();           
+
+        public get scaleX(): number {
+            return this._scaleX;
+        }
+
+        public set scaleX(value: number) {
+            if (this._scaleX === value) {
+                return;
+            }
+
+            this._scaleX = value;
+            this._markAsDirty();
+            this._isMatrixDirty = true;
+        }     
+
+        public get scaleY(): number {
+            return this._scaleY;
+        }
+
+        public set scaleY(value: number) {
+            if (this._scaleY === value) {
+                return;
+            }
+
+            this._scaleY = value;
+            this._markAsDirty();
+            this._isMatrixDirty = true;
+        }  
+
+        public get rotation(): number {
+            return this._rotation;
+        }
+
+        public set rotation(value: number) {
+            if (this._rotation === value) {
+                return;
+            }
+
+            this._rotation = value;
+            this._markAsDirty();
+            this._isMatrixDirty = true;
+        }    
+
+        public get transformCenterY(): number {
+            return this._transformCenterY;
+        }
+
+        public set transformCenterY(value: number) {
+            if (this._transformCenterY === value) {
+                return;
+            }
+
+            this._transformCenterY = value;
+            this._markAsDirty();
+            this._isMatrixDirty = true;
+        }     
+
+        public get transformCenterX(): number {
+            return this._transformCenterX;
+        }
+
+        public set transformCenterX(value: number) {
+            if (this._transformCenterX === value) {
+                return;
+            }
+
+            this._transformCenterX = value;
+            this._markAsDirty();
+            this._isMatrixDirty = true;
+        }    
+
         public get horizontalAlignment(): number {
             return this._horizontalAlignment;
         }
@@ -240,7 +329,39 @@ module BABYLON.GUI {
             this._host = host;
         }
 
-        protected applyStates(context: CanvasRenderingContext2D): void {
+        protected _transform(context: CanvasRenderingContext2D): void {
+            if (this._scaleX === 1 && this._scaleY ===1 && this._rotation === 0) {
+                return;
+            }
+
+            // preTranslate
+            var offsetX = this._currentMeasure.width * this._transformCenterX + this._currentMeasure.left;
+            var offsetY = this._currentMeasure.height * this._transformCenterY + this._currentMeasure.top;
+            context.translate(offsetX, offsetY);
+
+            // scale
+            context.scale(this._scaleX, this._scaleY);
+
+            // rotate
+            context.rotate(this._rotation);
+
+            // postTranslate
+            context.translate(-offsetX, -offsetY);    
+
+
+            // Need to update matrices?
+            if (this._isMatrixDirty || this._cachedOffsetX !== offsetX || this._cachedOffsetY !== offsetY) {
+                this._cachedOffsetX = offsetX;
+                this._cachedOffsetY = offsetY;
+                this._isMatrixDirty = false;
+
+                Matrix2D.ComposeToRef(offsetX, offsetY, this._rotation, this._scaleX, this._scaleY, this._root ? this._root._transformMatrix : null, this._transformMatrix);
+
+                this._transformMatrix.invertToRef(this._invertTransformMatrix);
+            }
+        }
+
+        protected _applyStates(context: CanvasRenderingContext2D): void {
             if (this._font) {
                 context.font = this._font;
             }
@@ -268,7 +389,10 @@ module BABYLON.GUI {
 
                 this._isDirty = false;
                 this._cachedParentMeasure.copyFrom(parentMeasure);
-            }      
+            }     
+
+            // Transform
+            this._transform(context); 
                         
             // Clip
             this._clip(context);
@@ -382,7 +506,13 @@ module BABYLON.GUI {
             // Do nothing
         }
 
-        protected _contains(x: number, y: number) : boolean {
+        public contains(x: number, y: number) : boolean {
+            // Invert transform
+            if (this._scaleX !== 1 || this._scaleY !== 1 || this.rotation !== 0) {
+               
+            }
+
+            // Check
             if (x < this._currentMeasure.left) {
                 return false;
             }
@@ -399,11 +529,14 @@ module BABYLON.GUI {
                 return false;
             } 
 
+            if (this.isPointerBlocker) {
+                this._host._shouldBlockPointer = true;
+            }
             return true;
         }
 
         public _processPicking(x: number, y: number, type: number): boolean {
-            if (!this._contains(x, y)) {
+            if (!this.contains(x, y)) {
                 return false;
             }
 
@@ -412,25 +545,69 @@ module BABYLON.GUI {
             return true;
         }
 
-        protected _processObservables(type: number): boolean {
-            if (type === BABYLON.PointerEventTypes.POINTERMOVE && this.onPointerMoveObservable.hasObservers()) {
+        protected _onPointerMove(): void {
+            if (this.onPointerMoveObservable.hasObservers()) {
                 this.onPointerMoveObservable.notifyObservers(this);
+            }
+        }
+
+        protected _onPointerEnter(): void {
+            if (this.onPointerEnterObservable.hasObservers()) {
+                this.onPointerEnterObservable.notifyObservers(this);
+            }
+        }
+
+        protected _onPointerOut(): void {
+            if (this.onPointerOutObservable.hasObservers()) {
+                this.onPointerOutObservable.notifyObservers(this);
+            }
+        }
+
+        protected _onPointerDown(): void {
+            if (this.onPointerDownObservable.hasObservers()) {
+                this.onPointerDownObservable.notifyObservers(this);
+            }
+        }
+
+        protected _onPointerUp(): void {
+            if (this.onPointerUpObservable.hasObservers()) {
+                this.onPointerUpObservable.notifyObservers(this);
+            }
+        }
+
+        protected _processObservables(type: number): boolean {
+            if (!this.isHitTestVisible) {
+                return false;
+            }
+
+            if (type === BABYLON.PointerEventTypes.POINTERMOVE) {
+                this._onPointerMove();
 
                 var previousControlOver = this._host._lastControlOver;
-                if (previousControlOver && previousControlOver !== this && previousControlOver.onPointerOutObservable.hasObservers()) {
-                    previousControlOver.onPointerOutObservable.notifyObservers(previousControlOver);
+                if (previousControlOver && previousControlOver !== this) {
+                    previousControlOver._onPointerOut();
                 }
+
+                if (previousControlOver !== this) {
+                    this._onPointerEnter();
+                }
+
                 this._host._lastControlOver = this;
                 return true;
             }
 
-            if (type === BABYLON.PointerEventTypes.POINTERDOWN && this.onPointerDownObservable.hasObservers()) {
-                this.onPointerDownObservable.notifyObservers(this);
+            if (type === BABYLON.PointerEventTypes.POINTERDOWN) {
+                this._onPointerDown();
+                this._host._lastControlDown = this;
                 return true;
             }
 
-            if (type === BABYLON.PointerEventTypes.POINTERUP && this.onPointerUpObservable.hasObservers()) {
-                this.onPointerUpObservable.notifyObservers(this);
+            if (type === BABYLON.PointerEventTypes.POINTERUP) {
+                this._onPointerUp();
+                if (this._host._lastControlDown !== this) {
+                    this._host._lastControlDown._onPointerUp();
+                    this._host._lastControlDown = null;
+                }
                 return true;
             }
         

+ 1 - 1
gui/src/controls/image.ts

@@ -42,7 +42,7 @@ module BABYLON.GUI {
         public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
             context.save();
 
-            this.applyStates(context);
+            this._applyStates(context);
             super._processMeasures(parentMeasure, context);
 
             if (this._loaded) {

+ 1 - 1
gui/src/controls/textBlock.ts

@@ -88,7 +88,7 @@ module BABYLON.GUI {
         public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
             context.save();
 
-            this.applyStates(context);
+            this._applyStates(context);
             super._processMeasures(parentMeasure, context);
             
             // Render lines

+ 96 - 0
gui/src/math2D.ts

@@ -0,0 +1,96 @@
+/// <reference path="../../dist/preview release/babylon.d.ts"/>
+
+module BABYLON.GUI {
+    export class Matrix2D {
+        public m = new Float32Array(6);
+
+        constructor(m00: number, m01: number, m10: number, m11: number, m20: number, m21: number) {
+            this.fromValues(m00, m01, m10, m11, m20, m21);
+        }
+
+        public fromValues(m00: number, m01: number, m10: number, m11: number, m20: number, m21: number): Matrix2D {
+            this.m[0] = m00; this.m[1] = m01; 
+            this.m[2] = m10; this.m[3] = m11;
+            this.m[4] = m20; this.m[5] = m21;
+            return this;
+        }
+
+        public determinant(): number {
+            return this.m[0] * this.m[3] - this.m[1] * this.m[2];
+        }
+
+        public invertToRef(result: Matrix2D): Matrix2D {
+            let l0 = this.m[0]; let l1 = this.m[1];
+            let l2 = this.m[2]; let l3 = this.m[3];
+            let l4 = this.m[4]; let l5 = this.m[5];
+
+            let det = this.determinant();
+            if (det < (Epsilon * Epsilon)) {
+                throw new Error("Can't invert matrix, near null determinant");
+            }
+
+            let detDiv = 1 / det;
+
+            let det4 = l2 * l5 - l3 * l4;
+            let det5 = l1 * l4 - l0 * l5;
+
+            result.m[0] = l3 * detDiv;     result.m[1] = -l1 * detDiv;
+            result.m[2] = -l2 * detDiv;    result.m[3] = l0 * detDiv;
+            result.m[4] = det4 * detDiv;   result.m[5] = det5 * detDiv;
+
+            return this;
+        }
+
+        public multiplyToRef(other: Matrix2D, result: Matrix2D): Matrix2D {
+            let l0 = this.m[0];     let l1 = this.m[1];
+            let l2 = this.m[2];     let l3 = this.m[3];
+            let l4 = this.m[4];     let l5 = this.m[5];
+
+            let r0 = other.m[0];    let r1 = other.m[1];
+            let r2 = other.m[2];    let r3 = other.m[3];
+            let r4 = other.m[4];    let r5 = other.m[5];
+
+            result.m[0] = l0 * r0 + l1 * r2;        result.m[1] = l0 * r1 + l1 * r3;
+            result.m[2] = l2 * r0 + l3 * r2;        result.m[3] = l2 * r1 + l3 * r3;
+            result.m[4] = l4 * r0 + l5 * r2 + r4;   result.m[5] = l4 * r1 + l5 * r3 + r5;
+
+            return this;
+        }
+
+        // Statics
+        public static Identity(): Matrix2D {
+            return new Matrix2D(1, 0, 0, 1, 0, 0);
+        }
+
+        public static TranslationToRef(x: number, y: number, result: Matrix2D): void {
+            result.fromValues(1, 0, 0, 1, x, y);
+        }
+
+        public static ScalingToRef(x: number, y: number, result: Matrix2D): void {
+            result.fromValues(x, 0, 0, y,  0, 0);
+        }
+
+        public static RotationToRef(angle: number, result: Matrix2D): void {
+            var s = Math.sin(angle);
+            var c = Math.cos(angle);
+
+            result.fromValues(c, s, -s, c,  0, 0);
+        }
+
+
+        private static _TempPreTranslationMatrix = Matrix2D.Identity();
+        private static _TempPostTranslationMatrix = Matrix2D.Identity();
+        private static _TempRotationMatrix = Matrix2D.Identity();
+        private static _TempScalingMatrix = Matrix2D.Identity();
+
+        public static ComposeToRef(tx: number, ty: number, angle: number, scaleX: number, scaleY: number, parentMatrix: Matrix2D,  result: Matrix2D): void {
+            Matrix2D.TranslationToRef(tx, ty, Matrix2D._TempPreTranslationMatrix);
+
+            Matrix2D.ScalingToRef(scaleX, scaleY, Matrix2D._TempScalingMatrix);
+
+            Matrix2D.RotationToRef(angle, Matrix2D._TempRotationMatrix);
+
+            Matrix2D.TranslationToRef(-tx, -ty, Matrix2D._TempPostTranslationMatrix);
+        }
+    }    
+}

+ 7 - 10
inspector/src/adapters/MeshAdapter.ts

@@ -95,7 +95,7 @@ module INSPECTOR {
             var x = new BABYLON.Vector3(8, 0, 0);
             var y = new BABYLON.Vector3(0, 8, 0);
             var z = new BABYLON.Vector3(0, 0, 8);
-
+            
             // Draw an axis of the given color
             let _drawAxis = (color, start, end): BABYLON.LinesMesh => {
                 let axis = BABYLON.Mesh.CreateLines("###axis###", [
@@ -110,26 +110,23 @@ module INSPECTOR {
             // X axis
             let xAxis = _drawAxis(
                 BABYLON.Color3.Red(),
-                this._obj.getAbsolutePosition(),
-                BABYLON.Vector3.TransformCoordinates(x, m));
-            xAxis.position.subtractInPlace(this._obj.position);
+                BABYLON.Vector3.Zero(),
+                x);
             xAxis.parent = this._obj;
             this._axis.push(xAxis);
             // Y axis        
             let yAxis = _drawAxis(
                 BABYLON.Color3.Green(),
-                this._obj.getAbsolutePosition(),
-                BABYLON.Vector3.TransformCoordinates(y, m));
+                BABYLON.Vector3.Zero(),
+                y);
             yAxis.parent = this._obj;
-            yAxis.position.subtractInPlace(this._obj.position);
             this._axis.push(yAxis);
             // Z axis
             let zAxis = _drawAxis(
                 BABYLON.Color3.Blue(),
-                this._obj.getAbsolutePosition(),
-                BABYLON.Vector3.TransformCoordinates(z, m));
+                BABYLON.Vector3.Zero(),
+                z);
             zAxis.parent = this._obj;
-            zAxis.position.subtractInPlace(this._obj.position);
             this._axis.push(zAxis);
         }
     }

+ 15 - 0
loaders/src/glTF/README.md

@@ -3,6 +3,8 @@
 # Usage
 The glTF file loader is a SceneLoader plugin.
 
+[glTF2 Playground example](http://www.babylonjs-playground.com/#6MZV8R)
+
 ## Step 1 - Include the glTF File Loader
 
 **Full Version**
@@ -47,6 +49,19 @@ BABYLON.SceneLoader.ImportMesh(["myMesh1", "myMesh2", "..."], "./", "duck.gltf",
 });
 ```
 
+You can also append a glTF file to a scene. When using `SceneLoader.Append`, configure the scene to use right handed system by setting the property `useRightHandedSystem` to true. 
+
+```
+// glTF Files use right handed system 
+scene.useRightHandedSystem = true;
+
+// Append sample glTF model to scene
+BABYLON.SceneLoader.Append("https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/BoomBox/glTF/", "BoomBox.gltf", scene, function (scene) {
+}, null, function (scene) {
+    alert("error");
+});
+```
+
 ## Step 3 (V1 Only) - Optionally Specify Flags
 
 If you want to disable incremental loading, you can set the property `IncrementalLoading` to false.

+ 0 - 145
localDev/captureMenu.css

@@ -1,145 +0,0 @@
-.captureMenuComponent {
-  position: absolute;
-  top: 10px;
-  left: 50%;
-  margin-left: -200px;
-  height: 40px;
-  width: 400px;
-  background-color: #222;
-  opacity: 0.6;
-  visibility: hidden;
-  display: none;
-  color: #f9f9f9;
-  font-family: Consolas, monaco, monospace;
-  font-size: 14px;
-  font-weight: 500; }
-  .captureMenuComponent.active {
-    visibility: visible;
-    display: block; }
-
-.canvasListComponent {
-  float: left;
-  width: 50%;
-  height: 100%; }
-  .canvasListComponent [commandName=onCanvasSelection] {
-    vertical-align: center;
-    margin: 10px;
-    line-height: 40px; }
-    .canvasListComponent [commandName=onCanvasSelection]:hover {
-      color: #c9c9c9;
-      cursor: pointer;
-      transition: color 0.3s;
-      -webkit-transition: color 0.3s;
-      -moz-transition: color 0.3s; }
-  .canvasListComponent ul {
-    margin: 0px;
-    padding: 0px;
-    list-style: none;
-    position: absolute;
-    top: 40px;
-    width: 400px;
-    background-color: #222; }
-    .canvasListComponent ul li {
-      margin: 10px; }
-      .canvasListComponent ul li:hover {
-        color: #c9c9c9;
-        cursor: pointer;
-        transition: color 0.3s;
-        -webkit-transition: color 0.3s;
-        -moz-transition: color 0.3s; }
-
-.captureMenuActionsComponent {
-  float: left;
-  width: 30%;
-  height: 100%;
-  margin-top: 7.5px; }
-  .captureMenuActionsComponent div {
-    float: left; }
-  .captureMenuActionsComponent [commandName=onCaptureRequested] {
-    border-radius: 50%;
-    background: #222;
-    border: 2px solid red;
-    width: 21px;
-    height: 21px; }
-    .captureMenuActionsComponent [commandName=onCaptureRequested]:hover {
-      background: red;
-      cursor: pointer;
-      transition: background 0.3s;
-      -webkit-transition: background 0.3s;
-      -moz-transition: background 0.3s; }
-  .captureMenuActionsComponent [commandName=onPlayRequested], .captureMenuActionsComponent [commandName=onPlayNextFrameRequested] {
-    width: 21px;
-    height: 21px;
-    border: 2px solid #f9f9f9;
-    border-radius: 50%;
-    margin-left: 9px; }
-    .captureMenuActionsComponent [commandName=onPlayRequested]:before, .captureMenuActionsComponent [commandName=onPlayNextFrameRequested]:before {
-      content: '';
-      position: absolute;
-      display: inline-block;
-      margin-top: 6px;
-      margin-left: 4px;
-      width: 7px;
-      height: 7px;
-      border-top: 2px solid #f9f9f9;
-      border-right: 2px solid #f9f9f9;
-      background-color: #f9f9f9;
-      -moz-transform: rotate(45deg);
-      -webkit-transform: rotate(45deg);
-      transform: rotate(45deg);
-      z-index: -20; }
-    .captureMenuActionsComponent [commandName=onPlayRequested]:after, .captureMenuActionsComponent [commandName=onPlayNextFrameRequested]:after {
-      content: '';
-      position: absolute;
-      display: inline-block;
-      width: 8px;
-      height: 20px;
-      background-color: #222;
-      z-index: -10; }
-    .captureMenuActionsComponent [commandName=onPlayRequested]:hover, .captureMenuActionsComponent [commandName=onPlayNextFrameRequested]:hover {
-      cursor: pointer;
-      border: 2px solid #c9c9c9;
-      transition: border 0.3s;
-      -webkit-transition: border 0.3s;
-      -moz-transition: border 0.3s; }
-  .captureMenuActionsComponent [commandName=onPauseRequested] {
-    width: 21px;
-    height: 21px;
-    border: 2px solid #f9f9f9;
-    border-radius: 50%;
-    margin-left: 9px; }
-    .captureMenuActionsComponent [commandName=onPauseRequested]:before {
-      content: '';
-      position: absolute;
-      display: inline-block;
-      width: 2px;
-      height: 13px;
-      margin-left: 12px;
-      margin-top: 4px;
-      background-color: #f9f9f9; }
-    .captureMenuActionsComponent [commandName=onPauseRequested]:after {
-      content: '';
-      position: absolute;
-      display: inline-block;
-      width: 2px;
-      height: 13px;
-      margin-left: 7px;
-      margin-top: 4px;
-      background-color: #f9f9f9; }
-    .captureMenuActionsComponent [commandName=onPauseRequested]:hover {
-      cursor: pointer;
-      border: 2px solid #c9c9c9;
-      transition: border 0.3s;
-      -webkit-transition: border 0.3s;
-      -moz-transition: border 0.3s; }
-  .captureMenuActionsComponent [commandName=onPlayNextFrameRequested]:before {
-    background-color: #222; }
-
-.fpsCounterComponent {
-  float: left;
-  width: 20%;
-  vertical-align: center;
-  line-height: 40px;
-  white-space: nowrap; }
-
-/*# sourceMappingURL=captureMenu.css.map */

BIN
localDev/localDev.zip


+ 0 - 245
localDev/resultView.css

@@ -1,245 +0,0 @@
-.resultViewComponent {
-  position: absolute;
-  top: 10px;
-  left: 10px;
-  bottom: 10px;
-  right: 10px;
-  background-color: #222;
-  opacity: 1;
-  visibility: hidden;
-  display: none;
-  color: #f9f9f9;
-  font-family: Consolas, monaco, monospace;
-  font-size: 14px;
-  font-weight: 500; }
-  .resultViewComponent.active {
-    visibility: visible;
-    display: block; }
-
-.resultViewMenuComponent {
-  font-size: 16px;
-  font-weight: 500;
-  line-height: 20px;
-  flex: 1 100%;
-  display: flex;
-  flex-flow: row wrap;
-  height: 60px;
-  list-style: none;
-  margin: 0;
-  background: #444;
-  display: -webkit-box;
-  display: -moz-box;
-  display: -ms-flexbox;
-  display: -webkit-flex;
-  display: flex;
-  -webkit-flex-flow: row wrap;
-  flex-flow: row wrap;
-  justify-content: flex-end; }
-
-.resultViewMenuComponent a {
-  text-decoration: none;
-  display: block;
-  padding: 20px;
-  color: #f9f9f9;
-  background: #444; }
-  .resultViewMenuComponent a.active {
-    background: #222;
-    color: #f29766; }
-
-.resultViewMenuComponent a:hover {
-  background: #222; }
-  .resultViewMenuComponent a:hover:hover {
-    color: #c9c9c9;
-    cursor: pointer;
-    transition: color 0.3s;
-    -webkit-transition: color 0.3s;
-    -moz-transition: color 0.3s; }
-    .resultViewMenuComponent a:hover:hover.active {
-      color: #f29766;
-      transition: color 0;
-      -webkit-transition: color 0;
-      -moz-transition: color 0; }
-
-.resultViewContentComponent {
-  position: absolute;
-  top: 60px;
-  left: 0;
-  bottom: 0;
-  right: 0; }
-
-.captureListComponent {
-  position: absolute;
-  top: 60px;
-  left: 0;
-  bottom: 0;
-  right: 0;
-  background: #222;
-  z-index: 9000;
-  display: none;
-  visibility: hidden;
-  overflow-y: visible;
-  overflow-x: hidden; }
-  .captureListComponent.active {
-    display: block;
-    visibility: visible; }
-  .captureListComponent ul {
-    margin: 0px;
-    padding: 0px;
-    list-style: none;
-    display: -webkit-box;
-    display: -moz-box;
-    display: -ms-flexbox;
-    display: -webkit-flex;
-    display: flex;
-    -webkit-flex-flow: row wrap;
-    flex-flow: row wrap;
-    justify-content: flex-start; }
-    .captureListComponent ul li {
-      margin: 10px; }
-      .captureListComponent ul li img {
-        width: 288px;
-        border: 1px solid #222;
-        background-image: -moz-linear-gradient(45deg, #d9d9d9 25%, transparent 25%), -moz-linear-gradient(-45deg, #d9d9d9 25%, transparent 25%), -moz-linear-gradient(45deg, transparent 75%, #d9d9d9 75%), -moz-linear-gradient(-45deg, transparent 75%, #d9d9d9 75%);
-        background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, #c9c9c9), color-stop(0.25, transparent)), -webkit-gradient(linear, 0 0, 100% 100%, color-stop(0.25, #c9c9c9), color-stop(0.25, transparent)), -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.75, transparent), color-stop(0.75, #c9c9c9)), -webkit-gradient(linear, 0 0, 100% 100%, color-stop(0.75, transparent), color-stop(0.75, #c9c9c9));
-        -moz-background-size: 50px 50px;
-        background-size: 50px 50px;
-        -webkit-background-size: 50px 51px;
-        background-position: 0 0, 25px 0, 25px -25px, 0px 25px; }
-      .captureListComponent ul li span {
-        display: block;
-        text-align: center; }
-      .captureListComponent ul li:hover {
-        cursor: pointer; }
-      .captureListComponent ul li.active img {
-        border: 1px solid #f29766; }
-
-.visualStateListComponent {
-  position: absolute;
-  top: 0;
-  left: 0;
-  bottom: 0;
-  right: 80%;
-  overflow-y: visible;
-  overflow-x: hidden; }
-  .visualStateListComponent ul {
-    margin: 0px;
-    padding: 0px;
-    list-style: none; }
-    .visualStateListComponent ul li {
-      margin: 10px; }
-      .visualStateListComponent ul li img {
-        width: 100%;
-        border: 1px solid #222;
-        background-image: -moz-linear-gradient(45deg, #d9d9d9 25%, transparent 25%), -moz-linear-gradient(-45deg, #d9d9d9 25%, transparent 25%), -moz-linear-gradient(45deg, transparent 75%, #d9d9d9 75%), -moz-linear-gradient(-45deg, transparent 75%, #d9d9d9 75%);
-        background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, #c9c9c9), color-stop(0.25, transparent)), -webkit-gradient(linear, 0 0, 100% 100%, color-stop(0.25, #c9c9c9), color-stop(0.25, transparent)), -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.75, transparent), color-stop(0.75, #c9c9c9)), -webkit-gradient(linear, 0 0, 100% 100%, color-stop(0.75, transparent), color-stop(0.75, #c9c9c9));
-        -moz-background-size: 50px 50px;
-        background-size: 50px 50px;
-        -webkit-background-size: 50px 51px;
-        background-position: 0 0, 25px 0, 25px -25px, 0px 25px; }
-      .visualStateListComponent ul li:hover {
-        cursor: pointer; }
-      .visualStateListComponent ul li.active img {
-        border: 1px solid #f29766; }
-
-.commandListComponent {
-  position: absolute;
-  top: 0;
-  left: 20%;
-  right: 40%;
-  bottom: 0; }
-  .commandListComponent ul {
-    margin: 0px;
-    margin-bottom: 5px;
-    padding: 0px;
-    list-style: none;
-    overflow-y: visible;
-    overflow-x: hidden;
-    height: 100%; }
-    .commandListComponent ul li {
-      padding: 10px; }
-      .commandListComponent ul li:hover {
-        color: #c9c9c9;
-        cursor: pointer;
-        transition: color 0.3s;
-        -webkit-transition: color 0.3s;
-        -moz-transition: color 0.3s; }
-      .commandListComponent ul li:nth-child(even) {
-        background: #444;
-        border: 1px solid #444; }
-      .commandListComponent ul li:nth-child(odd) {
-        background: #222;
-        border: 1px solid #222; }
-      .commandListComponent ul li .important {
-        font-weight: 800; }
-        .commandListComponent ul li .important.deprecated {
-          color: red; }
-        .commandListComponent ul li .important.unused {
-          color: yellow; }
-        .commandListComponent ul li .important.disabled {
-          color: gray; }
-        .commandListComponent ul li .important.redundant {
-          color: orange; }
-        .commandListComponent ul li .important.valid {
-          color: greenyellow; }
-      .commandListComponent ul li.active {
-        border: 1px solid #f29766; }
-
-.commandDetailComponent {
-  position: absolute;
-  top: 0;
-  left: 60%;
-  right: 0;
-  bottom: 0;
-  overflow-y: visible;
-  overflow-x: hidden; }
-
-.jsonGroupComponent {
-  display: block;
-  margin: 10px;
-  padding-bottom: 10px; }
-  .jsonGroupComponent .jsonGroupComponentTitle {
-    display: block;
-    font-size: 16px;
-    color: #5db0d7;
-    border-bottom: 1px solid #5db0d7;
-    padding-bottom: 10px;
-    margin-bottom: 10px;
-    text-transform: capitalize; }
-  .jsonGroupComponent ul {
-    margin: 0px;
-    padding: 0px;
-    list-style: none; }
-    .jsonGroupComponent ul li:nth-child(even) {
-      background: #222; }
-    .jsonGroupComponent ul li:nth-child(odd) {
-      background: #222; }
-
-.jsonItemComponentKey {
-  color: #f29766; }
-
-.jsonItemComponentValue {
-  white-space: pre-wrap; }
-
-.jsonVisualStateItemComponent {
-  text-align: center; }
-  .jsonVisualStateItemComponent img {
-    margin: 10px;
-    background-image: -moz-linear-gradient(45deg, #d9d9d9 25%, transparent 25%), -moz-linear-gradient(-45deg, #d9d9d9 25%, transparent 25%), -moz-linear-gradient(45deg, transparent 75%, #d9d9d9 75%), -moz-linear-gradient(-45deg, transparent 75%, #d9d9d9 75%);
-    background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, #c9c9c9), color-stop(0.25, transparent)), -webkit-gradient(linear, 0 0, 100% 100%, color-stop(0.25, #c9c9c9), color-stop(0.25, transparent)), -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.75, transparent), color-stop(0.75, #c9c9c9)), -webkit-gradient(linear, 0 0, 100% 100%, color-stop(0.75, transparent), color-stop(0.75, #c9c9c9));
-    -moz-background-size: 50px 50px;
-    background-size: 50px 50px;
-    -webkit-background-size: 50px 51px;
-    background-position: 0 0, 25px 0, 25px -25px, 0px 25px; }
-  .jsonVisualStateItemComponent span {
-    display: block; }
-
-.jsonContentComponent {
-  position: absolute;
-  top: 0;
-  left: 0;
-  right: 0;
-  bottom: 0;
-  overflow-y: visible;
-  overflow-x: hidden; }
-
-/*# sourceMappingURL=resultView.css.map */

Разлика између датотеке није приказан због своје велике величине
+ 0 - 5360
localDev/spector.js


+ 9 - 0
localDev/template/index.js

@@ -0,0 +1,9 @@
+// <reference path="../../dist/preview release/babylon.d.ts"/>
+
+var createScene = function() {
+	var scene = new BABYLON.Scene(engine);
+	var camera = new BABYLON.ArcRotateCamera("Camera", 0, Math.PI / 2, 12, BABYLON.Vector3.Zero(), scene);
+	camera.attachControl(canvas, true);
+
+	return scene;
+};

+ 8 - 2
materialsLibrary/index.html

@@ -3,7 +3,7 @@
 <head>
 	<title>Shaders Library</title>
 	<script src="../assets/refs/dat.gui.min.js"></script>
-	<script src="../tools/DevLoader/BabylonLoader.js"></script>
+	<script src="../Tools/DevLoader/BabylonLoader.js"></script>
 
 	<style>
 		html, body {
@@ -49,6 +49,7 @@
 	<script src="test/addsky.js"></script>
 	<script src="test/addgrid.js"></script>
     <script src="test/addpbr.js"></script>
+	<script src="test/addCell.js"></script>
 	
 	<script>
 	BABYLONDEVTOOLS.Loader.load(function() {
@@ -202,13 +203,15 @@
                 var grid = prepareGrid();
 
 				var shadowOnly = new BABYLON.ShadowOnlyMaterial();
+
+				var cell = prepareCell();
 				
 				// Default to std
 				var currentMaterial = std;
 				sphere.material = std;				
 				sphere.receiveShadows = true;
 
-				gui.add(options, 'material', ['standard', 'simple', 'water', 'fire', 'lava', 'normal', 'terrain', 'pbr', 'fur', 'triPlanar', 'gradient', 'sky', 'grid', 'shadowOnly']).onFinishChange(function () {
+				gui.add(options, 'material', ['standard', 'simple', 'water', 'fire', 'lava', 'normal', 'terrain', 'pbr', 'fur', 'triPlanar', 'gradient', 'sky', 'grid', 'shadowOnly', 'cell']).onFinishChange(function () {
 					water.enableRenderTargets(false);
 					skybox.material = skyboxMaterial;
 					currentMesh.isVisible = true;
@@ -258,6 +261,9 @@
                         case "grid":
                             currentMaterial = grid;
                             break;
+						case "cell":
+							currentMaterial = cell;
+							break;
 						default:
 							currentMaterial = std;
 							break;

+ 296 - 0
materialsLibrary/src/cell/babylon.cellMaterial.ts

@@ -0,0 +1,296 @@
+/// <reference path="../../../dist/preview release/babylon.d.ts"/>
+
+module BABYLON {
+    class CellMaterialDefines extends MaterialDefines {
+        public DIFFUSE = false;
+        public CLIPPLANE = false;
+        public ALPHATEST = false;
+        public POINTSIZE = false;
+        public FOG = false;
+        public NORMAL = false;
+        public UV1 = false;
+        public UV2 = false;
+        public VERTEXCOLOR = false;
+        public VERTEXALPHA = false;
+        public NUM_BONE_INFLUENCERS = 0;
+        public BonesPerMesh = 0;
+        public INSTANCES = false;
+        public NDOTL = true;
+        public CUSTOMUSERLIGHTING = true;
+        public CELLBASIC = true;
+
+        constructor() {
+            super();
+            this.rebuild();
+        }
+    }
+
+    export class CellMaterial extends PushMaterial {
+        @serializeAsTexture("diffuseTexture")
+        private _diffuseTexture: BaseTexture;
+        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
+        public diffuseTexture: BaseTexture;
+
+        @serializeAsColor3("diffuseColor")
+        public diffuseColor = new Color3(1, 1, 1);
+
+        @serialize("computeHighLevel")
+        public _computeHighLevel: boolean = false;
+        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
+        public computeHighLevel: boolean;
+        
+        @serialize("disableLighting")
+        private _disableLighting = false;
+        @expandToProperty("_markAllSubMeshesAsLightsDirty")
+        public disableLighting: boolean;   
+        
+        @serialize("maxSimultaneousLights")
+        private _maxSimultaneousLights = 4;
+        @expandToProperty("_markAllSubMeshesAsLightsDirty")
+        public maxSimultaneousLights: number; 
+
+        private _worldViewProjectionMatrix = Matrix.Zero();
+        private _scaledDiffuse = new Color3();
+        private _renderId: number;
+
+        constructor(name: string, scene: Scene) {
+            super(name, scene);
+        }
+
+        public needAlphaBlending(): boolean {
+            return (this.alpha < 1.0);
+        }
+
+        public needAlphaTesting(): boolean {
+            return false;
+        }
+
+        public getAlphaTestTexture(): BaseTexture {
+            return null;
+        }
+
+        // Methods   
+        public isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean {   
+            if (this.isFrozen) {
+                if (this._wasPreviouslyReady && subMesh.effect) {
+                    return true;
+                }
+            }
+
+            if (!subMesh._materialDefines) {
+                subMesh._materialDefines = new CellMaterialDefines();
+            }
+
+            var defines = <CellMaterialDefines>subMesh._materialDefines;
+            var scene = this.getScene();
+
+            if (!this.checkReadyOnEveryCall && subMesh.effect) {
+                if (this._renderId === scene.getRenderId()) {
+                    return true;
+                }
+            }
+
+            var engine = scene.getEngine();
+
+            // Textures
+            if (defines._areTexturesDirty) {
+                defines._needUVs = false;
+                if (scene.texturesEnabled) {
+                    if (this._diffuseTexture && StandardMaterial.DiffuseTextureEnabled) {
+                        if (!this._diffuseTexture.isReady()) {
+                            return false;
+                        } else {
+                            defines._needUVs = true;
+                            defines.DIFFUSE = true;
+                        }
+                    }                
+                }
+            }
+
+            // High level
+            defines.CELLBASIC = !this.computeHighLevel;
+
+            // Misc.
+            MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, this.pointsCloud, this.fogEnabled, defines);
+
+            // Lights
+            defines._needNormals = MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights, this._disableLighting);
+
+            // Values that need to be evaluated on every frame
+            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances);
+            
+            // Attribs
+            MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true);
+
+            // Get correct effect      
+            if (defines.isDirty) {
+                defines.markAsProcessed();
+                scene.resetCachedMaterial();
+
+                // Fallbacks
+                var fallbacks = new EffectFallbacks();             
+                if (defines.FOG) {
+                    fallbacks.addFallback(1, "FOG");
+                }
+
+                MaterialHelper.HandleFallbacksForShadows(defines, fallbacks, this.maxSimultaneousLights);
+                
+                if (defines.NUM_BONE_INFLUENCERS > 0) {
+                    fallbacks.addCPUSkinningFallback(0, mesh);
+                }
+
+                //Attributes
+                var attribs = [VertexBuffer.PositionKind];
+
+                if (defines.NORMAL) {
+                    attribs.push(VertexBuffer.NormalKind);
+                }
+
+                if (defines.UV1) {
+                    attribs.push(VertexBuffer.UVKind);
+                }
+
+                if (defines.UV2) {
+                    attribs.push(VertexBuffer.UV2Kind);
+                }
+
+                if (defines.VERTEXCOLOR) {
+                    attribs.push(VertexBuffer.ColorKind);
+                }
+
+                MaterialHelper.PrepareAttributesForBones(attribs, mesh, defines, fallbacks);
+                MaterialHelper.PrepareAttributesForInstances(attribs, defines);
+
+                var shaderName = "cell";
+                var join = defines.toString();
+                var uniforms = ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vDiffuseColor",
+                                "vFogInfos", "vFogColor", "pointSize",
+                                "vDiffuseInfos", 
+                                "mBones",
+                                "vClipPlane", "diffuseMatrix", "depthValues"
+                ];
+                var samplers = ["diffuseSampler"];
+                var uniformBuffers = [];
+
+                MaterialHelper.PrepareUniformsAndSamplersList(<EffectCreationOptions>{
+                    uniformsNames: uniforms, 
+                    uniformBuffersNames: uniformBuffers,
+                    samplers: samplers, 
+                    defines: defines, 
+                    maxSimultaneousLights: this.maxSimultaneousLights
+                });
+                subMesh.setEffect(scene.getEngine().createEffect(shaderName,
+                    <EffectCreationOptions>{
+                        attributes: attribs,
+                        uniformsNames: uniforms,
+                        uniformBuffersNames: uniformBuffers,
+                        samplers: samplers,
+                        defines: join,
+                        fallbacks: fallbacks,
+                        onCompiled: this.onCompiled,
+                        onError: this.onError,
+                        indexParameters: { maxSimultaneousLights: this.maxSimultaneousLights - 1 }
+                    }, engine), defines);
+
+            }
+            if (!subMesh.effect.isReady()) {
+                return false;
+            }
+
+            this._renderId = scene.getRenderId();
+            this._wasPreviouslyReady = true;
+
+            return true;
+        }
+
+        public bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void {
+            var scene = this.getScene();
+
+            var defines = <CellMaterialDefines>subMesh._materialDefines;
+            if (!defines) {
+                return;
+            }
+
+            var effect = subMesh.effect;
+            this._activeEffect = effect;
+
+            // Matrices        
+            this.bindOnlyWorldMatrix(world);
+            this._activeEffect.setMatrix("viewProjection", scene.getTransformMatrix());
+
+            // Bones
+            MaterialHelper.BindBonesParameters(mesh, this._activeEffect);
+
+            if (this._mustRebind(scene, effect)) {
+                // Textures        
+                if (this._diffuseTexture && StandardMaterial.DiffuseTextureEnabled) {
+                    this._activeEffect.setTexture("diffuseSampler", this._diffuseTexture);
+
+                    this._activeEffect.setFloat2("vDiffuseInfos", this._diffuseTexture.coordinatesIndex, this._diffuseTexture.level);
+                    this._activeEffect.setMatrix("diffuseMatrix", this._diffuseTexture.getTextureMatrix());
+                }
+                
+                // Clip plane
+                MaterialHelper.BindClipPlane(this._activeEffect, scene);
+
+                // Point size
+                if (this.pointsCloud) {
+                    this._activeEffect.setFloat("pointSize", this.pointSize);
+                }
+
+                this._activeEffect.setVector3("vEyePosition", scene._mirroredCameraPosition ? scene._mirroredCameraPosition : scene.activeCamera.position);                
+            }
+
+            this._activeEffect.setColor4("vDiffuseColor", this.diffuseColor, this.alpha * mesh.visibility);
+
+            // Lights
+            if (scene.lightsEnabled && !this.disableLighting) {
+                MaterialHelper.BindLights(scene, mesh, this._activeEffect, defines, this._maxSimultaneousLights);          
+            }
+
+            // View
+            if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE) {
+                this._activeEffect.setMatrix("view", scene.getViewMatrix());
+            }
+
+            // Fog
+            MaterialHelper.BindFogParameters(scene, mesh, this._activeEffect);
+
+            this._afterBind(mesh, this._activeEffect);
+        }
+
+        public getAnimatables(): IAnimatable[] {
+            var results = [];
+
+            if (this._diffuseTexture && this._diffuseTexture.animations && this._diffuseTexture.animations.length > 0) {
+                results.push(this._diffuseTexture);
+            }
+
+            return results;
+        }
+
+        public dispose(forceDisposeEffect?: boolean): void {
+            if (this._diffuseTexture) {
+                this._diffuseTexture.dispose();
+            }
+
+            super.dispose(forceDisposeEffect);
+        }
+
+        public clone(name: string): CellMaterial {
+            return SerializationHelper.Clone<CellMaterial>(() => new CellMaterial(name, this.getScene()), this);
+        }
+        
+        public serialize(): any {
+            var serializationObject = SerializationHelper.Serialize(this);
+            serializationObject.customType = "BABYLON.CellMaterial";
+            return serializationObject;
+        }
+
+        // Statics
+        public static Parse(source: any, scene: Scene, rootUrl: string): CellMaterial {
+            return SerializationHelper.Parse(() => new CellMaterial(source.name, scene), source, scene, rootUrl);
+        }
+    }
+} 
+

+ 144 - 0
materialsLibrary/src/cell/cell.fragment.fx

@@ -0,0 +1,144 @@
+precision highp float;
+
+// Constants
+uniform vec3 vEyePosition;
+uniform vec4 vDiffuseColor;
+
+// Input
+varying vec3 vPositionW;
+
+#ifdef NORMAL
+varying vec3 vNormalW;
+#endif
+
+#ifdef VERTEXCOLOR
+varying vec4 vColor;
+#endif
+
+// Lights
+#include<__decl__lightFragment>[0..maxSimultaneousLights]
+
+#include<lightsFragmentFunctions>
+#include<shadowsFragmentFunctions>
+
+// Samplers
+#ifdef DIFFUSE
+varying vec2 vDiffuseUV;
+uniform sampler2D diffuseSampler;
+uniform vec2 vDiffuseInfos;
+#endif
+
+#include<clipPlaneFragmentDeclaration>
+
+// Fog
+#include<fogFragmentDeclaration>
+
+// Custom
+vec3 computeCustomDiffuseLighting(lightingInfo info, vec3 diffuseBase, float shadow)
+{
+	diffuseBase = info.diffuse * shadow;
+
+#ifdef CELLBASIC
+	float level = 1.0;
+	if (info.ndl < 0.5)
+		level = 0.5;
+	
+	diffuseBase.rgb * vec3(level, level, level);
+#else
+	float ToonThresholds[4];
+	ToonThresholds[0] = 0.95;
+	ToonThresholds[1] = 0.5;
+	ToonThresholds[2] = 0.2;
+	ToonThresholds[3] = 0.03;
+
+	float ToonBrightnessLevels[5];
+	ToonBrightnessLevels[0] = 1.0;
+	ToonBrightnessLevels[1] = 0.8;
+	ToonBrightnessLevels[2] = 0.6;
+	ToonBrightnessLevels[3] = 0.35;
+	ToonBrightnessLevels[4] = 0.2;
+
+	if (info.ndl > ToonThresholds[0])
+	{
+		diffuseBase.rgb *= ToonBrightnessLevels[0];
+	}
+	else if (info.ndl > ToonThresholds[1])
+	{
+		diffuseBase.rgb *= ToonBrightnessLevels[1];
+	}
+	else if (info.ndl > ToonThresholds[2])
+	{
+		diffuseBase.rgb *= ToonBrightnessLevels[2];
+	}
+	else if (info.ndl > ToonThresholds[3])
+	{
+		diffuseBase.rgb *= ToonBrightnessLevels[3];
+	}
+	else
+	{
+		diffuseBase.rgb *= ToonBrightnessLevels[4];
+	}
+#endif
+
+	return max(diffuseBase, vec3(0.2));
+}
+
+void main(void)
+{
+#include<clipPlaneFragment>
+
+	vec3 viewDirectionW = normalize(vEyePosition - vPositionW);
+
+	// Base color
+	vec4 baseColor = vec4(1., 1., 1., 1.);
+	vec3 diffuseColor = vDiffuseColor.rgb;
+
+	// Alpha
+	float alpha = vDiffuseColor.a;
+
+#ifdef DIFFUSE
+	baseColor = texture2D(diffuseSampler, vDiffuseUV);
+
+#ifdef ALPHATEST
+	if (baseColor.a < 0.4)
+		discard;
+#endif
+
+	baseColor.rgb *= vDiffuseInfos.y;
+#endif
+
+#ifdef VERTEXCOLOR
+	baseColor.rgb *= vColor.rgb;
+#endif
+
+	// Normal
+#ifdef NORMAL
+	vec3 normalW = normalize(vNormalW);
+#else
+	vec3 normalW = vec3(1.0, 1.0, 1.0);
+#endif
+
+	// Lighting
+    lightingInfo info;
+	vec3 diffuseBase = vec3(0., 0., 0.);
+	float shadow = 1.;
+    float glossiness = 0.;
+
+#ifdef SPECULARTERM
+	vec3 specularBase = vec3(0., 0., 0.);
+#endif    
+#include<lightFragment>[0..maxSimultaneousLights]
+
+#ifdef VERTEXALPHA
+	alpha *= vColor.a;
+#endif
+
+	vec3 finalDiffuse = clamp(diffuseBase * diffuseColor, 0.0, 1.0) * baseColor.rgb;;
+
+	// Composition
+	vec4 color = vec4(finalDiffuse, alpha);
+
+#include<fogFragment>
+
+	gl_FragColor = color;
+}

+ 101 - 0
materialsLibrary/src/cell/cell.vertex.fx

@@ -0,0 +1,101 @@
+precision highp float;
+
+// Attributes
+attribute vec3 position;
+#ifdef NORMAL
+attribute vec3 normal;
+#endif
+#ifdef UV1
+attribute vec2 uv;
+#endif
+#ifdef UV2
+attribute vec2 uv2;
+#endif
+#ifdef VERTEXCOLOR
+attribute vec4 color;
+#endif
+
+#include<bonesDeclaration>
+
+// Uniforms
+#include<instancesDeclaration>
+
+uniform mat4 view;
+uniform mat4 viewProjection;
+
+#ifdef DIFFUSE
+varying vec2 vDiffuseUV;
+uniform mat4 diffuseMatrix;
+uniform vec2 vDiffuseInfos;
+#endif
+
+#ifdef POINTSIZE
+uniform float pointSize;
+#endif
+
+// Output
+varying vec3 vPositionW;
+#ifdef NORMAL
+varying vec3 vNormalW;
+#endif
+
+#ifdef VERTEXCOLOR
+varying vec4 vColor;
+#endif
+
+
+#include<clipPlaneVertexDeclaration>
+
+#include<fogVertexDeclaration>
+#include<shadowsVertexDeclaration>[0..maxSimultaneousLights]
+
+void main(void) {
+
+#include<instancesVertex>
+#include<bonesVertex>
+
+	gl_Position = viewProjection * finalWorld * vec4(position, 1.0);
+
+	vec4 worldPos = finalWorld * vec4(position, 1.0);
+	vPositionW = vec3(worldPos);
+
+#ifdef NORMAL
+	vNormalW = normalize(vec3(finalWorld * vec4(normal, 0.0)));
+#endif
+
+	// Texture coordinates
+#ifndef UV1
+	vec2 uv = vec2(0., 0.);
+#endif
+#ifndef UV2
+	vec2 uv2 = vec2(0., 0.);
+#endif
+
+#ifdef DIFFUSE
+	if (vDiffuseInfos.x == 0.)
+	{
+		vDiffuseUV = vec2(diffuseMatrix * vec4(uv, 1.0, 0.0));
+	}
+	else
+	{
+		vDiffuseUV = vec2(diffuseMatrix * vec4(uv2, 1.0, 0.0));
+	}
+#endif
+
+	// Clip plane
+#include<clipPlaneVertex>
+
+    // Fog
+#include<fogVertex>
+#include<shadowsVertex>[0..maxSimultaneousLights]
+
+	// Vertex color
+#ifdef VERTEXCOLOR
+	vColor = color;
+#endif
+
+	// Point size
+#ifdef POINTSIZE
+	gl_PointSize = pointSize;
+#endif
+}

Разлика између датотеке није приказан због своје велике величине
+ 0 - 1
materialsLibrary/src/custom/Babylon.CustomMaterial.js.map


+ 0 - 38
materialsLibrary/src/custom/babylon.customMaterial.js

@@ -1,38 +0,0 @@
-/// <reference path="../../../dist/preview release/babylon.d.ts"/>
-var __extends = (this && this.__extends) || (function () {
-    var extendStatics = Object.setPrototypeOf ||
-        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
-        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
-    return function (d, b) {
-        extendStatics(d, b);
-        function __() { this.constructor = d; }
-        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
-    };
-})();
-var BABYLON;
-(function (BABYLON) {
-    var CustomShaderHelper = (function () {
-        function CustomShaderHelper() {
-        }
-        return CustomShaderHelper;
-    }());
-    BABYLON.CustomShaderHelper = CustomShaderHelper;
-    var CustomMaterial = (function (_super) {
-        __extends(CustomMaterial, _super);
-        function CustomMaterial(name, builder, scene) {
-            var _this = _super.call(this, name, scene) || this;
-            _this._mainPart = 'void main(void) {';
-            _this._diffusePart = 'vec3 diffuseColor=vDiffuseColor.rgb;';
-            _this._vertexPositionPart = 'gl_Position=viewProjection*finalWorld*vec4(position,1.0);';
-            _this.builder = builder;
-            _this.customShaderNameResolve = function (shaderName) {
-                return _this.builder(new CustomShaderHelper(), shaderName, _this._mainPart, _this._diffusePart, _this._vertexPositionPart);
-            };
-            return _this;
-        }
-        return CustomMaterial;
-    }(BABYLON.StandardMaterial));
-    BABYLON.CustomMaterial = CustomMaterial;
-})(BABYLON || (BABYLON = {}));
-
-//# sourceMappingURL=babylon.customMaterial.js.map

+ 700 - 22
materialsLibrary/src/custom/babylon.customMaterial.ts

@@ -2,34 +2,712 @@
 
 module BABYLON { 
 
-  export class CustomShaderHelper{
+   
+  export class CustomShaderStructure {
+      
+       public FragmentStore : string; 
+       public VertexStore : string; 
+
+       constructor(){
+
+       }
+
+     
+  }
+
+  export class  ShaderSpecialParts{
  
+    constructor(){}
+
+    public Fragment_Begin:string;
+    public Fragment_Definations:string;
+    public Fragment_MainBegin: string;
+    
+    // diffuseColor
+    public Fragment_Custom_Diffuse: string;
+    
+    // alpha
+    public Fragment_Custom_Alpha : string;
+
+    public Fragment_Before_FragColor: string;
+
+    public Vertex_Begin:string;
+    public Vertex_Definations:string;
+    public Vertex_MainBegin: string;
+    
+    // positionUpdated
+    public Vertex_Before_PositionUpdated:string;
+
+    // normalUpdated
+    public Vertex_Before_NormalUpdated : string;
   }
 
-   export interface ICustomMaterialBuilder {
-         (builder:CustomShaderHelper , name: string ,mainPart: string , diffusePart:string ,vertexPositionPart:string ): string;
+  export class ShaderForVer3_0 extends CustomShaderStructure {
+
+       constructor() {
+            super();
+            
+            this.VertexStore = "";
+            
+            this.FragmentStore = "#include<__decl__defaultFragment>\n\
+#[Fragment_Begin]\n\
+#ifdef BUMP\n\
+#extension GL_OES_standard_derivatives : enable\n\
+#endif\n\
+#ifdef LOGARITHMICDEPTH\n\
+#extension GL_EXT_frag_depth : enable\n\
+#endif\n\
+\n\
+#define RECIPROCAL_PI2 0.15915494\n\
+uniform vec3 vEyePosition;\n\
+uniform vec3 vAmbientColor;\n\
+\n\
+varying vec3 vPositionW;\n\
+#ifdef NORMAL\n\
+varying vec3 vNormalW;\n\
+#endif\n\
+#ifdef VERTEXCOLOR\n\
+varying vec4 vColor;\n\
+#endif\n\
+\n\
+#include<helperFunctions>\n\
+\n\
+#include<__decl__lightFragment>[0..maxSimultaneousLights]\n\
+#include<lightsFragmentFunctions>\n\
+#include<shadowsFragmentFunctions>\n\
+\n\
+#ifdef DIFFUSE\n\
+varying vec2 vDiffuseUV;\n\
+uniform sampler2D diffuseSampler;\n\
+#endif\n\
+#ifdef AMBIENT\n\
+varying vec2 vAmbientUV;\n\
+uniform sampler2D ambientSampler;\n\
+#endif\n\
+#ifdef OPACITY\n\
+varying vec2 vOpacityUV;\n\
+uniform sampler2D opacitySampler;\n\
+#endif\n\
+#ifdef EMISSIVE\n\
+varying vec2 vEmissiveUV;\n\
+uniform sampler2D emissiveSampler;\n\
+#endif\n\
+#ifdef LIGHTMAP\n\
+varying vec2 vLightmapUV;\n\
+uniform sampler2D lightmapSampler;\n\
+#endif\n\
+#ifdef REFRACTION\n\
+#ifdef REFRACTIONMAP_3D\n\
+uniform samplerCube refractionCubeSampler;\n\
+#else\n\
+uniform sampler2D refraction2DSampler;\n\
+#endif\n\
+#endif\n\
+#if defined(SPECULAR) && defined(SPECULARTERM)\n\
+varying vec2 vSpecularUV;\n\
+uniform sampler2D specularSampler;\n\
+#endif\n\
+\n\
+#include<fresnelFunction>\n\
+\n\
+#ifdef REFLECTION\n\
+#ifdef REFLECTIONMAP_3D\n\
+uniform samplerCube reflectionCubeSampler;\n\
+#else\n\
+uniform sampler2D reflection2DSampler;\n\
+#endif\n\
+#ifdef REFLECTIONMAP_SKYBOX\n\
+varying vec3 vPositionUVW;\n\
+#else\n\
+#if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED)\n\
+varying vec3 vDirectionW;\n\
+#endif\n\
+#endif\n\
+#include<reflectionFunction>\n\
+#endif\n\
+#ifdef CAMERACOLORGRADING\n\
+#include<colorGradingDefinition> \n\
+#include<colorGrading>\n\
+#endif\n\
+#ifdef CAMERACOLORCURVES\n\
+#include<colorCurvesDefinition>\n\
+#include<colorCurves>\n\
+#endif\n\
+#include<bumpFragmentFunctions>\n\
+#include<clipPlaneFragmentDeclaration>\n\
+#include<logDepthDeclaration>\n\
+#include<fogFragmentDeclaration>\n\
+\n\
+#[Fragment_Definations]\n\
+\n\
+void main(void) {\n\
+\n\
+#[Fragment_MainBegin]\n\
+\n\
+#include<clipPlaneFragment>\n\
+vec3 viewDirectionW=normalize(vEyePosition-vPositionW);\n\
+\n\
+vec4 baseColor=vec4(1.,1.,1.,1.);\n\
+vec3 diffuseColor=vDiffuseColor.rgb;\n\
+#[Fragment_Custom_Diffuse]\n\
+\n\
+float alpha=vDiffuseColor.a;\n\
+#[Fragment_Custom_Alpha]\n\
+\n\
+#ifdef NORMAL\n\
+vec3 normalW=normalize(vNormalW);\n\
+#else\n\
+vec3 normalW=vec3(1.0,1.0,1.0);\n\
+#endif\n\
+#include<bumpFragment>\n\
+#ifdef TWOSIDEDLIGHTING\n\
+normalW=gl_FrontFacing ? normalW : -normalW;\n\
+#endif\n\
+#ifdef DIFFUSE\n\
+baseColor=texture2D(diffuseSampler,vDiffuseUV+uvOffset);\n\
+#ifdef ALPHATEST\n\
+if (baseColor.a<0.4)\n\
+discard;\n\
+#endif\n\
+#ifdef ALPHAFROMDIFFUSE\n\
+alpha*=baseColor.a;\n\
+#endif\n\
+baseColor.rgb*=vDiffuseInfos.y;\n\
+#endif\n\
+#ifdef VERTEXCOLOR\n\
+baseColor.rgb*=vColor.rgb;\n\
+#endif\n\
+\n\
+vec3 baseAmbientColor=vec3(1.,1.,1.);\n\
+#ifdef AMBIENT\n\
+baseAmbientColor=texture2D(ambientSampler,vAmbientUV+uvOffset).rgb*vAmbientInfos.y;\n\
+#endif\n\
+\n\
+#ifdef SPECULARTERM\n\
+float glossiness=vSpecularColor.a;\n\
+vec3 specularColor=vSpecularColor.rgb;\n\
+#ifdef SPECULAR\n\
+vec4 specularMapColor=texture2D(specularSampler,vSpecularUV+uvOffset);\n\
+specularColor=specularMapColor.rgb;\n\
+#ifdef GLOSSINESS\n\
+glossiness=glossiness*specularMapColor.a;\n\
+#endif\n\
+#endif\n\
+#else\n\
+float glossiness=0.;\n\
+#endif\n\
+\n\
+vec3 diffuseBase=vec3(0.,0.,0.);\n\
+lightingInfo info;\n\
+#ifdef SPECULARTERM\n\
+vec3 specularBase=vec3(0.,0.,0.);\n\
+#endif\n\
+float shadow=1.;\n\
+#ifdef LIGHTMAP\n\
+vec3 lightmapColor=texture2D(lightmapSampler,vLightmapUV+uvOffset).rgb*vLightmapInfos.y;\n\
+#endif\n\
+#include<lightFragment>[0..maxSimultaneousLights]\n\
+\n\
+vec3 refractionColor=vec3(0.,0.,0.);\n\
+#ifdef REFRACTION\n\
+vec3 refractionVector=normalize(refract(-viewDirectionW,normalW,vRefractionInfos.y));\n\
+#ifdef REFRACTIONMAP_3D\n\
+refractionVector.y=refractionVector.y*vRefractionInfos.w;\n\
+if (dot(refractionVector,viewDirectionW)<1.0)\n\
+{\n\
+refractionColor=textureCube(refractionCubeSampler,refractionVector).rgb*vRefractionInfos.x;\n\
+}\n\
+#else\n\
+vec3 vRefractionUVW=vec3(refractionMatrix*(view*vec4(vPositionW+refractionVector*vRefractionInfos.z,1.0)));\n\
+vec2 refractionCoords=vRefractionUVW.xy/vRefractionUVW.z;\n\
+refractionCoords.y=1.0-refractionCoords.y;\n\
+refractionColor=texture2D(refraction2DSampler,refractionCoords).rgb*vRefractionInfos.x;\n\
+#endif\n\
+#endif\n\
+\n\
+vec3 reflectionColor=vec3(0.,0.,0.);\n\
+#ifdef REFLECTION\n\
+vec3 vReflectionUVW=computeReflectionCoords(vec4(vPositionW,1.0),normalW);\n\
+#ifdef REFLECTIONMAP_3D\n\
+#ifdef ROUGHNESS\n\
+float bias=vReflectionInfos.y;\n\
+#ifdef SPECULARTERM\n\
+#ifdef SPECULAR\n\
+#ifdef GLOSSINESS\n\
+bias*=(1.0-specularMapColor.a);\n\
+#endif\n\
+#endif\n\
+#endif\n\
+reflectionColor=textureCube(reflectionCubeSampler,vReflectionUVW,bias).rgb*vReflectionInfos.x;\n\
+#else\n\
+reflectionColor=textureCube(reflectionCubeSampler,vReflectionUVW).rgb*vReflectionInfos.x;\n\
+#endif\n\
+#else\n\
+vec2 coords=vReflectionUVW.xy;\n\
+#ifdef REFLECTIONMAP_PROJECTION\n\
+coords/=vReflectionUVW.z;\n\
+#endif\n\
+coords.y=1.0-coords.y;\n\
+reflectionColor=texture2D(reflection2DSampler,coords).rgb*vReflectionInfos.x;\n\
+#endif\n\
+#ifdef REFLECTIONFRESNEL\n\
+float reflectionFresnelTerm=computeFresnelTerm(viewDirectionW,normalW,reflectionRightColor.a,reflectionLeftColor.a);\n\
+#ifdef REFLECTIONFRESNELFROMSPECULAR\n\
+#ifdef SPECULARTERM\n\
+reflectionColor*=specularColor.rgb*(1.0-reflectionFresnelTerm)+reflectionFresnelTerm*reflectionRightColor.rgb;\n\
+#else\n\
+reflectionColor*=reflectionLeftColor.rgb*(1.0-reflectionFresnelTerm)+reflectionFresnelTerm*reflectionRightColor.rgb;\n\
+#endif\n\
+#else\n\
+reflectionColor*=reflectionLeftColor.rgb*(1.0-reflectionFresnelTerm)+reflectionFresnelTerm*reflectionRightColor.rgb;\n\
+#endif\n\
+#endif\n\
+#endif\n\
+#ifdef REFRACTIONFRESNEL\n\
+float refractionFresnelTerm=computeFresnelTerm(viewDirectionW,normalW,refractionRightColor.a,refractionLeftColor.a);\n\
+refractionColor*=refractionLeftColor.rgb*(1.0-refractionFresnelTerm)+refractionFresnelTerm*refractionRightColor.rgb;\n\
+#endif\n\
+#ifdef OPACITY\n\
+vec4 opacityMap=texture2D(opacitySampler,vOpacityUV+uvOffset);\n\
+#ifdef OPACITYRGB\n\
+opacityMap.rgb=opacityMap.rgb*vec3(0.3,0.59,0.11);\n\
+alpha*=(opacityMap.x+opacityMap.y+opacityMap.z)* vOpacityInfos.y;\n\
+#else\n\
+alpha*=opacityMap.a*vOpacityInfos.y;\n\
+#endif\n\
+#endif\n\
+#ifdef VERTEXALPHA\n\
+alpha*=vColor.a;\n\
+#endif\n\
+#ifdef OPACITYFRESNEL\n\
+float opacityFresnelTerm=computeFresnelTerm(viewDirectionW,normalW,opacityParts.z,opacityParts.w);\n\
+alpha+=opacityParts.x*(1.0-opacityFresnelTerm)+opacityFresnelTerm*opacityParts.y;\n\
+#endif\n\
+\n\
+vec3 emissiveColor=vEmissiveColor;\n\
+#ifdef EMISSIVE\n\
+emissiveColor+=texture2D(emissiveSampler,vEmissiveUV+uvOffset).rgb*vEmissiveInfos.y;\n\
+#endif\n\
+#ifdef EMISSIVEFRESNEL\n\
+float emissiveFresnelTerm=computeFresnelTerm(viewDirectionW,normalW,emissiveRightColor.a,emissiveLeftColor.a);\n\
+emissiveColor*=emissiveLeftColor.rgb*(1.0-emissiveFresnelTerm)+emissiveFresnelTerm*emissiveRightColor.rgb;\n\
+#endif\n\
+\n\
+#ifdef DIFFUSEFRESNEL\n\
+float diffuseFresnelTerm=computeFresnelTerm(viewDirectionW,normalW,diffuseRightColor.a,diffuseLeftColor.a);\n\
+diffuseBase*=diffuseLeftColor.rgb*(1.0-diffuseFresnelTerm)+diffuseFresnelTerm*diffuseRightColor.rgb;\n\
+#endif\n\
+\n\
+#ifdef EMISSIVEASILLUMINATION\n\
+vec3 finalDiffuse=clamp(diffuseBase*diffuseColor+vAmbientColor,0.0,1.0)*baseColor.rgb;\n\
+#else\n\
+#ifdef LINKEMISSIVEWITHDIFFUSE\n\
+vec3 finalDiffuse=clamp((diffuseBase+emissiveColor)*diffuseColor+vAmbientColor,0.0,1.0)*baseColor.rgb;\n\
+#else\n\
+vec3 finalDiffuse=clamp(diffuseBase*diffuseColor+emissiveColor+vAmbientColor,0.0,1.0)*baseColor.rgb;\n\
+#endif\n\
+#endif\n\
+#ifdef SPECULARTERM\n\
+vec3 finalSpecular=specularBase*specularColor;\n\
+#ifdef SPECULAROVERALPHA\n\
+alpha=clamp(alpha+dot(finalSpecular,vec3(0.3,0.59,0.11)),0.,1.);\n\
+#endif\n\
+#else\n\
+vec3 finalSpecular=vec3(0.0);\n\
+#endif\n\
+#ifdef REFLECTIONOVERALPHA\n\
+alpha=clamp(alpha+dot(reflectionColor,vec3(0.3,0.59,0.11)),0.,1.);\n\
+#endif\n\
+\n\
+#ifdef EMISSIVEASILLUMINATION\n\
+vec4 color=vec4(clamp(finalDiffuse*baseAmbientColor+finalSpecular+reflectionColor+emissiveColor+refractionColor,0.0,1.0),alpha);\n\
+#else\n\
+vec4 color=vec4(finalDiffuse*baseAmbientColor+finalSpecular+reflectionColor+refractionColor,alpha);\n\
+#endif\n\
+\n\
+#ifdef LIGHTMAP\n\
+#ifndef LIGHTMAPEXCLUDED\n\
+#ifdef USELIGHTMAPASSHADOWMAP\n\
+color.rgb*=lightmapColor;\n\
+#else\n\
+color.rgb+=lightmapColor;\n\
+#endif\n\
+#endif\n\
+#endif\n\
+#include<logDepthFragment>\n\
+#include<fogFragment>\n\
+#ifdef CAMERACOLORGRADING\n\
+color=colorGrades(color);\n\
+#endif\n\
+#ifdef CAMERACOLORCURVES\n\
+color.rgb=applyColorCurves(color.rgb);\n\
+#endif\n\
+#[Fragment_Before_FragColor]\n\
+gl_FragColor=color;\n\
+}";
+
+
+this.VertexStore = "#include<__decl__defaultVertex>\n\
+\n\
+#[Vertex_Begin]\n\
+\n\
+attribute vec3 position;\n\
+#ifdef NORMAL\n\
+attribute vec3 normal;\n\
+#endif\n\
+#ifdef TANGENT\n\
+attribute vec4 tangent;\n\
+#endif\n\
+#ifdef UV1\n\
+attribute vec2 uv;\n\
+#endif\n\
+#ifdef UV2\n\
+attribute vec2 uv2;\n\
+#endif\n\
+#ifdef VERTEXCOLOR\n\
+attribute vec4 color;\n\
+#endif\n\
+#include<bonesDeclaration>\n\
+\n\
+#include<instancesDeclaration>\n\
+#ifdef DIFFUSE\n\
+varying vec2 vDiffuseUV;\n\
+#endif\n\
+#ifdef AMBIENT\n\
+varying vec2 vAmbientUV;\n\
+#endif\n\
+#ifdef OPACITY\n\
+varying vec2 vOpacityUV;\n\
+#endif\n\
+#ifdef EMISSIVE\n\
+varying vec2 vEmissiveUV;\n\
+#endif\n\
+#ifdef LIGHTMAP\n\
+varying vec2 vLightmapUV;\n\
+#endif\n\
+#if defined(SPECULAR) && defined(SPECULARTERM)\n\
+varying vec2 vSpecularUV;\n\
+#endif\n\
+#ifdef BUMP\n\
+varying vec2 vBumpUV;\n\
+#endif\n\
+\n\
+varying vec3 vPositionW;\n\
+#ifdef NORMAL\n\
+varying vec3 vNormalW;\n\
+#endif\n\
+#ifdef VERTEXCOLOR\n\
+varying vec4 vColor;\n\
+#endif\n\
+#include<bumpVertexDeclaration>\n\
+#include<clipPlaneVertexDeclaration>\n\
+#include<fogVertexDeclaration>\n\
+#include<shadowsVertexDeclaration>[0..maxSimultaneousLights]\n\
+#include<morphTargetsVertexGlobalDeclaration>\n\
+#include<morphTargetsVertexDeclaration>[0..maxSimultaneousMorphTargets]\n\
+#ifdef REFLECTIONMAP_SKYBOX\n\
+varying vec3 vPositionUVW;\n\
+#endif\n\
+#if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED)\n\
+varying vec3 vDirectionW;\n\
+#endif\n\
+#include<logDepthDeclaration>\n\
+\n\
+#[Vertex_Definations]\n\
+\n\
+void main(void) {\n\
+    \n\
+    #[Vertex_MainBegin]\n\
+    \n\
+vec3 positionUpdated=position;\n\
+#ifdef NORMAL \n\
+vec3 normalUpdated=normal;\n\
+#endif\n\
+#ifdef TANGENT\n\
+vec4 tangentUpdated=tangent;\n\
+#endif\n\
+#include<morphTargetsVertex>[0..maxSimultaneousMorphTargets]\n\
+#ifdef REFLECTIONMAP_SKYBOX\n\
+vPositionUVW=positionUpdated;\n\
+#endif \n\
+#include<instancesVertex>\n\
+#include<bonesVertex>\n\
+\n\
+#[Vertex_Before_PositionUpdated]\n\
+\n\
+gl_Position=viewProjection*finalWorld*vec4(positionUpdated,1.0);\n\
+vec4 worldPos=finalWorld*vec4(positionUpdated,1.0);\n\
+vPositionW=vec3(worldPos);\n\
+#ifdef NORMAL\n\
+\n\
+#[Vertex_Before_NormalUpdated]\n\
+\n\
+vNormalW=normalize(vec3(finalWorld*vec4(normalUpdated,0.0)));\n\
+#endif\n\
+#if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED)\n\
+vDirectionW=normalize(vec3(finalWorld*vec4(positionUpdated,0.0)));\n\
+#endif\n\
+\n\
+#ifndef UV1\n\
+vec2 uv=vec2(0.,0.);\n\
+#endif\n\
+#ifndef UV2\n\
+vec2 uv2=vec2(0.,0.);\n\
+#endif\n\
+#ifdef DIFFUSE\n\
+if (vDiffuseInfos.x == 0.)\n\
+{\n\
+vDiffuseUV=vec2(diffuseMatrix*vec4(uv,1.0,0.0));\n\
+}\n\
+else\n\
+{\n\
+vDiffuseUV=vec2(diffuseMatrix*vec4(uv2,1.0,0.0));\n\
+}\n\
+#endif\n\
+#ifdef AMBIENT\n\
+if (vAmbientInfos.x == 0.)\n\
+{\n\
+vAmbientUV=vec2(ambientMatrix*vec4(uv,1.0,0.0));\n\
+}\n\
+else\n\
+{\n\
+vAmbientUV=vec2(ambientMatrix*vec4(uv2,1.0,0.0));\n\
+}\n\
+#endif\n\
+#ifdef OPACITY\n\
+if (vOpacityInfos.x == 0.)\n\
+{\n\
+vOpacityUV=vec2(opacityMatrix*vec4(uv,1.0,0.0));\n\
+}\n\
+else\n\
+{\n\
+vOpacityUV=vec2(opacityMatrix*vec4(uv2,1.0,0.0));\n\
+}\n\
+#endif\n\
+#ifdef EMISSIVE\n\
+if (vEmissiveInfos.x == 0.)\n\
+{\n\
+vEmissiveUV=vec2(emissiveMatrix*vec4(uv,1.0,0.0));\n\
+}\n\
+else\n\
+{\n\
+vEmissiveUV=vec2(emissiveMatrix*vec4(uv2,1.0,0.0));\n\
+}\n\
+#endif\n\
+#ifdef LIGHTMAP\n\
+if (vLightmapInfos.x == 0.)\n\
+{\n\
+vLightmapUV=vec2(lightmapMatrix*vec4(uv,1.0,0.0));\n\
+}\n\
+else\n\
+{\n\
+vLightmapUV=vec2(lightmapMatrix*vec4(uv2,1.0,0.0));\n\
+}\n\
+#endif\n\
+#if defined(SPECULAR) && defined(SPECULARTERM)\n\
+if (vSpecularInfos.x == 0.)\n\
+{\n\
+vSpecularUV=vec2(specularMatrix*vec4(uv,1.0,0.0));\n\
+}\n\
+else\n\
+{\n\
+vSpecularUV=vec2(specularMatrix*vec4(uv2,1.0,0.0));\n\
+}\n\
+#endif\n\
+#ifdef BUMP\n\
+if (vBumpInfos.x == 0.)\n\
+{\n\
+vBumpUV=vec2(bumpMatrix*vec4(uv,1.0,0.0));\n\
+}\n\
+else\n\
+{\n\
+vBumpUV=vec2(bumpMatrix*vec4(uv2,1.0,0.0));\n\
+}\n\
+#endif\n\
+#include<bumpVertex>\n\
+#include<clipPlaneVertex>\n\
+#include<fogVertex>\n\
+#include<shadowsVertex>[0..maxSimultaneousLights]\n\
+#ifdef VERTEXCOLOR\n\
+\n\
+vColor=color;\n\
+#endif\n\
+#include<pointCloudVertex>\n\
+#include<logDepthVertex>\n\
+}";
+
+
+       }
+
+  }
+
+ 
+   export class StandardShaderVersions{
+
+        public static Ver3_0;
+
    } 
+
+    export class CustomMaterial extends StandardMaterial {
+         public static ShaderIndexer = 1;
+         public CustomParts :  ShaderSpecialParts;
+         public ShaderVersion : CustomShaderStructure ;
+         _customUnifrom : string[];
+         _newUnifroms : string[];
+         _newUnifromInstances : any[];
+         _newSamplerInstances : Texture[];
+
+         public AttachAfterBind(mesh:Mesh,effect:Effect){ 
+             for(var el in this._newUnifromInstances){
+                 var ea = el.toString().split('-');
+                 if(ea[0] == 'vec2') effect.setVector2(ea[1],this._newUnifromInstances[el]);
+                 else if(ea[0] == 'vec3') effect.setVector3(ea[1],this._newUnifromInstances[el]);
+                 else if(ea[0] == 'vec4') effect.setVector4(ea[1],this._newUnifromInstances[el]);
+                 else if(ea[0] == 'mat4') effect.setMatrix(ea[1],this._newUnifromInstances[el]);
+                 else if(ea[0] == 'float') effect.setFloat(ea[1],this._newUnifromInstances[el]); 
+             }
+
+              for(var el in this._newSamplerInstances){ 
+                 var ea = el.toString().split('-'); 
+                if(ea[0] == 'sampler2D' && this._newSamplerInstances[el].isReady && this._newSamplerInstances[el].isReady())
+                     effect.setTexture(ea[1],this._newSamplerInstances[el]); 
+              }
+         }
+
+         public ReviewUniform(name:string, arr : string[] ) : string[]{
+             if(name == "uniform")
+              {
+                  for(var ind in this._newUnifroms)
+                    if(this._customUnifrom[ind].indexOf('sampler')== -1) 
+                        arr.push(this._newUnifroms[ind]);
+              }
+
+                 if(name == "sampler")
+              {
+                   for(var ind in this._newUnifroms)
+                    if(this._customUnifrom[ind].indexOf('sampler')!= -1) 
+                        arr.push(this._newUnifroms[ind]);
+              }
+
+             return arr;
+         }
+         public Builder(shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: StandardMaterialDefines) : string {
+          
+            CustomMaterial.ShaderIndexer++;
+            var name = name+"custom_"+CustomMaterial.ShaderIndexer;
+
+            this.ReviewUniform("uniform",uniforms);
+            this.ReviewUniform("sampler",samplers);
+            
+
+            var fn_afterBind = this._afterBind;
+            this._afterBind = function(m,e){ 
+                this.AttachAfterBind(m,e);
+                try{fn_afterBind(m,e);}catch(e){};
+            } ;
+
+            BABYLON.Effect.ShadersStore[name+"VertexShader"] = this.ShaderVersion.VertexStore
+            .replace('#[Vertex_Begin]',(this.CustomParts.Vertex_Begin ? this.CustomParts.Vertex_Begin : ""))
+            .replace('#[Vertex_Definations]',(this._customUnifrom? this._customUnifrom.join("\n"):"")+ (this.CustomParts.Vertex_Definations ? this.CustomParts.Vertex_Definations : ""))
+            .replace('#[Vertex_MainBegin]',(this.CustomParts.Vertex_MainBegin ? this.CustomParts.Vertex_MainBegin : ""))
+            .replace('#[Vertex_Before_PositionUpdated]',(this.CustomParts.Vertex_Before_PositionUpdated ? this.CustomParts.Vertex_Before_PositionUpdated : ""))
+            .replace('#[Vertex_Before_NormalUpdated]',(this.CustomParts.Vertex_Before_NormalUpdated ? this.CustomParts.Vertex_Before_NormalUpdated : "")) ;
+
+            BABYLON.Effect.ShadersStore[name+"PixelShader"] = this.ShaderVersion.FragmentStore
+            .replace('#[Fragment_Begin]',(this.CustomParts.Fragment_Begin ? this.CustomParts.Fragment_Begin : ""))
+            .replace('#[Fragment_MainBegin]',(this.CustomParts.Fragment_MainBegin  ? this.CustomParts.Fragment_MainBegin : ""))
+            .replace('#[Fragment_Definations]',(this._customUnifrom? this._customUnifrom.join("\n"):"")+(this.CustomParts.Fragment_Definations ? this.CustomParts.Fragment_Definations : ""))
+            .replace('#[Fragment_Custom_Diffuse]',(this.CustomParts.Fragment_Custom_Diffuse ? this.CustomParts.Fragment_Custom_Diffuse : ""))
+            .replace('#[Fragment_Custom_Alpha]',(this.CustomParts.Fragment_Custom_Alpha ? this.CustomParts.Fragment_Custom_Alpha : ""))
+            .replace('#[Fragment_Before_FragColor]',(this.CustomParts.Fragment_Before_FragColor ? this.CustomParts.Fragment_Before_FragColor : "")) ;
  
-   export class CustomMaterial extends StandardMaterial  {
-        
-        public builder: ICustomMaterialBuilder;
-        private _mainPart = 'void main(void) {';
-        private _diffusePart = 'vec3 diffuseColor=vDiffuseColor.rgb;';
-        private _vertexPositionPart = 'gl_Position=viewProjection*finalWorld*vec4(position,1.0);';
-        
-        constructor (name: string, builder:ICustomMaterialBuilder, scene: Scene) {
-            super(name, scene);  
-            this.builder = builder;             
-
-            this.customShaderNameResolve = (shaderName) => {
-                return this.builder(
-                         new CustomShaderHelper(),
-                         shaderName, 
-                         this._mainPart,
-                         this._diffusePart, 
-                         this._vertexPositionPart ); 
+             return name ;
+         }
+
+      
+
+         public SelectVersion(ver:string){
+            switch(ver){
+                case "3.0.0" : this.ShaderVersion = new ShaderForVer3_0();break;
             }
-        }           
+         }
+        
+         constructor(name:string,scene:Scene ){
+            super(name,scene);
+            this.CustomParts = new ShaderSpecialParts();
+            this.customShaderNameResolve = this.Builder;  
+            this.SelectVersion("3.0.0"); 
+         } 
+         public AddUniform(name:string,kind:string,param:any):CustomMaterial{
+             if(!this._customUnifrom)
+              {  
+                  this._customUnifrom = new Array();
+                  this._newUnifroms = new Array();
+                  this._newSamplerInstances = new Array();
+                  this._newUnifromInstances = new Array();
+              }
+              if(param){
+              if(kind.indexOf("sampler") == -1) {
+                    this._newUnifromInstances[kind+"-"+name] = param;
+              }
+              else{
+                  this._newSamplerInstances[kind+"-"+name] = param;
+              }
+             }
+
+            this._customUnifrom.push("uniform "+kind+" "+name+";");
+            this._newUnifroms.push(name);
+             
+            return this;
+         }
+         public Fragment_Begin(shaderPart:string):CustomMaterial{            
+            this.CustomParts.Fragment_Begin = shaderPart;
+            return this;
+         }
+
+         public Fragment_Definations(shaderPart:string):CustomMaterial{            
+            this.CustomParts.Fragment_Definations = shaderPart;
+            return this;
+         }
+
+         public Fragment_MainBegin(shaderPart:string):CustomMaterial{            
+            this.CustomParts.Fragment_MainBegin = shaderPart;
+            return this;
+         }
+         public Fragment_Custom_Diffuse(shaderPart:string):CustomMaterial{            
+            this.CustomParts.Fragment_Custom_Diffuse = shaderPart.replace("result","diffuseColor");
+            return this;
+         }
+         public Fragment_Custom_Alpha(shaderPart:string):CustomMaterial{            
+            this.CustomParts.Fragment_Custom_Alpha = shaderPart.replace("result","alpha");
+            return this;
+         }
+         public Fragment_Before_FragColor(shaderPart:string):CustomMaterial{            
+            this.CustomParts.Fragment_Before_FragColor = shaderPart.replace("result","color");
+            return this;
+         }
+         public Vertex_Begin(shaderPart:string):CustomMaterial{            
+            this.CustomParts.Vertex_Begin = shaderPart;
+            return this;
+         }
+         public Vertex_Definations(shaderPart:string):CustomMaterial{            
+            this.CustomParts.Vertex_Definations = shaderPart;
+            return this;
+         }
+         public Vertex_MainBegin(shaderPart:string):CustomMaterial{            
+            this.CustomParts.Vertex_MainBegin = shaderPart;
+            return this;
+         }
+         public Vertex_Before_PositionUpdated(shaderPart:string):CustomMaterial{            
+            this.CustomParts.Vertex_Before_PositionUpdated = shaderPart.replace("result","positionUpdated");
+            return this;
+         } 
+         
+          public Vertex_Before_NormalUpdated(shaderPart:string):CustomMaterial{            
+            this.CustomParts.Vertex_Before_NormalUpdated = shaderPart.replace("result","normalUpdated");
+            return this;
+         } 
+          
     }
 }
      

+ 110 - 0
materialsLibrary/src/custom/readme.md

@@ -0,0 +1,110 @@
+
+CustomMaterial
+==============
+
+### CustomMaterial is a StandardMaterial with some customizable Options 
+1- manage part of current shader
+> CustomMaterial put some part of shader in special part of current shader and make new shader in ShaderStore 
+ > shaders struct  :
+ >
+ >   [ Begin ]
+ >
+ >   . // includes  extensions  varyng uniforms attributes  special functions 
+ >  
+ >   [ Definations ]
+ >
+ >   void main(){
+ >   
+ >       [ Main Begin ]  
+ >  
+ >       .
+ >       .
+ >       .
+ >  
+ >       [  ]
+ >   
+ >   }  
+
+
+
+method : SelectVersion(ver:string) 
+> Custom material for now Supported just ver 3.0.0 of BabylonJs and this is default of currentVersion for now
+> Add other old version in Progress %
+  
+  
+method : AddUniform(name:string,kind:string,param:any):CustomMaterial 
+> for append dynamic setting and manage </br>
+> this method Add Unforn in bouth of shaders(Fragment and Vertex) </br>
+> usage : new CustomMaterial(...).AddUniform('time','float') </br>
+>       : new CustomMaterial(...).AddUniform('direction','vec3',new BABYLON.Vector3(0.,0.,0.)) </br>
+>       : new CustomMaterial(...).AddUniform('txt1','sampler2D', new BABYLON.Texture("path",scene))  
+
+
+method : Fragment_Begin(shaderPart:string):CustomMaterial 
+> shaderPart is Shader Structure append in start of main function in fragment shader </br>
+> usage :  new CustomMaterial(...).Fragment_Begin('vec3 direction = vec3(0.);') 
+
+
+method : Fragment_Definations(shaderPart:string):CustomMaterial
+> shaderPart is Shader Structure append in befor of the main function in fragment shader </br>
+> you can define your varyng and functions from this  </br>
+> usage :  new CustomMaterial(...).Fragment_Definations('float func1(vec4 param1){ return param1.x;}')  </br>
+> * dont try use uniform with this function because uniforms need to add buffers
+
+
+method : Fragment_MainBegin(shaderPart:string):CustomMaterial 
+> shaderPart is Shader Structure append in start place of the main function in fragment shader 
+
+
+method : Fragment_Custom_Diffuse(shaderPart:string):CustomMaterial 
+> shaderPart is Shader Structure append after diffuseColor is defined of the main function in fragment shader </br>
+> usage : new CustomMaterial(...).Fragment_Custom_Diffuse('diffuseColor = vec3(sin(vPositionW.x));')  </br>
+>       : new CustomMaterial(...).Fragment_Custom_Diffuse('result = vec3(sin(vPositionW.x));')  </br>
+> * diffuseColor is vec3 variable </br>
+> * you can use result (vec3) too that replaced by diffuseColor
+
+
+method : Fragment_Custom_Alpha(shaderPart:string):CustomMaterial 
+> shaderPart is Shader Structure append when material need a alpha parameter in fragment shader </br>
+
+
+method : Fragment_Before_FragColor(shaderPart:string):CustomMaterial 
+> shaderPart is Shader Structure append before gl_FragColor wanna be set in fragment shader </br>
+> * color is vec4 parameter be set in last part to gl_fragcolor
+> * you can use result (vec4) too
+> * this part your last chance for change the frag color
+
+
+method : Vertex_Begin(shaderPart:string):CustomMaterial
+> shaderPart is Shader Structure append in start of main function in vertex shader </br>
+> usage :  new CustomMaterial(...).Vertex_Begin('vec3 direction = vec3(0.);') 
+
+
+method : Vertex_Definations(shaderPart:string):CustomMaterial 
+> shaderPart is Shader Structure append in befor of the main function in vertex shader </br>
+> you can define your varyng and functions from this  </br>
+> usage :  new CustomMaterial(...).Vertex_Definations('float func1(vec4 param1){ return param1.x;}')  </br>
+> * dont try use uniform with this function because uniforms need to add buffers </br>
+> * for connect any information between vertex and fragment part in shader you can define varying you need make that in both of definition part
+
+
+method :  Vertex_MainBegin(shaderPart:string):CustomMaterial 
+> shaderPart is Shader Structure append in start place of the main function in vertex shader 
+
+
+method : Vertex_Befor_PositionUpdated(shaderPart:string):CustomMaterial{        
+> shaderPart is Shader Structure append after positionUpdated is defined of the main function in vertex shader </br>
+> usage : new CustomMaterial(...).Vertex_Befor_PositionUpdated('positionUpdated = positionUpdated;')  </br>
+>       : new CustomMaterial(...).Vertex_Befor_PositionUpdated('result = positionUpdated * 1.5 ;')  </br>
+> * positionUpdated is vec3 variable </br>
+> * you can use result (vec3) too that replaced by positionUpdated
+> * you can use 'normal' attribute in this part too
+ 
+method : Vertex_Befor_NormalUpdated(shaderPart:string):CustomMaterial
+> shaderPart is Shader Structure append after normalUpdated is defined of the main function in vertex shader </br>
+> usage : new CustomMaterial(...).Vertex_Befor_NormalUpdated('normalUpdated = normalUpdated;')  </br>
+>       : new CustomMaterial(...).Vertex_Befor_NormalUpdated('result = normalUpdated   ;')  </br>
+> * normalUpdated is vec3 variable </br>
+> * you can use result (vec3) too that replaced by normalUpdated
+> * you can use positionUpdated too in this part
+           

+ 1 - 1
materialsLibrary/src/fur/readme.md

@@ -46,7 +46,7 @@ The leopard fur texture used in the test is by Martin Wegmann from [Wikimedia Co
 under the [license](https://creativecommons.org/licenses/by-sa/3.0/deed.en)
 
 ```
-furMaterial.diffuseTexture = new BABYLON.Texture("leopard_fur.jpg", scene); // Set the fur length with a texture.
+furMaterial.diffuseTexture = new BABYLON.Texture("leopard_fur.JPG, scene); // Set the fur length with a texture.
 ```
 
 # Using the High Level mode

+ 22 - 0
materialsLibrary/test/addCell.js

@@ -0,0 +1,22 @@
+window.prepareCell = function() {
+    var cell = new BABYLON.CellMaterial("cell", scene);
+	cell.diffuseTexture = new BABYLON.Texture("../assets/textures//amiga.jpg", scene);
+	cell.diffuseTexture.uScale = cell.diffuseTexture.vScale = 3;
+	cell.computeHighLevel = true;
+
+    registerRangeUI("cell", "Hight Level Cell", false, true, function(value) {
+        cell.computeHighLevel = value;
+    }, function() {
+        return cell.computeHighLevel;
+    });
+
+    registerColorPicker("cell", "Diffuse Color", "#FFFFFF", function(value) {		
+		cell.diffuseColor.r = value.r/255;
+		cell.diffuseColor.g = value.g/255;
+		cell.diffuseColor.b = value.b/255;
+	}, function() {
+		return cell.diffuseColor;
+	});
+
+    return cell;
+};

+ 1 - 1
materialsLibrary/test/addfur.js

@@ -2,7 +2,7 @@ window.prepareFur = function() {
 	var shells = 30;
 	var meshes = [];
 	
-	var diffuseTexture = new BABYLON.Texture("../assets/textures/leopard_fur.jpg", scene);
+	var diffuseTexture = new BABYLON.Texture("../assets/textures/leopard_fur.JPG", scene);
 	var heightTexture = new BABYLON.Texture("../assets/textures/speckles.jpg", scene);
 	var furTexture = BABYLON.FurMaterial.GenerateTexture("furTexture", scene);
 	

+ 1 - 1
materialsLibrary/test/addterrain.js

@@ -7,7 +7,7 @@ window.prepareTerrain = function() {
     terrain.diffuseTexture2 = new BABYLON.Texture("../assets/textures/rock.png", scene);
     terrain.diffuseTexture3 = new BABYLON.Texture("../assets/textures/grass.png", scene);
     
-    terrain.bumpTexture1 = new BABYLON.Texture("../assets/textures/floor_bump.png", scene);
+    terrain.bumpTexture1 = new BABYLON.Texture("../assets/textures/floor_bump.PNG", scene);
     terrain.bumpTexture2 = new BABYLON.Texture("../assets/textures/rockn.png", scene);
     terrain.bumpTexture3 = new BABYLON.Texture("../assets/textures/grassn.png", scene);
     

+ 4 - 4
src/Audio/babylon.sound.ts

@@ -289,14 +289,14 @@ module BABYLON {
                     this._soundPanner.maxDistance = Number.MAX_VALUE;
                     this._soundPanner.refDistance = 1;
                     this._soundPanner.rolloffFactor = 1;
-                    this._soundPanner.panningModel = this._panningModel;
+                    this._soundPanner.panningModel = this._panningModel as any;
                 }
                 else {
-                    this._soundPanner.distanceModel = this.distanceModel;
+                    this._soundPanner.distanceModel = this.distanceModel as any;
                     this._soundPanner.maxDistance = this.maxDistance;
                     this._soundPanner.refDistance = this.refDistance;
                     this._soundPanner.rolloffFactor = this.rolloffFactor;
-                    this._soundPanner.panningModel = this._panningModel;
+                    this._soundPanner.panningModel = this._panningModel as any;
                 }
             }
         }
@@ -313,7 +313,7 @@ module BABYLON {
 
         private _switchPanningModel() {
             if (Engine.audioEngine.canUseWebAudio && this.spatialSound) {
-                this._soundPanner.panningModel = this._panningModel;
+                this._soundPanner.panningModel = this._panningModel as any;
             }
         }
 

+ 24 - 25
src/Cameras/babylon.arcRotateCamera.ts

@@ -56,7 +56,7 @@ module BABYLON {
         @serialize()
         public inertialPanningY: number = 0;
 
-        //-- begin properties for backward compatibility for inputs       
+        //-- begin properties for backward compatibility for inputs
         public get angularSensibilityX() {
             var pointers = <ArcRotateCameraPointersInput>this.inputs.attached["pointers"];
             if (pointers)
@@ -168,8 +168,8 @@ module BABYLON {
             if (mousewheel)
                 mousewheel.wheelPrecision = value;
         }
-        
-        //-- end properties for backward compatibility for inputs        
+
+        //-- end properties for backward compatibility for inputs
 
         @serialize()
         public zoomOnFactor = 1;
@@ -185,7 +185,7 @@ module BABYLON {
         public inputs: ArcRotateCameraInputsManager;
 
         public _reset: () => void;
-        
+
         // Panning
         public panningAxis: Vector3 = new Vector3(1, 1, 0);
         private _localDirection: Vector3;
@@ -204,7 +204,7 @@ module BABYLON {
         private _previousRadius: number;
         //due to async collision inspection
         private _collisionTriggered: boolean;
-        
+
         private _targetBoundingCenter: Vector3;
 
         constructor(name: string, alpha: number, beta: number, radius: number, target: Vector3, scene: Scene) {
@@ -222,7 +222,7 @@ module BABYLON {
             this.getViewMatrix();
             this.inputs = new ArcRotateCameraInputsManager(this);
             this.inputs.addKeyboard().addMouseWheel().addPointers();
-        }      
+        }
 
         // Cache
         public _initCache(): void {
@@ -302,7 +302,7 @@ module BABYLON {
             this.inputs.checkInputs();
             // Inertia
             if (this.inertialAlphaOffset !== 0 || this.inertialBetaOffset !== 0 || this.inertialRadiusOffset !== 0) {
-                
+
                 if (this.getScene().useRightHandedSystem) {
                     this.alpha -= this.beta <= 0 ? -this.inertialAlphaOffset : this.inertialAlphaOffset;
                 } else {
@@ -315,11 +315,11 @@ module BABYLON {
                 this.inertialAlphaOffset *= this.inertia;
                 this.inertialBetaOffset *= this.inertia;
                 this.inertialRadiusOffset *= this.inertia;
-                if (Math.abs(this.inertialAlphaOffset) < Epsilon)
+                if (Math.abs(this.inertialAlphaOffset) < this.speed * Epsilon)
                     this.inertialAlphaOffset = 0;
-                if (Math.abs(this.inertialBetaOffset) < Epsilon)
+                if (Math.abs(this.inertialBetaOffset) < this.speed * Epsilon)
                     this.inertialBetaOffset = 0;
-                if (Math.abs(this.inertialRadiusOffset) < Epsilon)
+                if (Math.abs(this.inertialRadiusOffset) < this.speed * Epsilon)
                     this.inertialRadiusOffset = 0;
             }
 
@@ -330,14 +330,6 @@ module BABYLON {
                     this._transformedDirection = Vector3.Zero();
                 }
 
-                this.inertialPanningX *= this.inertia;
-                this.inertialPanningY *= this.inertia;
-
-                if (Math.abs(this.inertialPanningX) < Epsilon)
-                    this.inertialPanningX = 0;
-                if (Math.abs(this.inertialPanningY) < Epsilon)
-                    this.inertialPanningY = 0;
-
                 this._localDirection.copyFromFloats(this.inertialPanningX, this.inertialPanningY, this.inertialPanningY);
                 this._localDirection.multiplyInPlace(this.panningAxis);
                 this._viewMatrix.invertToRef(this._cameraTransformMatrix);
@@ -349,7 +341,15 @@ module BABYLON {
 
                 if (!this._targetHost) {
                     this._target.addInPlace(this._transformedDirection);
-                }                
+                }
+
+                this.inertialPanningX *= this.inertia;
+                this.inertialPanningY *= this.inertia;
+
+                if (Math.abs(this.inertialPanningX) < this.speed * Epsilon)
+                    this.inertialPanningX = 0;
+                if (Math.abs(this.inertialPanningY) < this.speed * Epsilon)
+                    this.inertialPanningY = 0;
             }
 
             // Limits
@@ -420,7 +420,7 @@ module BABYLON {
             this.rebuildAnglesAndRadius();
         }
 
-        public setTarget(target: AbstractMesh | Vector3, toBoundingCenter = false, allowSamePosition = false): void {                        
+        public setTarget(target: AbstractMesh | Vector3, toBoundingCenter = false, allowSamePosition = false): void {
 
             if ((<any>target).getBoundingInfo){
                 if (toBoundingCenter){
@@ -559,7 +559,7 @@ module BABYLON {
                 this.maxZ = distance * 2;
             }
         }
-        
+
         /**
          * @override
          * Override Camera.createRigCamera
@@ -581,7 +581,7 @@ module BABYLON {
             rigCam._cameraRigParams = {};
             return rigCam;
         }
-        
+
         /**
          * @override
          * Override Camera._updateRigCameras
@@ -589,7 +589,7 @@ module BABYLON {
         public _updateRigCameras() {
             var camLeft  = <ArcRotateCamera>this._rigCameras[0];
             var camRight = <ArcRotateCamera>this._rigCameras[1];
-            
+
             camLeft.beta = camRight.beta = this.beta;
             camLeft.radius = camRight.radius = this.radius;
 
@@ -618,5 +618,4 @@ module BABYLON {
             return "ArcRotateCamera";
         }
     }
-} 
-
+}

+ 5 - 5
src/Cameras/babylon.targetCamera.ts

@@ -199,26 +199,26 @@ module BABYLON {
 
             // Inertia
             if (needToMove) {
-                if (Math.abs(this.cameraDirection.x) < Epsilon) {
+                if (Math.abs(this.cameraDirection.x) < this.speed * Epsilon) {
                     this.cameraDirection.x = 0;
                 }
 
-                if (Math.abs(this.cameraDirection.y) < Epsilon) {
+                if (Math.abs(this.cameraDirection.y) < this.speed * Epsilon) {
                     this.cameraDirection.y = 0;
                 }
 
-                if (Math.abs(this.cameraDirection.z) < Epsilon) {
+                if (Math.abs(this.cameraDirection.z) < this.speed * Epsilon) {
                     this.cameraDirection.z = 0;
                 }
 
                 this.cameraDirection.scaleInPlace(this.inertia);
             }
             if (needToRotate) {
-                if (Math.abs(this.cameraRotation.x) < Epsilon) {
+                if (Math.abs(this.cameraRotation.x) < this.speed * Epsilon) {
                     this.cameraRotation.x = 0;
                 }
 
-                if (Math.abs(this.cameraRotation.y) < Epsilon) {
+                if (Math.abs(this.cameraRotation.y) < this.speed * Epsilon) {
                     this.cameraRotation.y = 0;
                 }
                 this.cameraRotation.scaleInPlace(this.inertia);

+ 13 - 21
src/Debug/babylon.axesViewer.ts

@@ -40,34 +40,26 @@
 
             var scaleLines = this.scaleLines;
 
-            var point1 = this._xline[0];
+            this._xmesh.position.copyFrom(position);
+            this._ymesh.position.copyFrom(position);
+            this._zmesh.position.copyFrom(position);
+
             var point2 = this._xline[1];
-            point1.x = position.x;
-            point1.y = position.y;
-            point1.z = position.z;
-            point2.x = point1.x + xaxis.x * scaleLines;
-            point2.y = point1.y + xaxis.y * scaleLines;
-            point2.z = point1.z + xaxis.z * scaleLines;
+            point2.x = xaxis.x * scaleLines;
+            point2.y = xaxis.y * scaleLines;
+            point2.z = xaxis.z * scaleLines;
             Mesh.CreateLines(null, this._xline, null, null, this._xmesh);
 
-            point1 = this._yline[0];
             point2 = this._yline[1];
-            point1.x = position.x;
-            point1.y = position.y;
-            point1.z = position.z;
-            point2.x = point1.x + yaxis.x * scaleLines;
-            point2.y = point1.y + yaxis.y * scaleLines;
-            point2.z = point1.z + yaxis.z * scaleLines;
+            point2.x = yaxis.x * scaleLines;
+            point2.y = yaxis.y * scaleLines;
+            point2.z = yaxis.z * scaleLines;
             Mesh.CreateLines(null, this._yline, null, null, this._ymesh);
 
-            point1 = this._zline[0];
             point2 = this._zline[1];
-            point1.x = position.x;
-            point1.y = position.y;
-            point1.z = position.z;
-            point2.x = point1.x + zaxis.x * scaleLines;
-            point2.y = point1.y + zaxis.y * scaleLines;
-            point2.z = point1.z + zaxis.z * scaleLines;
+            point2.x = zaxis.x * scaleLines;
+            point2.y = zaxis.y * scaleLines;
+            point2.z = zaxis.z * scaleLines;
             Mesh.CreateLines(null, this._zline, null, null, this._zmesh);
 
         }

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

@@ -1,5 +1,7 @@
 module BABYLON {
     export class BaseTexture {
+        public static DEFAULT_ANISOTROPIC_FILTERING_LEVEL = 4;
+
         @serialize()
         public name: string;
 
@@ -45,7 +47,7 @@
         public wrapV = Texture.WRAP_ADDRESSMODE;
 
         @serialize()
-        public anisotropicFilteringLevel = 4;
+        public anisotropicFilteringLevel = BaseTexture.DEFAULT_ANISOTROPIC_FILTERING_LEVEL;
 
         @serialize()
         public isCube = false;

+ 12 - 7
src/Materials/Textures/babylon.renderTargetTexture.ts

@@ -1,4 +1,12 @@
 module BABYLON {
+    export interface IRenderTargetOptions {
+        generateMipMaps: boolean,
+        type: number,
+        samplingMode: number,
+        generateDepthBuffer: boolean,
+        generateStencilBuffer: boolean
+    }
+
     export class RenderTargetTexture extends Texture {
         public static _REFRESHRATE_RENDER_ONCE: number = 0;
         public static _REFRESHRATE_RENDER_ONEVERYFRAME: number = 1;
@@ -100,13 +108,10 @@
         private _refreshRate = 1;
         private _textureMatrix: Matrix;
         private _samples = 1;
-        protected _renderTargetOptions: {
-            generateMipMaps: boolean,
-            type: number,
-            samplingMode: number,
-            generateDepthBuffer: boolean,
-            generateStencilBuffer: boolean
-        };
+        protected _renderTargetOptions: IRenderTargetOptions;
+        public get renderTargetOptions(): IRenderTargetOptions {
+            return this._renderTargetOptions;
+        }
 
         constructor(name: string, size: any, scene: Scene, generateMipMaps?: boolean, doNotChangeAspectRatio: boolean = true, type: number = Engine.TEXTURETYPE_UNSIGNED_INT, public isCube = false, samplingMode = Texture.TRILINEAR_SAMPLINGMODE, generateDepthBuffer = true, generateStencilBuffer = false) {
             super(null, scene, !generateMipMaps);

+ 1 - 1
src/Materials/babylon.effect.ts

@@ -364,7 +364,7 @@
             var result = preparedSourceCode.replace(regex, "");
 
             // Migrate to GLSL v300
-            result = result.replace(/varying\s/g, isFragment ? "in " : "out ");
+            result = result.replace(/varying(?![\n\r])\s/g, isFragment ? "in " : "out ");
             result = result.replace(/attribute[ \t]/g, "in ");
             result = result.replace(/[ \t]attribute/g, " in");
             

+ 8 - 7
src/Materials/babylon.standardMaterial.ts

@@ -289,7 +289,7 @@ module BABYLON {
         @expandToProperty("_markAllSubMeshesAsTexturesDirty")
         public cameraColorCurves: ColorCurves;             
 
-        public customShaderNameResolve: (shaderName: string) => string;
+        public customShaderNameResolve: (shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: StandardMaterialDefines) => string;
 
         protected _renderTargets = new SmartArray<RenderTargetTexture>(16);
         protected _worldViewProjectionMatrix = Matrix.Zero();
@@ -694,12 +694,7 @@ module BABYLON {
                 MaterialHelper.PrepareAttributesForMorphTargets(attribs, mesh, defines);
                 
                 var shaderName = "default";
-
-                if (this.customShaderNameResolve) {
-                    shaderName = this.customShaderNameResolve(shaderName);
-                }
-
-                var join = defines.toString();
+                
                 var uniforms = ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vAmbientColor", "vDiffuseColor", "vSpecularColor", "vEmissiveColor",
                     "vFogInfos", "vFogColor", "pointSize",
                     "vDiffuseInfos", "vAmbientInfos", "vOpacityInfos", "vReflectionInfos", "vEmissiveInfos", "vSpecularInfos", "vBumpInfos", "vLightmapInfos", "vRefractionInfos",
@@ -711,6 +706,7 @@ module BABYLON {
                 ];
 
                 var samplers = ["diffuseSampler", "ambientSampler", "opacitySampler", "reflectionCubeSampler", "reflection2DSampler", "emissiveSampler", "specularSampler", "bumpSampler", "lightmapSampler", "refractionCubeSampler", "refraction2DSampler"]
+
                 var uniformBuffers = ["Material", "Scene"];
 
                 if (defines.CAMERACOLORCURVES) {
@@ -727,6 +723,11 @@ module BABYLON {
                     maxSimultaneousLights: this._maxSimultaneousLights
                 });
 
+                if (this.customShaderNameResolve) {
+                    shaderName = this.customShaderNameResolve(shaderName, uniforms, uniformBuffers, samplers, defines);
+                }
+
+                var join = defines.toString();
                 subMesh.setEffect(scene.getEngine().createEffect(shaderName, <EffectCreationOptions>{
                     attributes: attribs,
                     uniformsNames: uniforms,

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

@@ -1287,7 +1287,7 @@
         public setMaterialByID(id: string): Mesh {
             var materials = this.getScene().materials;
             var index: number;
-            for (index = 0; index < materials.length; index++) {
+            for (index = materials.length - 1; index > -1; index--) {
                 if (materials[index].id === id) {
                     this.material = materials[index];
                     return this;
@@ -1296,7 +1296,7 @@
 
             // Multi
             var multiMaterials = this.getScene().multiMaterials;
-            for (index = 0; index < multiMaterials.length; index++) {
+            for (index = multiMaterials.length - 1; index > -1; index--) {
                 if (multiMaterials[index].id === id) {
                     this.material = multiMaterials[index];
                     return this;

+ 4 - 2
src/PostProcess/babylon.postProcess.ts

@@ -27,6 +27,7 @@
         private _effect: Effect;
         private _samplers: string[];
         private _fragmentUrl: string;
+        private _vertexUrl: string;
         private _parameters: string[];
         private _scaleRatio = new Vector2(1, 1);
 
@@ -102,7 +103,7 @@
             this._onAfterRenderObserver = this.onAfterRenderObservable.add(callback);
         }
 
-        constructor(public name: string, fragmentUrl: string, parameters: string[], samplers: string[], options: number | PostProcessOptions, camera: Camera, samplingMode: number = Texture.NEAREST_SAMPLINGMODE, engine?: Engine, reusable?: boolean, defines?: string, textureType: number = Engine.TEXTURETYPE_UNSIGNED_INT) {
+        constructor(public name: string, fragmentUrl: string, parameters: string[], samplers: string[], options: number | PostProcessOptions, camera: Camera, samplingMode: number = Texture.NEAREST_SAMPLINGMODE, engine?: Engine, reusable?: boolean, defines?: string, textureType: number = Engine.TEXTURETYPE_UNSIGNED_INT, vertexUrl: string = 'postprocess') {
             if (camera != null) {
                 this._camera = camera;
                 this._scene = camera.getScene();
@@ -122,6 +123,7 @@
             this._samplers.push("textureSampler");
 
             this._fragmentUrl = fragmentUrl;
+            this._vertexUrl = vertexUrl;
             this._parameters = parameters || [];
 
             this._parameters.push("scale");
@@ -130,7 +132,7 @@
         }
         
         public updateEffect(defines?: string) {
-            this._effect = this._engine.createEffect({ vertex: "postprocess", fragment: this._fragmentUrl },
+            this._effect = this._engine.createEffect({ vertex: this._vertexUrl, fragment: this._fragmentUrl },
                 ["position"],
                 this._parameters,
                 this._samplers, defines !== undefined ? defines : "");

+ 86 - 8
src/PostProcess/babylon.standardRenderingPipeline.ts

@@ -19,12 +19,13 @@ module BABYLON {
 
         public textureAdderFinalPostProcess: PostProcess = null;
         public lensFlareFinalPostProcess: PostProcess = null;
-
         public hdrFinalPostProcess: PostProcess = null;
 
         public lensFlarePostProcess: PostProcess = null;
         public lensFlareComposePostProcess: PostProcess = null;
 
+        public motionBlurPostProcess: PostProcess = null;
+
         public depthOfFieldPostProcess: PostProcess = null;
 
         // Values
@@ -75,6 +76,9 @@ module BABYLON {
         @serialize()
         public depthOfFieldBlurWidth: number = 2.0;
 
+        @serialize()
+        public motionStrength: number = 1.0;
+
         // IAnimatable
         public animations: Animation[] = [];
 
@@ -88,10 +92,13 @@ module BABYLON {
         private _currentHDRSource: PostProcess = null;
         private _hdrCurrentLuminance: number = 1.0;
 
+        private _motionBlurSamples: number = 64;
+
         // Getters and setters
         private _depthOfFieldEnabled: boolean = true;
         private _lensFlareEnabled: boolean = true;
         private _hdrEnabled: boolean = true;
+        private _motionBlurEnabled: boolean = true;
 
         public set DepthOfFieldEnabled(enabled: boolean) {
             var blurIndex = this.gaussianBlurHPostProcesses.length - 1;
@@ -170,6 +177,33 @@ module BABYLON {
             return this._hdrEnabled;
         }
 
+        public set MotionBlurEnabled(enabled: boolean) {
+            if (enabled && !this._motionBlurEnabled) {
+                this._scene.postProcessRenderPipelineManager.enableEffectInPipeline(this._name, "HDRMotionBlur", this._scene.cameras);
+                this._depthRenderer = this._scene.enableDepthRenderer();
+            }
+            else if (!enabled && this._motionBlurEnabled) {
+                this._scene.postProcessRenderPipelineManager.disableEffectInPipeline(this._name, "HDRMotionBlur", this._scene.cameras);
+            }
+
+            this._motionBlurEnabled = enabled;
+        }
+
+        @serialize()
+        public get MotionBlurEnabled(): boolean {
+            return this._motionBlurEnabled;
+        }
+
+        @serialize()
+        public get motionBlurSamples(): number {
+            return this._motionBlurSamples;
+        }
+
+        public set motionBlurSamples(samples: number) {
+            this.motionBlurPostProcess.updateEffect("#define MOTION_BLUR\n#define MAX_MOTION_SAMPLES " + samples.toFixed(1));
+            this._motionBlurSamples = samples;
+        }
+
         /**
          * @constructor
          * @param {string} name - The rendering pipeline name
@@ -185,9 +219,12 @@ module BABYLON {
             // Initialize
             this._scene = scene;
 
-            // Create pass post-processe
+            // Misc
+            var floatTextureType = scene.getEngine().getCaps().textureFloatRender ? Engine.TEXTURETYPE_FLOAT : Engine.TEXTURETYPE_HALF_FLOAT;
+
+            // Create pass post-process
             if (!originalPostProcess) {
-                this.originalPostProcess = new PostProcess("HDRPass", "standard", [], [], ratio, null, Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false, "#define PASS_POST_PROCESS", Engine.TEXTURETYPE_FLOAT);
+                this.originalPostProcess = new PostProcess("HDRPass", "standard", [], [], ratio, null, Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false, "#define PASS_POST_PROCESS", floatTextureType);
             }
             else {
                 this.originalPostProcess = originalPostProcess;
@@ -222,12 +259,12 @@ module BABYLON {
             this.addEffect(new PostProcessRenderEffect(scene.getEngine(), "HDRPostLensFlareDepthOfFieldSource", () => { return this.lensFlareFinalPostProcess; }, true));
 
             // Create luminance
-            this._createLuminancePostProcesses(scene);
+            this._createLuminancePostProcesses(scene, floatTextureType);
 
             // Create HDR
             this._createHdrPostProcess(scene, ratio);
 
-            // Create depth-of-field source post-process post lens-flare and disable it now
+            // Create depth-of-field source post-process post hdr and disable it now
             this.hdrFinalPostProcess = new PostProcess("HDRPostHDReDepthOfFieldSource", "standard", [], [], ratio, null, Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false, "#define PASS_POST_PROCESS", Engine.TEXTURETYPE_UNSIGNED_INT);
             this.addEffect(new PostProcessRenderEffect(scene.getEngine(), "HDRPostHDReDepthOfFieldSource", () => { return this.hdrFinalPostProcess; }, true));
 
@@ -237,6 +274,9 @@ module BABYLON {
             // Create depth-of-field post-process
             this._createDepthOfFieldPostProcess(scene, ratio);
 
+            // Create motion blur post-process
+            this._createMotionBlurPostProcess(scene, ratio);
+
             // Finish
             scene.postProcessRenderPipelineManager.addPipeline(this);
 
@@ -248,6 +288,7 @@ module BABYLON {
             this.LensFlareEnabled = false;
             this.DepthOfFieldEnabled = false;
             this.HDREnabled = false;
+            this.MotionBlurEnabled = false;
         }
 
         // Down Sample X4 Post-Processs
@@ -374,10 +415,10 @@ module BABYLON {
         }
 
         // Create luminance
-        private _createLuminancePostProcesses(scene: Scene): void {
+        private _createLuminancePostProcesses(scene: Scene, textureType: number): void {
             // Create luminance
             var size = Math.pow(3, StandardRenderingPipeline.LuminanceSteps);
-            this.luminancePostProcess = new PostProcess("HDRLuminance", "standard", ["lumOffsets"], [], { width: size, height: size }, null, Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false, "#define LUMINANCE", Engine.TEXTURETYPE_FLOAT);
+            this.luminancePostProcess = new PostProcess("HDRLuminance", "standard", ["lumOffsets"], [], { width: size, height: size }, null, Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false, "#define LUMINANCE", textureType);
 
             var offsets: number[] = [];
             this.luminancePostProcess.onApply = (effect: Effect) => {
@@ -408,7 +449,7 @@ module BABYLON {
                     defines += "#define FINAL_DOWN_SAMPLER";
                 }
 
-                var postProcess = new PostProcess("HDRLuminanceDownSample" + i, "standard", ["dsOffsets", "halfDestPixelSize"], [], { width: size, height: size }, null, Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false, defines, Engine.TEXTURETYPE_FLOAT);
+                var postProcess = new PostProcess("HDRLuminanceDownSample" + i, "standard", ["dsOffsets", "halfDestPixelSize"], [], { width: size, height: size }, null, Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false, defines, textureType);
                 this.luminanceDownSamplePostProcesses.push(postProcess);
             }
 
@@ -575,6 +616,42 @@ module BABYLON {
             this.addEffect(new PostProcessRenderEffect(scene.getEngine(), "HDRDepthOfField", () => { return this.depthOfFieldPostProcess; }, true));
         }
 
+        // Create motion blur post-process
+        private _createMotionBlurPostProcess(scene: Scene, ratio: number): void {
+            this.motionBlurPostProcess = new PostProcess("HDRMotionBlur", "standard",
+                ["inverseViewProjection", "prevViewProjection", "screenSize", "motionScale", "motionStrength"],
+                ["depthSampler"],
+                ratio, null, Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false, "#define MOTION_BLUR\n#define MAX_MOTION_SAMPLES " + this.motionBlurSamples.toFixed(1), Engine.TEXTURETYPE_UNSIGNED_INT);
+
+            var motionScale: number = 0;
+            var prevViewProjection = Matrix.Identity();
+            var invViewProjection = Matrix.Identity();
+            var viewProjection = Matrix.Identity();
+            var screenSize = Vector2.Zero();
+
+            this.motionBlurPostProcess.onApply = (effect: Effect) => {
+                viewProjection = scene.getProjectionMatrix().multiply(scene.getViewMatrix());
+
+                viewProjection.invertToRef(invViewProjection);
+                effect.setMatrix("inverseViewProjection", invViewProjection);
+
+                effect.setMatrix("prevViewProjection", prevViewProjection);
+                prevViewProjection = viewProjection;
+
+                screenSize.x = this.motionBlurPostProcess.width;
+                screenSize.y = this.motionBlurPostProcess.height;
+                effect.setVector2("screenSize", screenSize);
+
+                motionScale = scene.getEngine().getFps() / 60.0;
+                effect.setFloat("motionScale", motionScale);
+                effect.setFloat("motionStrength", this.motionStrength);
+
+                effect.setTexture("depthSampler", this._depthRenderer.getDepthMap());
+            };
+
+            this.addEffect(new PostProcessRenderEffect(scene.getEngine(), "HDRMotionBlur", () => { return this.motionBlurPostProcess; }, true));
+        }
+
         // Dispose
         public dispose(): void {
             for (var i = 0; i < this._cameras.length; i++) {
@@ -597,6 +674,7 @@ module BABYLON {
                 this.lensFlarePostProcess.dispose(camera);
                 this.lensFlareComposePostProcess.dispose(camera);
                 this.depthOfFieldPostProcess.dispose(camera);
+                this.motionBlurPostProcess.dispose(camera);
             }
 
             this._scene.postProcessRenderPipelineManager.detachCamerasFromRenderPipeline(this._name, this._cameras);

+ 10 - 3
src/Rendering/babylon.renderingManager.ts

@@ -21,6 +21,11 @@
          */
         public static MIN_RENDERINGGROUPS = 0;
 
+        /**
+         * Used to globally prevent autoclearing scenes.
+         */
+        public static AUTOCLEAR = true;
+
         private _scene: Scene;
         private _renderingGroups = new Array<RenderingGroup>();
         private _depthStencilBufferAlreadyCleaned: boolean;
@@ -93,9 +98,11 @@
                 }
 
                 // Clear depth/stencil if needed
-                let autoClear = this._autoClearDepthStencil[index];
-                if (autoClear && autoClear.autoClear) {
-                    this._clearDepthStencilBuffer(autoClear.depth, autoClear.stencil);
+                if (RenderingManager.AUTOCLEAR) {
+                    let autoClear = this._autoClearDepthStencil[index];
+                    if (autoClear && autoClear.autoClear) {
+                        this._clearDepthStencilBuffer(autoClear.depth, autoClear.stencil);
+                    }
                 }
 
                 if (observable) {

+ 6 - 1
src/Shaders/ShadersInclude/lightFragment.fx

@@ -37,7 +37,12 @@
 	#else
 		shadow = 1.;
 	#endif
-    #if defined(LIGHTMAP) && defined(LIGHTMAPEXCLUDED{X})
+	#ifdef CUSTOMUSERLIGHTING
+		diffuseBase += computeCustomDiffuseLighting(info, diffuseBase, shadow);
+		#ifdef SPECULARTERM
+			specularBase += computeCustomSpecularLighting(info, specularBase, shadow);
+		#endif
+    #elif defined(LIGHTMAP) && defined(LIGHTMAPEXCLUDED{X})
 	    diffuseBase += lightmapColor * shadow;
 	    #ifdef SPECULARTERM
             #ifndef LIGHTMAPNOSPECULAR{X}

+ 17 - 0
src/Shaders/ShadersInclude/lightsFragmentFunctions.fx

@@ -5,6 +5,9 @@ struct lightingInfo
 #ifdef SPECULARTERM
 	vec3 specular;
 #endif
+#ifdef NDOTL
+	float ndl;
+#endif
 };
 
 lightingInfo computeLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, vec3 specularColor, float range, float glossiness) {
@@ -26,6 +29,10 @@ lightingInfo computeLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData,
 
 	// diffuse
 	float ndl = max(0., dot(vNormal, lightVectorW));
+#ifdef NDOTL
+	result.ndl = ndl;
+#endif
+
 	result.diffuse = ndl * diffuseColor * attenuation;
 
 #ifdef SPECULARTERM
@@ -56,6 +63,9 @@ lightingInfo computeSpotLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightDa
 
 		// Diffuse
 		float ndl = max(0., dot(vNormal, lightVectorW));
+#ifdef NDOTL
+		result.ndl = ndl;
+#endif
 		result.diffuse = ndl * diffuseColor * attenuation;
 
 #ifdef SPECULARTERM
@@ -73,6 +83,9 @@ lightingInfo computeSpotLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightDa
 #ifdef SPECULARTERM
 	result.specular = vec3(0.);
 #endif
+#ifdef NDOTL
+	result.ndl = 0.;
+#endif
 
 	return result;
 }
@@ -82,6 +95,10 @@ lightingInfo computeHemisphericLighting(vec3 viewDirectionW, vec3 vNormal, vec4
 
 	// Diffuse
 	float ndl = dot(vNormal, lightData.xyz) * 0.5 + 0.5;
+#ifdef NDOTL
+	result.ndl = ndl;
+#endif
+
 	result.diffuse = mix(groundColor, diffuseColor, ndl);
 
 #ifdef SPECULARTERM

+ 40 - 0
src/Shaders/standard.fragment.fx

@@ -356,5 +356,45 @@ void main(void)
 	factor = clamp(factor, 0.0, 0.90);
 	gl_FragColor = mix(sharp, blur, factor);
 }
+#endif
+
+#if defined(MOTION_BLUR)
+uniform mat4 inverseViewProjection;
+uniform mat4 prevViewProjection;
+
+uniform vec2 screenSize;
+
+uniform float motionScale;
+uniform float motionStrength;
+
+uniform sampler2D depthSampler;
+
+void main(void)
+{
+	vec2 texelSize = 1.0 / screenSize;
+	float depth = texture2D(depthSampler, vUV).r;
+
+	vec4 cpos = vec4(vUV * 2.0 - 1.0, depth, 1.0);
+	cpos = cpos * inverseViewProjection;
+
+	vec4 ppos = cpos * prevViewProjection;
+	ppos.xyz /= ppos.w;
+	ppos.xy = ppos.xy * 0.5 + 0.5;
+
+	vec2 velocity = (ppos.xy - vUV) * motionScale * motionStrength;
+	float speed = length(velocity / texelSize);
+	int nSamples = int(clamp(speed, 1.0, MAX_MOTION_SAMPLES));
 
+	vec4 result = texture2D(textureSampler, vUV);
+
+	for (int i = 1; i < int(MAX_MOTION_SAMPLES); ++i) {
+		if (i >= nSamples)
+			break;
+		
+		vec2 offset1 = vUV + velocity * (float(i) / float(nSamples - 1) - 0.5);
+		result += texture2D(textureSampler, offset1);
+	}
+
+	gl_FragColor = result / float(nSamples);
+}
 #endif

+ 6 - 5
src/Tools/babylon.tools.ts

@@ -395,7 +395,7 @@
         }
 
         //ANY
-        public static LoadFile(url: string, callback: (data: any) => void, progressCallBack?: () => void, database?, useArrayBuffer?: boolean, onError?: () => void): void {
+        public static LoadFile(url: string, callback: (data: any) => void, progressCallBack?: (data: any) => void, database?, useArrayBuffer?: boolean, onError?: (request: XMLHttpRequest) => void): void {
             url = Tools.CleanUrl(url);
 
             var noIndexedDB = () => {
@@ -410,14 +410,15 @@
                 request.onprogress = progressCallBack;
 
                 request.onreadystatechange = () => {
-                    if (request.readyState === 4) {
+                    // In case of undefined state in some browsers.
+                    if (request.readyState === (XMLHttpRequest.DONE || 4)) {
                         request.onreadystatechange = null;//some browsers have issues where onreadystatechange can be called multiple times with the same value
 
                         if (request.status >= 200 && request.status < 300 || (navigator.isCocoonJS && (request.status === 0))) {
                             callback(!useArrayBuffer ? request.responseText : request.response);
                         } else { // Failed
                             if (onError) {
-                                onError();
+                                onError(request);
                             } else {
 
                                 throw new Error("Error status: " + request.status + " - Unable to load " + loadUrl);
@@ -436,10 +437,10 @@
             if (url.indexOf("file:") !== -1) {
                 var fileName = url.substring(5).toLowerCase();
                 if (FilesInput.FilesToLoad[fileName]) {
-                    Tools.ReadFile(FilesInput.FilesToLoad[fileName], callback, progressCallBack, useArrayBuffer); 
+                    Tools.ReadFile(FilesInput.FilesToLoad[fileName], callback, progressCallBack, useArrayBuffer);
                 }
                 else {
-                    Tools.Error("File: " + fileName + " not found. Did you forget to provide it?");  
+                    Tools.Error("File: " + fileName + " not found. Did you forget to provide it?");
                 }
             }
             else {

+ 14 - 5
src/babylon.engine.ts

@@ -1205,7 +1205,7 @@
             });
         }
 
-        public getVRDevice(name: string, callback: (device) => void) {
+        public getVRDevice(name: string, callback: (device: any) => void) {
             if (!this.vrDisplaysPromise) {
                 callback(null);
                 return;
@@ -3474,7 +3474,9 @@
             }
 
             // Release audio engine
-            Engine.audioEngine.dispose();
+            if (Engine.audioEngine) {
+                Engine.audioEngine.dispose();
+            }
 
             // Release effects
             this.releaseEffects();
@@ -3509,15 +3511,22 @@
 
         // Loading screen
         public displayLoadingUI(): void {
-            this.loadingScreen.displayLoadingUI();
+            const loadingScreen = this.loadingScreen;
+            if (loadingScreen) {
+                loadingScreen.displayLoadingUI();
+            }
         }
 
         public hideLoadingUI(): void {
-            this.loadingScreen.hideLoadingUI();
+            const loadingScreen = this.loadingScreen;
+            if (loadingScreen) {
+                loadingScreen.hideLoadingUI();
+            }
         }
 
         public get loadingScreen(): ILoadingScreen {
-            if (!this._loadingScreen) this._loadingScreen = new DefaultLoadingScreen(this._renderingCanvas)
+            if (!this._loadingScreen && DefaultLoadingScreen) 
+                this._loadingScreen = new DefaultLoadingScreen(this._renderingCanvas)
             return this._loadingScreen;
         }
 

+ 44 - 26
src/babylon.scene.ts

@@ -512,9 +512,9 @@
 
         public materials = new Array<Material>();
         public multiMaterials = new Array<MultiMaterial>();
-        private _defaultMaterial: StandardMaterial;
+        private _defaultMaterial: Material;
 
-        public get defaultMaterial(): StandardMaterial {
+        public get defaultMaterial(): Material {
             if (!this._defaultMaterial) {
                 this._defaultMaterial = new StandardMaterial("default material", this);
             }
@@ -522,6 +522,10 @@
             return this._defaultMaterial;
         }
 
+        public set defaultMaterial(value: Material) {
+            this._defaultMaterial = value;
+        }
+
         // Textures
         private _texturesEnabled = true;
         public set texturesEnabled(value : boolean) {
@@ -716,6 +720,8 @@
         private _externalData: StringDictionary<Object>;
         private _uid: string;
 
+        public offscreenRenderTarget: RenderTargetTexture = null;
+
         /**
          * @constructor
          * @param {BABYLON.Engine} engine - the engine to be used to render this scene.
@@ -2602,7 +2608,7 @@
                 this._intermediateRendering = true;
                 Tools.StartPerformanceCounter("Render targets", this._renderTargets.length > 0);
                 for (var renderIndex = 0; renderIndex < this._renderTargets.length; renderIndex++) {
-                    var renderTarget = this._renderTargets.data[renderIndex];
+                    let renderTarget = this._renderTargets.data[renderIndex];
                     if (renderTarget._shouldRender()) {
                         this._renderId++;
                         var hasSpecialRenderTargetCamera = renderTarget.activeCamera && renderTarget.activeCamera !== this.activeCamera;
@@ -2632,7 +2638,7 @@
 
                         renderhighlights = true;
 
-                        var renderTarget = (<RenderTargetTexture>(<any>highlightLayer)._mainTexture);
+                        let renderTarget = (<RenderTargetTexture>(<any>highlightLayer)._mainTexture);
                         if (renderTarget._shouldRender()) {
                             this._renderId++;
                             renderTarget.render(false, false);
@@ -2646,7 +2652,12 @@
             }
 
             if (needsRestoreFrameBuffer) {
-                engine.restoreDefaultFramebuffer();
+                if (this.offscreenRenderTarget) {
+                    engine.bindFramebuffer(this.offscreenRenderTarget._texture);
+                }
+                else {
+                    engine.restoreDefaultFramebuffer(); // Restore back buffer
+                }
             }
 
             this._renderTargetsDuration.endMonitoring(false);
@@ -2844,9 +2855,9 @@
 
             // Physics
             if (this._physicsEngine) {
-                Tools.StartPerformanceCounter("Physics");
-                this._physicsEngine._step(deltaTime / 1000.0);
-                Tools.EndPerformanceCounter("Physics");
+               Tools.StartPerformanceCounter("Physics");
+               this._physicsEngine._step(deltaTime / 1000.0);
+               Tools.EndPerformanceCounter("Physics");
             }
 
             // Before render
@@ -2883,9 +2894,16 @@
                 this._renderId++;
             }
 
-            if (this.customRenderTargets.length > 0) { // Restore back buffer
-                engine.restoreDefaultFramebuffer();
+            if (this.offscreenRenderTarget) {
+                engine.bindFramebuffer(this.offscreenRenderTarget._texture);
+            }
+            else {
+                // Restore back buffer
+                if (this.customRenderTargets.length > 0) {
+                    engine.restoreDefaultFramebuffer();
+                }
             }
+
             this._renderTargetsDuration.endMonitoring();
             this.activeCamera = currentActiveCamera;
 
@@ -3589,26 +3607,26 @@
 
             // Camera
             if (!this.activeCamera) {
-                // Compute position
                 var worldExtends = this.getWorldExtends();
-                var worldCenter = worldExtends.min.add(worldExtends.max.subtract(worldExtends.min).scale(0.5));
-
-                var camera;
+                var worldSize = worldExtends.max.subtract(worldExtends.min);
+                var worldCenter = worldExtends.min.add(worldSize.scale(0.5));
 
+                var camera: TargetCamera;
+                var radius = worldSize.length() * 1.5;
                 if (createArcRotateCamera) {
-                    camera = new ArcRotateCamera("default camera", 0, 0, 10, Vector3.Zero(), this);
-                    camera.setPosition(new Vector3(worldCenter.x, worldCenter.y, worldExtends.min.z - (worldExtends.max.z - worldExtends.min.z)));
-                    camera.lowerRadiusLimit = 0.5;
-                    camera.setTarget(worldCenter);
-                } else {
-                    camera = new FreeCamera("default camera", Vector3.Zero(), this);
-
-                    camera.position = new Vector3(worldCenter.x, worldCenter.y, worldExtends.min.z - (worldExtends.max.z - worldExtends.min.z));
-                    camera.setTarget(worldCenter);
+                    var arcRotateCamera = new ArcRotateCamera("default camera", 4.712, 1.571, radius, worldCenter, this);
+                    arcRotateCamera.lowerRadiusLimit = radius * 0.01;
+                    arcRotateCamera.wheelPrecision = 100 / radius;
+                    camera = arcRotateCamera;
+                }
+                else {
+                    var freeCamera = new FreeCamera("default camera", new Vector3(worldCenter.x, worldCenter.y, this.useRightHandedSystem ? -radius : radius), this);
+                    freeCamera.setTarget(worldCenter);
+                    camera = freeCamera;
                 }
-                camera.minZ = 0.1;
-                var maxDist = worldExtends.max.subtract(worldExtends.min).length();
-                camera.wheelPrecision = 100.0 / maxDist;
+                camera.minZ = radius * 0.01;
+                camera.maxZ = radius * 100;
+                camera.speed = radius * 0.2;
                 this.activeCamera = camera;
             }
         }