public override void PrepareFromPool(ParticlePool pool) { if (pool == null) { FieldAccessor = ParticleFieldAccessor <ParticleCollisionAttribute> .Invalid(); return; } FieldAccessor = pool.GetField(ParticleFields.CollisionControl); }
/// <summary> /// Gets a field accessor to the parent emitter's spawn control field, if it exists /// </summary> /// <returns></returns> protected ParticleFieldAccessor <ParticleChildrenAttribute> GetSpawnControlField() { var groupIndex = (int)parentControlFlag; if (groupIndex >= ParticleFields.ChildrenFlags.Length) { return(ParticleFieldAccessor <ParticleChildrenAttribute> .Invalid()); } return(Parent?.Pool?.GetField(ParticleFields.ChildrenFlags[groupIndex]) ?? ParticleFieldAccessor <ParticleChildrenAttribute> .Invalid()); }
public override void PrepareFromPool(ParticlePool pool) { if (pool == null) { FieldAccessor = ParticleFieldAccessor <float> .Invalid(); return; } FieldAccessor = pool.GetField(ParticleFields.RemainingLife); }
public override void PrepareFromPool(ParticlePool pool) { limitsAreInOrder = (LifetimeLowerLimit <= LifetimeUpperLimit); if (pool == null) { FieldAccessor = ParticleFieldAccessor <float> .Invalid(); return; } FieldAccessor = pool.GetField(ParticleFields.RemainingLife); }
public override void PrepareFromPool(ParticlePool pool) { if (pool == null) { FieldAccessor = ParticleFieldAccessor <Vector3> .Invalid(); SecondFieldAccessor = ParticleFieldAccessor <Vector3> .Invalid(); return; } FieldAccessor = pool.GetField(ParticleFields.Position); SecondFieldAccessor = pool.GetField(ParticleFields.OldPosition); }
/// <inheritdoc /> public unsafe override void Initialize(ParticlePool pool, int startIdx, int endIdx, int maxCapacity) { if (!pool.FieldExists(ParticleFields.Position) || !pool.FieldExists(ParticleFields.RandomSeed)) { return; } // Collect the total number of living particles in the parent pool which have a Position field var parentPool = Parent?.Pool; var parentParticlesCount = parentPool?.LivingParticles ?? 0; var posFieldParent = parentPool?.GetField(ParticleFields.Position) ?? ParticleFieldAccessor <Vector3> .Invalid(); if (!posFieldParent.IsValid()) { parentParticlesCount = 0; } var oldPosFieldParent = parentPool?.GetField(ParticleFields.OldPosition) ?? ParticleFieldAccessor <Vector3> .Invalid(); var spawnControlField = GetSpawnControlField(); var posField = pool.GetField(ParticleFields.Position); var rndField = pool.GetField(ParticleFields.RandomSeed); var oldField = pool.GetField(ParticleFields.OldPosition); var leftCorner = PositionMin * WorldScale; var xAxis = new Vector3(PositionMax.X * WorldScale.X - leftCorner.X, 0, 0); var yAxis = new Vector3(0, PositionMax.Y * WorldScale.Y - leftCorner.Y, 0); var zAxis = new Vector3(0, 0, PositionMax.Z * WorldScale.Z - leftCorner.Z); if (!WorldRotation.IsIdentity) { WorldRotation.Rotate(ref leftCorner); WorldRotation.Rotate(ref xAxis); WorldRotation.Rotate(ref yAxis); WorldRotation.Rotate(ref zAxis); } // Already inheriting from parent if (parentParticlesCount == 0) { leftCorner += WorldPosition; } var sequentialParentIndex = 0; var sequentialParentParticles = 0; var parentIndex = 0; // Interpolation - if parent particle has OldPosition field var stepF = 0f; var stepTotal = 0f; var positionDistance = new Vector3(0, 0, 0); var i = startIdx; while (i != endIdx) { var particle = pool.FromIndex(i); var randSeed = particle.Get(rndField); var particleRandPos = leftCorner; particleRandPos += xAxis * randSeed.GetFloat(RandomOffset.Offset3A + SeedOffset); particleRandPos += yAxis * randSeed.GetFloat(RandomOffset.Offset3B + SeedOffset); particleRandPos += zAxis * randSeed.GetFloat(RandomOffset.Offset3C + SeedOffset); if (parentParticlesCount > 0) { var parentParticlePosition = new Vector3(0, 0, 0); // Spawn is fixed - parent particles have spawned a very specific number of children each if (spawnControlField.IsValid()) { // Interpolation - if parent particle has OldPosition field while (sequentialParentParticles == 0) { // Early out - no more fixed number children. Rest of the particles (if any) are skipped intentionally if (sequentialParentIndex >= parentParticlesCount) { return; } parentIndex = sequentialParentIndex; var tempParentParticle = parentPool.FromIndex(parentIndex); sequentialParentIndex++; var childrenAttribute = (*((ParticleChildrenAttribute *)tempParentParticle[spawnControlField])); sequentialParentParticles = (int)childrenAttribute.ParticlesToEmit; if (oldPosFieldParent.IsValid()) { stepF = (sequentialParentParticles > 0) ? (1f / (float)sequentialParentParticles) : 1; stepTotal = 0f; positionDistance = ((*((Vector3 *)tempParentParticle[oldPosFieldParent])) - (*((Vector3 *)tempParentParticle[posFieldParent]))); } } sequentialParentParticles--; var parentParticle = parentPool.FromIndex(parentIndex); parentParticlePosition = (*((Vector3 *)parentParticle[posFieldParent])); parentParticlePosition += positionDistance * stepTotal; stepTotal += stepF; } // Spawn is not fixed - pick a parent at random else { parentIndex = (int)(parentParticlesCount * randSeed.GetFloat(RandomOffset.Offset1A + ParentSeedOffset)); var parentParticle = parentPool.FromIndex(parentIndex); parentParticlePosition = (*((Vector3 *)parentParticle[posFieldParent])); } // Convert from Local -> World space if needed if (Parent.SimulationSpace == EmitterSimulationSpace.Local) { WorldRotation.Rotate(ref parentParticlePosition); parentParticlePosition *= WorldScale.X; parentParticlePosition += WorldPosition; } particleRandPos += parentParticlePosition; } (*((Vector3 *)particle[posField])) = particleRandPos; if (oldField.IsValid()) { (*((Vector3 *)particle[oldField])) = particleRandPos; } i = (i + 1) % maxCapacity; } }
/// <inheritdoc /> public unsafe override void Initialize(ParticlePool pool, int startIdx, int endIdx, int maxCapacity) { if (!pool.FieldExists(ParticleFields.Size) || !pool.FieldExists(ParticleFields.RandomSeed)) { return; } var parentPool = Parent?.Pool; var parentParticlesCount = parentPool?.LivingParticles ?? 0; var sizeFieldParent = parentPool?.GetField(ParticleFields.Size) ?? ParticleFieldAccessor <float> .Invalid(); if (!sizeFieldParent.IsValid()) { parentParticlesCount = 0; } var spawnControlField = GetSpawnControlField(); var sizeField = pool.GetField(ParticleFields.Size); var rndField = pool.GetField(ParticleFields.RandomSeed); var minSize = WorldScale.X * RandomSize.X; var sizeGap = WorldScale.X * RandomSize.Y - minSize; var sequentialParentIndex = 0; var sequentialParentParticles = 0; var parentIndex = 0; var i = startIdx; while (i != endIdx) { var particle = pool.FromIndex(i); var randSeed = particle.Get(rndField); var particleRandomSize = minSize + sizeGap * randSeed.GetFloat(RandomOffset.Offset1A + SeedOffset); if (parentParticlesCount > 0) { var parentParticleSize = 1f; // Spawn is fixed - parent particles have spawned a very specific number of children each if (spawnControlField.IsValid()) { while (sequentialParentParticles == 0) { // Early out - no more fixed number children. Rest of the particles (if any) are skipped intentionally if (sequentialParentIndex >= parentParticlesCount) { return; } parentIndex = sequentialParentIndex; var tempParentParticle = parentPool.FromIndex(parentIndex); sequentialParentIndex++; var childrenAttribute = (*((ParticleChildrenAttribute *)tempParentParticle[spawnControlField])); sequentialParentParticles = (int)childrenAttribute.ParticlesToEmit; } sequentialParentParticles--; var parentParticle = parentPool.FromIndex(parentIndex); parentParticleSize = (*((float *)parentParticle[sizeFieldParent])); } // Spawn is not fixed - pick a parent at random else { parentIndex = (int)(parentParticlesCount * randSeed.GetFloat(RandomOffset.Offset1A + ParentSeedOffset)); var parentParticle = parentPool.FromIndex(parentIndex); parentParticleSize = (*((float *)parentParticle[sizeFieldParent])); } // Convert from Local -> World space if needed if (Parent.SimulationSpace == EmitterSimulationSpace.Local) { parentParticleSize *= WorldScale.X; } particleRandomSize *= parentParticleSize; } (*((float *)particle[sizeField])) = particleRandomSize; i = (i + 1) % maxCapacity; } }
/// <inheritdoc /> public unsafe override void Initialize(ParticlePool pool, int startIdx, int endIdx, int maxCapacity) { if (!pool.FieldExists(ParticleFields.Velocity) || !pool.FieldExists(ParticleFields.RandomSeed)) { return; } // Collect the total number of living particles in the parent pool which have a Velocity field var parentPool = Parent?.Pool; var parentParticlesCount = parentPool?.LivingParticles ?? 0; var velFieldParent = parentPool?.GetField(ParticleFields.Velocity) ?? ParticleFieldAccessor <Vector3> .Invalid(); if (!velFieldParent.IsValid()) { parentParticlesCount = 0; } var spawnControlField = GetSpawnControlField(); var velField = pool.GetField(ParticleFields.Velocity); var rndField = pool.GetField(ParticleFields.RandomSeed); var leftCorner = VelocityMin * WorldScale; var xAxis = new Vector3(VelocityMax.X * WorldScale.X - leftCorner.X, 0, 0); var yAxis = new Vector3(0, VelocityMax.Y * WorldScale.Y - leftCorner.Y, 0); var zAxis = new Vector3(0, 0, VelocityMax.Z * WorldScale.Z - leftCorner.Z); if (!WorldRotation.IsIdentity) { WorldRotation.Rotate(ref leftCorner); WorldRotation.Rotate(ref xAxis); WorldRotation.Rotate(ref yAxis); WorldRotation.Rotate(ref zAxis); } var sequentialParentIndex = 0; var sequentialParentParticles = 0; var parentIndex = 0; var i = startIdx; while (i != endIdx) { var particle = pool.FromIndex(i); var randSeed = particle.Get(rndField); var particleRandVel = leftCorner; particleRandVel += xAxis * randSeed.GetFloat(RandomOffset.Offset3A + SeedOffset); particleRandVel += yAxis * randSeed.GetFloat(RandomOffset.Offset3B + SeedOffset); particleRandVel += zAxis * randSeed.GetFloat(RandomOffset.Offset3C + SeedOffset); if (parentParticlesCount > 0) { var parentParticleVelocity = new Vector3(0, 0, 0); // Spawn is fixed - parent particles have spawned a very specific number of children each if (spawnControlField.IsValid()) { while (sequentialParentParticles == 0) { // Early out - no more fixed number children. Rest of the particles (if any) are skipped intentionally if (sequentialParentIndex >= parentParticlesCount) { return; } parentIndex = sequentialParentIndex; var tempParentParticle = parentPool.FromIndex(parentIndex); sequentialParentIndex++; var childrenAttribute = (*((ParticleChildrenAttribute *)tempParentParticle[spawnControlField])); sequentialParentParticles = (int)childrenAttribute.ParticlesToEmit; } sequentialParentParticles--; var parentParticle = parentPool.FromIndex(parentIndex); parentParticleVelocity = (*((Vector3 *)parentParticle[velFieldParent])); } // Spawn is not fixed - pick a parent at random else { parentIndex = (int)(parentParticlesCount * randSeed.GetFloat(RandomOffset.Offset1A + ParentSeedOffset)); var parentParticle = parentPool.FromIndex(parentIndex); parentParticleVelocity = (*((Vector3 *)parentParticle[velFieldParent])); } // Convert from Local -> World space if needed if (Parent.SimulationSpace == EmitterSimulationSpace.Local) { WorldRotation.Rotate(ref parentParticleVelocity); parentParticleVelocity *= WorldScale.X; } particleRandVel += parentParticleVelocity * ParentVelocityFactor; } (*((Vector3 *)particle[velField])) = particleRandVel; i = (i + 1) % maxCapacity; } }
/// <inheritdoc /> public unsafe override void Initialize(ParticlePool pool, int startIdx, int endIdx, int maxCapacity) { if (!pool.FieldExists(ParticleFields.Order)) { return; } // Collect the total number of living particles in the parent pool which have a Order field var parentPool = Parent?.Pool; var parentParticlesCount = parentPool?.LivingParticles ?? 0; var orderFieldParent = parentPool?.GetField(ParticleFields.Order) ?? ParticleFieldAccessor <uint> .Invalid(); var childOrderFieldParent = parentPool?.GetField(ParticleFields.ChildOrder) ?? ParticleFieldAccessor <uint> .Invalid(); if (!orderFieldParent.IsValid()) { parentParticlesCount = 0; } var spawnControlField = GetSpawnControlField(); var orderField = pool.GetField(ParticleFields.Order); var randomField = pool.GetField(ParticleFields.RandomSeed); var sequentialParentIndex = 0; var sequentialParentParticles = 0; var parentIndex = 0; var i = startIdx; while (i != endIdx) { var particle = pool.FromIndex(i); // Will loop every so often, but the loop condition should be unreachable for normal games uint particleOrder = spawnOrder++; if (parentParticlesCount > 0) { uint parentParticleOrder = 0; // Spawn is fixed - parent particles have spawned a very specific number of children each if (spawnControlField.IsValid()) { while (sequentialParentParticles == 0) { // Early out - no more fixed number children. Rest of the particles (if any) are skipped intentionally if (sequentialParentIndex >= parentParticlesCount) { return; } parentIndex = sequentialParentIndex; var tempParentParticle = parentPool.FromIndex(parentIndex); sequentialParentIndex++; var childrenAttribute = (*((ParticleChildrenAttribute *)tempParentParticle[spawnControlField])); sequentialParentParticles = (int)childrenAttribute.ParticlesToEmit; } sequentialParentParticles--; var parentParticle = parentPool.FromIndex(parentIndex); parentParticleOrder = (*((uint *)parentParticle[orderFieldParent])); if (childOrderFieldParent.IsValid()) { particleOrder = (*((uint *)parentParticle[childOrderFieldParent])); (*((uint *)parentParticle[childOrderFieldParent])) = (particleOrder + 1); particleOrder = (particleOrder & 0x0000FFFF) | ((parentParticleOrder << 16) & 0xFFFF0000); } else { particleOrder = (particleOrder & 0x000FFFFF) | ((parentParticleOrder << 20) & 0xFFF00000); } } // Spawn is not fixed - pick a parent at random else { var randSeed = particle.Get(randomField); parentIndex = (int)(parentParticlesCount * randSeed.GetFloat(RandomOffset.Offset1A + ParentSeedOffset)); var parentParticle = parentPool.FromIndex(parentIndex); parentParticleOrder = (*((uint *)parentParticle[orderFieldParent])); if (childOrderFieldParent.IsValid()) { particleOrder = (*((uint *)parentParticle[childOrderFieldParent])); (*((uint *)parentParticle[childOrderFieldParent])) = (particleOrder + 1); particleOrder = (particleOrder & 0x0000FFFF) | ((parentParticleOrder << 16) & 0xFFFF0000); } else { particleOrder = (particleOrder & 0x000FFFFF) | ((parentParticleOrder << 20) & 0xFFF00000); } } } (*((uint *)particle[orderField])) = particleOrder; i = (i + 1) % maxCapacity; } }
/// <inheritdoc /> public unsafe override void Initialize(ParticlePool pool, int startIdx, int endIdx, int maxCapacity) { if (!pool.FieldExists(ParticleFields.Color) || !pool.FieldExists(ParticleFields.RandomSeed)) { return; } // Collect the total number of living particles in the parent pool which have a Color field var parentPool = Parent?.Pool; var parentParticlesCount = parentPool?.LivingParticles ?? 0; var colorFieldParent = parentPool?.GetField(ParticleFields.Color) ?? ParticleFieldAccessor <Color4> .Invalid(); if (!colorFieldParent.IsValid()) { parentParticlesCount = 0; } var spawnControlField = GetSpawnControlField(); var colorField = pool.GetField(ParticleFields.Color); var rndField = pool.GetField(ParticleFields.RandomSeed); var sequentialParentIndex = 0; var sequentialParentParticles = 0; var parentIndex = 0; var i = startIdx; while (i != endIdx) { var particle = pool.FromIndex(i); var randSeed = particle.Get(rndField); var color = Color4.Lerp(ColorMin, ColorMax, randSeed.GetFloat(RandomOffset.Offset1A + SeedOffset)); // If there are living parent particles, the newly created particle will inherit Color from one of them if (parentParticlesCount > 0) { var parentParticleColor = new Color4(1, 1, 1, 1); // Spawn is fixed - parent particles have spawned a very specific number of children each if (spawnControlField.IsValid()) { while (sequentialParentParticles == 0) { // Early out - no more fixed number children. Rest of the particles (if any) are skipped intentionally if (sequentialParentIndex >= parentParticlesCount) { return; } parentIndex = sequentialParentIndex; var tempParentParticle = parentPool.FromIndex(parentIndex); sequentialParentIndex++; var childrenAttribute = (*((ParticleChildrenAttribute *)tempParentParticle[spawnControlField])); sequentialParentParticles = (int)childrenAttribute.ParticlesToEmit; } sequentialParentParticles--; var parentParticle = parentPool.FromIndex(parentIndex); parentParticleColor = (*((Color4 *)parentParticle[colorFieldParent])); } // Spawn is not fixed - pick a parent at random else { parentIndex = (int)(parentParticlesCount * randSeed.GetFloat(RandomOffset.Offset1A + ParentSeedOffset)); var parentParticle = parentPool.FromIndex(parentIndex); parentParticleColor = (*((Color4 *)parentParticle[colorFieldParent])); } color *= parentParticleColor; } // Premultiply alpha // This can't be done in advance for ColorMin and ColorMax because it will change the math color.R *= color.A; color.G *= color.A; color.B *= color.A; (*((Color4 *)particle[colorField])) = color; i = (i + 1) % maxCapacity; } }