Christopher Yovanovitch 7 lat temu
rodzic
commit
685db1e486

+ 0 - 3
assets/particles/fire.json

@@ -1,3 +0,0 @@
-{
-  "type": "fire"
-}

+ 14 - 0
assets/particles/systems.json

@@ -0,0 +1,14 @@
+[
+  {
+    "type": "fire",
+    "data": {
+
+    }
+  },
+  {
+    "type": "smoke",
+    "data": {
+
+    }
+  }
+]

BIN
assets/particles/textures/Flare2.png


BIN
assets/particles/textures/fire.jpg


BIN
assets/particles/textures/fire.png


BIN
assets/particles/textures/flare3.png


Plik diff jest za duży
+ 10485 - 10458
dist/preview release/babylon.d.ts


Plik diff jest za duży
+ 27 - 27
dist/preview release/babylon.js


Plik diff jest za duży
+ 75 - 28
dist/preview release/babylon.max.js


Plik diff jest za duży
+ 75 - 28
dist/preview release/babylon.no-module.max.js


Plik diff jest za duży
+ 27 - 27
dist/preview release/babylon.worker.js


Plik diff jest za duży
+ 75 - 28
dist/preview release/es6.js


Plik diff jest za duży
+ 27 - 27
dist/preview release/viewer/babylon.viewer.js


Plik diff jest za duży
+ 75 - 28
dist/preview release/viewer/babylon.viewer.max.js


+ 10 - 7
dist/preview release/what's new.md

@@ -6,15 +6,18 @@
 
 ### Core Engine
 
-- Add the choice of [forming a closed loop](http://doc.babylonjs.com/how_to/how_to_use_curve3#catmull-rom-spline) to the catamull-rom-spline curve3 ([johnk](https://github.com/babylonjsguide))
-- Add support for specifying the center of rotation to textures ([bghgary](http://www.github.com/bghgary))
-- Add webVR support for Oculus Go ([TrevorDev](https://github.com/TrevorDev))
-- Add ability to not generate polynomials harmonics upon prefiltered texture creation ([sebavan](http://www.github.com/sebavan))
-- Add predicate function to customize the list of mesh included in the computation of bounding vectors in the ```getHierarchyBoundingVectors``` method ([sebavan](http://www.github.com/sebavan))
+- Added new `Animatable.waitAsync` function to use Promises with animations. Demo [Here](https://www.babylonjs-playground.com/#HZBCXR) ([Deltakosh](https://github.com/deltakosh)) 
+- Added the choice of [forming a closed loop](http://doc.babylonjs.com/how_to/how_to_use_curve3#catmull-rom-spline) to the catamull-rom-spline curve3 ([johnk](https://github.com/babylonjsguide))
+- Added support for specifying the center of rotation to textures ([bghgary](http://www.github.com/bghgary))
+- Added webVR support for Oculus Go ([TrevorDev](https://github.com/TrevorDev))
+- Added ability to not generate polynomials harmonics upon prefiltered texture creation ([sebavan](http://www.github.com/sebavan))
+- Added predicate function to customize the list of mesh included in the computation of bounding vectors in the ```getHierarchyBoundingVectors``` method ([sebavan](http://www.github.com/sebavan))
+- Added webVR constructor options: disable laser pointer toggle, teleportation floor meshes ([TrevorDev](https://github.com/TrevorDev))
+
 
 ### glTF Loader
 
-- Add support for KHR_texture_transform ([bghgary](http://www.github.com/bghgary))
+- Added support for KHR_texture_transform ([bghgary](http://www.github.com/bghgary))
 
 ### Viewer
 
@@ -26,7 +29,7 @@
 
 ### Core Engine
 
-- Fix ```shadowEnabled``` property on lights. Shadows are not visble anymore when disabled ([sebavan](http://www.github.com/sebavan))
+- Fixed ```shadowEnabled``` property on lights. Shadows are not visble anymore when disabled ([sebavan](http://www.github.com/sebavan))
 - Physics `unregisterOnPhysicsCollide` didn't remove callback correctly [#4291](https://github.com/BabylonJS/Babylon.js/issues/4291) ([RaananW](https://github.com/RaananW))
 - Added missing getter and setter for global exposure in ColorCurves ([RaananW](https://github.com/RaananW))
 - Fixed an issue with view matrix when `ArcRotateCamera` was used with collisions ([Deltakosh](https://github.com/deltakosh)) 

+ 32 - 13
src/Animations/babylon.animatable.ts

@@ -12,6 +12,11 @@
         public animationStarted = false;
 
         /**
+         * Observer raised when the animation ends
+         */
+        public onAnimationEndObservable = new Observable<Animatable>();
+
+        /**
          * Gets the root Animatable used to synchronize and normalize animations
          */
         public get syncRoot(): Animatable {
@@ -190,10 +195,16 @@
             this._paused = false;
         }
 
-        public stop(animationName?: string): void {
+        private _raiseOnAnimationEnd() {            
+            if (this.onAnimationEnd) {
+                this.onAnimationEnd();
+            }
 
-            if (animationName) {
+            this.onAnimationEndObservable.notifyObservers(this);
+        }
 
+        public stop(animationName?: string): void {
+            if (animationName) {
                 var idx = this._scene._activeAnimatables.indexOf(this);
 
                 if (idx > -1) {
@@ -211,10 +222,7 @@
 
                     if (runtimeAnimations.length == 0) {
                         this._scene._activeAnimatables.splice(idx, 1);
-
-                        if (this.onAnimationEnd) {
-                            this.onAnimationEnd();
-                        }
+                        this._raiseOnAnimationEnd();
                     }
                 }
 
@@ -230,14 +238,24 @@
                         runtimeAnimations[index].dispose();
                     }
 
-                    if (this.onAnimationEnd) {
-                        this.onAnimationEnd();
-                    }
+                    this._raiseOnAnimationEnd();
                 }
-
             }
         }
 
+        /**
+         * Wait asynchronously for the animation to end
+         * @returns a promise which will be fullfilled when the animation ends
+         */
+        public waitAsync(): Promise<Animatable> {
+            return new Promise((resolve, reject) => {
+                this.onAnimationEndObservable.add(() => {
+                    resolve(this);
+                }, undefined, undefined, this, true);
+            });
+        }
+
+        /** @hidden */
         public _animate(delay: number): boolean {
             if (this._paused) {
                 this.animationStarted = false;
@@ -283,9 +301,10 @@
                 }
             }
 
-            if (!running && this.onAnimationEnd) {
-                this.onAnimationEnd();
-                this.onAnimationEnd = null;
+            if (!running) {
+                this._raiseOnAnimationEnd();
+                this.onAnimationEnd = null
+                this.onAnimationEndObservable.clear();
             }
 
             return running;

+ 8 - 3
src/Helpers/babylon.particleHelper.ts

@@ -23,7 +23,7 @@ module BABYLON {
         /**
          * Base Assets URL.
          */
-        private static _baseAssetsUrl = "https://assets.babylonjs.com/particles/";
+        private static _baseAssetsUrl = "https://assets.babylonjs.com/particles";
 
         private static _scene: Scene;
 
@@ -38,6 +38,11 @@ module BABYLON {
          * @returns the ParticleSystem created.
          */
         public static Create(type: string, emitter: AbstractMesh, scene: Nullable<Scene> = Engine.LastCreatedScene, gpu: boolean = false): ParticleSystem {
+            
+            Tools.LoadFile(`${this._baseAssetsUrl}/fire.json`, (data, response) => {
+                console.log(data, response);
+            });
+            
             const typeParsed = this._parseType(type);
             if (typeParsed === ParticleSystemType.None) {
                 throw new Error("This particle system type doesn't exist.");
@@ -80,7 +85,7 @@ module BABYLON {
             // Create a particle system
             const fireSystem = new ParticleSystem("particles", 2000, this._scene);
             // Texture of each particle
-            fireSystem.particleTexture = new Texture(`${this._baseAssetsUrl}textures/flare.png`, this._scene);
+            fireSystem.particleTexture = new Texture(`${this._baseAssetsUrl}/textures/flare.png`, this._scene);
             // Where the particles come from
             fireSystem.emitter = this._emitter; // the starting object, the emitter
             fireSystem.minEmitBox = new Vector3(-0.5, 1, -0.5); // Starting all from
@@ -126,7 +131,7 @@ module BABYLON {
 
         private static _createSmoke(): ParticleSystem {
             const smokeSystem = new ParticleSystem("smoke", 1000, this._scene);
-            smokeSystem.particleTexture = new Texture(`${this._baseAssetsUrl}textures/flare.png`, this._scene);
+            smokeSystem.particleTexture = new Texture(`${this._baseAssetsUrl}/textures/flare.png`, this._scene);
             smokeSystem.emitter = this._emitter;
             smokeSystem.minEmitBox = new Vector3(-0.5, 1, -0.5);
             smokeSystem.maxEmitBox = new Vector3(0.5, 1, 0.5);

+ 1 - 1
src/Particles/EmitterTypes/babylon.coneParticleEmitter.ts

@@ -111,7 +111,7 @@ module BABYLON {
          */        
         public applyToShader(effect: Effect): void {
             effect.setFloat("radius", this.radius);
-            effect.setFloat("angle", this.angle);
+            effect.setFloat("coneAngle", this.angle);
             effect.setFloat("height", this._height);
             effect.setFloat("directionRandomizer", this.directionRandomizer);
         }

+ 28 - 7
src/Particles/babylon.gpuParticleSystem.ts

@@ -57,7 +57,7 @@
 
         private _randomTexture: RawTexture;
 
-        private readonly _attributesStrideSize = 14;
+        private readonly _attributesStrideSize = 16;
         private _updateEffectOptions: EffectCreationOptions;
 
         private _randomTextureSize: number;
@@ -155,6 +155,15 @@
         public maxEmitPower = 1;        
 
         /**
+         * Minimum angular speed of emitting particles (Z-axis rotation for each particle).
+         */
+        public minAngularSpeed = 0;
+        /**
+         * Maximum angular speed of emitting particles (Z-axis rotation for each particle).
+         */
+        public maxAngularSpeed = 0;
+
+        /**
          * The particle emitter type defines the emitter used by the particle system.
          * It can be for example box, sphere, or cone...
          */
@@ -346,9 +355,10 @@
             this._scene.particleSystems.push(this);
 
             this._updateEffectOptions = {
-                attributes: ["position", "age", "life", "seed", "size", "color", "direction"],
+                attributes: ["position", "age", "life", "seed", "size", "color", "direction", "angle"],
                 uniformsNames: ["currentCount", "timeDelta", "generalRandoms", "emitterWM", "lifeTime", "color1", "color2", "sizeRange", "gravity", "emitPower",
-                                "direction1", "direction2", "minEmitBox", "maxEmitBox", "radius", "directionRandomizer", "height", "angle", "stopFactor"],
+                                "direction1", "direction2", "minEmitBox", "maxEmitBox", "radius", "directionRandomizer", "height", "coneAngle", "stopFactor", 
+                                "angleRange"],
                 uniformBuffersNames: [],
                 samplers:["randomSampler"],
                 defines: "",
@@ -357,7 +367,7 @@
                 onError: null,
                 indexParameters: null,
                 maxSimultaneousLights: 0,                                                      
-                transformFeedbackVaryings: ["outPosition", "outAge", "outLife", "outSeed", "outSize", "outColor", "outDirection"]
+                transformFeedbackVaryings: ["outPosition", "outAge", "outLife", "outSeed", "outSize", "outColor", "outDirection", "outAngle"]
             };
 
             // Random data
@@ -386,6 +396,7 @@
             updateVertexBuffers["size"] = source.createVertexBuffer("size", 6, 1);
             updateVertexBuffers["color"] = source.createVertexBuffer("color", 7, 4);
             updateVertexBuffers["direction"] = source.createVertexBuffer("direction", 11, 3);
+            updateVertexBuffers["angle"] = source.createVertexBuffer("angle", 14, 2);
            
             let vao = this._engine.recordVertexArrayObject(updateVertexBuffers, null, this._updateEffect);
             this._engine.bindArrayBuffer(null);
@@ -400,6 +411,7 @@
             renderVertexBuffers["life"] = source.createVertexBuffer("life", 4, 1, this._attributesStrideSize, true);
             renderVertexBuffers["size"] = source.createVertexBuffer("size", 6, 1, this._attributesStrideSize, true);           
             renderVertexBuffers["color"] = source.createVertexBuffer("color", 7, 4, this._attributesStrideSize, true);
+            renderVertexBuffers["angle"] = source.createVertexBuffer("angle", 14, 2, this._attributesStrideSize, true);
 
             renderVertexBuffers["offset"] = spriteSource.createVertexBuffer("offset", 0, 2);
             renderVertexBuffers["uv"] = spriteSource.createVertexBuffer("uv", 2, 2);
@@ -442,7 +454,11 @@
               // direction
               data.push(0.0);
               data.push(0.0);
-              data.push(0.0);              
+              data.push(0.0);     
+              
+              // angle
+              data.push(0.0);  
+              data.push(0.0); 
             }
 
             // Sprite data
@@ -494,7 +510,7 @@
             }
 
             this._renderEffect = new Effect("gpuRenderParticles", 
-                                            ["position", "age", "life", "size", "color", "offset", "uv"], 
+                                            ["position", "age", "life", "size", "color", "offset", "uv", "angle"], 
                                             ["view", "projection", "colorDead", "invView", "vClipPlane"], 
                                             ["textureSampler"], this._scene.getEngine(), defines);
         }        
@@ -555,6 +571,7 @@
             this._updateEffect.setDirectColor4("color1", this.color1);
             this._updateEffect.setDirectColor4("color2", this.color2);
             this._updateEffect.setFloat2("sizeRange", this.minSize, this.maxSize);
+            this._updateEffect.setFloat2("angleRange", this.minAngularSpeed, this.maxAngularSpeed);
             this._updateEffect.setVector3("gravity", this.gravity);
 
             if (this.particleEmitterType) {
@@ -757,7 +774,9 @@
             serializationObject.minEmitPower = this.minEmitPower;
             serializationObject.maxEmitPower = this.maxEmitPower;
             serializationObject.minLifeTime = this.minLifeTime;
-            serializationObject.maxLifeTime = this.maxLifeTime;
+            serializationObject.maxLifeTime = this.maxLifeTime;            
+            serializationObject.minAngularSpeed = this.minAngularSpeed;
+            serializationObject.maxAngularSpeed = this.maxAngularSpeed;
             serializationObject.emitRate = this.emitRate;
             serializationObject.gravity = this.gravity.asArray();
             serializationObject.color1 = this.color1.asArray();
@@ -817,6 +836,8 @@
             particleSystem.maxSize = parsedParticleSystem.maxSize;
             particleSystem.minLifeTime = parsedParticleSystem.minLifeTime;
             particleSystem.maxLifeTime = parsedParticleSystem.maxLifeTime;
+            particleSystem.minAngularSpeed = parsedParticleSystem.minAngularSpeed;
+            particleSystem.maxAngularSpeed = parsedParticleSystem.maxAngularSpeed;
             particleSystem.minEmitPower = parsedParticleSystem.minEmitPower;
             particleSystem.maxEmitPower = parsedParticleSystem.maxEmitPower;
             particleSystem.emitRate = parsedParticleSystem.emitRate;

+ 11 - 1
src/Shaders/gpuRenderParticles.vertex.fx

@@ -12,6 +12,7 @@ in float size;
 in vec4 color;
 in vec2 offset;
 in vec2 uv;
+in vec2 angle;
 
 out vec2 vUV;
 out vec4 vColor;
@@ -28,9 +29,18 @@ void main() {
   float ratio = age / life;
   vColor = color * vec4(1.0 - ratio) + colorDead * vec4(ratio);
 
+  vec2 cornerPos = offset * size;
+
+  // Rotate
+	vec4 rotatedCorner;
+	rotatedCorner.x = cornerPos.x * cos(angle.x) - cornerPos.y * sin(angle.x);
+	rotatedCorner.y = cornerPos.x * sin(angle.x) + cornerPos.y * cos(angle.x);
+	rotatedCorner.z = 0.;
+  rotatedCorner.w = 0.;
+
   // Expand position
   vec4 viewPosition = view * vec4(position, 1.0);
-  gl_Position = projection * (viewPosition + vec4(offset * size, 0., 0.));
+  gl_Position = projection * (viewPosition + rotatedCorner);
 
 	// Clip plane
 #ifdef CLIPPLANE

+ 11 - 2
src/Shaders/gpuUpdateParticles.vertex.fx

@@ -14,6 +14,7 @@ uniform vec4 color1;
 uniform vec4 color2;
 uniform vec3 gravity;
 uniform sampler2D randomSampler;
+uniform vec2 angleRange;
 
 #ifdef BOXEMITTER
 uniform vec3 direction1;
@@ -34,7 +35,7 @@ uniform float radius;
 
 #ifdef CONEEMITTER
 uniform float radius;
-uniform float angle;
+uniform float coneAngle;
 uniform float height;
 uniform float directionRandomizer;
 #endif
@@ -47,6 +48,7 @@ in float seed;
 in float size;
 in vec4 color;
 in vec3 direction;
+in vec2 angle;
 
 // Output
 out vec3 outPosition;
@@ -56,6 +58,7 @@ out float outSeed;
 out float outSize;
 out vec4 outColor;
 out vec3 outDirection;
+out vec2 outAngle;
 
 vec3 getRandomVec3(float offset) {
   return texture(randomSampler, vec2(float(gl_VertexID) * offset / currentCount, 0)).rgb;
@@ -76,6 +79,7 @@ void main() {
       outColor = vec4(0.,0.,0.,0.);
       outSize = 0.;
       outDirection = direction;
+      outAngle = angle;
       return;
     }
     vec3 position;
@@ -97,6 +101,10 @@ void main() {
     // Color
     outColor = color1 + (color2 - color1) * randoms.b;
 
+    // Angular speed
+    outAngle.y = angleRange.x + (angleRange.y - angleRange.x) * randoms.a;
+    outAngle.x = 0.;
+
     // Position / Direction (based on emitter type)
 #ifdef BOXEMITTER
     vec3 randoms2 = getRandomVec3(generalRandoms.y);
@@ -142,7 +150,7 @@ void main() {
     position = vec3(randX, randY, randZ); 
 
     // Direction
-    if (angle == 0.) {
+    if (coneAngle == 0.) {
         direction = vec3(0., 1.0, 0.);
     } else {
         vec3 randoms3 = getRandomVec3(generalRandoms.z);
@@ -169,5 +177,6 @@ void main() {
     outColor = color;
     outSize = size;
     outDirection = direction + gravity * timeDelta;
+    outAngle = vec2(angle.x + angle.y * timeDelta, angle.y);
   }
 }

+ 2 - 2
src/Shaders/particles.vertex.fx

@@ -21,12 +21,12 @@ varying float fClipDistance;
 
 void main(void) {	
 	vec3 viewPos = (view * vec4(position, 1.0)).xyz; 
-	vec3 cornerPos;
+	vec2 cornerPos;
 	float size = options.y;
 	float angle = options.x;
 	vec2 offset = options.zw;
 	
-	cornerPos = vec3(offset.x - 0.5, offset.y  - 0.5, 0.) * size;
+	cornerPos = vec2(offset.x - 0.5, offset.y  - 0.5) * size;
 
 	// Rotate
 	vec3 rotatedCorner;

+ 40 - 0
tests/unit/babylon/src/Helpers/ babylon.particleHelper.tests.ts

@@ -0,0 +1,40 @@
+/**
+ * Describes the test suite.
+ */
+describe('Babylon Particle Helper', function () {
+  let subject: BABYLON.Engine;
+
+  /**
+   * Loads the dependencies.
+   */
+  before(function (done) {
+      this.timeout(180000);
+      (BABYLONDEVTOOLS).Loader
+          .useDist()
+          .load(function () {
+              // Force apply promise polyfill for consistent behavior between PhantomJS, IE11, and other browsers.
+              BABYLON.PromisePolyfill.Apply(true);
+              done();
+          });
+  });
+
+  /**
+   * Create a new engine subject before each test.
+   */
+  beforeEach(function () {
+      subject = new BABYLON.NullEngine({
+          renderHeight: 256,
+          renderWidth: 256,
+          textureSize: 256,
+          deterministicLockstep: false,
+          lockstepMaxSteps: 1
+      });
+  });
+
+  describe('#JSON', () => {
+      it('creates a fire particle system', () => {
+          const scene = new BABYLON.Scene(subject);
+          //
+      });
+  });
+});