diff --git a/packages/dev/core/src/Particles/Node/nodeParticleSystemSet.helper.ts b/packages/dev/core/src/Particles/Node/nodeParticleSystemSet.helper.ts index f8389292c0d..9e7320efa13 100644 --- a/packages/dev/core/src/Particles/Node/nodeParticleSystemSet.helper.ts +++ b/packages/dev/core/src/Particles/Node/nodeParticleSystemSet.helper.ts @@ -29,6 +29,8 @@ import { ParticleMathBlock, ParticleMathBlockOperations } from "./Blocks/particl import { ParticleRandomBlock, ParticleRandomBlockLocks } from "./Blocks/particleRandomBlock"; import { ParticleTextureSourceBlock } from "./Blocks/particleSourceTextureBlock"; import { SystemBlock } from "./Blocks/systemBlock"; +import { ParticleVectorLengthBlock } from "./Blocks/particleVectorLengthBlock"; +import { ParticleConditionBlock, ParticleConditionBlockTests } from "./Blocks/Conditions/particleConditionBlock"; import { CreateParticleBlock } from "./Blocks/Emitters/createParticleBlock"; import { BoxShapeBlock } from "./Blocks/Emitters/boxShapeBlock"; import { ConeShapeBlock } from "./Blocks/Emitters/coneShapeBlock"; @@ -136,7 +138,7 @@ function _SystemBlockGroup(oldSystem: ParticleSystem, context: RuntimeConversion // ------------- CREATE PARTICLE FUNCTIONS ------------- // The creation of the different properties follows the order they are added to the CreationQueue in ThinParticleSystem: -// Lifetime, Emit Power, Size, Scale/StartSize, Angle, VelocityLimit, Color, Drag, Noise, ColorDead, Ramp, Sheet +// Lifetime, Emit Power, Size, Scale/StartSize, Angle, Color, Drag, Noise, ColorDead, Ramp, Sheet function _CreateParticleBlockGroup(oldSystem: ParticleSystem, context: RuntimeConversionContext): CreateParticleBlock { // Create particle block const createParticleBlock = new CreateParticleBlock("Create Particle"); @@ -457,11 +459,15 @@ function _UpdateParticleBlockGroup(inputParticle: NodeParticleConnectionPoint, o updateBlockGroupOutput = _UpdateParticleAngleBlockGroup(updateBlockGroupOutput, oldSystem, context); if (oldSystem._velocityGradients && oldSystem._velocityGradients.length > 0) { - context.scaledDirection = _UpdateParticleVelocityGradientBlockGroup(updateBlockGroupOutput, oldSystem._velocityGradients, context); + context.scaledDirection = _UpdateParticleVelocityGradientBlockGroup(oldSystem._velocityGradients, context); } updateBlockGroupOutput = _UpdateParticlePositionBlockGroup(updateBlockGroupOutput, oldSystem.isLocal, context); + if (oldSystem._limitVelocityGradients && oldSystem._limitVelocityGradients.length > 0 && oldSystem.limitVelocityDamping !== 0) { + updateBlockGroupOutput = _UpdateParticleVelocityLimitGradientBlockGroup(updateBlockGroupOutput, oldSystem._limitVelocityGradients, oldSystem.limitVelocityDamping, context); + } + if (oldSystem._sizeGradients && oldSystem._sizeGradients.length > 0) { updateBlockGroupOutput = _UpdateParticleSizeGradientBlockGroup(updateBlockGroupOutput, oldSystem._sizeGradients, context); } @@ -548,16 +554,11 @@ function _UpdateParticleAngleBlockGroup(inputParticle: NodeParticleConnectionPoi /** * Creates the group of blocks that represent the particle velocity update - * @param inputParticle The input particle to update - * @param velocityGradients The velocity gradients (if any) + * @param velocityGradients The velocity gradients * @param context The context of the current conversion * @returns The output of the group of blocks that represent the particle velocity update */ -function _UpdateParticleVelocityGradientBlockGroup( - inputParticle: NodeParticleConnectionPoint, - velocityGradients: Array, - context: RuntimeConversionContext -): NodeParticleConnectionPoint { +function _UpdateParticleVelocityGradientBlockGroup(velocityGradients: Array, context: RuntimeConversionContext): NodeParticleConnectionPoint { context.ageToLifeTimeRatioBlockGroupOutput = _CreateAgeToLifeTimeRatioBlockGroup(context); // Generate the gradient @@ -570,7 +571,7 @@ function _UpdateParticleVelocityGradientBlockGroup( _CreateAndConnectContextualSource("Direction Scale", NodeParticleContextualSources.DirectionScale, multiplyScaleByVelocity.right); // Update the particle direction scale - const multiplyDirection = new ParticleMathBlock("Multiply Direction"); + const multiplyDirection = new ParticleMathBlock("Scaled Direction"); multiplyDirection.operation = ParticleMathBlockOperations.Multiply; multiplyScaleByVelocity.output.connectTo(multiplyDirection.left); _CreateAndConnectContextualSource("Direction", NodeParticleContextualSources.Direction, multiplyDirection.right); @@ -580,6 +581,56 @@ function _UpdateParticleVelocityGradientBlockGroup( return multiplyDirection.output; } +/** + * Creates the group of blocks that represent the particle velocity limit update + * @param inputParticle The input particle to update + * @param velocityLimitGradients The velocity limit gradients + * @param limitVelocityDamping The limit velocity damping factor + * @param context The context of the current conversion + * @returns The output of the group of blocks that represent the particle velocity limit update + */ +function _UpdateParticleVelocityLimitGradientBlockGroup( + inputParticle: NodeParticleConnectionPoint, + velocityLimitGradients: Array, + limitVelocityDamping: number, + context: RuntimeConversionContext +): NodeParticleConnectionPoint { + context.ageToLifeTimeRatioBlockGroupOutput = _CreateAgeToLifeTimeRatioBlockGroup(context); + + // Calculate the current speed + const currentSpeedBlock = new ParticleVectorLengthBlock("Current Speed"); + _CreateAndConnectContextualSource("Direction", NodeParticleContextualSources.Direction, currentSpeedBlock.input); + + // Calculate the velocity limit from the gradient + const velocityLimitValueOutput = _CreateGradientBlockGroup( + context.ageToLifeTimeRatioBlockGroupOutput, + velocityLimitGradients, + ParticleRandomBlockLocks.OncePerParticle, + "Velocity Limit" + ); + + // Blocks that will calculate the new velocity if over the limit + const damped = new ParticleMathBlock("Damped Speed"); + damped.operation = ParticleMathBlockOperations.Multiply; + _CreateAndConnectContextualSource("Direction", NodeParticleContextualSources.Direction, damped.left); + _CreateAndConnectInput("Limit Velocity Damping", limitVelocityDamping, damped.right); + + // Compare current speed and limit + const compareSpeed = new ParticleConditionBlock("Compare Speed to Limit"); + compareSpeed.test = ParticleConditionBlockTests.GreaterThan; + currentSpeedBlock.output.connectTo(compareSpeed.left); + velocityLimitValueOutput.connectTo(compareSpeed.right); + damped.output.connectTo(compareSpeed.ifTrue); + _CreateAndConnectContextualSource("Direction", NodeParticleContextualSources.Direction, compareSpeed.ifFalse); + + // Update the direction based on the calculted value + const updateDirection = new UpdateDirectionBlock("Direction Update"); + inputParticle.connectTo(updateDirection.particle); + compareSpeed.output.connectTo(updateDirection.direction); + + return updateDirection.output; +} + /** * Creates the group of blocks that represent the particle position update * @param inputParticle The input particle to update