瀏覽代碼

Merge pull request #4288 from yovanoc/particle-helper

Particle helper
David Catuhe 7 年之前
父節點
當前提交
804dfd6865

文件差異過大導致無法顯示
+ 4214 - 2427
Playground/babylon.d.txt


+ 9 - 0
Tools/Gulp/config.json

@@ -111,6 +111,7 @@
             "instrumentation",
             "backgroundMaterial",
             "environmentHelper",
+            "particleHelper",
             "videoDome"
         ],
         "minimal": [
@@ -1170,6 +1171,14 @@
                 "additionalTextures"
             ]
         },
+        "particleHelper": {
+            "files": [
+                "../../src/Helpers/babylon.particleHelper.js"
+            ],
+            "dependUpon": [
+                "particles"
+            ]
+        },
         "videoDome": {
             "files": [
                 "../../src/Helpers/babylon.videoDome.js"

+ 25 - 0
assets/particles/systems/fire.json

@@ -0,0 +1,25 @@
+{
+  "type": "fire",
+  "emitterType": "box",
+  "capacity": 2000,
+  "textureFile": "flare.png",
+  "minEmitBox": { "x": -0.5, "y": 1, "z": -0.5 },
+  "maxEmitBox": { "x": 0.5, "y": 1, "z": 0.5 },
+  "color1": { "r": 1, "g": 0.5, "b": 0, "a": 1.0 },
+  "color2": { "r": 1, "g": 0.5, "b": 0, "a": 1.0 },
+  "colorDead": { "r": 0, "g": 0, "b": 0, "a": 0.0 },
+  "minSize": 0.3,
+  "maxSize": 1,
+  "minLifeTime": 0.2,
+  "maxLifeTime": 0.4,
+  "emitRate": 600,
+  "blendMode": 0,
+  "gravity": { "x": 0, "y": 0, "z": 0 },
+  "direction1": { "x": 0, "y": 4, "z": 0 },
+  "direction2": { "x": 0, "y": 4, "z": 0 },
+  "minAngularSpeed": 0,
+  "maxAngularSpeed": 3.141592653589793,
+  "minEmitPower": 1,
+  "maxEmitPower": 3,
+  "updateSpeed": 0.007
+}

+ 25 - 0
assets/particles/systems/smoke.json

@@ -0,0 +1,25 @@
+{
+  "type": "smoke",
+  "emitterType": "box",
+  "capacity": 1000,
+  "textureFile": "flare.png",
+  "minEmitBox": { "x": -0.5, "y": 1, "z": -0.5 },
+  "maxEmitBox": { "x": 0.5, "y": 1, "z": 0.5 },
+  "color1": { "r": 0.1, "g": 0.1, "b": 0.1, "a": 1.0 },
+  "color2": { "r": 0.1, "g": 0.1, "b": 0.1, "a": 1.0 },
+  "colorDead": { "r": 0, "g": 0, "b": 0, "a": 0.0 },
+  "minSize": 0.3,
+  "maxSize": 1,
+  "minLifeTime": 0.3,
+  "maxLifeTime": 1.5,
+  "emitRate": 350,
+  "blendMode": 0,
+  "gravity": { "x": 0, "y": 0, "z": 0 },
+  "direction1": { "x": -1.5, "y": 8, "z": -1.5 },
+  "direction2": { "x": 1.5, "y": 8, "z": 1.5 },
+  "minAngularSpeed": 0,
+  "maxAngularSpeed": 3.141592653589793,
+  "minEmitPower": 0.5,
+  "maxEmitPower": 1.5,
+  "updateSpeed": 0.005
+}

二進制
assets/particles/textures/flare.png


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

@@ -2,6 +2,8 @@
 
 ## Major updates
 
+- Added a ParticleHelper class to create some pre-configured particle systems in a one-liner method style ([DevChris](https://github.com/yovanoc))
+
 ## Updates
 
 ### Core Engine

+ 1 - 1
package.json

@@ -43,4 +43,4 @@
         "base64-font-loader": "0.0.4",
         "typescript": "^2.8.1"
     }
-}
+}

+ 237 - 0
src/Helpers/babylon.particleHelper.ts

@@ -0,0 +1,237 @@
+module BABYLON {
+    /**
+     * Represents all the data needed to create a ParticleSystem.
+     */
+    export interface IParticleSystemData {
+        /**
+         * ParticleSystem type
+         */
+        type: string;
+        /**
+         * Shape of the emitter
+         */
+        emitterType: string
+        /**
+         * Maximum number of particles in the system
+         */
+        capacity: number;
+        /**
+         * Link for the texture file
+         */
+        textureFile: string;
+        /**
+         * minEmitBox Vector3
+         */
+        minEmitBox?: { x: number, y: number, z: number };
+        /**
+         * maxEmitBox Vector3
+         */
+        maxEmitBox?: { x: number, y: number, z: number };
+        /**
+         * color1 Color4
+         */
+        color1: { r: number, g: number, b: number, a: number };
+        /**
+         * color2 Color4
+         */
+        color2: { r: number, g: number, b: number, a: number };
+        /**
+         * colorDead Color4
+         */
+        colorDead: { r: number, g: number, b: number, a: number };
+        /**
+         * Minimum size of each particle
+         */
+        minSize: number;
+        /**
+         * Maximum size of each particle
+         */
+        maxSize: number;
+        /**
+         * Minimum lifetime for each particle
+         */
+        minLifeTime: number;
+        /**
+         * Maximum lifetime for each particle
+         */
+        maxLifeTime: number;
+        /**
+         * Emit rate
+         */
+        emitRate: number;
+        /**
+         * Blend Mode
+         */
+        blendMode: number;
+        /**
+         * gravity Vector3
+         */
+        gravity: { x: number, y: number, z: number };
+        /**
+         * direction1 Vector3
+         */
+        direction1?: { x: number, y: number, z: number };
+        /**
+         * direction2 Vector3
+         */
+        direction2?: { x: number, y: number, z: number };
+        /**
+         * Minimum Angular Speed
+         */
+        minAngularSpeed: number;
+        /**
+         * Maximum Angular Speed
+         */
+        maxAngularSpeed: number;
+        /**
+         * Minimum Emit Power
+         */
+        minEmitPower: number;
+        /**
+         * Maximum Emit Power
+         */
+        maxEmitPower: number;
+        /**
+         * Update Speed
+         */
+        updateSpeed: number;
+        /**
+         * Radius
+         */
+        radius?: number;
+        /**
+         * Angle
+         */
+        angle?: number;
+    }
+    /**
+     * This class is made for on one-liner static method to help creating particle systems.
+     */
+    export class ParticleHelper {
+        /**
+         * Base Assets URL.
+         */
+        private static _baseAssetsUrl = "https://assets.babylonjs.com/particles";
+
+        private static _scene: Scene;
+
+        private static _emitter: AbstractMesh;
+
+        /**
+         * This is the main static method (one-liner) of this helper to create different particle systems.
+         * @param type This string represents the type to the particle system to create
+         * @param emitter The object where the particle system will start to emit from.
+         * @param scene The scene where the particle system should live.
+         * @param gpu If the system will use gpu.
+         * @returns the ParticleSystem created.
+         */
+        public static CreateAsync(type: string, emitter: AbstractMesh,
+                                   scene: Nullable<Scene> = Engine.LastCreatedScene, gpu: boolean = false): Promise<ParticleSystem> {
+            
+            return new Promise((resolve, reject) => {
+                if (scene) {
+                    this._scene = scene;
+                } else {
+                    return reject("A particle system need a scene.");
+                }
+
+                if (gpu && !GPUParticleSystem.IsSupported) {
+                    return reject("Particle system with GPU is not supported.");
+                }
+
+                this._emitter = emitter;
+
+                Tools.LoadFile(`${this._baseAssetsUrl}/systems/${type}.json`, (data, response) => {
+                    const newData = JSON.parse(data.toString()) as IParticleSystemData;
+                    return resolve(this._createSystem(newData));
+                }, undefined, undefined, undefined, (req, exception) => {
+                    return reject(`An error occured while the creation of your particle system. Check if your type '${type}' exists.`);
+                });
+
+            });
+        }
+
+        private static _createSystem(data: IParticleSystemData): ParticleSystem {
+            // Create a particle system
+            const system = new ParticleSystem(data.type, data.capacity, this._scene);
+            // Texture of each particle
+            system.particleTexture = new Texture(`${this._baseAssetsUrl}/textures/${data.textureFile}`, this._scene);
+            // Where the particles come from
+            system.emitter = this._emitter; // the starting object, the emitter
+
+            // Colors of all particles
+            system.color1 = new Color4(data.color1.r, data.color1.g, data.color1.b, data.color1.a);
+            system.color2 = new Color4(data.color2.r, data.color2.g, data.color2.b, data.color2.a);
+            system.colorDead = new Color4(data.colorDead.r, data.colorDead.g, data.colorDead.b, data.colorDead.a);
+
+            // Size of each particle (random between...
+            system.minSize = data.minSize;
+            system.maxSize = data.maxSize;
+
+            // Life time of each particle (random between...
+            system.minLifeTime = data.minLifeTime;
+            system.maxLifeTime = data.maxLifeTime;
+
+            // Emission rate
+            system.emitRate = data.emitRate;
+
+            // Blend mode : BLENDMODE_ONEONE, or BLENDMODE_STANDARD
+            system.blendMode = data.blendMode;
+
+            // Set the gravity of all particles
+            system.gravity = new Vector3(data.gravity.x, data.gravity.y, data.gravity.z);
+
+            // Angular speed, in radians
+            system.minAngularSpeed = data.minAngularSpeed;
+            system.maxAngularSpeed = data.maxAngularSpeed;
+
+            // Speed
+            system.minEmitPower = data.minEmitPower;
+            system.maxEmitPower = data.maxEmitPower;
+            system.updateSpeed = data.updateSpeed;
+
+            switch (data.emitterType) {
+                case "box":
+
+                    if (!data.direction1 || !data.direction2) {
+                        throw new Error("Directions are missing in this particle system.");
+                    }
+
+                    if (!data.minEmitBox || !data.maxEmitBox) {
+                        throw new Error("EmitBox is missing in this particle system.");
+                    }
+
+                    system.createBoxEmitter(
+                        new Vector3(data.direction1.x, data.direction1.y, data.direction1.z),
+                        new Vector3(data.direction2.x, data.direction2.y, data.direction2.z),
+                        new Vector3(data.minEmitBox.x, data.minEmitBox.y, data.minEmitBox.z),
+                        new Vector3(data.maxEmitBox.x, data.maxEmitBox.y, data.maxEmitBox.z)
+                    );
+                    break;
+                case "sphere":
+                    system.createSphereEmitter(data.radius);
+                    break;
+                case "directed_sphere":
+                    
+                    if (!data.direction1 || !data.direction2) {
+                        throw new Error("Directions are missing in this particle system.");
+                    }
+                    
+                    system.createDirectedSphereEmitter(
+                        data.radius,
+                        new Vector3(data.direction1.x, data.direction1.y, data.direction1.z),
+                        new Vector3(data.direction2.x, data.direction2.y, data.direction2.z)
+                    );
+                    break;
+                case "cone":
+                    system.createConeEmitter(data.radius, data.angle);
+                    break;
+                default:
+                    break;
+            }
+
+            return system;
+        }
+    }
+
+}

+ 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);
+          //
+      });
+  });
+});

+ 1 - 0
tests/unit/karma.conf.js

@@ -16,6 +16,7 @@ module.exports = function (config) {
             './tests/unit/babylon/babylon.example.tests.js',
             './tests/unit/babylon/serializers/babylon.glTFSerializer.tests.js',
             './tests/unit/babylon/src/babylon.node.tests.js',
+            './tests/unit/babylon/src/Helpers/babylon.particleHelper.tests.js',
             './tests/unit/babylon/src/Loading/babylon.sceneLoader.tests.js',
             './tests/unit/babylon/src/PostProcess/babylon.postProcess.tests.js',
             './tests/unit/babylon/src/Material/babylon.material.tests.js',

+ 1 - 1
tests/unit/package.json

@@ -4,7 +4,7 @@
   "description": "Unit Tests Suite For Babylon.js",
   "main": "",
   "repository": {
-      "url": "https://github.com/BabylonJS/Babylon.js/"
+    "url": "https://github.com/BabylonJS/Babylon.js/"
   },
   "readme": "https://github.com/BabylonJS/Babylon.js/edit/master/readme.md",
   "license": "(Apache-2.0)",