예제 #1
0
        /// <summary>
        /// Sets the parent (particle system's) translation, rotation and scale (uniform)
        /// The module can choose to inherit, use or ignore any of the elements
        /// </summary>
        /// <param name="translation">Particle System's translation (from the Transform component)</param>
        /// <param name="rotation">Particle System's quaternion rotation (from the Transform component)</param>
        /// <param name="scale">Particle System's uniform scale (from the Transform component)</param>
        public virtual void SetParentTrs(ref Vector3 translation, ref Quaternion rotation, float scale)
        {
            var hasPos = InheritLocation.HasFlag(InheritLocation.Position);
            var hasRot = InheritLocation.HasFlag(InheritLocation.Rotation);
            var hasScl = InheritLocation.HasFlag(InheritLocation.Scale);

            WorldScale = (hasScl) ? ParticleLocator.Scale * scale : ParticleLocator.Scale;

            WorldRotation = (hasRot) ? ParticleLocator.Rotation * rotation : ParticleLocator.Rotation;

            var offsetTranslation = ParticleLocator.Translation * WorldScale;

            WorldRotation.Rotate(ref offsetTranslation);
            WorldPosition = (hasPos) ? translation + offsetTranslation : offsetTranslation;
        }
예제 #2
0
        public unsafe override void Initialize(ParticlePool pool, int startIdx, int endIdx, int maxCapacity)
        {
            if (!pool.FieldExists(ParticleFields.Position) || !pool.FieldExists(ParticleFields.Velocity) || !pool.FieldExists(ParticleFields.RandomSeed))
            {
                return;
            }

            var posField = pool.GetField(ParticleFields.Position);
            var velField = pool.GetField(ParticleFields.Velocity);
            var rndField = pool.GetField(ParticleFields.RandomSeed);

            var range     = (float)(Angle * Math.PI / 180f);
            var magnitude = WorldScale.X;

            var i = startIdx;

            while (i != endIdx)
            {
                var particle = pool.FromIndex(i);
                var randSeed = particle.Get(rndField);

                var x = (randSeed.GetFloat(RandomOffset.Offset2A + SeedOffset) - 0.5f) * range;
                var z = (randSeed.GetFloat(RandomOffset.Offset2B + SeedOffset) - 0.5f) * range;

                var u = (randSeed.GetFloat(RandomOffset.Offset2A + SeedOffset) - 0.5f) * range;
                var v = (randSeed.GetFloat(RandomOffset.Offset2B + SeedOffset) - 0.5f) * Math.PI;

//                var particleRandPos = new Vector3(x, 1, z);

                var xz = (float)Math.Sin(u);
                var particleRandPos = new Vector3((float)Math.Cos(v) * xz, (float)Math.Sqrt(1 - u * u), (float)Math.Sin(v) * xz);
                particleRandPos.Normalize();


                particleRandPos *= magnitude;
                WorldRotation.Rotate(ref particleRandPos);

                (*((Vector3 *)particle[posField])) = particleRandPos + WorldPosition;

                (*((Vector3 *)particle[velField])) = particleRandPos * Strength;

                i = (i + 1) % maxCapacity;
            }
        }
예제 #3
0
        public unsafe override void Initialize(ParticlePool pool, int startIdx, int endIdx, int maxCapacity)
        {
            if (!pool.FieldExists(ParticleFields.Position) || !pool.FieldExists(ParticleFields.RandomSeed))
            {
                return;
            }

            var posField = pool.GetField(ParticleFields.Position);
            var rndField = pool.GetField(ParticleFields.RandomSeed);

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

            leftCorner += WorldPosition;


            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);

                (*((Vector3 *)particle[posField])) = particleRandPos;

                i = (i + 1) % maxCapacity;
            }
        }
예제 #4
0
        /// <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.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;
            }
        }
예제 #6
0
        /// <inheritdoc />
        public unsafe override void Initialize(ParticlePool pool, int startIdx, int endIdx, int maxCapacity)
        {
            if (!pool.FieldExists(ParticleFields.Position) || !pool.FieldExists(ParticleFields.RandomSeed))
            {
                return;
            }

            var posField = pool.GetField(ParticleFields.Position);
            var oldField = pool.GetField(ParticleFields.OldPosition);
            var rndField = pool.GetField(ParticleFields.RandomSeed);

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

            leftCorner += WorldPosition;

            var i = startIdx;

            if (Interpolate)
            {
                // Interpolate positions between the old and the new one

                var positionDistance = (hasBegun) ? oldPosition - WorldPosition : Vector3.Zero;
                oldPosition = WorldPosition;
                hasBegun    = true;

                var totalCountLessOne = (startIdx < endIdx) ? (endIdx - startIdx - 1) : (endIdx - startIdx + maxCapacity - 1);
                var stepF             = (totalCountLessOne > 1) ? (1f / totalCountLessOne) : 1f;
                var step = 0f;

                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);

                    particleRandPos += positionDistance * step;
                    step            += stepF;

                    (*((Vector3 *)particle[posField])) = particleRandPos;

                    if (oldField.IsValid())
                    {
                        (*((Vector3 *)particle[oldField])) = particleRandPos;
                    }

                    i = (i + 1) % maxCapacity;
                }
            }
            else
            {
                // Do not interpolate position
                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);

                    (*((Vector3 *)particle[posField])) = particleRandPos;

                    if (oldField.IsValid())
                    {
                        (*((Vector3 *)particle[oldField])) = particleRandPos;
                    }

                    i = (i + 1) % maxCapacity;
                }
            }
        }
예제 #7
0
        /// <inheritdoc />
        public unsafe override void Initialize(ParticlePool pool, int startIdx, int endIdx, int maxCapacity)
        {
            if (!pool.FieldExists(ParticleFields.Position) || !pool.FieldExists(ParticleFields.RandomSeed))
            {
                return;
            }

            var posField = pool.GetField(ParticleFields.Position);
            var rndField = pool.GetField(ParticleFields.RandomSeed);

            var arcOffset = new Vector3(0, ArcHeight, 0);

            if (!WorldRotation.IsIdentity)
            {
                WorldRotation.Rotate(ref arcOffset);
            }

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

            var targetCornerAdd = Target?.WorldMatrix.TranslationVector - WorldPosition ?? FallbackTarget;

            var totalCountLessOne = (FixedLength > 0) ? (FixedLength - 1) : (startIdx < endIdx) ? (endIdx - startIdx - 1) : (endIdx - startIdx + maxCapacity - 1);
            var stepF             = (totalCountLessOne > 1) ? (1f / totalCountLessOne) : 1f;
            var step = -stepF;

            var i = startIdx;

            while (i != endIdx)
            {
                var particle = pool.FromIndex(i);
                var randSeed = particle.Get(rndField);

                if (Sequential)
                {
                    step += stepF;
                    if (FixedLength > 0)
                    {
                        step = (i % FixedLength) * stepF;
                    }
                }
                else
                {
                    step = randSeed.GetFloat(RandomOffset.Offset1A + SeedOffset);
                }

                var positionOffsetFactor = (float)Math.Sin(step * Math.PI);
                var particleRandPos      = leftCorner * positionOffsetFactor + targetCornerAdd * step + arcOffset * positionOffsetFactor + WorldPosition;

                particleRandPos += xAxis * positionOffsetFactor * randSeed.GetFloat(RandomOffset.Offset3A + SeedOffset);
                particleRandPos += yAxis * positionOffsetFactor * randSeed.GetFloat(RandomOffset.Offset3B + SeedOffset);
                particleRandPos += zAxis * positionOffsetFactor * randSeed.GetFloat(RandomOffset.Offset3C + SeedOffset);

                (*((Vector3 *)particle[posField])) = particleRandPos;

                i = (i + 1) % maxCapacity;
            }
        }