コード例 #1
0
        /// <summary>
        /// Update given particle over passed time interval, in seconds.
        /// </summary>
        /// <param name="particle">Particle to integrate.</param>
        /// <param name="dt">Amount to advance time, in seconds.</param>
        public void IntegrateParticle(ref T2DParticle particle, float dt)
        {
            // Increase particle age.
            particle.Age += dt;

            // Calculate Particle unit-age.
            float unitAge = particle.Age / particle.Lifetime;

            // **********************************************************************************************************************
            // Scale Speed.
            // **********************************************************************************************************************

            float renderSpeed = particle._speed * _emitterData.SpeedLife[unitAge];

            // **********************************************************************************************************************
            // Scale Fixed-Force.
            // **********************************************************************************************************************

            float renderFixedForce = particle._fixedForce * _emitterData.FixedForceLife[unitAge];

            // **********************************************************************************************************************
            // Scale Random-Motion.
            // **********************************************************************************************************************

            float renderRandomMotion = particle._randomMotion * _emitterData.RandomMotionLife[unitAge];

            // **********************************************************************************************************************
            // Calculate New Velocity...
            // **********************************************************************************************************************

            // Is random motion non-zero?
            if (Epsilon.FloatIsNotZero(renderRandomMotion))
            {
                // Yes, so fetch half random motion.
                float randomMotion = renderRandomMotion * 0.5f;

                // Add integrated random motion into velocity.
                particle._velocity.X += TorqueUtil.GetFastRandomFloat(-randomMotion, randomMotion) * dt;
                particle._velocity.Y += TorqueUtil.GetFastRandomFloat(-randomMotion, randomMotion) * dt;
            }

            Vector2 outVel;

            // Add integrated fixed force into velocity.
            //particle._velocity += _emitterData.FixedForceDirection * renderFixedForce * dt;
            Vector2 dir = _emitterData.FixedForceDirection;
            Vector2.Multiply(ref dir, renderFixedForce * dt, out outVel);
            Vector2.Add(ref outVel, ref particle._velocity, out particle._velocity);

            // Adjust particle position.
            //particle._position += particle._velocity * renderSpeed * dt;
            Vector2.Multiply(ref particle._velocity, renderSpeed * dt, out outVel);
            Vector2.Add(ref outVel, ref particle._position, out particle._position);

            // **********************************************************************************************************************
            // Aligning to motion.
            // **********************************************************************************************************************

            // Are we aligning to motion?
            if (_emitterData.ParticleOrientation == T2DParticleEmitterData.ParticleOrientationMode.Aligned)
            {
                // Yes, so calculate last movement direction.
                float movementAngle = T2DVectorUtil.AngleFromVector(particle._velocity);

                // Set new Orientation Angle.
                particle._rotationAngle = movementAngle + _emitterData.OrientationAngleOffset;
            }
            else
            {
                // Calculate render spin.
                float renderSpin = particle._spin * _emitterData.SpinLife[unitAge];

                // Have we got some spin?
                if (Epsilon.FloatIsNotZero(renderSpin))
                {
                    // Yes, so add integrated spin into orientation.
                    particle._rotationAngle += renderSpin * dt;
                    // Keep within bounds.
                    particle._rotationAngle %= 360.0f;
                }
            }

            // **********************************************************************************************************************
            // Update emitter clip boundary
            // **********************************************************************************************************************

            //Vector2 renderSize = particle._size * _maxParticleSize;
            Vector2 renderSize;
            Vector2.Multiply(ref particle._size, ref _maxParticleSize, out renderSize);

            Vector2 center = particle._position;

            // compute upper bound for maximum extent from center
            float radius = renderSize.X + renderSize.Y;
            radius += Math.Abs(_emitterData.ParticlePivotPoint.X) * _maxParticleSize.X;
            radius += Math.Abs(_emitterData.ParticlePivotPoint.Y) * _maxParticleSize.Y;
            if (center.X - radius < _particleExtentTopLeft.X)
                _particleExtentTopLeft.X = center.X - radius;
            if (center.X + radius > _particleExtentBottomRight.X)
                _particleExtentBottomRight.X = center.X + radius;
            if (center.Y - radius < _particleExtentTopLeft.Y)
                _particleExtentTopLeft.Y = center.Y - radius;
            if (center.Y + radius > _particleExtentBottomRight.Y)
                _particleExtentBottomRight.Y = center.Y + radius;
        }
コード例 #2
0
        /// <summary>
        /// Initialize given particle.
        /// </summary>
        /// <param name="particle">Particle to initialize.</param>
        public void InitializeParticle(ref T2DParticle particle)
        {
            // Fetch Effect Age.
            float effectAge = _parentEffect.Age;
            // Fetch Effect Position.
            Vector2 effectPosition = _parentEffect.Position;
            // Fetch Parent Effect Effect-Data.
            T2DParticleEffectData parentEffectData = _parentEffect.CurrentEffectData;

            // **********************************************************************************************************************
            // Calculate Particle Position...
            // **********************************************************************************************************************

            // Single Particle?
            if (_emitterData.SingleParticle)
            {
                // Yes, so are we using effect position?
                if (_emitterData.AttachPositionToEmitter)
                {
                    // Yes, so set position.
                    particle.Position = Vector2.Zero;
                }
                else
                {
                    // No, so use effect position.
                    particle.Position = effectPosition;
                }
            }
            else
            {
                // No, so select emitter type.
                switch (_emitterData.EmitterArea)
                {
                    // Point.
                    case T2DParticleEmitterData.EmitterAreaType.Point:
                        {
                            // Set Particle position.
                            particle.Position = Vector2.Zero;

                        } break;

                    // LineX.
                    case T2DParticleEmitterData.EmitterAreaType.LineX:
                        {
                            // Calculate Area Size X.
                            float areaSizeX = 0.5f * TorqueUtil.GetFastRandomFloat(0.0f, _parentEffect.Size.X);

                            // Calculate Sign.
                            if ((TorqueUtil.GetFastRandomInt() & 1) == 0)
                            {
                                areaSizeX = -areaSizeX;
                            }

                            // Choose particle location.
                            particle.PositionX = areaSizeX;
                            particle.PositionY = 0.0f;

                        } break;

                    // LineY.
                    case T2DParticleEmitterData.EmitterAreaType.LineY:
                        {
                            // Calculate Area Size Y.
                            float areaSizeY = 0.5f * TorqueUtil.GetFastRandomFloat(0.0f, _parentEffect.Size.Y);

                            // Calculate Sign.
                            if ((TorqueUtil.GetFastRandomInt() & 1) == 0)
                            {
                                areaSizeY = -areaSizeY;
                            }

                            // Choose particle location.
                            particle.PositionX = 0.0f;
                            particle.PositionY = 0.0f + areaSizeY;

                        } break;

                    // Rectangle.
                    case T2DParticleEmitterData.EmitterAreaType.Rectangle:
                        {
                            // Calculate Min/Max Area Size X.
                            float minAreaSizeX = 0.0f;
                            float maxAreaSizeX = 0.5f * _parentEffect.Size.X;

                            // Inline Clamp.
                            if (maxAreaSizeX < minAreaSizeX)
                            {
                                maxAreaSizeX = minAreaSizeX;
                            }

                            // Choose Random Area.
                            float areaSizeX = TorqueUtil.GetFastRandomFloat(maxAreaSizeX);

                            // Assume Fixed Area Aspect.
                            float minAreaSizeY;
                            float maxAreaSizeY;
                            float areaSizeY;

                            if (_emitterData.FixedAreaAspect)
                            {
                                // Yes, so calculate Min/Max Area Size Y (using X).
                                minAreaSizeY = minAreaSizeX;
                                maxAreaSizeY = maxAreaSizeX;
                            }
                            else
                            {
                                // No, so calculate Area Size Y.
                                minAreaSizeY = 0.0f;
                                maxAreaSizeY = 0.5f * _parentEffect.Size.Y;
                            }

                            // Inline Clamp.
                            if (maxAreaSizeY < minAreaSizeY)
                            {
                                maxAreaSizeY = minAreaSizeY;
                            }

                            // Choose Random Area.
                            areaSizeY = TorqueUtil.GetFastRandomFloat(maxAreaSizeY);

                            // Inner Region X?
                            if (areaSizeX < minAreaSizeX && areaSizeY < minAreaSizeY)
                            {
                                // Yes, so randomize within outer region.
                                areaSizeX = minAreaSizeX + (areaSizeX % Math.Abs(maxAreaSizeX - minAreaSizeX + Epsilon.Value));
                            }

                            // Inner Region Y?
                            if (areaSizeY < minAreaSizeY && areaSizeX < minAreaSizeX)
                            {
                                // Yes, so randomize within outer region.
                                areaSizeY = minAreaSizeY + (areaSizeY % Math.Abs(maxAreaSizeY - minAreaSizeY + Epsilon.Value));
                            }

                            // Calculate Sign.
                            int areaFlip = TorqueUtil.GetFastRandomInt();
                            if ((areaFlip & 1) == 0)
                            {
                                areaSizeX = -areaSizeX;
                            }

                            // Calculate Sign.
                            if ((areaFlip & 2) == 0)
                            {
                                areaSizeY = -areaSizeY;
                            }

                            // Choose particle location.
                            particle.PositionX = areaSizeX;
                            particle.PositionY = areaSizeY;

                        } break;
                }

                // Attach position to emitter?
                if (!_emitterData.AttachPositionToEmitter)
                {
                    // No, so attach rotation to emitter?
                    if (!_emitterData.AttachRotationToEmitter)
                    {
                        // No, so we need to fully transform in non-scaled effect world-space.
                        particle.Position = Vector2.Transform(particle.Position, _parentEffect.EffectRotationTranslationMatrix);
                    }
                    else
                    {
                        // Yes, so we need to transform in non-scaled, non-rotated effect world-space.
                        particle.Position = Vector2.Transform(particle.Position, _parentEffect.EffectTranslationMatrix);
                    }
                }
            }

            // **********************************************************************************************************************
            // Calculate Particle Lifetime.
            // **********************************************************************************************************************

            // Reset Age.
            particle.Age = 0.0f;

            // Calculate Lifetime.
            particle.Lifetime = T2DKeyGraph.CalcGraphBVE(_emitterData.ParticleLifeBase, _emitterData.ParticleLifeVariation, parentEffectData.ParticleLifeScale, effectAge);
            if (particle.Lifetime < Epsilon.Value)
                particle.Lifetime = Epsilon.Value;

            // **********************************************************************************************************************
            // Calculate Particle Size.
            // **********************************************************************************************************************

            // Calculate SizeX.
            particle.SizeX = T2DKeyGraph.CalcGraphBVE(_emitterData.SizeXBase, _emitterData.SizeXVariation, parentEffectData.SizeXScale, effectAge);
            particle.SizeY = _emitterData.FixedParticleAspect ? particle.SizeX : T2DKeyGraph.CalcGraphBVE(_emitterData.SizeYBase, _emitterData.SizeYVariation, parentEffectData.SizeYScale, effectAge);
            Assert.Fatal(particle.SizeX > 0.0f && particle.SizeY > 0.0f, "Zero or negative size particles not recommended.");

            // **********************************************************************************************************************
            // Calculate Speed, Fixed-Force, Random Motion
            // **********************************************************************************************************************

            if (_emitterData.SingleParticle)
            {
                particle.Speed = 0.0f;
                particle.FixedForce = 0.0f;
                particle.RandomMotion = 0.0f;
            }
            else
            {
                particle.Speed = T2DKeyGraph.CalcGraphBVE(_emitterData.SpeedBase, _emitterData.SpeedVariation, parentEffectData.SpeedScale, effectAge);
                particle.FixedForce = T2DKeyGraph.CalcGraphBVE(_emitterData.FixedForceBase, _emitterData.FixedForceVariation, parentEffectData.FixedForceScale, effectAge);
                particle.RandomMotion = T2DKeyGraph.CalcGraphBVE(_emitterData.RandomMotionBase, _emitterData.RandomMotionVariation, parentEffectData.RandomMotionScale, effectAge);
            }

            // **********************************************************************************************************************
            // Calculate Spin.
            // **********************************************************************************************************************

            particle.Spin = T2DKeyGraph.CalcGraphBVE(_emitterData.SpinBase, _emitterData.SpinVariation, parentEffectData.SpinScale, effectAge);

            // **********************************************************************************************************************
            // Calculate Emission Angle.
            // **********************************************************************************************************************

            float emissionForce = 0.0f;
            float emissionAngle = 0.0f;
            float emissionArc = 0.0f;

            // Ignore if we're using Single Particle.
            if (!_emitterData.SingleParticle)
            {
                // Are we using effect emission?
                if (_emitterData.UseEffectEmission)
                {
                    // Yes, so calculate emission from effect.
                    emissionForce = -T2DKeyGraph.CalcGraphBV(parentEffectData.EmissionForceBase, parentEffectData.EmissionForceVariation, effectAge);
                    emissionAngle = T2DKeyGraph.CalcGraphBV(parentEffectData.EmissionAngleBase, parentEffectData.EmissionAngleVariation, effectAge);
                    // NOTE:-   We're only interested in half the emission arc!
                    emissionArc = T2DKeyGraph.CalcGraphBV(parentEffectData.EmissionArcBase, parentEffectData.EmissionArcVariation, effectAge) * 0.5f;

                }
                else
                {
                    // No, so calculate emission from emitter.
                    emissionForce = T2DKeyGraph.CalcGraphBV(_emitterData.EmissionForceBase, _emitterData.EmissionForceVariation, effectAge);

                    // No, so calculate standard emission angle.
                    emissionAngle = T2DKeyGraph.CalcGraphBV(_emitterData.EmissionAngleBase, _emitterData.EmissionAngleVariation, effectAge);

                    // Calculate Emission Arc.
                    // NOTE:-   We're only interested in half the emission arc!
                    emissionArc = T2DKeyGraph.CalcGraphBV(_emitterData.EmissionArcBase, _emitterData.EmissionArcVariation, effectAge) * 0.5f;
                }

                // Is the emission rotation linked?
                if (_emitterData.LinkEmissionRotation)
                {
                    // Yes, so add effect rotation onto emission angle.
                    emissionAngle += _parentEffect.Rotation;
                }

                // Calculate final emission angle by choosing random arc.
                emissionAngle = TorqueUtil.GetFastRandomFloat(emissionAngle - emissionArc, emissionAngle + emissionArc) % 360.0f;
                float emissionAngleRad = MathHelper.ToRadians(emissionAngle);
                particle.VelocityX = emissionForce * (float)Math.Sin(emissionAngleRad);
                particle.VelocityY = emissionForce * (float)-Math.Cos(emissionAngleRad);
            }

            // **********************************************************************************************************************
            // Calculate Orientation Angle.
            // **********************************************************************************************************************

            switch (_emitterData.ParticleOrientation)
            {
                // Aligned.
                case T2DParticleEmitterData.ParticleOrientationMode.Aligned:
                    {
                        // Use the emission angle plus offset.
                        particle.RotationAngle = (emissionAngle + _emitterData.OrientationAngleOffset) % 360.0f;

                    } break;

                // Fixed.
                case T2DParticleEmitterData.ParticleOrientationMode.Fixed:
                    {
                        // Use fixed angle.
                        particle.RotationAngle = _emitterData.OrientationAngleOffset % 360.0f;

                    } break;

                // Random.
                case T2DParticleEmitterData.ParticleOrientationMode.Random:
                    {
                        float halfRandomArc = _emitterData.OrientationRandomArc * 0.5f;
                        // Use the emission angle plus offset.
                        particle.RotationAngle = TorqueUtil.GetFastRandomFloat(_emitterData.OrientationAngleOffset - halfRandomArc, _emitterData.OrientationAngleOffset + halfRandomArc) % 360.0f;

                    } break;
            }
        }