Browse Source

Added translationPivot for particles

David Catuhe 7 years ago
parent
commit
daab025ec9

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

@@ -62,7 +62,7 @@ module BABYLON {
          * @param particle is the particle we are computed the direction for
          * @param particle is the particle we are computed the direction for
          */
          */
         public startDirectionFunction(worldMatrix: Matrix, directionToUpdate: Vector3, particle: Particle): void {
         public startDirectionFunction(worldMatrix: Matrix, directionToUpdate: Vector3, particle: Particle): void {
-            if (this._angle === 0) {
+            if (Math.abs(Math.cos(this._angle)) === 1.0) {
                 Vector3.TransformNormalFromFloatsToRef(0, 1.0, 0, worldMatrix, directionToUpdate);
                 Vector3.TransformNormalFromFloatsToRef(0, 1.0, 0, worldMatrix, directionToUpdate);
             }
             }
             else {
             else {
@@ -88,7 +88,7 @@ module BABYLON {
          */
          */
         startPositionFunction(worldMatrix: Matrix, positionToUpdate: Vector3, particle: Particle): void {
         startPositionFunction(worldMatrix: Matrix, positionToUpdate: Vector3, particle: Particle): void {
             var s = Scalar.RandomRange(0, Math.PI * 2);
             var s = Scalar.RandomRange(0, Math.PI * 2);
-            var h = Scalar.RandomRange(0, 1);
+            var h = Scalar.RandomRange(0, 1.0);
             // Better distribution in a cone at normal angles.
             // Better distribution in a cone at normal angles.
             h = 1 - h * h;
             h = 1 - h * h;
             var radius = Scalar.RandomRange(0, this._radius);
             var radius = Scalar.RandomRange(0, this._radius);

+ 4 - 1
src/Particles/babylon.IParticleSystem.ts

@@ -171,7 +171,10 @@ module BABYLON {
         /**
         /**
          * If using a spritesheet (isAnimationSheetEnabled), defines the sprite cell height to use
          * If using a spritesheet (isAnimationSheetEnabled), defines the sprite cell height to use
          */
          */
-        spriteCellHeight: number;        
+        spriteCellHeight: number;           
+
+        /** Gets or sets a Vector2 used to move the pivot (by default (0,0)) */
+        translationPivot: Vector2;
 
 
         /**
         /**
          * Gets the maximum number of particles active at the same time.
          * Gets the maximum number of particles active at the same time.

+ 5 - 1
src/Particles/babylon.gpuParticleSystem.ts

@@ -323,6 +323,9 @@
          * If using a spritesheet (isAnimationSheetEnabled), defines the sprite cell height to use
          * If using a spritesheet (isAnimationSheetEnabled), defines the sprite cell height to use
          */
          */
         public spriteCellHeight = 0;
         public spriteCellHeight = 0;
+
+        /** Gets or sets a Vector2 used to move the pivot (by default (0,0)) */
+        public translationPivot = new Vector2(0, 0);        
                 
                 
         private _isAnimationSheetEnabled: boolean;
         private _isAnimationSheetEnabled: boolean;
 
 
@@ -889,7 +892,7 @@
 
 
             this._renderEffect = new Effect("gpuRenderParticles", 
             this._renderEffect = new Effect("gpuRenderParticles", 
                                             ["position", "age", "life", "size", "color", "offset", "uv", "initialDirection", "angle", "cellIndex"], 
                                             ["position", "age", "life", "size", "color", "offset", "uv", "initialDirection", "angle", "cellIndex"], 
-                                            ["view", "projection", "colorDead", "invView", "vClipPlane", "sheetInfos"], 
+                                            ["view", "projection", "colorDead", "invView", "vClipPlane", "sheetInfos", "translationPivot"], 
                                             ["textureSampler", "colorGradientSampler"], this._scene.getEngine(), defines);
                                             ["textureSampler", "colorGradientSampler"], this._scene.getEngine(), defines);
         }        
         }        
 
 
@@ -1064,6 +1067,7 @@
                 this._renderEffect.setMatrix("view", viewMatrix);
                 this._renderEffect.setMatrix("view", viewMatrix);
                 this._renderEffect.setMatrix("projection", this._scene.getProjectionMatrix());
                 this._renderEffect.setMatrix("projection", this._scene.getProjectionMatrix());
                 this._renderEffect.setTexture("textureSampler", this.particleTexture);
                 this._renderEffect.setTexture("textureSampler", this.particleTexture);
+                this._renderEffect.setVector2("translationPivot", this.translationPivot);
                 if (this._colorGradientsTexture) {
                 if (this._colorGradientsTexture) {
                     this._renderEffect.setTexture("colorGradientSampler", this._colorGradientsTexture);
                     this._renderEffect.setTexture("colorGradientSampler", this._colorGradientsTexture);
                 } else {
                 } else {

+ 1 - 1
src/Particles/babylon.particle.ts

@@ -106,7 +106,7 @@
          */
          */
         public updateCellIndex(): void {
         public updateCellIndex(): void {
             let dist = (this._initialEndSpriteCellID - this._initialStartSpriteCellID);
             let dist = (this._initialEndSpriteCellID - this._initialStartSpriteCellID);
-            let ratio = Scalar.Clamp(((this.age * this.particleSystem.spriteCellChangeSpeed) / this.lifeTime) % this.lifeTime);
+            let ratio = Scalar.Clamp(((this.age * this.particleSystem.spriteCellChangeSpeed) % this.lifeTime) / this.lifeTime);
 
 
             this.cellIndex = this._initialStartSpriteCellID + (ratio * dist) | 0;
             this.cellIndex = this._initialStartSpriteCellID + (ratio * dist) | 0;
         }
         }

+ 5 - 1
src/Particles/babylon.particleSystem.ts

@@ -349,6 +349,9 @@
         /** Gets or sets a value indicating the time step multiplier to use in pre-warm mode (default is 1) */
         /** Gets or sets a value indicating the time step multiplier to use in pre-warm mode (default is 1) */
         public preWarmStepOffset = 1;
         public preWarmStepOffset = 1;
 
 
+        /** Gets or sets a Vector2 used to move the pivot (by default (0,0)) */
+        public translationPivot = new Vector2(0, 0);
+
         /**
         /**
         * An event triggered when the system is disposed
         * An event triggered when the system is disposed
         */
         */
@@ -1081,7 +1084,7 @@
         }
         }
 
 
         public static _GetEffectCreationOptions(isAnimationSheetEnabled = false): string[] {
         public static _GetEffectCreationOptions(isAnimationSheetEnabled = false): string[] {
-            var effectCreationOption = ["invView", "view", "projection", "vClipPlane", "textureMask"];
+            var effectCreationOption = ["invView", "view", "projection", "vClipPlane", "textureMask", "translationPivot"];
 
 
             if (isAnimationSheetEnabled) {
             if (isAnimationSheetEnabled) {
                 effectCreationOption.push("particlesInfos")
                 effectCreationOption.push("particlesInfos")
@@ -1272,6 +1275,7 @@
                 effect.setFloat3("particlesInfos", this.spriteCellWidth / baseSize.width, this.spriteCellHeight / baseSize.height, baseSize.width / this.spriteCellWidth);
                 effect.setFloat3("particlesInfos", this.spriteCellWidth / baseSize.width, this.spriteCellHeight / baseSize.height, baseSize.width / this.spriteCellWidth);
             }
             }
 
 
+            effect.setVector2("translationPivot", this.translationPivot);
             effect.setFloat4("textureMask", this.textureMask.r, this.textureMask.g, this.textureMask.b, this.textureMask.a);
             effect.setFloat4("textureMask", this.textureMask.r, this.textureMask.g, this.textureMask.b, this.textureMask.a);
 
 
             if (this._scene.clipPlane) {
             if (this._scene.clipPlane) {

+ 16 - 14
src/Particles/babylon.particleSystemSet.ts

@@ -12,7 +12,7 @@ module BABYLON {
      */
      */
     export class ParticleSystemSet implements IDisposable {
     export class ParticleSystemSet implements IDisposable {
         private _emitterCreationOptions: ParticleSystemSetEmitterCreationOptions;
         private _emitterCreationOptions: ParticleSystemSetEmitterCreationOptions;
-        private _emitterMesh: Nullable<Mesh>;
+        private _emitterNode: Nullable<TransformNode>;
 
 
         /**
         /**
          * Gets the particle system list
          * Gets the particle system list
@@ -20,10 +20,10 @@ module BABYLON {
         public systems = new Array<IParticleSystem>();
         public systems = new Array<IParticleSystem>();
 
 
         /**
         /**
-         * Gets the emitter mesh used with this set
+         * Gets the emitter node used with this set
          */
          */
-        public get emitterMesh(): Nullable<Mesh> {
-            return this._emitterMesh;
+        public get emitterNode(): Nullable<TransformNode> {
+            return this._emitterNode;
         }
         }
 
 
         /**
         /**
@@ -33,8 +33,8 @@ module BABYLON {
          * @param scene defines the hosting scene
          * @param scene defines the hosting scene
          */
          */
         public setEmitterAsSphere(options: {diameter: number, segments: number, color: Color3} , renderingGroupId: number, scene: Scene) {
         public setEmitterAsSphere(options: {diameter: number, segments: number, color: Color3} , renderingGroupId: number, scene: Scene) {
-            if (this._emitterMesh) {
-                this._emitterMesh.dispose();
+            if (this._emitterNode) {
+                this._emitterNode.dispose();
             }
             }
 
 
             this._emitterCreationOptions = {
             this._emitterCreationOptions = {
@@ -43,16 +43,18 @@ module BABYLON {
                 renderingGroupId: renderingGroupId
                 renderingGroupId: renderingGroupId
             }
             }
 
 
-            this._emitterMesh = MeshBuilder.CreateSphere("emitterSphere", {diameter: options.diameter, segments: options.segments}, scene);
-            this._emitterMesh.renderingGroupId = renderingGroupId;
+            let emitterMesh = MeshBuilder.CreateSphere("emitterSphere", {diameter: options.diameter, segments: options.segments}, scene);
+            emitterMesh.renderingGroupId = renderingGroupId;
 
 
             var material = new BABYLON.StandardMaterial("emitterSphereMaterial", scene)
             var material = new BABYLON.StandardMaterial("emitterSphereMaterial", scene)
             material.emissiveColor = options.color;    
             material.emissiveColor = options.color;    
-            this._emitterMesh.material = material;     
+            emitterMesh.material = material;     
             
             
             for (var system of this.systems) {
             for (var system of this.systems) {
-                system.emitter = this._emitterMesh;
+                system.emitter = emitterMesh;
             }
             }
+
+            this._emitterNode = emitterMesh;
         }
         }
 
 
         /**
         /**
@@ -78,9 +80,9 @@ module BABYLON {
 
 
             this.systems = [];
             this.systems = [];
 
 
-            if (this._emitterMesh) {
-                this._emitterMesh.dispose();
-                this._emitterMesh = null;
+            if (this._emitterNode) {
+                this._emitterNode.dispose();
+                this._emitterNode = null;
             }
             }
         }
         }
 
 
@@ -96,7 +98,7 @@ module BABYLON {
                 result.systems.push(system.serialize());
                 result.systems.push(system.serialize());
             }
             }
 
 
-            if (this._emitterMesh) {
+            if (this._emitterNode) {
                 result.emitter = this._emitterCreationOptions;
                 result.emitter = this._emitterCreationOptions;
             }
             }
 
 

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

@@ -3,6 +3,7 @@
 
 
 uniform mat4 view;
 uniform mat4 view;
 uniform mat4 projection;
 uniform mat4 projection;
+uniform vec2 translationPivot;
 
 
 // Particles state
 // Particles state
 in vec3 position;
 in vec3 position;
@@ -58,8 +59,7 @@ void main() {
 	vColor = color * vec4(1.0 - ratio) + colorDead * vec4(ratio);
 	vColor = color * vec4(1.0 - ratio) + colorDead * vec4(ratio);
 #endif
 #endif
   
   
-
-  vec2 cornerPos = offset * size.yz * size.x;
+  vec2 cornerPos = (offset - translationPivot) * size.yz * size.x + translationPivot;
 
 
 #ifdef BILLBOARD
 #ifdef BILLBOARD
   // Rotate
   // Rotate

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

@@ -132,7 +132,11 @@ void main() {
     outSeed = seed;
     outSeed = seed;
 
 
     // Size
     // Size
+#ifdef SIZEGRADIENTS    
     outSize.x = texture(sizeGradientSampler, vec2(0, 0)).r;
     outSize.x = texture(sizeGradientSampler, vec2(0, 0)).r;
+#else
+    outSize.x = sizeRange.x + (sizeRange.y - sizeRange.x) * randoms.g;
+#endif
     outSize.y = scaleRange.x + (scaleRange.y - scaleRange.x) * randoms.b;
     outSize.y = scaleRange.x + (scaleRange.y - scaleRange.x) * randoms.b;
     outSize.z = scaleRange.z + (scaleRange.w - scaleRange.z) * randoms.a; 
     outSize.z = scaleRange.z + (scaleRange.w - scaleRange.z) * randoms.a; 
 
 
@@ -190,7 +194,7 @@ void main() {
     position = vec3(randX, randY, randZ); 
     position = vec3(randX, randY, randZ); 
 
 
     // Direction
     // Direction
-    if (coneAngle == 0.) {
+    if (abs(cos(coneAngle)) == 1.0) {
         direction = vec3(0., 1.0, 0.);
         direction = vec3(0., 1.0, 0.);
     } else {
     } else {
         vec3 randoms3 = getRandomVec3(seed.z);
         vec3 randoms3 = getRandomVec3(seed.z);
@@ -239,7 +243,7 @@ void main() {
     outAngle = vec2(angle.x + angle.y * timeDelta, angle.y);
     outAngle = vec2(angle.x + angle.y * timeDelta, angle.y);
 #ifdef ANIMATESHEET      
 #ifdef ANIMATESHEET      
     float dist = cellInfos.y - cellInfos.x;
     float dist = cellInfos.y - cellInfos.x;
-    float ratio = clamp(mod(((outAge * cellInfos.z) / life), life), 0., 1.0);
+    float ratio = clamp(mod(outAge * cellInfos.z, life) / life, 0., 1.0);
 
 
     outCellIndex = float(int(cellInfos.x + ratio * dist));
     outCellIndex = float(int(cellInfos.x + ratio * dist));
 #endif
 #endif

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

@@ -14,6 +14,7 @@ attribute vec2 offset;
 // Uniforms
 // Uniforms
 uniform mat4 view;
 uniform mat4 view;
 uniform mat4 projection;
 uniform mat4 projection;
+uniform vec2 translationPivot;
 
 
 #ifdef ANIMATESHEET	
 #ifdef ANIMATESHEET	
 uniform vec3 particlesInfos; // x (number of rows) y(number of columns) z(rowSize)
 uniform vec3 particlesInfos; // x (number of rows) y(number of columns) z(rowSize)
@@ -32,7 +33,7 @@ varying float fClipDistance;
 void main(void) {	
 void main(void) {	
 	vec2 cornerPos;
 	vec2 cornerPos;
 	
 	
-	cornerPos = vec2(offset.x - 0.5, offset.y  - 0.5) * size;
+	cornerPos = (vec2(offset.x - 0.5, offset.y  - 0.5) - translationPivot) * size + translationPivot;
 
 
 #ifdef BILLBOARD	
 #ifdef BILLBOARD	
 	// Rotate
 	// Rotate