private void CreateParticle(Vector3D interpolatedEffectPosition)
        {
            MyAnimatedParticle particle = MyTransparentGeometry.AddAnimatedParticle();

            if (particle == null)
            {
                return;
            }

            particle.Type = (MyParticleTypeEnum)ParticleType.GetValue <int>();

            MyUtils.AssertIsValid(m_effect.WorldMatrix);

            Vector3D startOffset;

            m_emitter.CalculateStartPosition(m_effect.GetElapsedTime(), MatrixD.CreateWorld(interpolatedEffectPosition, m_effect.WorldMatrix.Forward, m_effect.WorldMatrix.Up), m_effect.UserEmitterScale * m_effect.UserScale, out startOffset, out particle.StartPosition);

            Vector3D particlePosition = particle.StartPosition;

            m_AABB = m_AABB.Include(ref particlePosition);

            Life.GetInterpolatedValue <float>(m_effect.GetElapsedTime(), out particle.Life);
            float lifeVar = LifeVar;

            if (lifeVar > 0)
            {
                particle.Life = MathHelper.Max(MyUtils.GetRandomFloat(particle.Life - lifeVar, particle.Life + lifeVar), 0.1f);
            }

            Vector3 vel;

            Velocity.GetInterpolatedValue <Vector3>(m_effect.GetElapsedTime(), out vel);
            vel.X            *= m_effect.UserScale;
            vel.Y            *= m_effect.UserScale;
            vel.Z            *= m_effect.UserScale;
            particle.Velocity = vel;

            if (VelocityDir == MyVelocityDirEnum.FromEmitterCenter)
            {
                if (!MyUtils.IsZero(startOffset - particle.StartPosition))
                {
                    float length = particle.Velocity.Length();
                    particle.Velocity = MyUtils.Normalize(particle.StartPosition - (Vector3D)startOffset) * length;
                }
            }
            particle.Velocity = Vector3D.TransformNormal(particle.Velocity, GetEffect().WorldMatrix);

            Angle.GetInterpolatedValue <float>(m_effect.GetElapsedTime(), out particle.Angle);
            float angleVar = AngleVar;

            if (angleVar > 0)
            {
                particle.Angle = MyUtils.GetRandomFloat(particle.Angle - AngleVar, particle.Angle + AngleVar);
            }

            RotationSpeed.GetInterpolatedValue <float>(m_effect.GetElapsedTime(), out particle.RotationSpeed);
            float rotationSpeedVar = RotationSpeedVar;

            if (rotationSpeedVar > 0)
            {
                particle.RotationSpeed = MyUtils.GetRandomFloat(particle.RotationSpeed - RotationSpeedVar, particle.RotationSpeed + RotationSpeedVar);
            }

            float radiusVar;

            RadiusVar.GetInterpolatedValue <float>(m_effect.GetElapsedTime(), out radiusVar);
            float lodRadius = 1.0f;

            if (GetEffect().EnableLods)
            {
                LODRadius.GetInterpolatedValue <float>(GetEffect().Distance, out lodRadius);
            }

            Radius.GetInterpolatedKeys(m_effect.GetElapsedTime(),
                                       radiusVar,
                                       (EnableCustomRadius.GetValue <bool>() ? m_effect.UserRadiusMultiplier : 1.0f)
                                       * lodRadius
                                       * GetEffect().UserScale,
                                       particle.Radius);

            if (particle.Type != MyParticleTypeEnum.Point)
            {
                Thickness.GetInterpolatedValue <float>(m_effect.GetElapsedTime(), out particle.Thickness);
            }

            particle.Thickness *= lodRadius;

            float colorVar;

            ColorVar.GetInterpolatedValue <float>(m_effect.GetElapsedTime(), out colorVar);
            Color.GetInterpolatedKeys(m_effect.GetElapsedTime(), colorVar, 1.0f, particle.Color);

            Material.GetInterpolatedKeys(m_effect.GetElapsedTime(), 0, 1.0f, particle.Material);

            particle.Flags  = 0;
            particle.Flags |= BlendTextures.GetValue <bool>() ? MyAnimatedParticle.ParticleFlags.BlendTextures : 0;
            particle.Flags |= GetEffect().IsInFrustum ? MyAnimatedParticle.ParticleFlags.IsInFrustum : 0;

            particle.Start(this);

            m_particles.Add(particle);
        }
        public void Deserialize(XmlReader reader)
        {
            m_name = reader.GetAttribute("name");
            int version = Convert.ToInt32(reader.GetAttribute("version"), CultureInfo.InvariantCulture);

            reader.ReadStartElement(); //ParticleGeneration

            foreach (IMyConstProperty property in m_properties)
            {
                if (reader.Name == "Emitter")
                {
                    break; //we added new property which is not in xml yet
                }
                property.Deserialize(reader);
            }

            reader.ReadStartElement();
            m_emitter.Deserialize(reader);
            reader.ReadEndElement();

            reader.ReadEndElement(); //ParticleGeneration

            //Disable texture blending if it is set but unneccessary
            if (BlendTextures)
            {
                bool someMaterialKeysDifferent = false;
                for (int j = 0; j < Material.GetKeysCount(); j++)
                {
                    MyAnimatedPropertyTransparentMaterial key;
                    float time;
                    Material.GetKey(j, out time, out key);

                    MyTransparentMaterial previousMaterial = null;
                    for (int i = 0; i < key.GetKeysCount(); i++)
                    {
                        float timeMat;
                        MyTransparentMaterial material;
                        key.GetKey(i, out timeMat, out material);

                        if (previousMaterial != null && (previousMaterial != material))
                        {
                            if (previousMaterial.Texture != material.Texture)
                            {
                                someMaterialKeysDifferent = true;
                                break;
                            }
                        }
                        previousMaterial = material;
                    }

                    if (someMaterialKeysDifferent)
                    {
                        break;
                    }
                }

                if (!someMaterialKeysDifferent)
                {
                    BlendTextures.SetValue(false);
                }
            }
        }
        public void Init()
        {
            System.Diagnostics.Debug.Assert(Birth == null);

            AddProperty(MyGenerationPropertiesEnum.Birth, new MyAnimatedPropertyFloat("Birth"));
            AddProperty(MyGenerationPropertiesEnum.BirthVar, new MyConstPropertyFloat("Birth var"));

            AddProperty(MyGenerationPropertiesEnum.Life, new MyAnimatedPropertyFloat("Life"));
            AddProperty(MyGenerationPropertiesEnum.LifeVar, new MyConstPropertyFloat("Life var"));

            AddProperty(MyGenerationPropertiesEnum.Velocity, new MyAnimatedPropertyVector3("Velocity"));
            AddProperty(MyGenerationPropertiesEnum.VelocityDir, new MyConstPropertyEnum("Velocity dir", typeof(MyVelocityDirEnum), s_velocityDirStrings));

            AddProperty(MyGenerationPropertiesEnum.Angle, new MyAnimatedPropertyFloat("Angle"));
            AddProperty(MyGenerationPropertiesEnum.AngleVar, new MyConstPropertyFloat("Angle var"));

            AddProperty(MyGenerationPropertiesEnum.RotationSpeed, new MyAnimatedPropertyFloat("Rotation speed"));
            AddProperty(MyGenerationPropertiesEnum.RotationSpeedVar, new MyConstPropertyFloat("Rotation speed var"));

            AddProperty(MyGenerationPropertiesEnum.Radius, new MyAnimatedProperty2DFloat("Radius"));
            AddProperty(MyGenerationPropertiesEnum.RadiusVar, new MyAnimatedPropertyFloat("Radius var"));

            AddProperty(MyGenerationPropertiesEnum.Color, new MyAnimatedProperty2DVector4("Color"));
            AddProperty(MyGenerationPropertiesEnum.ColorVar, new MyAnimatedPropertyFloat("Color var"));

            AddProperty(MyGenerationPropertiesEnum.Material, new MyAnimatedProperty2DTransparentMaterial("Material", MyTransparentMaterialInterpolator.Switch));

            AddProperty(MyGenerationPropertiesEnum.ParticleType, new MyConstPropertyEnum("Particle type", typeof(MyParticleTypeEnum), s_particleTypeStrings));

            AddProperty(MyGenerationPropertiesEnum.Thickness, new MyAnimatedPropertyFloat("Thickness"));

            AddProperty(MyGenerationPropertiesEnum.Enabled, new MyConstPropertyBool("Enabled"));
            Enabled.SetValue(true);

            AddProperty(MyGenerationPropertiesEnum.BlendTextures, new MyConstPropertyBool("Blend textures"));
            BlendTextures.SetValue(true);

            AddProperty(MyGenerationPropertiesEnum.EnableCustomRadius, new MyConstPropertyBool("Enable custom radius"));
            AddProperty(MyGenerationPropertiesEnum.EnableCustomVelocity, new MyConstPropertyBool("Enable custom velocity"));
            AddProperty(MyGenerationPropertiesEnum.EnableCustomBirth, new MyConstPropertyBool("Enable custom birth"));

            AddProperty(MyGenerationPropertiesEnum.OnDie, new MyConstPropertyGenerationIndex("OnDie"));
            OnDie.SetValue(-1);
            AddProperty(MyGenerationPropertiesEnum.OnLife, new MyConstPropertyGenerationIndex("OnLife"));
            OnLife.SetValue(-1);

            AddProperty(MyGenerationPropertiesEnum.LODBirth, new MyAnimatedPropertyFloat("LODBirth"));
            AddProperty(MyGenerationPropertiesEnum.LODRadius, new MyAnimatedPropertyFloat("LODRadius"));

            AddProperty(MyGenerationPropertiesEnum.MotionInheritance, new MyAnimatedPropertyFloat("Motion inheritance"));

            AddProperty(MyGenerationPropertiesEnum.UseLayerSorting, new MyConstPropertyBool("Use layer sorting"));
            AddProperty(MyGenerationPropertiesEnum.SortLayer, new MyConstPropertyInt("Sort layer"));
            AddProperty(MyGenerationPropertiesEnum.AlphaAnisotropic, new MyConstPropertyBool("Alpha anisotropic"));

            AddProperty(MyGenerationPropertiesEnum.Gravity, new MyConstPropertyFloat("Gravity"));

            Thickness.AddKey(0, 1.0f);

            LODBirth.AddKey(0, 1.0f);
            LODRadius.AddKey(0, 1.0f);

            UseLayerSorting.SetValue(false);
            SortLayer.SetValue(-1);

            m_emitter.Init();
        }