Просмотр исходного кода

Merge remote-tracking branch 'upstream/master'

sebastien 7 лет назад
Родитель
Сommit
4307c7e9df
27 измененных файлов с 12936 добавлено и 18553 удалено
  1. 6088 6043
      Playground/babylon.d.txt
  2. 6074 6029
      dist/preview release/babylon.d.ts
  3. 1 1
      dist/preview release/babylon.js
  4. 175 53
      dist/preview release/babylon.max.js
  5. 175 53
      dist/preview release/babylon.no-module.max.js
  6. 1 1
      dist/preview release/babylon.worker.js
  7. 177 55
      dist/preview release/es6.js
  8. 0 609
      dist/preview release/inspector/babylon.inspector.css
  9. 0 5597
      dist/preview release/inspector/babylon.inspector.js
  10. 0 4
      dist/preview release/inspector/babylon.inspector.min.js
  11. 1 15
      dist/preview release/viewer/babylon.viewer.d.ts
  12. 1 1
      dist/preview release/viewer/babylon.viewer.js
  13. 1 1
      dist/preview release/viewer/babylon.viewer.max.js
  14. 1 18
      dist/preview release/viewer/babylon.viewer.module.d.ts
  15. 1 0
      dist/preview release/what's new.md
  16. 12 4
      src/Instrumentation/babylon.sceneInstrumentation.ts
  17. 11 0
      src/Particles/babylon.baseParticleSystem.ts
  18. 43 8
      src/Particles/babylon.gpuParticleSystem.ts
  19. 23 2
      src/Particles/babylon.particle.ts
  20. 21 12
      src/Particles/babylon.particleSystem.ts
  21. 1 1
      src/Physics/babylon.IPhysicsEngine.ts
  22. 1 1
      src/Physics/babylon.physicsEngine.ts
  23. 87 1
      src/Physics/babylon.physicsEngineComponent.ts
  24. 2 2
      src/Rendering/babylon.geometryBufferRendererSceneComponent.ts
  25. 21 6
      src/Shaders/gpuUpdateParticles.vertex.fx
  26. 17 36
      src/babylon.scene.ts
  27. 1 0
      src/babylon.sceneComponent.ts

Разница между файлами не показана из-за своего большого размера
+ 6088 - 6043
Playground/babylon.d.txt


Разница между файлами не показана из-за своего большого размера
+ 6074 - 6029
dist/preview release/babylon.d.ts


Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/babylon.js


Разница между файлами не показана из-за своего большого размера
+ 175 - 53
dist/preview release/babylon.max.js


Разница между файлами не показана из-за своего большого размера
+ 175 - 53
dist/preview release/babylon.no-module.max.js


Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/babylon.worker.js


Разница между файлами не показана из-за своего большого размера
+ 177 - 55
dist/preview release/es6.js


+ 0 - 609
dist/preview release/inspector/babylon.inspector.css

@@ -1,609 +0,0 @@
-@import url(https://use.fontawesome.com/releases/v5.0.13/css/all.css);
-@import url(https://fonts.googleapis.com/css?family=Inconsolata);
-
-@import url(https://use.fontawesome.com/releases/v5.0.13/css/all.css);
-@import url(https://fonts.googleapis.com/css?family=Inconsolata);
-.insp-wrapper {
-  user-select: none;
-  display: flex;
-  font-size: 0.9em;
-  font-family: "Inconsolata", sans-serif;
-  background-color: #242424;
-  /**
- * A tool contained in the tree panel (available for each item of the tree)
- */
-  /**
- * The toolbar contains : 
- * - a refresh tool - refresh the whole panel
- * - a popup tool - Open the inspector in a new panel
- * ...
- */
-  /*
-* 1. Set to 0 height and width, and remove border for a slider without a thumb
-*/ }
-  .insp-wrapper .gutter {
-    background-color: #2c2c2c; }
-    .insp-wrapper .gutter.gutter-vertical:not(.blocked) {
-      cursor: ns-resize; }
-    .insp-wrapper .gutter.gutter-horizontal:not(.blocked) {
-      cursor: ew-resize; }
-  .insp-wrapper .insp-right-panel {
-    width: 750px;
-    overflow-y: auto;
-    display: flex;
-    flex-direction: column;
-    flex-shrink: 0; }
-    .insp-wrapper .insp-right-panel.popupmode {
-      width: 100% !important; }
-    .insp-wrapper .insp-right-panel .top-panel {
-      width: 100%;
-      height: 100%;
-      position: relative;
-      background-color: #242424;
-      color: #ccc;
-      font-size: 1em; }
-      .insp-wrapper .insp-right-panel .top-panel .tab-panel-content {
-        width: 100%;
-        height: calc(100% - 50px); }
-      .insp-wrapper .insp-right-panel .top-panel .more-tabs-panel {
-        position: absolute;
-        z-index: 10;
-        top: 50px;
-        right: 0;
-        width: 100px;
-        display: none;
-        flex-direction: column;
-        align-items: center;
-        justify-content: center;
-        border: 1px solid #454545;
-        background-color: #242424; }
-        .insp-wrapper .insp-right-panel .top-panel .more-tabs-panel .invisible-tab {
-          height: 25px;
-          width: 100%;
-          line-height: 25px;
-          text-align: center;
-          background-color: #2c2c2c;
-          cursor: pointer; }
-          .insp-wrapper .insp-right-panel .top-panel .more-tabs-panel .invisible-tab:hover {
-            background-color: #383838; }
-          .insp-wrapper .insp-right-panel .top-panel .more-tabs-panel .invisible-tab:active {
-            background-color: #454545; }
-  .insp-wrapper .tooltip {
-    position: absolute;
-    top: 50px;
-    right: 0;
-    color: #f29766;
-    display: none;
-    z-index: 4;
-    font-family: "Inconsolata", sans-serif;
-    padding: 2px;
-    background-color: #242424;
-    border: 1px solid #454545; }
-  .insp-wrapper .treeTool {
-    margin: 3px 8px 3px 3px;
-    cursor: pointer;
-    position: relative; }
-    .insp-wrapper .treeTool:hover {
-      color: #5db0d7; }
-    .insp-wrapper .treeTool.active {
-      color: #5db0d7; }
-  .insp-wrapper .tab-panel {
-    height: 100%; }
-    .insp-wrapper .tab-panel.searchable {
-      height: calc(100% - 30px - 10px); }
-    .insp-wrapper .tab-panel .texture-image {
-      max-height: 400px; }
-    .insp-wrapper .tab-panel .scene-actions {
-      overflow-y: auto;
-      padding-left: 5px; }
-      .insp-wrapper .tab-panel .scene-actions .actions-title {
-        font-size: 1.1em;
-        padding-bottom: 10px;
-        border-bottom: 1px solid #5db0d7;
-        margin: 10px 0 10px 0; }
-      .insp-wrapper .tab-panel .scene-actions .defaut-action, .insp-wrapper .tab-panel .scene-actions .action-radio, .insp-wrapper .tab-panel .scene-actions .action {
-        height: 20px;
-        line-height: 20px;
-        width: 100%;
-        cursor: pointer; }
-        .insp-wrapper .tab-panel .scene-actions .defaut-action:hover, .insp-wrapper .tab-panel .scene-actions .action-radio:hover, .insp-wrapper .tab-panel .scene-actions .action:hover {
-          background-color: #2c2c2c; }
-        .insp-wrapper .tab-panel .scene-actions .defaut-action:active, .insp-wrapper .tab-panel .scene-actions .action-radio:active, .insp-wrapper .tab-panel .scene-actions .action:active {
-          background-color: #383838; }
-      .insp-wrapper .tab-panel .scene-actions .action-radio:before {
-        width: 1em;
-        height: 1em;
-        line-height: 1em;
-        display: inline-block;
-        font-family: "Font Awesome 5 Free", sans-serif;
-        content: "\f111";
-        margin-right: 10px; }
-      .insp-wrapper .tab-panel .scene-actions .action-radio.active:before {
-        width: 1em;
-        height: 1em;
-        line-height: 1em;
-        display: inline-block;
-        font-family: "Font Awesome 5 Free", sans-serif;
-        content: "\f192";
-        color: #5db0d7;
-        margin-right: 10px; }
-      .insp-wrapper .tab-panel .scene-actions .action:before {
-        width: 1em;
-        height: 1em;
-        line-height: 1em;
-        display: inline-block;
-        font-family: "Font Awesome 5 Free", sans-serif;
-        content: "\f0c8";
-        margin-right: 10px; }
-      .insp-wrapper .tab-panel .scene-actions .action.active:before {
-        width: 1em;
-        height: 1em;
-        line-height: 1em;
-        display: inline-block;
-        font-family: "Font Awesome 5 Free", sans-serif;
-        content: "\f14a";
-        color: #5db0d7;
-        margin-right: 10px; }
-  .insp-wrapper .tab-panel .shader-tree-panel {
-    height: 30px; }
-    .insp-wrapper .tab-panel .shader-tree-panel select {
-      height: 30px;
-      background-color: transparent;
-      color: #ccc;
-      height: 30px;
-      width: 100%;
-      max-width: 300px;
-      padding-left: 15px;
-      border: 1px solid #2c2c2c;
-      outline: 1px solid #454545; }
-      .insp-wrapper .tab-panel .shader-tree-panel select option {
-        padding: 5px;
-        color: gray; }
-  .insp-wrapper .tab-panel .shader-panel {
-    min-height: 100px;
-    user-select: text;
-    box-sizing: border-box;
-    padding: 0 15px; }
-    .insp-wrapper .tab-panel .shader-panel pre {
-      margin: 0;
-      white-space: pre-wrap; }
-      .insp-wrapper .tab-panel .shader-panel pre code {
-        background-color: #242424 !important;
-        padding: 0;
-        margin: 0; }
-    .insp-wrapper .tab-panel .shader-panel .shader-panel-title {
-      height: 25px;
-      border-bottom: 1px solid #383838;
-      text-transform: uppercase;
-      line-height: 25px;
-      margin-bottom: 10px; }
-  .insp-wrapper .tab-panel .console-panel {
-    min-height: 100px;
-    user-select: text;
-    box-sizing: border-box;
-    padding: 0 15px; }
-    .insp-wrapper .tab-panel .console-panel .console-panel-title {
-      height: 25px;
-      border-bottom: 1px solid #383838;
-      text-transform: uppercase;
-      line-height: 25px;
-      margin-bottom: 10px; }
-    .insp-wrapper .tab-panel .console-panel .console-panel-content {
-      overflow-y: auto;
-      overflow-x: hidden;
-      height: calc(100% - 30px); }
-    .insp-wrapper .tab-panel .console-panel .defaut-line, .insp-wrapper .tab-panel .console-panel .log, .insp-wrapper .tab-panel .console-panel .warn, .insp-wrapper .tab-panel .console-panel .error, .insp-wrapper .tab-panel .console-panel .object {
-      word-wrap: break-word;
-      padding: 3px 0 3px 5px; }
-    .insp-wrapper .tab-panel .console-panel .caller {
-      padding: 3px 0 3px 0;
-      color: #349ccd; }
-    .insp-wrapper .tab-panel .console-panel .log {
-      color: white; }
-    .insp-wrapper .tab-panel .console-panel .warn {
-      color: orange; }
-    .insp-wrapper .tab-panel .console-panel .error {
-      color: orangered; }
-    .insp-wrapper .tab-panel .console-panel .object {
-      color: #5db0d7; }
-  .insp-wrapper .tab-panel.stats-panel {
-    overflow-y: auto; }
-  .insp-wrapper .tab-panel .stats-fps {
-    font-weight: 600;
-    color: #f29766; }
-  .insp-wrapper .tab-panel .stat-title1 {
-    font-size: 1.1em;
-    padding: 10px; }
-  .insp-wrapper .tab-panel .stat-title2 {
-    margin: 10px 0 10px 0;
-    font-size: 1.05em;
-    border-bottom: 1px solid #5db0d7;
-    box-sizing: border-box; }
-  .insp-wrapper .tab-panel .stat-label {
-    display: inline-block;
-    width: 80%;
-    padding: 2px;
-    background-color: #2c2c2c;
-    border-bottom: 1px solid #242424;
-    border-top: 1px solid #242424;
-    height: 30px;
-    line-height: 30px;
-    box-sizing: border-box; }
-  .insp-wrapper .tab-panel .stat-value {
-    display: inline-block;
-    width: 20%;
-    padding: 2px;
-    background-color: #2c2c2c;
-    border-top: 1px solid #242424;
-    border-bottom: 1px solid #242424;
-    height: 30px;
-    line-height: 30px;
-    box-sizing: border-box; }
-  .insp-wrapper .tab-panel .stat-infos {
-    width: 100%;
-    padding: 4px; }
-  .insp-wrapper .tab-panel .gltf-actions {
-    overflow-y: auto;
-    padding-left: 5px; }
-    .insp-wrapper .tab-panel .gltf-actions .gltf-title {
-      font-size: 1.1em;
-      padding-bottom: 10px;
-      border-bottom: 1px solid #5db0d7;
-      margin: 10px 0 10px 0; }
-    .insp-wrapper .tab-panel .gltf-actions .gltf-action, .insp-wrapper .tab-panel .gltf-actions .gltf-checkbox {
-      height: 20px;
-      line-height: 20px;
-      width: 100%;
-      cursor: pointer;
-      white-space: nowrap; }
-      .insp-wrapper .tab-panel .gltf-actions .gltf-action:hover, .insp-wrapper .tab-panel .gltf-actions .gltf-checkbox:hover {
-        background-color: #2c2c2c; }
-    .insp-wrapper .tab-panel .gltf-actions .gltf-checkbox:before {
-      width: 1em;
-      height: 1em;
-      line-height: 1em;
-      display: inline-block;
-      font-family: "Font Awesome 5 Free", sans-serif;
-      content: "\f0c8";
-      margin-right: 10px; }
-    .insp-wrapper .tab-panel .gltf-actions .gltf-checkbox.active:before {
-      width: 1em;
-      height: 1em;
-      line-height: 1em;
-      display: inline-block;
-      font-family: "Font Awesome 5 Free", sans-serif;
-      content: "\f14a";
-      color: #5db0d7;
-      margin-right: 10px; }
-    .insp-wrapper .tab-panel .gltf-actions .gltf-input {
-      background-color: #2c2c2c;
-      border: none;
-      outline: none;
-      font-family: "Inconsolata", sans-serif;
-      color: #b3b3b3;
-      padding: 5px;
-      margin: 0px 6px 0px 0; }
-      .insp-wrapper .tab-panel .gltf-actions .gltf-input:hover {
-        background-color: #383838; }
-    .insp-wrapper .tab-panel .gltf-actions .gltf-button {
-      background-color: #2c2c2c;
-      border: none;
-      outline: none;
-      font-family: "Inconsolata", sans-serif;
-      color: #ccc;
-      padding: 5px 10px;
-      margin: 0px 6px 0px 0; }
-      .insp-wrapper .tab-panel .gltf-actions .gltf-button:hover {
-        background-color: #383838; }
-      .insp-wrapper .tab-panel .gltf-actions .gltf-button:active {
-        background-color: #454545; }
-  .insp-wrapper .tab-panel.tools-panel {
-    overflow-y: auto; }
-  .insp-wrapper .tab-panel .tool-title1 {
-    font-size: 1.1em;
-    padding: 10px; }
-  .insp-wrapper .tab-panel .tool-title2 {
-    margin: 10px 0 10px 0;
-    font-size: 1.05em;
-    border-bottom: 1px solid #5db0d7;
-    box-sizing: border-box; }
-  .insp-wrapper .tab-panel .tool-label, .insp-wrapper .tab-panel .tool-label-line, .insp-wrapper .tab-panel .tool-label-error {
-    background-color: #2c2c2c;
-    border: none;
-    outline: none;
-    font-family: "Inconsolata", sans-serif;
-    color: #b3b3b3;
-    padding: 5px;
-    margin: 0px 6px 0px 0; }
-  .insp-wrapper .tab-panel .tool-label-line {
-    width: 100%; }
-  .insp-wrapper .tab-panel .tool-label-error {
-    color: #fa371d;
-    width: 100%;
-    background-color: none; }
-  .insp-wrapper .tab-panel .tool-value {
-    display: inline-block;
-    width: 25%;
-    padding: 2px;
-    background-color: #2c2c2c;
-    border-top: 1px solid #242424;
-    border-bottom: 1px solid #242424;
-    height: 30px;
-    line-height: 30px;
-    box-sizing: border-box; }
-  .insp-wrapper .tab-panel .tool-infos {
-    width: 100%;
-    padding: 4px; }
-  .insp-wrapper .tab-panel .tool-input {
-    background-color: #2c2c2c;
-    border: none;
-    outline: none;
-    font-family: "Inconsolata", sans-serif;
-    color: #ccc;
-    padding: 5px 10px;
-    margin: 0px 6px 0px 0;
-    width: 100%;
-    border-top: 1px solid #242424;
-    border-bottom: 1px solid #242424;
-    text-align: left; }
-    .insp-wrapper .tab-panel .tool-input:hover {
-      background-color: #383838;
-      cursor: pointer; }
-    .insp-wrapper .tab-panel .tool-input:active {
-      background-color: #454545; }
-  .insp-wrapper .property-type {
-    color: #5db0d7; }
-  .insp-wrapper .property-name, .insp-wrapper .insp-details .base-row .prop-name, .insp-wrapper .insp-details .row .prop-name, .insp-wrapper .insp-details .header-row .prop-name {
-    color: #f29766; }
-  .insp-wrapper .insp-tree {
-    overflow-y: auto;
-    overflow-x: hidden;
-    height: calc(50% - 50px - 30px); }
-    .insp-wrapper .insp-tree .line {
-      padding: 3px;
-      cursor: pointer; }
-      .insp-wrapper .insp-tree .line:hover {
-        background-color: #2c2c2c; }
-      .insp-wrapper .insp-tree .line.active {
-        background-color: #454545; }
-        .insp-wrapper .insp-tree .line.active .line-content {
-          background-color: #242424; }
-      .insp-wrapper .insp-tree .line.unfolded:before {
-        width: 1em;
-        height: 1em;
-        line-height: 1em;
-        display: inline-block;
-        font-family: "Font Awesome 5 Free", sans-serif;
-        content: "\f107";
-        font-weight: 900; }
-      .insp-wrapper .insp-tree .line.folded:before {
-        width: 1em;
-        height: 1em;
-        line-height: 1em;
-        display: inline-block;
-        font-family: "Font Awesome 5 Free", sans-serif;
-        content: "\f105";
-        font-weight: 900; }
-      .insp-wrapper .insp-tree .line.unfolded.transformNode > span:first-of-type {
-        color: #f29766; }
-      .insp-wrapper .insp-tree .line.folded.transformNode > span:first-of-type {
-        color: #f29766; }
-      .insp-wrapper .insp-tree .line .line-content {
-        padding-left: 15px; }
-        .insp-wrapper .insp-tree .line .line-content:hover {
-          background-color: #242424; }
-        .insp-wrapper .insp-tree .line .line-content .line:hover:first-child {
-          background-color: #383838; }
-    .insp-wrapper .insp-tree .line_invisible {
-      display: none; }
-  .insp-wrapper .insp-details {
-    background-color: #242424;
-    overflow-y: auto;
-    overflow-x: auto;
-    color: #ccc;
-    font-family: "Inconsolata", sans-serif; }
-    .insp-wrapper .insp-details .details {
-      padding-left: 5px; }
-    .insp-wrapper .insp-details .base-row, .insp-wrapper .insp-details .row, .insp-wrapper .insp-details .header-row {
-      display: flex;
-      width: 100%; }
-      .insp-wrapper .insp-details .base-row .base-property, .insp-wrapper .insp-details .row .base-property, .insp-wrapper .insp-details .header-row .base-property, .insp-wrapper .insp-details .base-row .prop-name, .insp-wrapper .insp-details .row .prop-name, .insp-wrapper .insp-details .header-row .prop-name, .insp-wrapper .insp-details .base-row .prop-value, .insp-wrapper .insp-details .row .prop-value, .insp-wrapper .insp-details .header-row .prop-value {
-        padding: 2px 0 2px 0;
-        text-overflow: ellipsis;
-        white-space: nowrap;
-        overflow: hidden; }
-      .insp-wrapper .insp-details .base-row .prop-name, .insp-wrapper .insp-details .row .prop-name, .insp-wrapper .insp-details .header-row .prop-name {
-        width: 35%; }
-      .insp-wrapper .insp-details .base-row .prop-value, .insp-wrapper .insp-details .row .prop-value, .insp-wrapper .insp-details .header-row .prop-value {
-        width: 59%;
-        padding-left: 5px; }
-        .insp-wrapper .insp-details .base-row .prop-value.clickable, .insp-wrapper .insp-details .row .prop-value.clickable, .insp-wrapper .insp-details .header-row .prop-value.clickable {
-          cursor: pointer; }
-          .insp-wrapper .insp-details .base-row .prop-value.clickable:hover, .insp-wrapper .insp-details .row .prop-value.clickable:hover, .insp-wrapper .insp-details .header-row .prop-value.clickable:hover {
-            background-color: #383838; }
-          .insp-wrapper .insp-details .base-row .prop-value.clickable:after, .insp-wrapper .insp-details .row .prop-value.clickable:after, .insp-wrapper .insp-details .header-row .prop-value.clickable:after {
-            font-family: "Font Awesome 5 Free", sans-serif;
-            content: "\00a0 \00a0 \00a0 \f105";
-            font-weight: 900; }
-    .insp-wrapper .insp-details .row:nth-child(even) {
-      background-color: #2c2c2c; }
-    .insp-wrapper .insp-details .row.unfolded .prop-value.clickable:after {
-      font-family: "Font Awesome 5 Free", sans-serif;
-      content: "\00a0 \00a0 \00a0 \f107";
-      font-weight: 900; }
-    .insp-wrapper .insp-details .header-row {
-      background-color: #2c2c2c;
-      color: #ccc;
-      width: 100%;
-      max-width: 100%; }
-      .insp-wrapper .insp-details .header-row > * {
-        color: #ccc !important;
-        padding: 5px 0 5px 5px !important;
-        cursor: pointer; }
-        .insp-wrapper .insp-details .header-row > *:hover {
-          background-color: #383838; }
-      .insp-wrapper .insp-details .header-row .header-col {
-        display: flex;
-        justify-content: space-between;
-        align-items: center; }
-        .insp-wrapper .insp-details .header-row .header-col .sort-direction {
-          margin-right: 5px; }
-    .insp-wrapper .insp-details .element-viewer, .insp-wrapper .insp-details .color-element, .insp-wrapper .insp-details .texture-element {
-      position: relative;
-      width: 10px;
-      height: 10px;
-      display: inline-block;
-      margin-left: 5px; }
-    .insp-wrapper .insp-details .color-element {
-      width: 20px;
-      height: 15px; }
-    .insp-wrapper .insp-details .texture-element {
-      color: #f29766;
-      margin-left: 10px; }
-      .insp-wrapper .insp-details .texture-element .texture-viewer {
-        color: #ccc;
-        position: absolute;
-        z-index: 10;
-        bottom: 0;
-        right: 0;
-        display: block;
-        width: 150px;
-        height: 150px;
-        border: 1px solid #454545;
-        background-color: #242424;
-        transform: translateX(100%) translateY(100%);
-        display: none;
-        flex-direction: column;
-        justify-content: flex-start;
-        align-items: center; }
-        .insp-wrapper .insp-details .texture-element .texture-viewer .texture-viewer-img {
-          margin: 10px 0 10px 0;
-          max-width: 110px;
-          max-height: 110px; }
-  .insp-wrapper .tabbar {
-    height: 50px;
-    display: flex;
-    align-items: center;
-    border-bottom: 1px solid #383838;
-    width: 100%;
-    overflow-x: auto;
-    overflow-y: hidden;
-    box-sizing: border-box; }
-    .insp-wrapper .tabbar .tab {
-      height: calc(50px - 2px);
-      width: auto;
-      padding: 0 10px 0 10px;
-      color: #ccc;
-      line-height: 50px;
-      text-align: center;
-      cursor: pointer;
-      margin: 0 5px 0 5px;
-      box-sizing: border-box; }
-      .insp-wrapper .tabbar .tab:hover {
-        border-bottom: 1px solid #f29766;
-        background-color: #2c2c2c; }
-      .insp-wrapper .tabbar .tab:active {
-        background-color: #383838; }
-      .insp-wrapper .tabbar .tab.active {
-        border-bottom: 1px solid #f29766; }
-    .insp-wrapper .tabbar .more-tabs {
-      width: 50px;
-      height: 50px;
-      display: flex;
-      justify-content: center;
-      align-items: center;
-      cursor: pointer;
-      position: relative;
-      border-right: 1px solid #383838; }
-      .insp-wrapper .tabbar .more-tabs:hover {
-        background-color: #383838; }
-      .insp-wrapper .tabbar .more-tabs:active {
-        color: #f29766;
-        background-color: #454545; }
-      .insp-wrapper .tabbar .more-tabs.active {
-        color: #f29766; }
-  .insp-wrapper .toolbar {
-    display: flex; }
-    .insp-wrapper .toolbar .tool {
-      width: 50px;
-      height: 50px;
-      display: flex;
-      justify-content: center;
-      align-items: center;
-      cursor: pointer;
-      position: relative;
-      border-right: 1px solid #383838; }
-      .insp-wrapper .toolbar .tool:hover {
-        background-color: #383838; }
-      .insp-wrapper .toolbar .tool:active {
-        color: #f29766;
-        background-color: #454545; }
-      .insp-wrapper .toolbar .tool.active {
-        color: #f29766; }
-  .insp-wrapper .searchbar {
-    border: 1px solid #2c2c2c;
-    margin-bottom: 5px;
-    display: flex;
-    align-items: center;
-    color: #b3b3b3; }
-    .insp-wrapper .searchbar input {
-      background-color: #242424;
-      border: none;
-      width: 100%;
-      outline: none;
-      font-family: "Inconsolata", sans-serif;
-      color: #b3b3b3;
-      padding: 3px 0 3px 10px;
-      margin: 6px 0 6px 0; }
-  .insp-wrapper input[type="range"] {
-    margin: auto;
-    -webkit-appearance: none;
-    position: relative;
-    overflow: hidden;
-    height: 15px;
-    width: 50%;
-    cursor: pointer;
-    border-radius: 0;
-    /* iOS */ }
-  .insp-wrapper ::-webkit-slider-runnable-track {
-    background: #ddd; }
-  .insp-wrapper ::-webkit-slider-thumb {
-    -webkit-appearance: none;
-    width: 20px;
-    /* 1 */
-    height: 15px;
-    /* 1 */
-    background: #fff;
-    box-shadow: -100vw 0 0 100vw dodgerblue;
-    border: 0px solid #999;
-    /* 1 */ }
-  .insp-wrapper ::-moz-range-track {
-    height: 15px;
-    background: #ddd; }
-  .insp-wrapper ::-moz-range-thumb {
-    background: #fff;
-    height: 15px;
-    width: 20px;
-    border: 0px solid #999;
-    border-radius: 0 !important;
-    box-shadow: -100vw 0 0 100vw dodgerblue;
-    box-sizing: border-box; }
-  .insp-wrapper ::-ms-fill-lower {
-    background: dodgerblue; }
-  .insp-wrapper ::-ms-thumb {
-    background: #fff;
-    border: 0px solid #999;
-    height: 15px;
-    width: 20px;
-    box-sizing: border-box; }
-  .insp-wrapper ::-ms-ticks-after {
-    display: none; }
-  .insp-wrapper ::-ms-ticks-before {
-    display: none; }
-  .insp-wrapper ::-ms-track {
-    background: #ddd;
-    color: transparent;
-    height: 15px;
-    border: none; }
-  .insp-wrapper ::-ms-tooltip {
-    display: none; }

Разница между файлами не показана из-за своего большого размера
+ 0 - 5597
dist/preview release/inspector/babylon.inspector.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 4
dist/preview release/inspector/babylon.inspector.min.js


+ 1 - 15
dist/preview release/viewer/babylon.viewer.d.ts

@@ -924,7 +924,7 @@ declare module BabylonViewer {
       * @param name the name of the custom optimizer configuration
       * @param upgrade set to true if you want to upgrade optimizer and false if you want to degrade
       */
-    export function getCustomOptimizerByName(name: string, upgrade?: boolean): typeof extendedUpgrade;
+    export function getCustomOptimizerByName(name: string, upgrade?: boolean): (sceneManager: SceneManager) => boolean;
     export function registerCustomOptimizer(name: string, optimizer: (sceneManager: SceneManager) => boolean): void;
 }
 declare module BabylonViewer {
@@ -1558,20 +1558,6 @@ declare module BabylonViewer {
     export function addLoaderPlugin(name: string, plugin: ILoaderPlugin): void;
 }
 declare module BabylonViewer {
-    /**
-        * A custom upgrade-oriented function configuration for the scene optimizer.
-        *
-        * @param viewer the viewer to optimize
-        */
-    export function extendedUpgrade(sceneManager: SceneManager): boolean;
-    /**
-        * A custom degrade-oriented function configuration for the scene optimizer.
-        *
-        * @param viewer the viewer to optimize
-        */
-    export function extendedDegrade(sceneManager: SceneManager): boolean;
-}
-declare module BabylonViewer {
 }
 declare module BabylonViewer {
     export interface IEnvironmentMapConfiguration {

Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/viewer/babylon.viewer.js


Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/viewer/babylon.viewer.max.js


+ 1 - 18
dist/preview release/viewer/babylon.viewer.module.d.ts

@@ -985,14 +985,13 @@ declare module 'babylonjs-viewer/templating/viewerTemplatePlugin' {
 }
 
 declare module 'babylonjs-viewer/optimizer/custom' {
-    import { extendedUpgrade } from "babylonjs-viewer/optimizer/custom/extended";
     import { SceneManager } from "babylonjs-viewer/managers/sceneManager";
     /**
       *
       * @param name the name of the custom optimizer configuration
       * @param upgrade set to true if you want to upgrade optimizer and false if you want to degrade
       */
-    export function getCustomOptimizerByName(name: string, upgrade?: boolean): typeof extendedUpgrade;
+    export function getCustomOptimizerByName(name: string, upgrade?: boolean): (sceneManager: SceneManager) => boolean;
     export function registerCustomOptimizer(name: string, optimizer: (sceneManager: SceneManager) => boolean): void;
 }
 
@@ -1663,22 +1662,6 @@ declare module 'babylonjs-viewer/loader/plugins' {
     export function addLoaderPlugin(name: string, plugin: ILoaderPlugin): void;
 }
 
-declare module 'babylonjs-viewer/optimizer/custom/extended' {
-    import { SceneManager } from 'babylonjs-viewer/managers/sceneManager';
-    /**
-        * A custom upgrade-oriented function configuration for the scene optimizer.
-        *
-        * @param viewer the viewer to optimize
-        */
-    export function extendedUpgrade(sceneManager: SceneManager): boolean;
-    /**
-        * A custom degrade-oriented function configuration for the scene optimizer.
-        *
-        * @param viewer the viewer to optimize
-        */
-    export function extendedDegrade(sceneManager: SceneManager): boolean;
-}
-
 declare module 'babylonjs-viewer/configuration/interfaces' {
     export * from 'babylonjs-viewer/configuration/interfaces/cameraConfiguration';
     export * from 'babylonjs-viewer/configuration/interfaces/colorGradingConfiguration';

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

@@ -44,6 +44,7 @@
   - Attached sub emitters. [Doc](http://doc.babylonjs.com/how_to/sub_emitters) ([TrevorDev](https://github.com/TrevorDev))
   - Cylinder particle emitter and constructor in baseParticle [Doc](https://doc.babylonjs.com/babylon101/particles#cylinder-emitter) ([TrevorDev](https://github.com/TrevorDev))
   - Added support for cylinder particle emitter. [Doc](https://doc.babylonjs.com/babylon101/particles#cylinder-emitter) ([TrevorDev](https://github.com/TrevorDev))
+  - Added startDelay to support delaying system start of sub emitters [Doc](https://doc.babylonjs.com/babylon101/particles#creating-the-particles) ([TrevorDev](https://github.com/TrevorDev))
   - Added support for random start cell when using animated sprite sheets. [Doc](http://doc.babylonjs.com/how_to/animate)
 - Added SceneComponent to help decoupling Scene from its components. ([sebavan](http://www.github.com/sebavan))
 - Added [Environment Texture Tools](https://doc.babylonjs.com/how_to/physically_based_rendering#creating-a-compressed-environment-texture) to reduce the size of the usual .DDS file ([sebavan](http://www.github.com/sebavan))

+ 12 - 4
src/Instrumentation/babylon.sceneInstrumentation.ts

@@ -259,6 +259,10 @@ module BABYLON {
                 return;
             }
 
+            if (!this.scene.onBeforePhysicsObservable) {
+                return;
+            }
+
             this._capturePhysicsTime = value;
 
             if (value) {
@@ -549,11 +553,15 @@ module BABYLON {
             this.scene.onAfterDrawPhaseObservable.remove(this._onAfterDrawPhaseObserver);
             this._onAfterDrawPhaseObserver = null;
 
-            this.scene.onBeforePhysicsObservable.remove(this._onBeforePhysicsObserver);
-            this._onBeforePhysicsObserver = null;
+            if (this._onBeforePhysicsObserver) {
+                this.scene.onBeforePhysicsObservable.remove(this._onBeforePhysicsObserver);
+                this._onBeforePhysicsObserver = null;
+            }
 
-            this.scene.onAfterPhysicsObservable.remove(this._onAfterPhysicsObserver);
-            this._onAfterPhysicsObserver = null;
+            if (this._onAfterPhysicsObserver) {
+                this.scene.onAfterPhysicsObservable.remove(this._onAfterPhysicsObserver);
+                this._onAfterPhysicsObserver = null;
+            }
 
             this.scene.onAfterAnimationsObservable.remove(this._onAfterAnimationsObserver);
             this._onAfterAnimationsObserver = null;

+ 11 - 0
src/Particles/babylon.baseParticleSystem.ts

@@ -266,6 +266,17 @@ module BABYLON {
         protected _rampGradients: Nullable<Array<Color3Gradient>> = null;
         protected _colorRemapGradients: Nullable<Array<FactorGradient>> = null;
         protected _alphaRemapGradients: Nullable<Array<FactorGradient>> = null;        
+        
+        protected _hasTargetStopDurationDependantGradient(){
+            return (this._startSizeGradients && this._startSizeGradients.length > 0)
+                || (this._emitRateGradients && this._emitRateGradients.length > 0)
+                || (this._lifeTimeGradients && this._lifeTimeGradients.length > 0);
+        }
+
+        /**
+         * Defines the delay in milliseconds before starting the system (0 by default)
+         */
+        public startDelay = 0;
 
         /**
          * Gets the current list of drag gradients.

+ 43 - 8
src/Particles/babylon.gpuParticleSystem.ts

@@ -117,9 +117,12 @@
 
         /**
          * Starts the particle system and begins to emit
-         * @param delay defines the delay in milliseconds before starting the system (0 by default)
+         * @param delay defines the delay in milliseconds before starting the system (this.startDelay by default)
          */
-        public start(delay = 0): void {
+        public start(delay = this.startDelay): void {
+            if(!this.targetStopDuration && this._hasTargetStopDurationDependantGradient()){
+                throw "Particle system started with a targetStopDuration dependant gradient (eg. startSizeGradients) but no targetStopDuration set";
+            }
             if (delay) {
                 setTimeout(()=> {
                     this.start(0);
@@ -580,7 +583,7 @@
             this._scene.particleSystems.push(this);
 
             this._updateEffectOptions = {
-                attributes: ["position", "age", "life", "seed", "size", "color", "direction", "initialDirection", "angle", "cellIndex", "cellStartOffset"],
+                attributes: ["position", "age", "life", "seed", "size", "color", "direction", "initialDirection", "angle", "cellIndex", "cellStartOffset", "noiseCoordinates1", "noiseCoordinates2"],
                 uniformsNames: ["currentCount", "timeDelta", "emitterWM", "lifeTime", "color1", "color2", "sizeRange", "scaleRange","gravity", "emitPower",
                                 "direction1", "direction2", "minEmitBox", "maxEmitBox", "radius", "directionRandomizer", "height", "coneAngle", "stopFactor", 
                                 "angleRange", "radiusRange", "cellInfos", "noiseStrength", "limitVelocityDamping"],
@@ -665,7 +668,14 @@
                     updateVertexBuffers["cellStartOffset"] = source.createVertexBuffer("cellStartOffset", offset, 1);
                     offset += 1;
                 }
-            }            
+            }           
+            
+            if (this.noiseTexture) {
+                updateVertexBuffers["noiseCoordinates1"] = source.createVertexBuffer("noiseCoordinates1", offset, 3);
+                offset += 3;
+                updateVertexBuffers["noiseCoordinates2"] = source.createVertexBuffer("noiseCoordinates2", offset, 3);
+                offset += 3;
+            }
            
             let vao = this._engine.recordVertexArrayObject(updateVertexBuffers, null, this._updateEffect);
             this._engine.bindArrayBuffer(null);
@@ -708,7 +718,14 @@
                     renderVertexBuffers["cellStartOffset"] = source.createVertexBuffer("cellStartOffset", offset, 1, this._attributesStrideSize, true);
                     offset += 1;
                 }
-            }               
+            }     
+            
+            if (this.noiseTexture) {
+                renderVertexBuffers["noiseCoordinates1"] = source.createVertexBuffer("noiseCoordinates1", offset, 3, this._attributesStrideSize, true);
+                offset += 3;
+                renderVertexBuffers["noiseCoordinates2"] = source.createVertexBuffer("noiseCoordinates2", offset, 3, this._attributesStrideSize, true);
+                offset += 3;
+            }
 
             renderVertexBuffers["offset"] = spriteSource.createVertexBuffer("offset", 0, 2);
             renderVertexBuffers["uv"] = spriteSource.createVertexBuffer("uv", 2, 2);
@@ -744,7 +761,11 @@
                 if (this.spriteRandomStartCell) {
                     this._attributesStrideSize += 1;
                 }
-            }            
+            }     
+            
+            if (this.noiseTexture) {
+                this._attributesStrideSize += 6;
+            }
 
             for (var particleIndex = 0; particleIndex < this._capacity; particleIndex++) {
                 // position
@@ -799,7 +820,16 @@
                     if (this.spriteRandomStartCell) {
                         data.push(0.0); 
                     }
-                }                
+                }    
+                
+                if (this.noiseTexture) { // Random coordinates for reading into noise texture
+                    data.push(Math.random());
+                    data.push(Math.random());
+                    data.push(Math.random());
+                    data.push(Math.random());
+                    data.push(Math.random());
+                    data.push(Math.random());
+                }
             }
 
             // Sprite data
@@ -895,7 +925,12 @@
                 if (this.spriteRandomStartCell) {
                     this._updateEffectOptions.transformFeedbackVaryings.push("outCellStartOffset");
                 }
-            }               
+            }         
+            
+            if (this.noiseTexture) {
+                this._updateEffectOptions.transformFeedbackVaryings.push("outNoiseCoordinates1");
+                this._updateEffectOptions.transformFeedbackVaryings.push("outNoiseCoordinates2");
+            }
 
             this._updateEffectOptions.defines = defines;
             this._updateEffect = new Effect("gpuUpdateParticles", this._updateEffectOptions, this._scene.getEngine());   

+ 23 - 2
src/Particles/babylon.particle.ts

@@ -124,6 +124,11 @@
         public _currentDrag1 = 0;
         /** @hidden */
         public _currentDrag2 = 0;  
+
+        /** @hidden */
+        public _randomNoiseCoordinates1: Vector3;
+        /** @hidden */
+        public _randomNoiseCoordinates2: Vector3;
      
 
         /**
@@ -152,16 +157,23 @@
          */
         public updateCellIndex(): void {
             let offsetAge = this.age;
+            let changeSpeed = this.particleSystem.spriteCellChangeSpeed;
 
             if (this.particleSystem.spriteRandomStartCell) {
                 if (this._randomCellOffset === undefined) {         
                     this._randomCellOffset = Math.random() * this.lifeTime;
                 }
-                offsetAge += this._randomCellOffset;
+
+                if (changeSpeed === 0) { // Special case when speed = 0 meaning we want to stay on initial cell
+                    changeSpeed = 1;
+                    offsetAge = this._randomCellOffset;
+                } else {
+                    offsetAge += this._randomCellOffset;
+                }
             }
 
             let dist = (this._initialEndSpriteCellID - this._initialStartSpriteCellID);
-            let ratio = Scalar.Clamp(((offsetAge * this.particleSystem.spriteCellChangeSpeed) % this.lifeTime) / this.lifeTime);
+            let ratio = Scalar.Clamp(((offsetAge * changeSpeed) % this.lifeTime) / this.lifeTime);
 
             this.cellIndex = this._initialStartSpriteCellID + (ratio * dist) | 0;
         }
@@ -245,6 +257,15 @@
             if (this.particleSystem.useRampGradients) {
                 other.remapData.copyFrom(this.remapData);
             }
+            if (this._randomNoiseCoordinates1) {
+                if (other._randomNoiseCoordinates1) {
+                    other._randomNoiseCoordinates1.copyFromFloats(Math.random(), Math.random(), Math.random());
+                    other._randomNoiseCoordinates2.copyFromFloats(Math.random(), Math.random(), Math.random());
+                } else {
+                    other._randomNoiseCoordinates1 = new Vector3(Math.random(), Math.random(), Math.random());
+                    other._randomNoiseCoordinates2 = new Vector3(Math.random(), Math.random(), Math.random());
+                }
+            }
         }
     }
 } 

+ 21 - 12
src/Particles/babylon.particleSystem.ts

@@ -295,15 +295,9 @@
 
                         // Noise
                         if (noiseTextureData && noiseTextureSize) {
-                            let localPosition = Tmp.Vector3[0];
-                            let emitterPosition = Tmp.Vector3[1];
-
-                            this._emitterWorldMatrix.getTranslationToRef(emitterPosition);
-                            particle.position.subtractToRef(emitterPosition, localPosition);
-
-                            let fetchedColorR = this._fetchR(localPosition.y, localPosition.z, noiseTextureSize.width, noiseTextureSize.height, noiseTextureData);
-                            let fetchedColorG = this._fetchR(localPosition.x + 0.33, localPosition.z + 0.33, noiseTextureSize.width, noiseTextureSize.height, noiseTextureData);
-                            let fetchedColorB = this._fetchR(localPosition.x - 0.33, localPosition.y - 0.33, noiseTextureSize.width, noiseTextureSize.height, noiseTextureData);
+                            let fetchedColorR = this._fetchR(particle._randomNoiseCoordinates1.x, particle._randomNoiseCoordinates1.y, noiseTextureSize.width, noiseTextureSize.height, noiseTextureData);
+                            let fetchedColorG = this._fetchR(particle._randomNoiseCoordinates1.z, particle._randomNoiseCoordinates2.x, noiseTextureSize.width, noiseTextureSize.height, noiseTextureData);
+                            let fetchedColorB = this._fetchR(particle._randomNoiseCoordinates2.y, particle._randomNoiseCoordinates2.z, noiseTextureSize.width, noiseTextureSize.height, noiseTextureData);
 
                             let force = Tmp.Vector3[0];
                             let scaledForce = Tmp.Vector3[1];
@@ -997,9 +991,12 @@
 
         /**
          * Starts the particle system and begins to emit
-         * @param delay defines the delay in milliseconds before starting the system (0 by default)
+         * @param delay defines the delay in milliseconds before starting the system (this.startDelay by default)
          */
-        public start(delay = 0): void {
+        public start(delay = this.startDelay): void {
+            if(!this.targetStopDuration && this._hasTargetStopDurationDependantGradient()){
+                throw "Particle system started with a targetStopDuration dependant gradient (eg. startSizeGradients) but no targetStopDuration set";
+            }
             if (delay) {
                 setTimeout(() => {
                     this.start(0);
@@ -1286,7 +1283,7 @@
                 particle.scale.copyFromFloats(Scalar.RandomRange(this.minScaleX, this.maxScaleX), Scalar.RandomRange(this.minScaleY, this.maxScaleY));
 
                 // Adjust scale by start size
-                if (this._startSizeGradients && this._startSizeGradients[0]) {
+                if (this._startSizeGradients && this._startSizeGradients[0] && this.targetStopDuration) {
                     const ratio = this._actualFrame / this.targetStopDuration;
                     Tools.GetCurrentGradient(ratio, this._startSizeGradients, (currentGradient, nextGradient, scale) => {
                         if (currentGradient !== this._currentStartSizeGradient) {
@@ -1385,6 +1382,18 @@
                 if (this._useRampGradients) {
                     particle.remapData = new Vector4(0, 1, 0, 1);
                 }
+
+                // Noise texture coordinates
+                if (this.noiseTexture) {
+                    if (particle._randomNoiseCoordinates1) {
+                        particle._randomNoiseCoordinates1.copyFromFloats(Math.random(), Math.random(), Math.random());
+                        particle._randomNoiseCoordinates2.copyFromFloats(Math.random(), Math.random(), Math.random());
+                    } else {
+                        particle._randomNoiseCoordinates1 = new Vector3(Math.random(), Math.random(), Math.random());
+                        particle._randomNoiseCoordinates2 = new Vector3(Math.random(), Math.random(), Math.random());
+                    }            
+                }
+    
             }
         }
 

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

@@ -152,7 +152,7 @@ module BABYLON {
          * Called by the scene. No need to call it.
          * @param delta defines the timespam between frames
          */
-        step(delta: number): void;
+        _step(delta: number): void;
     }
 
 }

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

@@ -149,7 +149,7 @@
          * Called by the scene. No need to call it.
          * @param delta defines the timespam between frames
          */
-        public step(delta: number) {
+        public _step(delta: number) {
             //check if any mesh has no body / requires an update
             this._impostors.forEach((impostor) => {
 

+ 87 - 1
src/Physics/babylon.physicsEngineComponent.ts

@@ -1,7 +1,7 @@
 module BABYLON {
     export interface Scene {
         /** @hidden (Backing field) */        
-        _physicsEngine: Nullable<IPhysicsEngine>;
+        _physicsEngine: Nullable<IPhysicsEngine>;             
 
         /**
          * Gets the current physics engine
@@ -33,6 +33,16 @@ module BABYLON {
          * @param compound defines the compound to delete
          */
         deleteCompoundImpostor(compound: any): void;
+
+        /**
+        * An event triggered when physic simulation is about to be run
+        */
+        onBeforePhysicsObservable: Observable<Scene>;
+
+        /**
+         * An event triggered when physic simulation has been done
+         */
+        onAfterPhysicsObservable: Observable<Scene>;
     }
 
     /** 
@@ -53,6 +63,13 @@ module BABYLON {
         if (this._physicsEngine) {
             return true;
         }
+        
+        // Register the component to the scene
+        let component = this._getComponent(SceneComponentConstants.NAME_PHYSICSENGINE) as PhysicsEngineSceneComponent;
+        if (!component) {
+            component = new PhysicsEngineSceneComponent(this);
+            this._addComponent(component);
+        }
 
         try {
             this._physicsEngine = new PhysicsEngine(gravity, plugin);
@@ -95,4 +112,73 @@ module BABYLON {
             mesh.physicsImpostor = null;
         }
     }
+
+    /** @hidden */
+    Scene.prototype._advancePhysicsEngineStep = function(step: number) {
+        if (this._physicsEngine) {
+            this.onBeforePhysicsObservable.notifyObservers(this);
+            this._physicsEngine._step(step / 1000);
+            this.onAfterPhysicsObservable.notifyObservers(this);
+        }
+    }
+   
+    /**
+     * Defines the physics engine scene component responsible to manage a physics engine
+     */
+    export class PhysicsEngineSceneComponent implements ISceneComponent {
+        /**
+         * The component name helpful to identify the component in the list of scene components.
+         */
+        public readonly name = SceneComponentConstants.NAME_PHYSICSENGINE;
+
+        /**
+         * The scene the component belongs to.
+         */
+        public scene: Scene;
+
+        /**
+         * Creates a new instance of the component for the given scene
+         * @param scene Defines the scene to register the component in
+         */
+        constructor(scene: Scene) {
+            this.scene = scene;
+            this.scene.onBeforePhysicsObservable = new Observable<Scene>();
+            this.scene.onAfterPhysicsObservable = new Observable<Scene>();
+
+            // Replace the function used to get the deterministic frame time
+            this.scene.getDeterministicFrameTime = () => {    
+                if (this.scene._physicsEngine) {
+                    return this.scene._physicsEngine.getTimeStep() * 1000;
+                }
+
+                return 1000.0 / 60.0;
+            }        
+        }
+
+        /**
+         * Registers the component in a given scene
+         */
+        public register(): void {
+        }
+
+        /**
+         * Rebuilds the elements related to this component in case of
+         * context lost for instance.
+         */
+        public rebuild(): void {
+            // Nothing to do for this component
+        }
+
+        /**
+         * Disposes the component and the associated ressources
+         */
+        public dispose(): void {
+            this.scene.onBeforePhysicsObservable.clear();
+            this.scene.onAfterPhysicsObservable.clear();
+
+            if (this.scene._physicsEngine) {
+                this.scene.disablePhysicsEngine();
+            }
+        }
+    }
 }

+ 2 - 2
src/Rendering/babylon.geometryBufferRendererSceneComponent.ts

@@ -57,12 +57,12 @@ module BABYLON {
     }
 
     /**
-     * Defines the Geometry Buffer scene component responsible to manage a G-Buffer usefull
+     * Defines the Geometry Buffer scene component responsible to manage a G-Buffer useful
      * in several rendering techniques.
      */
     export class GeometryBufferRendererSceneComponent implements ISceneComponent {
         /**
-         * The component name helpfull to identify the component in the list of scene components.
+         * The component name helpful to identify the component in the list of scene components.
          */
         public readonly name = SceneComponentConstants.NAME_GEOMETRYBUFFERRENDERER;
 

+ 21 - 6
src/Shaders/gpuUpdateParticles.vertex.fx

@@ -91,6 +91,10 @@ in float cellIndex;
 in float cellStartOffset;
 #endif
 #endif
+#ifdef NOISE
+in vec3 noiseCoordinates1;
+in vec3 noiseCoordinates2;
+#endif
 
 // Output
 out vec3 outPosition;
@@ -116,6 +120,10 @@ out float outCellIndex;
 out float outCellStartOffset;
 #endif
 #endif
+#ifdef NOISE
+out vec3 outNoiseCoordinates1;
+out vec3 outNoiseCoordinates2;
+#endif
 
 #ifdef SIZEGRADIENTS
 uniform sampler2D sizeGradientSampler;
@@ -157,9 +165,7 @@ vec4 getRandomVec4(float offset) {
 }
 
 void main() {
-  float newAge = age + timeDelta;
-
-    
+  float newAge = age + timeDelta;    
 
   // If particle is dead and system is not stopped, spawn as new particle
   if (newAge >= life && stopFactor != 0.) {
@@ -320,6 +326,11 @@ void main() {
 #endif    
 #endif
 
+#ifdef NOISE
+    outNoiseCoordinates1 = noiseCoordinates1;
+    outNoiseCoordinates2 = noiseCoordinates2;
+#endif
+
   } else {
     float directionScale = timeDelta;
     outAge = newAge;
@@ -369,13 +380,17 @@ void main() {
 #ifdef NOISE
     vec3 localPosition = outPosition - emitterWM[3].xyz;
 
-    float fetchedR = texture(noiseSampler, vec2(localPosition.y, localPosition.z) * vec2(0.5) + vec2(0.5)).r;
-    float fetchedG = texture(noiseSampler, vec2(localPosition.x + 0.33, localPosition.z + 0.33) * vec2(0.5) + vec2(0.5)).r;
-    float fetchedB = texture(noiseSampler, vec2(localPosition.z - 0.33, localPosition.y - 0.33) * vec2(0.5) + vec2(0.5)).r;
+    float fetchedR = texture(noiseSampler, vec2(noiseCoordinates1.x, noiseCoordinates1.y) * vec2(0.5) + vec2(0.5)).r;
+    float fetchedG = texture(noiseSampler, vec2(noiseCoordinates1.z, noiseCoordinates2.x) * vec2(0.5) + vec2(0.5)).r;
+    float fetchedB = texture(noiseSampler, vec2(noiseCoordinates2.y, noiseCoordinates2.z) * vec2(0.5) + vec2(0.5)).r;
 
     vec3 force = vec3(2. * fetchedR - 1., 2. * fetchedG - 1., 2. * fetchedB - 1.) * noiseStrength;
 
     outDirection = outDirection + force * timeDelta;
+
+    outNoiseCoordinates1 = noiseCoordinates1;
+    outNoiseCoordinates2 = noiseCoordinates2;
+
 #endif    
 
 #ifdef ANGULARSPEEDGRADIENTS

+ 17 - 36
src/babylon.scene.ts

@@ -91,7 +91,7 @@
          */
         public static MaxDeltaTime = 1000.0;
 
-        // Members
+        // Members   
 
         /**
          * Gets or sets a boolean that indicates if the scene must clear the render buffer before rendering a frame
@@ -330,16 +330,6 @@
         public onAfterDrawPhaseObservable = new Observable<Scene>();
 
         /**
-        * An event triggered when physic simulation is about to be run
-        */
-        public onBeforePhysicsObservable = new Observable<Scene>();
-
-        /**
-        * An event triggered when physic simulation has been done
-        */
-        public onAfterPhysicsObservable = new Observable<Scene>();
-
-        /**
         * An event triggered when the scene is ready
         */
         public onReadyObservable = new Observable<Scene>();
@@ -4380,6 +4370,18 @@
             }
         }
 
+        /** @hidden */
+        public _advancePhysicsEngineStep(step: number) {
+            // Do nothing. Code will be replaced if physics engine component is referenced
+        }
+
+        /**
+         * User updatable function that will return a deterministic frame time when engine is in deterministic lock step mode
+         */
+        public getDeterministicFrameTime: () => number = () => {
+            return 1000.0 / 60.0; // frame time in ms
+        }
+
         /** 
          * Render the scene
          * @param updateCameras defines a boolean indicating if cameras must update according to their inputs (true by default)
@@ -4413,11 +4415,8 @@
 
                 var defaultFPS = (60.0 / 1000.0);
 
-                let defaultFrameTime = 1000 / 60; // frame time in MS
+                let defaultFrameTime = this.getDeterministicFrameTime();
 
-                if (this._physicsEngine) {
-                    defaultFrameTime = this._physicsEngine.getTimeStep() * 1000;
-                }
                 let stepsTaken = 0;
 
                 var maxSubSteps = this._engine.getLockstepMaxSteps();
@@ -4434,11 +4433,7 @@
                     this.onAfterAnimationsObservable.notifyObservers(this);
 
                     // Physics
-                    if (this._physicsEngine) {
-                        this.onBeforePhysicsObservable.notifyObservers(this);
-                        this._physicsEngine.step(defaultFrameTime / 1000);
-                        this.onAfterPhysicsObservable.notifyObservers(this);
-                    }
+                    this._advancePhysicsEngineStep(defaultFrameTime);
 
                     this.onAfterStepObservable.notifyObservers(this);
                     this._currentStepId++;
@@ -4459,11 +4454,7 @@
                 this.onAfterAnimationsObservable.notifyObservers(this);
 
                 // Physics
-                if (this._physicsEngine) {
-                    this.onBeforePhysicsObservable.notifyObservers(this);
-                    this._physicsEngine.step(deltaTime / 1000.0);
-                    this.onAfterPhysicsObservable.notifyObservers(this);
-                }
+                this._advancePhysicsEngineStep(deltaTime);
             }
 
             // Before camera update steps
@@ -4829,8 +4820,6 @@
             this.onAfterParticlesRenderingObservable.clear();
             this.onBeforeDrawPhaseObservable.clear();
             this.onAfterDrawPhaseObservable.clear();
-            this.onBeforePhysicsObservable.clear();
-            this.onAfterPhysicsObservable.clear();
             this.onBeforeAnimationsObservable.clear();
             this.onAfterAnimationsObservable.clear();
             this.onDataLoadedObservable.clear();
@@ -4914,11 +4903,6 @@
             // Post-processes
             this.postProcessManager.dispose();
 
-            // Physics
-            if (this._physicsEngine) {
-                this.disablePhysicsEngine();
-            }
-
             // Remove from engine
             index = this._engine.scenes.indexOf(this);
 
@@ -5298,10 +5282,7 @@
         public getPointerOverMesh(): Nullable<AbstractMesh> {
             return this._pointerOverMesh;
         }
-
-        // Physics
-
-      
+     
         // Misc.
         /** @hidden */
         public _rebuildGeometries(): void {

+ 1 - 0
src/babylon.sceneComponent.ts

@@ -19,6 +19,7 @@
         public static readonly NAME_PROCEDURALTEXTURE = "ProceduralTexture";
         public static readonly NAME_SHADOWGENERATOR = "ShadowGenerator";
         public static readonly NAME_OCTREE = "Octree";
+        public static readonly NAME_PHYSICSENGINE = "PhysicsEngine";
 
         public static readonly STEP_ISREADYFORMESH_EFFECTLAYER = 0;