Class that holds the information of a particle.
        private void ResetParticle(ref Particle p)
        {
            if (this.disposed)
            {
                throw new ObjectDisposedException("ParticleSystemRenderer");
            }

            if (!p.Alive)
            {
                p.Alive = true;
                p.Life = TimeSpan.FromMilliseconds(this.random.NextDouble() * (this.numParticles * InitTimeMultipler)).TotalMilliseconds;
                p.Position.X = 0;
                p.Position.Y = 0;
                p.Position.Z = 0;
                p.Velocity.X = 0;
                p.Velocity.Y = 0;
                p.Velocity.Z = 0;
                p.VelocityRotation = 0;
                p.Angle = 0;
                p.Size = 0;
                p.TimeLife = 0;
            }
            else
            {
                // Life
                if (this.settings.MinLife != this.settings.MaxLife)
                {
                    TimeSpan time = TimeSpan.FromMilliseconds(MathHelper.Lerp(
                                                                            (float)this.settings.MinLife.TotalMilliseconds,
                                                                            (float)this.settings.MaxLife.TotalMilliseconds,
                                                                            (float)this.random.NextDouble()));
                    p.TimeLife = time.TotalMilliseconds;
                }
                else
                {
                    p.TimeLife = this.settings.MinLife.TotalMilliseconds;
                }

                p.Life = p.TimeLife;

                // Velocity
                if (this.settings.RandomVelocity != Vector3.Zero)
                {
                    p.Velocity = this.settings.LocalVelocity;

                    p.Velocity.X = p.Velocity.X + (this.settings.RandomVelocity.X * (((float)this.random.NextDouble() * 2) - 1));
                    p.Velocity.Y = p.Velocity.Y + (this.settings.RandomVelocity.Y * (((float)this.random.NextDouble() * 2) - 1));
                    p.Velocity.Z = p.Velocity.Z + (this.settings.RandomVelocity.Z * (((float)this.random.NextDouble() * 2) - 1));
                }
                else
                {
                    p.Velocity = this.settings.LocalVelocity;
                }

                p.Position = this.Transform.LocalWorld.Translation;

                if (this.settings.EmitterSize != Vector2.Zero)
                {
                    switch (this.settings.EmitterShape)
                    {
                        case ParticleSystem3D.Shape.Circle:
                            {
                                float radius = this.settings.EmitterSize.X > this.settings.EmitterSize.Y ? (this.settings.EmitterSize.X / 2) : (this.settings.EmitterSize.Y / 2);
                                double angle = this.random.NextDouble() * MathHelper.TwoPi;
                                float x = (float)Math.Cos(angle);
                                float y = (float)Math.Sin(angle);

                                p.Position.X = p.Position.X + (x * radius);
                                p.Position.Z = p.Position.Z + (y * radius);

                                break;
                            }

                        case ParticleSystem3D.Shape.FillCircle:
                            {
                                float rnd0 = ((float)this.random.NextDouble() * 2) - 1;
                                float rnd1 = ((float)this.random.NextDouble() * 2) - 1;
                                float radius = this.settings.EmitterSize.X > this.settings.EmitterSize.Y ? (this.settings.EmitterSize.X / 2) : (this.settings.EmitterSize.Y / 2);
                                double angle = this.random.NextDouble() * MathHelper.TwoPi;
                                float x = (float)Math.Cos(angle);
                                float y = (float)Math.Sin(angle);

                                p.Position.X = p.Position.X + (x * radius * rnd0);
                                p.Position.Z = p.Position.Z + (y * radius * rnd1);

                                break;
                            }

                        case ParticleSystem3D.Shape.Rectangle:
                            {
                                int c = this.random.Next(4);
                                float rnd0 = ((float)this.random.NextDouble() * 2) - 1;
                                float xside = this.settings.EmitterSize.X / 2;
                                float yside = this.settings.EmitterSize.Y / 2;

                                switch (c)
                                {
                                    case 0:
                                        p.Position.X = p.Position.X + xside;
                                        p.Position.Z = p.Position.Z + (yside * rnd0);
                                        break;
                                    case 1:
                                        p.Position.X = p.Position.X - xside;
                                        p.Position.Z = p.Position.Z + (yside * rnd0);
                                        break;
                                    case 2:
                                        p.Position.X = p.Position.X + (xside * rnd0);
                                        p.Position.Z = p.Position.Z + yside;
                                        break;
                                    case 3:
                                    default:
                                        p.Position.X = p.Position.X + (xside * rnd0);
                                        p.Position.Z = p.Position.Z - yside;
                                        break;
                                }

                                break;
                            }

                        case ParticleSystem3D.Shape.FillRectangle:
                            {
                                float rnd0 = ((float)this.random.NextDouble() * 2) - 1;
                                float rnd1 = ((float)this.random.NextDouble() * 2) - 1;

                                p.Position.X = p.Position.X + ((this.settings.EmitterSize.X / 2) * rnd0);
                                p.Position.Z = p.Position.Z + ((this.settings.EmitterSize.Y / 2) * rnd1);
                                break;
                            }

                        default:
                            {
                                throw new ArgumentException("Invalid particleSystem shape");
                            }
                    }
                }

                // Initial Angle
                if (this.settings.InitialAngle.Distinct(0))
                {
                    float randomAngle = ((float)this.random.NextDouble() * 2) - 1;
                    p.Angle = this.settings.InitialAngle * randomAngle;
                }

                // Velocity Rotation
                if (this.settings.MinRotateSpeed.Distinct(this.settings.MaxRotateSpeed))
                {
                    p.VelocityRotation = MathHelper.Lerp(this.settings.MinRotateSpeed, this.settings.MaxRotateSpeed, (float)this.random.NextDouble());
                }
                else
                {
                    p.VelocityRotation = this.settings.MinRotateSpeed;
                }

                // Size
                if (this.settings.MinSize.Distinct(this.settings.MaxSize))
                {
                    p.Size = MathHelper.Lerp(this.settings.MinSize, this.settings.MaxSize, (float)this.random.NextDouble());
                }
                else
                {
                    p.Size = this.settings.MinSize;
                }

                // Color
                if (this.settings.MinColor != this.settings.MaxColor)
                {
                    p.CurrentColor = Color.Lerp(ref this.settings.MinColor, ref this.settings.MaxColor, 1 - (float)this.random.NextDouble());
                }
                else
                {
                    p.CurrentColor = this.settings.MinColor;
                }

                p.Color = p.CurrentColor;

                Matrix.CreateFromYawPitchRoll(this.Transform.Rotation.Y, this.Transform.Rotation.X, this.Transform.Rotation.Z, out this.rotationMatrix);
            }
        }
        /// <summary>
        /// Calculates the local world.
        /// </summary>
        /// <param name="p">The p.</param>
        /// <returns>World matrix.</returns>
        /// <exception cref="ObjectDisposedException">ParticleSystemRenderer has been disposed.</exception>
        private Matrix CalculateLocalWorld(ref Particle p)
        {
            if (this.disposed)
            {
                throw new ObjectDisposedException("ParticleSystemRenderer");
            }

            // Optimización del código
            // Matrix matrix = Matrix.CreateRotationZ(p.Angle)
            //               * Matrix.CreateScale(p.Size)
            //                 *Matrix.CreateBillboard(p.Position, RenderManager.Camera.Position, Vector3.Up, null);
            Matrix matrix;

            float cos = (float)Math.Cos(p.Angle);
            float sin = (float)Math.Sin(p.Angle);

            float scale = 0;

            if (this.settings.EndDeltaScale.Equal(1))
            {
                scale = p.Size;
            }
            else
            {
                float age = 1 - (float)(p.Life / p.TimeLife);
                scale = p.Size * (1 + ((this.settings.EndDeltaScale - 1) * age));
            }

            float cosscale = cos * scale;
            float sinscale = sin * scale;
            float negsinscale = -sin * scale;

            Vector3 cameraPosition = this.RenderManager.Camera.Position;
            Vector3 vector;
            Vector3 vector2;
            Vector3 vector3;
            vector.X = p.Position.X - cameraPosition.X;
            vector.Y = p.Position.Y - cameraPosition.Y;
            vector.Z = p.Position.Z - cameraPosition.Z;
            float num = vector.LengthSquared();
            if (num < 0.0001f)
            {
                vector = Vector3.Forward;
            }
            else
            {
                Vector3.Multiply(ref vector, (float)(1f / ((float)Math.Sqrt((double)num))), out vector);
            }

            ////Vector3 cameraUpVector = Vector3.Up;
            // Vector3.Cross(ref cameraUpVector, ref vector, out vector3);
            vector3.X = vector.Z;
            vector3.Y = 0;
            vector3.Z = -vector.X;

            vector3.Normalize();

            // Vector3.Cross(ref vector, ref vector3, out vector2);
            vector2.X = (vector.Y * vector3.Z) - (vector.Z * vector3.Y);
            vector2.Y = (vector.Z * vector3.X) - (vector.X * vector3.Z);
            vector2.Z = (vector.X * vector3.Y) - (vector.Y * vector3.X);

            matrix.M11 = (cosscale * vector3.X) + (sinscale * vector2.X);
            matrix.M12 = (cosscale * vector3.Y) + (sinscale * vector2.Y);
            matrix.M13 = (cosscale * vector3.Z) + (sinscale * vector2.Z);
            matrix.M14 = 0f;
            matrix.M21 = (negsinscale * vector3.X) + (cosscale * vector2.X);
            matrix.M22 = (negsinscale * vector3.Y) + (cosscale * vector2.Y);
            matrix.M23 = (negsinscale * vector3.Z) + (cosscale * vector2.Z);
            matrix.M24 = 0f;
            matrix.M31 = scale * vector.X;
            matrix.M32 = scale * vector.Y;
            matrix.M33 = scale * vector.Z;
            matrix.M34 = 0f;
            matrix.M41 = p.Position.X;
            matrix.M42 = p.Position.Y;
            matrix.M43 = p.Position.Z;
            matrix.M44 = 1f;

            return matrix;
        }
        /// <summary>
        /// Calculates the local world.
        /// </summary>
        /// <param name="p">The p.</param>
        /// <returns>World matrix.</returns>
        /// <exception cref="ObjectDisposedException">ParticleSystemRenderer has been disposed.</exception>
        private Matrix CalculateLocalWorld(ref Particle p)
        {
            if (this.disposed)
            {
                throw new ObjectDisposedException("ParticleSystemRenderer");
            }

            float cos = (float)Math.Cos(p.Angle);
            float sin = (float)Math.Sin(p.Angle);

            float scale;

            if (this.settings.EndDeltaScale.Equal(1))
            {
                scale = p.Size;
            }
            else
            {
                float age = 1 - (float)(p.Life / p.TimeLife);
                scale = p.Size * (1 + ((this.settings.EndDeltaScale - 1) * age));
            }

            float scaleCos = scale * cos;
            float scaleSin = scale * sin;

            Matrix matrix;
            matrix.M11 = scaleCos;
            matrix.M12 = scaleSin;
            matrix.M13 = 0;
            matrix.M14 = 0;
            matrix.M21 = -scaleSin;
            matrix.M22 = scaleCos;
            matrix.M23 = 0;
            matrix.M24 = 0;
            matrix.M31 = 0f;
            matrix.M32 = 0f;
            matrix.M33 = 1f;
            matrix.M34 = 0f;
            matrix.M41 = p.Position.X;
            matrix.M42 = p.Position.Y;
            matrix.M43 = p.Position.Z;
            matrix.M44 = 1f;

            return matrix;
        }
        private void ResetParticle(ref Particle p)
        {
            if (this.disposed)
            {
                throw new ObjectDisposedException("ParticleSystemRenderer");
            }

            this.emitedParticle = true;

            p.Alive = true;

            if (this.settings.MinLife != this.settings.MaxLife)
            {
                float pLife = MathHelper.Lerp(
                                                                            this.settings.MinLife,
                                                                            this.settings.MaxLife,
                                                                            (float)this.random.NextDouble());
                p.TimeLife = pLife;
            }
            else
            {
                p.TimeLife = this.settings.MinLife;
            }

            p.Life = p.TimeLife;

            // Velocity
            if (this.settings.RandomVelocity != Vector2.Zero)
            {
                p.Velocity.X = this.settings.LocalVelocity.X + (this.settings.RandomVelocity.X * (((float)this.random.NextDouble() * 2) - 1));
                p.Velocity.Y = this.settings.LocalVelocity.Y + (this.settings.RandomVelocity.Y * (((float)this.random.NextDouble() * 2) - 1));
            }
            else
            {
                p.Velocity.X = this.settings.LocalVelocity.X;
                p.Velocity.Y = this.settings.LocalVelocity.Y;
            }

            p.Position = (this.Transform as Transform3D).Position;

            p.StartTime = DateTime.Now.Ticks;

            if (this.settings.EmitterSize != Vector3.Zero)
            {
                switch (this.settings.EmitterShape)
                {
                    case ParticleSystem2D.Shape.Circle:
                        {
                            float radius = this.settings.EmitterSize.X > this.settings.EmitterSize.Y ? (this.settings.EmitterSize.X / 2) : (this.settings.EmitterSize.Y / 2);
                            double angle = this.random.NextDouble() * MathHelper.TwoPi;
                            float x = (float)Math.Cos(angle);
                            float y = (float)Math.Sin(angle);

                            p.Position.X = p.Position.X + (x * radius);
                            p.Position.Y = p.Position.Y + (y * radius);

                            break;
                        }

                    case ParticleSystem2D.Shape.FillCircle:
                        {
                            float rnd0 = ((float)this.random.NextDouble() * 2) - 1;
                            float rnd1 = ((float)this.random.NextDouble() * 2) - 1;
                            float radius = this.settings.EmitterSize.X > this.settings.EmitterSize.Y ? (this.settings.EmitterSize.X / 2) : (this.settings.EmitterSize.Y / 2);
                            double angle = this.random.NextDouble() * MathHelper.TwoPi;
                            float x = (float)Math.Cos(angle);
                            float y = (float)Math.Sin(angle);

                            p.Position.X = p.Position.X + (x * radius * rnd0);
                            p.Position.Y = p.Position.Y + (y * radius * rnd1);

                            break;
                        }

                    case ParticleSystem2D.Shape.Rectangle:
                        {
                            int c = this.random.Next(4);
                            float rnd0 = ((float)this.random.NextDouble() * 2) - 1;
                            float xside = this.settings.EmitterSize.X / 2;
                            float yside = this.settings.EmitterSize.Y / 2;

                            switch (c)
                            {
                                case 0:
                                    p.Position.X = p.Position.X + xside;
                                    p.Position.Y = p.Position.Y + (yside * rnd0);
                                    break;
                                case 1:
                                    p.Position.X = p.Position.X - xside;
                                    p.Position.Y = p.Position.Y + (yside * rnd0);
                                    break;
                                case 2:
                                    p.Position.X = p.Position.X + (xside * rnd0);
                                    p.Position.Y = p.Position.Y + yside;
                                    break;
                                case 3:
                                default:
                                    p.Position.X = p.Position.X + (xside * rnd0);
                                    p.Position.Y = p.Position.Y - yside;
                                    break;
                            }

                            break;
                        }

                    case ParticleSystem2D.Shape.FillRectangle:
                        {
                            float rnd0 = ((float)this.random.NextDouble() * 2) - 1;
                            float rnd1 = ((float)this.random.NextDouble() * 2) - 1;

                            p.Position.X = p.Position.X + ((this.settings.EmitterSize.X / 2) * rnd0);
                            p.Position.Y = p.Position.Y + ((this.settings.EmitterSize.Y / 2) * rnd1);
                            break;
                        }

                    case ParticleSystem2D.Shape.FillBox:
                        {
                            float rnd0 = ((float)this.random.NextDouble() * 2) - 1;
                            float rnd1 = ((float)this.random.NextDouble() * 2) - 1;
                            float rnd2 = ((float)this.random.NextDouble() * 2) - 1;

                            p.Position.X = p.Position.X + ((this.settings.EmitterSize.X / 2) * rnd0);
                            p.Position.Y = p.Position.Y + ((this.settings.EmitterSize.Y / 2) * rnd1);
                            p.Position.Z = p.Position.Z + ((this.settings.EmitterSize.Z / 2) * rnd1);
                            break;
                        }

                    default:
                        {
                            throw new ArgumentException("Invalid particleSystem shape");
                        }
                }
            }

            // Initial Angle
            if (this.settings.InitialAngle.Distinct(0) || this.settings.InitialAngleVariation.Distinct(0))
            {
                float randomAngle = this.settings.InitialAngleVariation * (((float)this.random.NextDouble() * 2) - 1);
                p.Angle = this.settings.InitialAngle + randomAngle;
            }

            // Velocity Rotation
            if (this.settings.MinRotateSpeed.Distinct(this.settings.MaxRotateSpeed))
            {
                p.VelocityRotation = MathHelper.Lerp(this.settings.MinRotateSpeed, this.settings.MaxRotateSpeed, (float)this.random.NextDouble());
            }
            else
            {
                p.VelocityRotation = this.settings.MinRotateSpeed;
            }

            // Size
            if (this.settings.MinSize.Distinct(this.settings.MaxSize))
            {
                p.Size = MathHelper.Lerp(this.settings.MinSize, this.settings.MaxSize, (float)this.random.NextDouble());
            }
            else
            {
                p.Size = this.settings.MinSize;
            }

            // Color
            if (this.settings.MinColor != this.settings.MaxColor)
            {
                p.CurrentColor = Color.Lerp(this.settings.MinColor, this.settings.MaxColor, 1 - (float)this.random.NextDouble());
            }
            else
            {
                p.CurrentColor = this.settings.MinColor;
            }

            p.Color = p.CurrentColor;
            p.CurrentIndex = -1;

            Matrix.CreateFromYawPitchRoll(0, 0, this.Transform.Rotation, out this.rotationMatrix);
        }
        /// <summary>
        /// Calculates the local world.
        /// </summary>
        /// <param name="p">The p.</param>
        /// <returns>World matrix.</returns>
        /// <exception cref="ObjectDisposedException">ParticleSystemRenderer has been disposed.</exception>
        private Matrix CalculateLocalWorld(ref Particle p)
        {
            if (this.disposed)
            {
                throw new ObjectDisposedException("ParticleSystemRenderer");
            }

            ////Matrix matrix = Matrix.CreateRotationZ(p.Angle)
            ////                * Matrix.CreateScale(p.Size)
            ////                * Matrix.CreateTranslation(p.Position);

            float cos = (float)Math.Cos(p.Angle);
            float sin = (float)Math.Sin(p.Angle);

            float scale;

            if (this.settings.EndDeltaScale.Equal(1))
            {
                scale = p.Size;
            }
            else
            {
                float age = 1 - (float)(p.Life / p.TimeLife);
                scale = p.Size * (1 + ((this.settings.EndDeltaScale - 1) * age));
            }

            float scaleCos = scale * cos;
            float scaleSin = scale * sin;

            Matrix matrix;

            if (!this.viewportEnabled)
            {
                matrix.M11 = scaleCos;
                matrix.M12 = scaleSin;
                matrix.M13 = 0;
                matrix.M14 = 0;
                matrix.M21 = -scaleSin;
                matrix.M22 = scaleCos;
                matrix.M23 = 0;
                matrix.M24 = 0;
                matrix.M31 = 0f;
                matrix.M32 = 0f;
                matrix.M33 = 1f;
                matrix.M34 = 0f;
                matrix.M41 = p.Position.X;
                matrix.M42 = p.Position.Y;
                matrix.M43 = 0;
                matrix.M44 = 1f;
            }
            else
            {
                matrix.M11 = scaleCos * this.viewportScale.X;
                matrix.M12 = scaleSin * this.viewportScale.Y;
                matrix.M13 = 0;
                matrix.M14 = 0;
                matrix.M21 = -scaleSin * this.viewportScale.X;
                matrix.M22 = scaleCos * this.viewportScale.Y;
                matrix.M23 = 0;
                matrix.M24 = 0;
                matrix.M31 = 0f;
                matrix.M32 = 0f;
                matrix.M33 = 1f;
                matrix.M34 = 0f;
                matrix.M41 = (p.Position.X * this.viewportScale.X) + this.viewportTranslate.X;
                matrix.M42 = (p.Position.Y * this.viewportScale.Y) + this.viewportTranslate.Y;
                matrix.M43 = 0;
                matrix.M44 = 1f;
            }

            return matrix;
        }