예제 #1
0
    // Is there a particle effector property for a particle parameter that is not set?
    public static string CheckForUninitializedEffectorProperties(ParticleSystem particleSystem)
    {
      string message = "Following effector properties are required but not set: ";
      bool uninitializedPropertyFound = false;

      foreach (var effector in particleSystem.Effectors)
      {
        foreach (var propertyInfo in GetProperties(effector))
        {
          // Handle effector properties with a ParticleParameterAttribute.
          var particleParameterAttribute = propertyInfo.GetCustomAttributes(typeof(ParticleParameterAttribute), true).Cast<ParticleParameterAttribute>().FirstOrDefault();
          if (particleParameterAttribute != null && !particleParameterAttribute.Optional)
          {
            var parameterName = propertyInfo.GetValue(effector, null) as string;
            if (string.IsNullOrEmpty(parameterName))
            {
              // The property is a mandatory particle parameter name and is not set.
              uninitializedPropertyFound = true;
              message += string.Format("{0}.{1} ", effector.GetType().Name, propertyInfo.Name);
            }
          }
        }
      }

      return uninitializedPropertyFound ? message : null;
    }
        protected virtual void CloneCore(ParticleSystem source)
        {
            Name = source.Name;
              Enabled = source.Enabled;
              MaxNumberOfParticles = source.MaxNumberOfParticles;
              InitialDelay = source.InitialDelay;
              PreloadDuration = source.PreloadDuration;
              PreloadDeltaTime = source.PreloadDeltaTime;
              TimeScaling = source.TimeScaling;
              EnableMultithreading = source.EnableMultithreading;
              ReferenceFrame = source.ReferenceFrame;

              // Cloning the particle parameter collection is tricky because the parameters are generics.
              // We use an internal method of the parameter to do the job.
              foreach (var parameter in source.Parameters)
            ((IParticleParameterInternal)parameter).AddCopyToCollection(Parameters);

              foreach (var effector in source.Effectors)
            Effectors.Add(effector.Clone());

              if (source.Children != null)
              {
            Children = new ParticleSystemCollection();
            foreach (var particleSystem in source.Children)
              Children.Add(particleSystem.Clone());
              }

              Pose = source.Pose;
              Shape = source.Shape.Clone();
        }
예제 #3
0
    public static ParticleSystem CreateWaterFall(ContentManager contentManager)
    {
      var ps = new ParticleSystem
      {
        Name = "WaterFall",

        // Preload 2 seconds of the effect using a larger time step.
        PreloadDuration = TimeSpan.FromSeconds(2),
        PreloadDeltaTime = TimeSpan.FromSeconds(0.1),

        Children = new ParticleSystemCollection
        {
          CreateSpray(contentManager),
          CreateWater(contentManager),
        }
      };

      // This parent particle system defines the uniform Gravity parameter for the child
      // particle systems. Uniform particle parameters can be "inherited" - if a child
      // does not have a required uniform parameter, it uses the parameter of the parent.
      ps.Parameters.AddUniform<Vector3F>("Gravity").DefaultValue = new Vector3F(0, -1f, 0);

      ParticleSystemValidator.Validate(ps);
      ParticleSystemValidator.Validate(ps.Children[0]);
      ParticleSystemValidator.Validate(ps.Children[1]);

      return ps;
    }
예제 #4
0
    public RibbonSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      GraphicsScreen.DrawReticle = true;

      GameObjectService.Objects.Add(new GrabObject(Services));

      // Load a sphere model.
      _modelNode = ContentManager.Load<ModelNode>("Particles/Sphere").Clone();
      GraphicsScreen.Scene.Children.Add(_modelNode);

      // Add gravity and damping to the physics simulation.
      Simulation.ForceEffects.Add(new Gravity());
      Simulation.ForceEffects.Add(new Damping());

      // Create a rigid body for the sphere.
      _rigidBody = new RigidBody(new SphereShape(0.5f))
      {
        Pose = new Pose(new Vector3F(-3, 0, 0)),
        LinearVelocity = new Vector3F(10, 10, -3f),
      };
      Simulation.RigidBodies.Add(_rigidBody);

      _particleSystem = RibbonEffect.Create(ContentManager);
      ParticleSystemService.ParticleSystems.Add(_particleSystem);
      _particleSystemNode = new ParticleSystemNode(_particleSystem);
      GraphicsScreen.Scene.Children.Add(_particleSystemNode);
    }
예제 #5
0
    public RingOfFireSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      // Create a new "empty" particle system.
      var particleSystem = new ParticleSystem();

      // Particle systems can have child particle systems. 
      // Add a fire and a smoke effect as children.
      var fire = Fire.Create(ContentManager);
      var smoke = Smoke.Create(ContentManager);  // The smoke effect from the previous sample.
      particleSystem.Children = new ParticleSystemCollection { fire, smoke };

      // If we need to, we can modify the predefined effects.
      // Change the smoke particle lifetime.
      smoke.Parameters.Get<float>(ParticleParameterNames.Lifetime).DefaultValue = 4;
      // Change the smoke's start positions to a ring.
      smoke.Effectors.OfType<StartPositionEffector>().First().Distribution =
        new CircleDistribution { InnerRadius = 2, OuterRadius = 2 };

      // Position the particle system (including its child) in the level.
      particleSystem.Pose = new Pose(new Vector3F(0, 3, 0));

      // We only need to add the parent particle system to the particle system service.
      // The service will automatically update the parent system each frame. The parent
      // system will automatically update its children.
      ParticleSystemService.ParticleSystems.Add(particleSystem);

      // Add the particle system to the scene graph.
      _particleSystemNode = new ParticleSystemNode(particleSystem);
      GraphicsScreen.Scene.Children.Add(_particleSystemNode);
    }
예제 #6
0
    public RainSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      _particleSystem = Rain.Create(ContentManager);
      ParticleSystemService.ParticleSystems.Add(_particleSystem);

      _particleSystemNode = new ParticleSystemNode(_particleSystem);
      GraphicsScreen.Scene.Children.Add(_particleSystemNode);
    }
예제 #7
0
    public static int CountNumberOfParticles(ParticleSystem particleSystem)
    {
      int count = 0;
      count += particleSystem.NumberOfLivingParticles;
      if (particleSystem.Children != null)
        count += CountNumberOfParticles(particleSystem.Children);

      return count;
    }
예제 #8
0
    public static ParticleSystem Create(ContentManager contentManager)
    {
      var ps = new ParticleSystem
      {
        Name = "Grass",
        MaxNumberOfParticles = 400,
      };

      // The grass particles do not die.
      ps.Parameters.AddUniform<float>(ParticleParameterNames.Lifetime).DefaultValue = float.PositiveInfinity;

      // We create all particles instantly. Up to 400 particles. Then the emission stops.
      ps.Effectors.Add(new StreamEmitter
      {
        DefaultEmissionRate = 400 * 60,
        EmissionLimit = 400,
      });

      ps.Parameters.AddVarying<Vector3F>(ParticleParameterNames.Position);
      ps.Effectors.Add(new StartPositionEffector
      {
        Parameter = ParticleParameterNames.Position,
        Distribution = new BoxDistribution { MinValue = new Vector3F(-10, 0.4f, -10), MaxValue = new Vector3F(10, 0.4f, 10) }
      });

      ps.Parameters.AddVarying<float>(ParticleParameterNames.SizeX);
      ps.Effectors.Add(new StartValueEffector<float>
      {
        Parameter = ParticleParameterNames.SizeX,
        Distribution = new UniformDistributionF(0.6f, 1),
      });
      ps.Parameters.AddVarying<float>(ParticleParameterNames.SizeY);
      ps.Effectors.Add(new StartValueEffector<float>
      {
        Parameter = ParticleParameterNames.SizeY,
        Distribution = new UniformDistributionF(0.6f, 1),
      });

      ps.Parameters.AddVarying<Vector3F>(ParticleParameterNames.Color);
      ps.Effectors.Add(new StartValueEffector<Vector3F>
      {
        Parameter = ParticleParameterNames.Color,
        Distribution = new LineSegmentDistribution { Start = new Vector3F(0.82f, 0.92f, 1) * 0.9f, End = new Vector3F(1, 1, 1) }
      });

      ps.Parameters.AddUniform<Texture2D>(ParticleParameterNames.Texture).DefaultValue =
        contentManager.Load<Texture2D>("Particles/Grass");

      ps.Parameters.AddUniform<BillboardOrientation>(ParticleParameterNames.BillboardOrientation).DefaultValue =
        BillboardOrientation.AxialViewPlaneAligned;

      ps.Parameters.AddUniform<bool>(ParticleParameterNames.IsDepthSorted).DefaultValue = true;

      ParticleSystemValidator.Validate(ps);

      return ps;
    }
예제 #9
0
    public static ParticleSystem Create(ContentManager contentManager)
    {
      var ps = new ParticleSystem
      {
        Name = "Decals",
        MaxNumberOfParticles = 50,
      };

      ps.Parameters.AddUniform<float>(ParticleParameterNames.Lifetime).DefaultValue = 5;
      ps.Parameters.AddUniform<float>(ParticleParameterNames.Size).DefaultValue = 0.3f;

      // Following particle parameters are initialized externally:
      ps.Parameters.AddVarying<Vector3F>(ParticleParameterNames.Position);
      ps.Parameters.AddVarying<Vector3F>("Normal");
      ps.Parameters.AddVarying<Vector3F>("Axis");

      ps.Parameters.AddUniform<Vector3F>(ParticleParameterNames.Color).DefaultValue = new Vector3F(0.667f, 0.667f, 0.667f);

      ps.Parameters.AddVarying<float>(ParticleParameterNames.Alpha);
      ps.Effectors.Add(new SingleLinearSegment3Effector
      {
        OutputParameter = ParticleParameterNames.Alpha,
        Time0 = 0,
        Value0 = 1,
        Time1 = 0.9f,
        Value1 = 1,
        Time2 = 1,
        Value2 = 0,
      });

      ps.Parameters.AddVarying<float>(ParticleParameterNames.Angle);
      ps.Effectors.Add(new StartValueEffector<float>
      {
        Parameter = ParticleParameterNames.Angle,
        Distribution = new UniformDistributionF(-0.5f, 0.5f),
      });

      ps.Parameters.AddUniform<Texture2D>(ParticleParameterNames.Texture).DefaultValue =
        contentManager.Load<Texture2D>("Particles/BulletHole");

      // Particle billboards use a custom billboard orientation:
      ps.Parameters.AddUniform<BillboardOrientation>(ParticleParameterNames.BillboardOrientation).DefaultValue =
        BillboardOrientation.WorldOriented;

      ps.Parameters.AddUniform<BlendState>(ParticleParameterNames.BlendState).DefaultValue = BlendState.AlphaBlend;

      // If the user places too many decals, then we run out of particles. If the
      // MaxNumberOfParticles limit is reached, no more decals can be placed. To 
      // avoid this we add the ReserveParticleEffector, which kills old particles 
      // if the MaxNumberOfParticles limit is reached.
      ps.Effectors.Add(new ReserveParticleEffector());

      ParticleSystemValidator.Validate(ps);

      return ps;
    }
예제 #10
0
    public FlameJetSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      _flameJet = FlameJet.Create(ContentManager);
      _flameJet.Pose = new Pose(new Vector3F(0, 2, 0), Matrix33F.CreateRotationY(ConstantsF.PiOver2));
      ParticleSystemService.ParticleSystems.Add(_flameJet);

      _particleSystemNode = new ParticleSystemNode(_flameJet);
      GraphicsScreen.Scene.Children.Add(_particleSystemNode);
    }
예제 #11
0
    // Creates a particle system that display a single particle: a bright billboard 
    // for a "flash" effect.
    private ParticleSystem CreateFlash(ContentManager contentManager)
    {
      var ps = new ParticleSystem
      {
        Name = "Flash",
        MaxNumberOfParticles = 1,
        ReferenceFrame = ParticleReferenceFrame.World,

        // Optimization tip: Use same random number generator as parent.
        Random = Random,
      };

      ps.Parameters.AddUniform<float>(ParticleParameterNames.Lifetime).DefaultValue = 0.3f;

      ps.Parameters.AddVarying<Vector3F>(ParticleParameterNames.Position);
      ps.Effectors.Add(new StartPositionEffector
      {
        Parameter = ParticleParameterNames.Position,
        DefaultValue = Vector3F.Zero,
      });

      ps.Parameters.AddVarying<float>(ParticleParameterNames.Size);
      ps.Parameters.AddUniform<float>("StartSize").DefaultValue = 0.0f;
      ps.Parameters.AddUniform<float>("EndSize").DefaultValue = 40.0f;
      ps.Effectors.Add(new SingleLerpEffector
      {
        ValueParameter = ParticleParameterNames.Size,
        FactorParameter = ParticleParameterNames.NormalizedAge,
        StartParameter = "StartSize",
        EndParameter = "EndSize",
      });

      ps.Parameters.AddVarying<float>(ParticleParameterNames.Alpha);
      ps.Parameters.AddUniform<float>("TargetAlpha").DefaultValue = 0.8f;
      ps.Effectors.Add(new SingleFadeEffector
      {
        ValueParameter = ParticleParameterNames.Alpha,
        TargetValueParameter = "TargetAlpha",
        TimeParameter = ParticleParameterNames.NormalizedAge,
        FadeInStart = 0.0f,
        FadeInEnd = 0.2f,
        FadeOutStart = 0.75f,
        FadeOutEnd = 1.0f,
      });

      ps.Parameters.AddUniform<Vector3F>(ParticleParameterNames.Color).DefaultValue =
        new Vector3F(1, 1, 216.0f / 255.0f);

      ps.Parameters.AddUniform<Texture2D>(ParticleParameterNames.Texture).DefaultValue =
        contentManager.Load<Texture2D>("Particles/Flash");

      ps.Parameters.AddUniform<float>(ParticleParameterNames.BlendMode).DefaultValue = 0;

      return ps;
    }
예제 #12
0
    private void CreateParticleSystem()
    {
      // Load a sphere model.
      var modelNode = ContentManager.Load<ModelNode>("Particles/Sphere");
      var meshNode = (MeshNode)modelNode.Children[0];

      // Add gravity and damping to the physics simulation.
      Simulation.ForceEffects.Add(new Gravity());
      Simulation.ForceEffects.Add(new Damping());

      // Create two instances of the sphere model.
      _meshNode0 = meshNode.Clone();
      GraphicsScreen.Scene.Children.Add(_meshNode0);
      _meshNode1 = meshNode.Clone();
      GraphicsScreen.Scene.Children.Add(_meshNode1);

      // Create a rigid body for the left sphere.
      _rigidBody0 = new RigidBody(new SphereShape(0.5f))
      {
        Pose = new Pose(new Vector3F(-3, 4, 0)),
      };
      Simulation.RigidBodies.Add(_rigidBody0);

      // Create a rigid body for the right sphere. (Sharing the same shape, mass and material.)
      _rigidBody1 = new RigidBody(_rigidBody0.Shape, _rigidBody0.MassFrame, _rigidBody0.Material)
      {
        Pose = new Pose(new Vector3F(3, 4, 0)),
      };
      Simulation.RigidBodies.Add(_rigidBody1);

      // Extract basic triangle mesh from the sphere model.
      var triangleMesh = meshNode.Mesh.Submeshes[0].ToTriangleMesh();

      // Create a particle system for the left ball. This particle system uses
      // ReferenceFrame == ParticleReferenceFrame.World - which is the default for all 
      // particle systems. Particles are all relative to world space. The particle system pose 
      // determines the start positions and direction (when the StartPositionEffector and 
      // StartDirectionEffector are in use). Particles do not move with the particle system.
      _particleSystem0 = GlowingMeshEffect.Create(triangleMesh, ContentManager);
      _particleSystem0.ReferenceFrame = ParticleReferenceFrame.World;
      ParticleSystemService.ParticleSystems.Add(_particleSystem0);

      _particleSystemNode0 = new ParticleSystemNode(_particleSystem0);
      _meshNode0.Children = new SceneNodeCollection { _particleSystemNode0 };

      // Create a particle system for the right ball. This particle system uses
      // ReferenceFrame == ParticleReferenceFrame.Local. Particles are all relative to the 
      // particle system pose. Particles move with the particle system.
      _particleSystem1 = GlowingMeshEffect.Create(triangleMesh, ContentManager);
      _particleSystem1.ReferenceFrame = ParticleReferenceFrame.Local;
      ParticleSystemService.ParticleSystems.Add(_particleSystem1);

      _particleSystemNode1 = new ParticleSystemNode(_particleSystem1);
      _meshNode1.Children = new SceneNodeCollection { _particleSystemNode1 };
    }
예제 #13
0
    public DecalSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      GraphicsScreen.DrawReticle = true;
      SetCamera(new Vector3F(0, 2, 6), 0, 0);

      _decals = Decals.Create(ContentManager);
      ParticleSystemService.ParticleSystems.Add(_decals);

      _particleSystemNode = new ParticleSystemNode(_decals);
      GraphicsScreen.Scene.Children.Add(_particleSystemNode);
    }
예제 #14
0
    public AnimatedTextureSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      _beeSwarm = BeeSwarm.Create(ContentManager);
      _beeSwarm.Pose = new Pose(new Vector3F(0, 4, 0));

      // Create 100 bees.
      _beeSwarm.AddParticles(100);

      ParticleSystemService.ParticleSystems.Add(_beeSwarm);

      _particleSystemNode = new ParticleSystemNode(_beeSwarm);
      GraphicsScreen.Scene.Children.Add(_particleSystemNode);
    }
예제 #15
0
    public void Initialize(ContentManager contentManager)
    {
      if (ParticleSystemNode == null)
      {
        // This is the first time this instance is used.

        var ps = new ParticleSystem
        {
          Name = "Teleport" + _count,
          ReferenceFrame = ParticleReferenceFrame.Local,
          Children = new ParticleSystemCollection
          {
            CreateSparkles(contentManager),
            CreateFastBeams(contentManager),
            CreateSlowBeams(contentManager),
          }
        };

        // Add a uniform float particle parameter that contains the particle system time.
        ps.Parameters.AddUniform<float>("Time");
        ps.Effectors.Add(new TimeToSingleEffector { Parameter = "Time" });

        // Add a uniform GlobalAlpha parameter. This parameter controls the alpha of all
        // child particle systems. 
        ps.Parameters.AddUniform<float>("GlobalAlpha");
        ps.Effectors.Add(new SingleFadeEffector
        {
          ValueParameter = "GlobalAlpha",
          TimeParameter = "Time",
          FadeInStart = 0,
          FadeInEnd = 2,
          FadeOutStart = 2,
          FadeOutEnd = 3,
        });

        ParticleSystemValidator.Validate(ps);
        ParticleSystemValidator.Validate(ps.Children[0]);
        ParticleSystemValidator.Validate(ps.Children[1]);
        ParticleSystemValidator.Validate(ps.Children[2]);

        ParticleSystemNode = new ParticleSystemNode(ps) { Name = "TeleportNode" + _count };
        _count++;
      }
      else
      {
        ParticleSystem.Reset();
        ParticleSystemNode.PoseWorld = Pose.Identity;
      }
    }
예제 #16
0
    public static void Validate(ParticleSystem particleSystem)
    {
      var message1 = CheckForUninitializedEffectorProperties(particleSystem);
      var message2 = CheckForMissingParticleParameters(particleSystem);
      var message3 = CheckForUninitializedParticleParameters(particleSystem);

      if (message1 != null || message2 != null || message3 != null)
      {
        Debug.WriteLine("----- \"{0}\" (type {1}):", particleSystem.Name, particleSystem.GetType().Name);

        if (message1 != null)
          Debug.WriteLine(message1);

        if (message2 != null)
          Debug.WriteLine(message2);

        if (message3 != null)
          Debug.WriteLine(message3);
      }
    }
예제 #17
0
    // Is there a particle parameter that is required by an effector but is missing in the 
    // particle system?
    public static string CheckForMissingParticleParameters(ParticleSystem particleSystem)
    {
      string message = "Parameters missing in particle system: ";
      List<string> missing = new List<string>();

      foreach (var effector in particleSystem.Effectors)
      {
        foreach (var propertyInfo in GetProperties(effector))
        {
          // Handle effector properties with a ParticleParameterAttribute.
          var particleParameterAttribute = propertyInfo.GetCustomAttributes(typeof(ParticleParameterAttribute), true).Cast<ParticleParameterAttribute>().FirstOrDefault();
          if (particleParameterAttribute != null)
          {
            var parameterName = propertyInfo.GetValue(effector, null) as string;

            if (string.IsNullOrEmpty(parameterName))
              continue;                // Property is probably not in use.

            if (particleSystem.Parameters.Contains(parameterName))
              continue;                // Parameter was found in the particle system.

            if (missing.Contains(parameterName))
              continue;                // Parameter was already reported as missing.

            if (particleSystem.Parent != null && particleSystem.Parent.Parameters.Any(p => p.IsUniform && p.Name == parameterName))
              continue;                // Parameter is uniform and was found in the parent particle system.

            // The particle parameter is missing.
            missing.Add(parameterName);
            message += string.Format("\"{0}\" ", parameterName);
          }
        }
      }

      return missing.Count > 0 ? message : null;
    }
예제 #18
0
    private static ParticleSystem CreateSmoke(ContentManager content)
    {
      ParticleSystem ps = new ParticleSystem
      {
        Name = "CampfireSmoke",
        MaxNumberOfParticles = 24,
        PreloadDuration = new TimeSpan(0, 0, 0, 2),
      };

      // Make all computations relative to the pose (position and orientation) of the
      // particle system to allow instancing. (I.e. the particle system can be added
      // more than once to the scene.)
      ps.ReferenceFrame = ParticleReferenceFrame.Local;

      // Each particle lives for a random time span.
      ps.Parameters.AddVarying<float>(ParticleParameterNames.Lifetime);
      ps.Effectors.Add(new StartValueEffector<float>
      {
        Parameter = ParticleParameterNames.Lifetime,
        Distribution = new UniformDistributionF(2.0f, 2.4f),
      });

      // Add an effector that emits particles at a constant rate.
      ps.Effectors.Add(new StreamEmitter
      {
        DefaultEmissionRate = 10,
      });

      // Particle positions start on a circular area (in the xy-plane).
      ps.Parameters.AddVarying<Vector3F>(ParticleParameterNames.Position);
      ps.Effectors.Add(new StartPositionEffector
      {
        Parameter = ParticleParameterNames.Position,
        Distribution = new CircleDistribution { OuterRadius = 0.4f, InnerRadius = 0 }
      });

      // Set default axis of billboards. (Usually Vector3F.Up, but in this case the 
      // particle system is rotated.)
      ps.Parameters.AddUniform<Vector3F>(ParticleParameterNames.Axis).DefaultValue = Vector3F.Forward;

      // Particles move in up direction with a slight random deviation with a random speed.
      ps.Parameters.AddVarying<Vector3F>(ParticleParameterNames.Direction);
      ps.Effectors.Add(new StartDirectionEffector
      {
        Parameter = ParticleParameterNames.Direction,
        Distribution = new DirectionDistribution { Deviation = 0.15f, Direction = Vector3F.Forward },
      });
      ps.Parameters.AddVarying<float>(ParticleParameterNames.LinearSpeed);
      ps.Effectors.Add(new StartValueEffector<float>
      {
        Parameter = ParticleParameterNames.LinearSpeed,
        Distribution = new UniformDistributionF(0, 1),
      });

      // The LinearVelocityEffector uses the Direction and LinearSpeed to update the Position
      // of particles.
      ps.Effectors.Add(new LinearVelocityEffector());

      // Lets apply a damping (= exponential decay) to the LinearSpeed using the SingleDampingEffector.
      ps.Parameters.AddUniform<float>(ParticleParameterNames.Damping).DefaultValue = 1.0f;
      ps.Effectors.Add(new SingleDampingEffector
      {
        // Following parameters are equal to the default values. No need to set them.
        //ValueParameter = ParticleParameterNames.LinearSpeed,
        //DampingParameter = ParticleParameterNames.Damping,
      });

      // To create a wind effect, we apply an acceleration to all particles.
      ps.Parameters.AddUniform<Vector3F>("Wind").DefaultValue = new Vector3F(-1, -0.5f, -3);//new Vector3F(-1, 3, -0.5f);
      ps.Effectors.Add(new LinearAccelerationEffector { AccelerationParameter = "Wind" });

      // Each particle starts with a random rotation angle and a random angular speed.
      ps.Parameters.AddVarying<float>(ParticleParameterNames.Angle);
      ps.Effectors.Add(new StartValueEffector<float>
      {
        Parameter = ParticleParameterNames.Angle,
        Distribution = new UniformDistributionF(-ConstantsF.PiOver2, ConstantsF.PiOver2),
      });
      ps.Parameters.AddVarying<float>(ParticleParameterNames.AngularSpeed);
      ps.Effectors.Add(new StartValueEffector<float>
      {
        Parameter = ParticleParameterNames.AngularSpeed,
        Distribution = new UniformDistributionF(-2f, 2f),
      });

      // The AngularVelocityEffector uses the AngularSpeed to update the particle Angle.
      ps.Effectors.Add(new AngularVelocityEffector
      {
        AngleParameter = ParticleParameterNames.Angle,
        SpeedParameter = ParticleParameterNames.AngularSpeed,
      });

      // Each particle gets a random start and end size.
      ps.Parameters.AddVarying<float>("StartSize");
      ps.Effectors.Add(new StartValueEffector<float>
      {
        Parameter = "StartSize",
        Distribution = new UniformDistributionF(0.5f, 0.7f),
      });
      ps.Parameters.AddVarying<float>("EndSize");
      ps.Effectors.Add(new StartValueEffector<float>
      {
        Parameter = "EndSize",
        Distribution = new UniformDistributionF(1.0f, 1.4f),
      });

      // The Size is computed from linear interpolation between the StartSize and the EndSize.
      ps.Parameters.AddVarying<float>(ParticleParameterNames.Size);
      ps.Effectors.Add(new SingleLerpEffector
      {
        ValueParameter = ParticleParameterNames.Size,
        FactorParameter = ParticleParameterNames.NormalizedAge,
        StartParameter = "StartSize",
        EndParameter = "EndSize",
      });

      // The Color slowly changes linearly from light gray to a darker gray.
      ps.Parameters.AddUniform<Vector3F>("StartColor").DefaultValue = new Vector3F(0.1f, 0.1f, 0.1f);
      ps.Parameters.AddUniform<Vector3F>("EndColor").DefaultValue = new Vector3F(0.01f, 0.01f, 0.01f);
      ps.Parameters.AddVarying<Vector3F>(ParticleParameterNames.Color);
      ps.Effectors.Add(new Vector3FLerpEffector
      {
        ValueParameter = ParticleParameterNames.Color,
        StartParameter = "StartColor",
        EndParameter = "EndColor",
      });

      // The Alpha value is 0 for a short time, then it fades in to the TargetAlpha and finally
      // it fades out again.
      ps.Parameters.AddVarying<float>(ParticleParameterNames.Alpha);
      ps.Parameters.AddUniform<float>("TargetAlpha").DefaultValue = 1.0f;
      ps.Effectors.Add(new SingleFadeEffector
      {
        ValueParameter = ParticleParameterNames.Alpha,
        TargetValueParameter = "TargetAlpha",
        TimeParameter = ParticleParameterNames.NormalizedAge,
        FadeInStart = 0.36f,
        FadeInEnd = 0.6f,
        FadeOutStart = 0.6f,
        FadeOutEnd = 1.0f,
      });

      // DigitalRune Graphics supports a "Texture" parameter of type Texture2D or 
      // PackedTexture. The texture "Smoke2.png" contains a tile set, which can be 
      // described using the PackedTexture class.
      ps.Parameters.AddUniform<PackedTexture>(ParticleParameterNames.Texture).DefaultValue =
        new PackedTexture("Smoke", content.Load<Texture2D>("Campfire/Smoke2"), Vector2F.Zero, Vector2F.One, 2, 1);

      // Each particle chooses a random image of the tile set when it is created.
      // The "AnimationTime" parameter selects an image:
      //   0 = start of animation = first image in tile set
      //   1 = end of animation = last image in tile set)
      ps.Parameters.AddVarying<float>(ParticleParameterNames.AnimationTime);
      ps.Effectors.Add(new StartValueEffector<float>
      {
        Parameter = ParticleParameterNames.AnimationTime,
        Distribution = new UniformDistributionF(0, 1),  // Random value between 0 and 1.
      });

      // The smoke effect uses a mix of additive blending (BlendMode = 0)
      // and alpha blending (BlendMode = 1).
      ps.Parameters.AddUniform<float>(ParticleParameterNames.BlendMode).DefaultValue = 0.5f;

      // Optional: Set a bounding shape for frustum culling. The bounding shape needs 
      // to be large enough to include all smoke particles.
      ps.Shape = new TransformedShape(new GeometricObject(new BoxShape(3, 3, 4), new Pose(new Vector3F(-1, 0, -3))));

      ps.Parameters.AddUniform<int>(ParticleParameterNames.DrawOrder).DefaultValue = 1;

      return ps;
    }
예제 #19
0
    // Check out the ParticleSample ("Samples/DigitalRune.Particles/ParticleSample")
    // to learn more about DigitalRune Particles. Also, make sure to read the class 
    // documentation of the ParticleSystemNode. The documentation describes all particle 
    // parameters that are supported by DigitalRune Graphics!
    private static ParticleSystem CreateFire(ContentManager content)
    {
      ParticleSystem ps = new ParticleSystem
      {
        Name = "Campfire",
        MaxNumberOfParticles = 25
      };

      // Make all computations relative to the pose (position and orientation) of the
      // particle system to allow instancing. (I.e. the particle system can be added
      // more than once to the scene.)
      ps.ReferenceFrame = ParticleReferenceFrame.Local;

      // Each particle lives for a random time span.
      ps.Parameters.AddVarying<float>(ParticleParameterNames.Lifetime);
      ps.Effectors.Add(new StartValueEffector<float>
      {
        Parameter = ParticleParameterNames.Lifetime,
        Distribution = new UniformDistributionF(0.8f, 1.2f),
      });

      // Add an effector that emits particles at a constant rate.
      ps.Effectors.Add(new StreamEmitter
      {
        DefaultEmissionRate = 20,
      });

      // Particle positions start on a circular area (in the xy-plane).
      ps.Parameters.AddVarying<Vector3F>(ParticleParameterNames.Position);
      ps.Effectors.Add(new StartPositionEffector
      {
        Parameter = ParticleParameterNames.Position,
        Distribution = new CircleDistribution { OuterRadius = 0.4f, InnerRadius = 0 }
      });

      // Set default axis of billboards. (Usually Vector3F.Up, but in this case the 
      // particle system is rotated.)
      ps.Parameters.AddUniform<Vector3F>(ParticleParameterNames.Axis).DefaultValue = Vector3F.Forward;

      // Particles move in forward direction with a random speed.
      ps.Parameters.AddUniform<Vector3F>(ParticleParameterNames.Direction).DefaultValue = Vector3F.Forward;
      ps.Parameters.AddVarying<float>(ParticleParameterNames.LinearSpeed);
      ps.Effectors.Add(new StartValueEffector<float>
      {
        Parameter = ParticleParameterNames.LinearSpeed,
        Distribution = new UniformDistributionF(0, 1),
      });

      // The LinearVelocityEffector uses the Direction and LinearSpeed to update the Position
      // of particles.
      ps.Effectors.Add(new LinearVelocityEffector());

      // Lets apply a damping (= exponential decay) to the LinearSpeed using the SingleDampingEffector.
      ps.Parameters.AddUniform<float>(ParticleParameterNames.Damping).DefaultValue = 1.0f;
      ps.Effectors.Add(new SingleDampingEffector
      {
        // Following parameters are equal to the default values. No need to set them.
        //ValueParameter = ParticleParameterNames.LinearSpeed,
        //DampingParameter = ParticleParameterNames.Damping,
      });

      // To create a wind effect, we apply an acceleration to all particles.
      ps.Parameters.AddUniform<Vector3F>("Wind").DefaultValue = new Vector3F(-1, -0.5f, -3);//new Vector3F(-1, 3, -0.5f);
      ps.Effectors.Add(new LinearAccelerationEffector { AccelerationParameter = "Wind" });

      // Each particle starts with a random rotation angle and a random angular speed.
      ps.Parameters.AddVarying<float>(ParticleParameterNames.Angle);
      ps.Effectors.Add(new StartValueEffector<float>
      {
        Parameter = ParticleParameterNames.Angle,
        Distribution = new UniformDistributionF(-ConstantsF.Pi, ConstantsF.Pi),
      });
      ps.Parameters.AddVarying<float>(ParticleParameterNames.AngularSpeed);
      ps.Effectors.Add(new StartValueEffector<float>
      {
        Parameter = ParticleParameterNames.AngularSpeed,
        Distribution = new UniformDistributionF(-2f, 2f),
      });

      // The AngularVelocityEffector uses the AngularSpeed to update the particle Angle.
      ps.Effectors.Add(new AngularVelocityEffector());

      // All particle have the same size.
      ps.Parameters.AddUniform<float>(ParticleParameterNames.Size).DefaultValue = 0.8f;

      // Particle alpha fades in to 1 and then back out to 0.
      ps.Parameters.AddVarying<float>(ParticleParameterNames.Alpha);
      ps.Effectors.Add(new SingleFadeEffector
      {
        ValueParameter = ParticleParameterNames.Alpha,
        FadeInStart = 0.0f,
        FadeInEnd = 0.3f,
        FadeOutStart = 0.7f,
        FadeOutEnd = 1.0f,
      });

      ps.Parameters.AddUniform<Vector3F>(ParticleParameterNames.Color).DefaultValue = new Vector3F(5, 5, 5);

      // DigitalRune Graphics supports a "Texture" parameter of type Texture2D or 
      // PackedTexture. The texture "FireParticles.tga" is a tile set, which can be 
      // described using a PackedTexture.
      ps.Parameters.AddUniform<PackedTexture>(ParticleParameterNames.Texture).DefaultValue =
        new PackedTexture("FireParticles", content.Load<Texture2D>("Campfire/FireParticles"), Vector2F.Zero, Vector2F.One, 4, 1);

      // Each particle chooses a random image of the tile set when it is created.
      // The "AnimationTime" parameter selects an image:
      //   0 = start of animation = first image in tile set
      //   1 = end of animation = last image in tile set)
      ps.Parameters.AddVarying<float>(ParticleParameterNames.AnimationTime);
      ps.Effectors.Add(new StartValueEffector<float>
      {
        Parameter = ParticleParameterNames.AnimationTime,
        Distribution = new UniformDistributionF(0, 1),  // Random value between 0 and 1.
      });

      // The fire effect uses additive blending (BlendMode = 0).
      ps.Parameters.AddUniform<float>(ParticleParameterNames.BlendMode).DefaultValue = 0;

      // Enable soft particles.
      ps.Parameters.AddUniform<float>(ParticleParameterNames.Softness).DefaultValue = float.NaN; // NaN = automatic

      // Optional: Set a bounding shape for frustum culling. The bounding shape needs 
      // to be large enough to include all fire particles.
      ps.Shape = new TransformedShape(new GeometricObject(new BoxShape(2.5f, 2.5f, 2.5f), new Pose(new Vector3F(0, 0, -1))));

      return ps;
    }
예제 #20
0
    private ParticleSystem CreateExplosionDistortionParticleSystem()
    {
      ParticleSystem ps = new ParticleSystem
      {
        Name = "ExplosionDistortion",
        MaxNumberOfParticles = 60,
      };

      ps.ReferenceFrame = ParticleReferenceFrame.Local;

      // Lifetime
      ps.Parameters.AddUniform<float>(ParticleParameterNames.Lifetime).DefaultValue = 0.5f;

      // Position
      ps.Parameters.AddVarying<Vector3F>(ParticleParameterNames.Position);
      ps.Effectors.Add(new StartPositionEffector
      {
        Parameter = ParticleParameterNames.Position,
        DefaultValue = Vector3F.Zero,
      });

      // Velocity
      ps.Parameters.AddVarying<Vector3F>(ParticleParameterNames.Direction);
      ps.Effectors.Add(new StartDirectionEffector
      {
        Parameter = ParticleParameterNames.Direction,
        Distribution = new SphereDistribution { InnerRadius = 1.0f, OuterRadius = 1.0f },
      });
      ps.Parameters.AddVarying<float>(ParticleParameterNames.LinearSpeed);
      ps.Effectors.Add(new StartValueEffector<float>
      {
        Parameter = ParticleParameterNames.LinearSpeed,
        Distribution = new UniformDistributionF(10, 20),
      });
      ps.Effectors.Add(new LinearVelocityEffector());

      // Angle
      ps.Parameters.AddVarying<float>(ParticleParameterNames.Angle);
      ps.Effectors.Add(new StartValueEffector<float>
      {
        Parameter = ParticleParameterNames.Angle,
        Distribution = new UniformDistributionF(-ConstantsF.Pi, ConstantsF.Pi),
      });

      // Angular Velocity
      ps.Parameters.AddVarying<float>(ParticleParameterNames.AngularSpeed);
      ps.Effectors.Add(new StartValueEffector<float>
      {
        Parameter = ParticleParameterNames.AngularSpeed,
        Distribution = new UniformDistributionF(-0.4f, 0.4f),
      });
      ps.Effectors.Add(new AngularVelocityEffector());

      // Size
      ps.Parameters.AddVarying<float>("StartSize");
      ps.Effectors.Add(new StartValueEffector<float>
      {
        Parameter = "StartSize",
        Distribution = new UniformDistributionF(2f, 4.0f),
      });
      ps.Parameters.AddVarying<float>("EndSize");
      ps.Effectors.Add(new StartValueEffector<float>
      {
        Parameter = "EndSize",
        Distribution = new UniformDistributionF(6f, 16.0f),
      });
      ps.Parameters.AddVarying<float>(ParticleParameterNames.Size);
      ps.Effectors.Add(new SingleLerpEffector
      {
        ValueParameter = ParticleParameterNames.Size,
        FactorParameter = ParticleParameterNames.NormalizedAge,
        StartParameter = "StartSize",
        EndParameter = "EndSize",
      });

      // Alpha
      ps.Parameters.AddVarying<float>(ParticleParameterNames.Alpha);
      ps.Parameters.AddUniform<float>("TargetAlpha").DefaultValue = 1.0f;
      ps.Effectors.Add(new SingleFadeEffector
      {
        ValueParameter = ParticleParameterNames.Alpha,
        TargetValueParameter = "TargetAlpha",
        TimeParameter = ParticleParameterNames.NormalizedAge,
        FadeInStart = 0.0f,
        FadeInEnd = 0.05f,
        FadeOutStart = 0.5f,
        FadeOutEnd = 1.0f,
      });

      // Texture
      ps.Parameters.AddUniform<Texture2D>(ParticleParameterNames.Texture).DefaultValue =
        ContentManager.Load<Texture2D>("Particles/Distortion");

      // Softness
      ps.Parameters.AddUniform<float>(ParticleParameterNames.Softness).DefaultValue = float.NaN; // NaN = automatic

      // Bounding shape
      ps.Shape = new SphereShape(10);

      return ps;
    }
예제 #21
0
    private ParticleSystem CreateNovaDistortionParticleSystem()
    {
      ParticleSystem ps = new ParticleSystem
      {
        Name = "NovaDistortion",
        MaxNumberOfParticles = 80,
      };

      ps.ReferenceFrame = ParticleReferenceFrame.Local;

      // Lifetime
      ps.Parameters.AddUniform<float>(ParticleParameterNames.Lifetime).DefaultValue = 0.3f;

      // Position
      ps.Parameters.AddVarying<Vector3F>(ParticleParameterNames.Position);
      ps.Effectors.Add(new StartPositionEffector
      {
        Parameter = ParticleParameterNames.Position,
        DefaultValue = Vector3F.Zero,
      });

      // Velocity
      ps.Parameters.AddVarying<Vector3F>(ParticleParameterNames.Direction);
      ps.Effectors.Add(new StartDirectionEffector
      {
        Parameter = ParticleParameterNames.Direction,
        Distribution = new CircleDistribution { InnerRadius = 1.0f, OuterRadius = 1.0f },
      });

      ps.Parameters.AddUniform<float>(ParticleParameterNames.LinearSpeed).DefaultValue = 20;
      ps.Effectors.Add(new LinearVelocityEffector());

      // Size
      ps.Parameters.AddUniform<float>(ParticleParameterNames.Size).DefaultValue = 2;

      // Alpha
      ps.Parameters.AddVarying<float>(ParticleParameterNames.Alpha);
      ps.Parameters.AddUniform<float>("TargetAlpha").DefaultValue = 1.0f;
      ps.Effectors.Add(new SingleFadeEffector
      {
        ValueParameter = ParticleParameterNames.Alpha,
        TargetValueParameter = "TargetAlpha",
        TimeParameter = ParticleParameterNames.NormalizedAge,
        FadeInStart = 0.0f,
        FadeInEnd = 0.01f,
        FadeOutStart = 0.90f,
        FadeOutEnd = 1.0f,
      });

      // Texture
      ps.Parameters.AddUniform<Texture2D>(ParticleParameterNames.Texture).DefaultValue =
        ContentManager.Load<Texture2D>("Particles/Distortion");

      // Softness
      ps.Parameters.AddUniform<float>(ParticleParameterNames.Softness).DefaultValue = float.NaN; // NaN = automatic

      // Bounding shape
      ps.Shape = new BoxShape(15, 15, 2);

      return ps;
    }
예제 #22
0
    // Is there a particle parameter that is not initialized by a start value effector?
    public static string CheckForUninitializedParticleParameters(ParticleSystem particleSystem)
    {
      // Get the names of all varying particle parameters
      List<string> parameters = particleSystem.Parameters.Where(p => !p.IsUniform).Select(p => p.Name).ToList();

      // "NormalizedAge" is the only parameter handled by the particle system itself.
      parameters.Remove(ParticleParameterNames.NormalizedAge);

      foreach (var effector in particleSystem.Effectors)
      {
        foreach (var propertyInfo in GetProperties(effector))
        {
          // Handle effector properties with a ParticleParameterAttribute.
          var particleParameterAttribute = propertyInfo.GetCustomAttributes(typeof(ParticleParameterAttribute), true).Cast<ParticleParameterAttribute>().FirstOrDefault();
          if (particleParameterAttribute != null)
          {
            var parameterName = propertyInfo.GetValue(effector, null) as string;
            if (!string.IsNullOrEmpty(parameterName) && particleParameterAttribute.Usage == ParticleParameterUsage.Out)
            {
              // The effector initializes this particle parameter.
              parameters.Remove(parameterName);
            }
          }
        }
      }

      if (parameters.Count > 0)
      {
        string message = "Parameters possibly not initialized by any start value effector: ";
        foreach (var parameter in parameters)
          message += string.Format("\"{0}\" ", parameter);
        return message;
      }

      return null;
    }
예제 #23
0
    public static ParticleSystem Create(ContentManager contentManager)
    {
      var ps = new ParticleSystem
      {
        Name = "BeeSwarm",
        MaxNumberOfParticles = 100,
      };

      ps.Parameters.AddUniform<float>(ParticleParameterNames.Lifetime).DefaultValue = float.PositiveInfinity;

      ps.Parameters.AddVarying<Vector3F>(ParticleParameterNames.Position);
      ps.Effectors.Add(new StartPositionEffector
      {
        Parameter = ParticleParameterNames.Position,
        DefaultValue = new Vector3F(0, 0, 0)
      });

      ps.Parameters.AddUniform<float>(ParticleParameterNames.SizeY).DefaultValue = 0.1f;

      // The SizeX is varying because the BeeEffector sets a negative size if the bee should look in the
      // opposite direction.
      ps.Parameters.AddVarying<float>(ParticleParameterNames.SizeX);
      ps.Effectors.Add(new StartValueEffector<float>
      {
        Parameter = ParticleParameterNames.SizeX,
        DefaultValue = 0.1f,
      });

      ps.Parameters.AddVarying<float>(ParticleParameterNames.LinearSpeed);
      ps.Effectors.Add(new StartValueEffector<float>
      {
        Parameter = ParticleParameterNames.LinearSpeed,
        Distribution = new UniformDistributionF(1, 2),
      });

      // The BeeEffector creates the random movement of the bees.
      ps.Parameters.AddVarying<Vector3F>("TargetPosition");
      ps.Parameters.AddUniform<Pose>("CameraPose").DefaultValue = Pose.Identity;
      ps.Effectors.Add(new BeeEffector
      {
        PositionParameter = ParticleParameterNames.Position,
        TargetPositionParameter = "TargetPosition",
        SpeedParameter = ParticleParameterNames.LinearSpeed,
        SizeXParameter = ParticleParameterNames.SizeX,
        CameraPoseParameter = "CameraPose",
        InvertLookDirection = true,
        MaxRange = 4.0f,
      });

      // The texture is a set of 3 images.
      ps.Parameters.AddUniform<PackedTexture>(ParticleParameterNames.Texture).DefaultValue =
        new PackedTexture(
          "Bee",
          contentManager.Load<Texture2D>("Particles/beeWingFlap"),
          Vector2F.Zero, Vector2F.One,
          3, 1);

      // The Frame particle parameter stores the index of the animation frame and the
      // AnimationTime particle parameter stores the current progress in seconds. 
      ps.Parameters.AddVarying<int>("Frame");
      ps.Parameters.AddVarying<float>("AnimationTime");

      // Initialize the AnimationTime with a random value, otherwise all bees would look
      // the same.
      ps.Effectors.Add(new StartValueEffector<float>
      {
        Parameter = "AnimationTime",
        Distribution = new UniformDistributionF(0, 0.125f),
      });

      // The AnimationEffector advances the AnimationTime and sets the Frame. 
      // It changes frames at 24 fps.
      ps.Effectors.Add(new AnimationEffector
      {
        AnimationTimeParameter = "AnimationTime",
        FramesPerSecond = 24,
        NumberOfFrames = 3,
      });

      ParticleSystemValidator.Validate(ps);

      return ps;
    }
예제 #24
0
    public static ParticleSystem Create(ContentManager contentManager)
    {
      var ps = new ParticleSystem
      {
        Name = "BouncingSparks",
        MaxNumberOfParticles = 200,
      };

      ps.Parameters.AddUniform<float>(ParticleParameterNames.Lifetime).DefaultValue = 3;

      ps.Effectors.Add(new StreamEmitter
      {
        DefaultEmissionRate = 40,
      });

      ps.Parameters.AddVarying<Vector3F>(ParticleParameterNames.Position);
      ps.Effectors.Add(new StartPositionEffector
      {
        Parameter = ParticleParameterNames.Position,
        Distribution = new LineSegmentDistribution { Start = new Vector3F(-0.2f, 0, -6), End = new Vector3F(0.2f, 0, -6) }
      });

      // The particles are rendered using axial billboards.
      ps.Parameters.AddUniform<BillboardOrientation>(ParticleParameterNames.BillboardOrientation).DefaultValue = 
        BillboardOrientation.AxialViewPlaneAligned;

      // The "Axis" parameter defines the up-axis of the particle billboard. In this
      // case the "Axis" is the direction of each particle.
      ps.Parameters.AddVarying<Vector3F>(ParticleParameterNames.Axis);
      ps.Effectors.Add(new StartDirectionEffector
      {
        Parameter = ParticleParameterNames.Axis,
        Distribution = new DirectionDistribution { Deviation = 0.3f, Direction = new Vector3F(1, 0.5f, -1f).Normalized },
      });

      ps.Parameters.AddVarying<float>(ParticleParameterNames.LinearSpeed);
      ps.Effectors.Add(new StartValueEffector<float>
      {
        Parameter = ParticleParameterNames.LinearSpeed,
        Distribution = new UniformDistributionF(15, 20),
      });

      ps.Effectors.Add(new LinearVelocityEffector
      {
        DirectionParameter = ParticleParameterNames.Axis,
      });

      ps.Parameters.AddUniform<float>(ParticleParameterNames.Damping).DefaultValue = 0.5f;
      ps.Effectors.Add(new SingleDampingEffector());

      ps.Parameters.AddUniform<Vector3F>(ParticleParameterNames.LinearAcceleration).DefaultValue = new Vector3F(0, -5f, 0);
      ps.Effectors.Add(new LinearAccelerationEffector
      {
        DirectionParameter = ParticleParameterNames.Axis
      });

      // Create a collision plane effector for the ground.
      // We do not position the collision plane at height. Instead, we add a small offset otherwise
      // the particle billboards would be cut off by the visible ground.
      ps.Effectors.Add(new CollisionPlaneEffector
      {
        DirectionParameter = ParticleParameterNames.Axis,
        Plane = new Plane(new Vector3F(0, 1, 0), 0.03f),
      });

      // Add more collision plane effectors for the 4 walls of our sandbox.
      const float offset = 0.08f;
      ps.Effectors.Add(new CollisionPlaneEffector
      {
        DirectionParameter = ParticleParameterNames.Axis,
        Plane = new Plane(new Vector3F(-1, 0, 0), -10 + offset),
      });
      ps.Effectors.Add(new CollisionPlaneEffector
      {
        DirectionParameter = ParticleParameterNames.Axis,
        Plane = new Plane(new Vector3F(0, 0, 1), -10 + offset),
      });
      ps.Effectors.Add(new CollisionPlaneEffector
      {
        DirectionParameter = ParticleParameterNames.Axis,
        Plane = new Plane(new Vector3F(1, 0, 0), -10 + offset),
      });
      ps.Effectors.Add(new CollisionPlaneEffector
      {
        DirectionParameter = ParticleParameterNames.Axis,
        Plane = new Plane(new Vector3F(0, 0, -1), -10 + offset),
      });

      // Particles billboards get stretched in the y-direction. The stretch is time-dependent.
      // (The y-direction of a particle is defined by the "Axis" parameter.)
      ps.Parameters.AddUniform<float>(ParticleParameterNames.SizeX).DefaultValue = 0.05f;
      ps.Parameters.AddVarying<float>(ParticleParameterNames.SizeY);
      ps.Effectors.Add(new SingleLinearSegment3Effector
      {
        OutputParameter = ParticleParameterNames.SizeY,
        Time0 = 0,
        Value0 = 0.05f,
        Time1 = 0.01f,
        Value1 = 0.5f,
        Time2 = 1,
        Value2 = 0.03f,
      });

      ps.Parameters.AddUniform<Vector3F>("StartColor").DefaultValue = new Vector3F(1.0f, 1.0f, 0.8f);
      ps.Parameters.AddUniform<Vector3F>("EndColor").DefaultValue = new Vector3F(1.0f, 0.3f, 0.0f);
      ps.Parameters.AddVarying<Vector3F>(ParticleParameterNames.Color);
      ps.Effectors.Add(new Vector3FLerpEffector
      {
        ValueParameter = ParticleParameterNames.Color,
        StartParameter = "StartColor",
        EndParameter = "EndColor",
      });

      ps.Parameters.AddVarying<float>(ParticleParameterNames.Alpha);
      ps.Parameters.AddUniform<float>("TargetAlpha").DefaultValue = 1f;
      ps.Effectors.Add(new SingleFadeEffector
      {
        ValueParameter = ParticleParameterNames.Alpha,
        TargetValueParameter = "TargetAlpha",
        FadeInStart = 0f,
        FadeInEnd = 0.0f,
        FadeOutStart = 0.99f,
        FadeOutEnd = 1f,
      });

      ps.Parameters.AddUniform<Texture2D>(ParticleParameterNames.Texture).DefaultValue =
        contentManager.Load<Texture2D>("Particles/Spark");

      ps.Parameters.AddUniform<float>(ParticleParameterNames.BlendMode).DefaultValue = 0.0f;
      
      return ps;
    }
예제 #25
0
    public BasicParticlesSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      // Create a new "empty" particle system.
      _particleSystem = new ParticleSystem();

      // Names are optional, but very useful for debugging.
      _particleSystem.Name = "MyFirstParticleSystem";

      // The particle system uses pre-allocated arrays. We should define an upper limit for
      // the number of particles that can be alive at the same moment.
      _particleSystem.MaxNumberOfParticles = 200;

      // The particle system's Pose defines the position and orientation of the particle system
      // in the world. 
      _particleSystem.Pose = new Pose(new Vector3F(0, 2, 0));

      // The properties of the particles in the particle system are defined using 
      // "particle parameters" (in the collection _particleSystem.Parameters).
      // Per default, there is only one parameter: "NormalizedAge" - which is managed
      // by the particle system itself and is the age of a particle in the range 0 - 1.

      // All our particles should live for 1 second after they have been created. Therefore,
      // we add a "uniform" parameter called "Lifetime" and set it to 1.
      var lifetimeParameter = _particleSystem.Parameters.AddUniform<float>("Lifetime");
      lifetimeParameter.DefaultValue = 1f;

      // Each particle should have a position value. Therefore, we add a "varying" parameter
      // called "Position". "Varying" means that each particle has its own position value.
      // The particle system will internally allocate a Vector3F array to store all particle
      // positions.
      _particleSystem.Parameters.AddVarying<Vector3F>("Position");

      // When particles are created, we want them to appear at random position in a spherical
      // volume. We add an effector which initializes the particle "Positions" of newly created
      // particles.
      _particleSystem.Effectors.Add(new StartPositionEffector
      {
        // This effector should initialize the "Position" parameter.
        // Parameter = "Position",     // "Position" is the default value anyway.

        // The start values should be chosen from this random value distribution:
        Distribution = new SphereDistribution { OuterRadius = 2 }
      });

      // The particles should slowly fade in and out to avoid sudden appearance and disappearance.
      // We add a varying particle parameter called "Alpha" to store the alpha value per particle.
      _particleSystem.Parameters.AddVarying<float>("Alpha");

      // The SingleFadeEffector animates a float parameter from 0 to a target value and
      // back to 0.
      _particleSystem.Effectors.Add(new SingleFadeEffector
      {
        // If TargetValueParameter is not set, then the target value is 1.
        //TargetValueParameter = 1,

        // The fade-in/out times are relative to a time parameter. 
        // By default the "NormalizedAge" of the particles is used.
        //TimeParameter = "NormalizedAge",

        // The Alpha value should be animated.
        ValueParameter = "Alpha",

        // The fade-in/out times relative to the normalized age.
        FadeInStart = 0.0f,
        FadeInEnd = 0.3f,
        FadeOutStart = 0.5f,
        FadeOutEnd = 1.0f,
      });

      // Next, we choose a texture for the particles. All particles use the same texture 
      // parameter, which means the parameter is "uniform".
      var textureParameter = _particleSystem.Parameters.AddUniform<Texture2D>("Texture");
      textureParameter.DefaultValue = ContentManager.Load<Texture2D>("Particles/LensFlare");

      // The blend mode is a value between 0 and 1, where 0 means additive blending
      // 1 means alpha blending. Values between 0 and 1 are allowed. The particles in
      // this example should be drawn using additive alpha blending. 
      var blendModeParameter = _particleSystem.Parameters.AddUniform<float>("BlendMode");
      blendModeParameter.DefaultValue = 0.0f;

      // There is a lot to configure. Did we forget anything? - We can use an optional helper method
      // to validate our particle system. Uninitialized or missing parameters are printed to the
      // Console. Check the Visual Studio Output window for any messages.
      ParticleSystemValidator.Validate(_particleSystem);

      // Adding the particle system to a ParticleSystemService is optional but very useful
      // because the service will update the particle system for us in each frame.
      ParticleSystemService.ParticleSystems.Add(_particleSystem);

      // To render the particle effect, we need to create a scene node and add it to the
      // scene graph.
      _particleSystemNode = new ParticleSystemNode(_particleSystem);
      GraphicsScreen.Scene.Children.Add(_particleSystemNode);

      // A tip for the future: 
      // The class ParticleParameterNames is a collection of strings that can be used for 
      // common particle parameters. It is recommended to use the particle parameter names in
      // this class to avoid problems because of typing errors in the source code.
    }
예제 #26
0
        public void Update(ParticleSystem particleSystem)
        {
            Particles.Clear();

              var numberOfParticles = particleSystem.NumberOfActiveParticles;
              if (numberOfParticles == 0)
              {
            // Clear texture reference to allow garbage collection.
            // (Only relevant, if user switches texture.)
            Texture = null;
            return;
              }

              // Pose (relative to root particle system)
              var parent = particleSystem.Parent;
              if (parent == null)
              {
            Pose = Pose.Identity;
              }
              else
              {
            // Collect all poses except for the root particle system pose.
            Pose = particleSystem.Pose;
            while (parent.Parent != null)
            {
              Pose = parent.Pose * Pose;
              parent = parent.Parent;
            }
              }

              // ReferenceFrame
              ReferenceFrame = particleSystem.ReferenceFrame;

              // ----- Uniform particle parameters
              // Texture
              var packedTextureParameter = TextureParameter as IParticleParameter<PackedTexture>;
              if (packedTextureParameter != null)
              {
            Texture = packedTextureParameter.DefaultValue;
              }
              else
              {
            var textureParameter = TextureParameter as IParticleParameter<Texture2D>;
            if (textureParameter != null)
            {
              var texture = textureParameter.DefaultValue;
              if (texture != null)
              {
            if (Texture == null || Texture.TextureAtlas != texture)
              Texture = new PackedTexture(texture);
              }
              else
              {
            Texture = null;
              }
            }
              }

              // Particles are not rendered without a texture.
              if (Texture == null)
            return;

              float aspectRatio = 1.0f;
              if (Texture != null)
              {
            var texture = Texture.TextureAtlas;
            float textureAspectRatio = (float)texture.Width / texture.Height;
            Vector2F texCoordTopLeft = Texture.Offset;
            Vector2F texCoordBottomRight = Texture.Offset + (Texture.Scale / new Vector2F(Texture.NumberOfColumns, Texture.NumberOfRows));
            aspectRatio = textureAspectRatio * (texCoordBottomRight.X - texCoordTopLeft.X) / (texCoordBottomRight.Y - texCoordTopLeft.Y);
              }

              // AlphaTest
              AlphaTest = (AlphaTestParameter != null) ? AlphaTestParameter.DefaultValue : 0.0f;

              // BillboardOrientation
              BillboardOrientation = (BillboardOrientationParameter != null) ? BillboardOrientationParameter.DefaultValue : BillboardOrientation.ViewPlaneAligned;

              // DrawOrder
              DrawOrder = (DrawOrderParameter != null) ? DrawOrderParameter.DefaultValue : 0;

              // IsDepthSorted
              IsDepthSorted = (IsDepthSortedParameter != null) ? IsDepthSortedParameter.DefaultValue : false;

              // Softness
              Softness = (SoftnessParameter != null) ? SoftnessParameter.DefaultValue : 0;
              if (Numeric.IsNaN(Softness))
            Softness = -1;

              // ParticleType (particles vs. ribbons)
              IsRibbon = (TypeParameter != null) ? (TypeParameter.DefaultValue == ParticleType.Ribbon) : false;

              // StartsAtOrigin
              //StartsAtOrigin = (StartsAtOriginParameter != null) ? StartsAtOriginParameter.DefaultValue : false;

              // TextureTiling
              TextureTiling = (TextureTilingParameter != null) ? TextureTilingParameter.DefaultValue : 0;

              // ----- Varying particle parameters
              Particles.AddRange(numberOfParticles); // Values are set below.

              var targetArray = Particles.Array;

              // Determine default size of particles. If one dimension is missing, calculate the
              // missing value using the aspect ratio of the texture.
              Vector2F size = Vector2F.One;
              if (SizeParameter != null)
            size = new Vector2F(SizeParameter.DefaultValue);
              if (SizeXParameter != null)
            size.X = SizeXParameter.DefaultValue;
              if (SizeYParameter != null)
            size.Y = SizeYParameter.DefaultValue;
              if (SizeParameter == null && SizeXParameter != null && SizeYParameter == null)
            size.Y = size.X / aspectRatio;
              if (SizeParameter == null && SizeXParameter == null && SizeYParameter != null)
            size.X = size.Y * aspectRatio;

              // Initialize particles with default values.
              var defaultParticle = new Particle
              {
            Position = (PositionParameter != null) ? PositionParameter.DefaultValue : new Vector3F(),
            Normal = (NormalParameter != null) ? NormalParameter.DefaultValue : Vector3F.UnitZ,
            Axis = (AxisParameter != null) ? AxisParameter.DefaultValue : Vector3F.Up,
            Size = size,
            Angle = (AngleParameter != null) ? AngleParameter.DefaultValue : 0.0f,
            Color = (ColorParameter != null) ? ColorParameter.DefaultValue : Vector3F.One,
            Alpha = (AlphaParameter != null) ? AlphaParameter.DefaultValue : 1.0f,
            BlendMode = (BlendModeParameter != null) ? BlendModeParameter.DefaultValue : 1.0f,

            // AnimationTime is initialized with NormalizedAge below.
              };

              for (int i = 0; i < numberOfParticles; i++)
            targetArray[i] = defaultParticle;

              int startIndex = particleSystem.ParticleStartIndex;
              int totalCount = numberOfParticles;
              int count0 = totalCount;
              int endIndex0 = startIndex + count0;
              int endIndex1 = 0;
              if (endIndex0 > particleSystem.MaxNumberOfParticles)
              {
            count0 = particleSystem.MaxNumberOfParticles - startIndex;
            endIndex0 = particleSystem.MaxNumberOfParticles;
            endIndex1 = numberOfParticles - count0;
              }

              // NormalizedAge
              if (NormalizedAgeParameter != null && !NormalizedAgeParameter.IsUniform)
              {
            var sourceArray = NormalizedAgeParameter.Values;
            for (int sourceIndex = startIndex, targetIndex = 0; sourceIndex < endIndex0; sourceIndex++, targetIndex++)
            {
              targetArray[targetIndex].IsAlive = (sourceArray[sourceIndex] < 1.0f);
              targetArray[targetIndex].AnimationTime = sourceArray[sourceIndex];
            }

            for (int sourceIndex = 0, targetIndex = count0; sourceIndex < endIndex1; sourceIndex++, targetIndex++)
            {
              targetArray[targetIndex].IsAlive = (sourceArray[sourceIndex] < 1.0f);
              targetArray[targetIndex].AnimationTime = sourceArray[sourceIndex];
            }
              }

              // Position
              if (PositionParameter != null && !PositionParameter.IsUniform)
              {
            var sourceArray = PositionParameter.Values;
            for (int sourceIndex = startIndex, targetIndex = 0; sourceIndex < endIndex0; sourceIndex++, targetIndex++)
              targetArray[targetIndex].Position = sourceArray[sourceIndex];

            for (int sourceIndex = 0, targetIndex = count0; sourceIndex < endIndex1; sourceIndex++, targetIndex++)
              targetArray[targetIndex].Position = sourceArray[sourceIndex];
              }

              // Normal
              if (NormalParameter != null && !NormalParameter.IsUniform)
              {
            var sourceArray = NormalParameter.Values;
            for (int sourceIndex = startIndex, targetIndex = 0; sourceIndex < endIndex0; sourceIndex++, targetIndex++)
              targetArray[targetIndex].Normal = sourceArray[sourceIndex];

            for (int sourceIndex = 0, targetIndex = count0; sourceIndex < endIndex1; sourceIndex++, targetIndex++)
              targetArray[targetIndex].Normal = sourceArray[sourceIndex];
              }

              // Axis
              if (AxisParameter != null && !AxisParameter.IsUniform)
              {
            var sourceArray = AxisParameter.Values;
            for (int sourceIndex = startIndex, targetIndex = 0; sourceIndex < endIndex0; sourceIndex++, targetIndex++)
              targetArray[targetIndex].Axis = sourceArray[sourceIndex];

            for (int sourceIndex = 0, targetIndex = count0; sourceIndex < endIndex1; sourceIndex++, targetIndex++)
              targetArray[targetIndex].Axis = sourceArray[sourceIndex];
              }

              // Size
              if (SizeParameter != null && !SizeParameter.IsUniform)
              {
            var sourceArray = SizeParameter.Values;
            for (int sourceIndex = startIndex, targetIndex = 0; sourceIndex < endIndex0; sourceIndex++, targetIndex++)
              targetArray[targetIndex].Size = new Vector2F(sourceArray[sourceIndex]);

            for (int sourceIndex = 0, targetIndex = count0; sourceIndex < endIndex1; sourceIndex++, targetIndex++)
              targetArray[targetIndex].Size = new Vector2F(sourceArray[sourceIndex]);
              }
              if (SizeXParameter != null && !SizeXParameter.IsUniform)
              {
            var sourceArray = SizeXParameter.Values;
            for (int sourceIndex = startIndex, targetIndex = 0; sourceIndex < endIndex0; sourceIndex++, targetIndex++)
              targetArray[targetIndex].Size.X = sourceArray[sourceIndex];

            for (int sourceIndex = 0, targetIndex = count0; sourceIndex < endIndex1; sourceIndex++, targetIndex++)
              targetArray[targetIndex].Size.X = sourceArray[sourceIndex];
              }
              if (SizeYParameter != null && !SizeYParameter.IsUniform)
              {
            var sourceArray = SizeYParameter.Values;
            for (int sourceIndex = startIndex, targetIndex = 0; sourceIndex < endIndex0; sourceIndex++, targetIndex++)
              targetArray[targetIndex].Size.Y = sourceArray[sourceIndex];

            for (int sourceIndex = 0, targetIndex = count0; sourceIndex < endIndex1; sourceIndex++, targetIndex++)
              targetArray[targetIndex].Size.Y = sourceArray[sourceIndex];
              }
              if (SizeParameter == null && SizeXParameter != null && !SizeXParameter.IsUniform && SizeYParameter == null)
              {
            for (int i = 0; i < numberOfParticles; i++)
              targetArray[i].Size.Y = targetArray[i].Size.X / aspectRatio;
              }
              if (SizeParameter == null && SizeXParameter == null && SizeYParameter != null && !SizeYParameter.IsUniform)
              {
            for (int i = 0; i < numberOfParticles; i++)
              targetArray[i].Size.X = targetArray[i].Size.Y * aspectRatio;
              }

              // Angle
              if (AngleParameter != null && !AngleParameter.IsUniform)
              {
            var sourceArray = AngleParameter.Values;
            for (int sourceIndex = startIndex, targetIndex = 0; sourceIndex < endIndex0; sourceIndex++, targetIndex++)
              targetArray[targetIndex].Angle = sourceArray[sourceIndex];

            for (int sourceIndex = 0, targetIndex = count0; sourceIndex < endIndex1; sourceIndex++, targetIndex++)
              targetArray[targetIndex].Angle = sourceArray[sourceIndex];
              }

              // Color
              if (ColorParameter != null && !ColorParameter.IsUniform)
              {
            var sourceArray = ColorParameter.Values;
            for (int sourceIndex = startIndex, targetIndex = 0; sourceIndex < endIndex0; sourceIndex++, targetIndex++)
              targetArray[targetIndex].Color = sourceArray[sourceIndex];

            for (int sourceIndex = 0, targetIndex = count0; sourceIndex < endIndex1; sourceIndex++, targetIndex++)
              targetArray[targetIndex].Color = sourceArray[sourceIndex];
              }

              // Alpha
              if (AlphaParameter != null && !AlphaParameter.IsUniform)
              {
            var sourceArray = AlphaParameter.Values;
            for (int sourceIndex = startIndex, targetIndex = 0; sourceIndex < endIndex0; sourceIndex++, targetIndex++)
              targetArray[targetIndex].Alpha = sourceArray[sourceIndex];

            for (int sourceIndex = 0, targetIndex = count0; sourceIndex < endIndex1; sourceIndex++, targetIndex++)
              targetArray[targetIndex].Alpha = sourceArray[sourceIndex];
              }

              // AnimationTime
              if (AnimationTimeParameter != null)
              {
            // AnimationTime has been initialized with NormalizedAge for automatic animations.
            // But the "AnimationTime" parameter is set explicitly!
            if (AnimationTimeParameter.IsUniform)
            {
              float animationTime = AnimationTimeParameter.DefaultValue;
              for (int i = 0; i < numberOfParticles; i++)
            targetArray[i].AnimationTime = animationTime;
            }
            else
            {
              var sourceArray = AnimationTimeParameter.Values;
              for (int sourceIndex = startIndex, targetIndex = 0; sourceIndex < endIndex0; sourceIndex++, targetIndex++)
            targetArray[targetIndex].AnimationTime = sourceArray[sourceIndex];

              for (int sourceIndex = 0, targetIndex = count0; sourceIndex < endIndex1; sourceIndex++, targetIndex++)
            targetArray[targetIndex].AnimationTime = sourceArray[sourceIndex];
            }
              }

              // BlendMode
              if (BlendModeParameter != null && !BlendModeParameter.IsUniform)
              {
            var sourceArray = BlendModeParameter.Values;
            for (int sourceIndex = startIndex, targetIndex = 0; sourceIndex < endIndex0; sourceIndex++, targetIndex++)
              targetArray[targetIndex].BlendMode = sourceArray[sourceIndex];

            for (int sourceIndex = 0, targetIndex = count0; sourceIndex < endIndex1; sourceIndex++, targetIndex++)
              targetArray[targetIndex].BlendMode = sourceArray[sourceIndex];
              }
        }
예제 #27
0
        //--------------------------------------------------------------
        public void RequeryParameters(ParticleSystem particleSystem)
        {
            var parameters = particleSystem.Parameters;

              // Uniform particle parameters.
              TextureParameter = parameters.GetUnchecked<PackedTexture>(ParticleParameterNames.Texture);
              if (TextureParameter == null)
            TextureParameter = parameters.GetUnchecked<Texture2D>(ParticleParameterNames.Texture);
              AlphaTestParameter = parameters.Get<float>(ParticleParameterNames.AlphaTest);
              BillboardOrientationParameter = parameters.Get<BillboardOrientation>(ParticleParameterNames.BillboardOrientation);
              DrawOrderParameter = parameters.Get<int>(ParticleParameterNames.DrawOrder);
              IsDepthSortedParameter = parameters.Get<bool>(ParticleParameterNames.IsDepthSorted);
              TypeParameter = parameters.Get<ParticleType>(ParticleParameterNames.Type);
              TextureTilingParameter = parameters.Get<int>(ParticleParameterNames.TextureTiling);

              // Uniform or varying particle parameters.
              NormalizedAgeParameter = parameters.Get<float>(ParticleParameterNames.NormalizedAge);
              PositionParameter = parameters.Get<Vector3F>(ParticleParameterNames.Position);
              NormalParameter = parameters.Get<Vector3F>(ParticleParameterNames.Normal);
              AxisParameter = parameters.Get<Vector3F>(ParticleParameterNames.Axis);
              SizeParameter = parameters.Get<float>(ParticleParameterNames.Size);
              SizeXParameter = parameters.Get<float>(ParticleParameterNames.SizeX);
              SizeYParameter = parameters.Get<float>(ParticleParameterNames.SizeY);
              AngleParameter = parameters.Get<float>(ParticleParameterNames.Angle);
              ColorParameter = parameters.Get<Vector3F>(ParticleParameterNames.Color);
              AlphaParameter = parameters.Get<float>(ParticleParameterNames.Alpha);
              AnimationTimeParameter = parameters.Get<float>(ParticleParameterNames.AnimationTime);
              BlendModeParameter = parameters.Get<float>(ParticleParameterNames.BlendMode);
              SoftnessParameter = parameters.Get<float>(ParticleParameterNames.Softness);
              //StartsAtOriginParameter = parameters.Get<bool>(ParticleParameterNames.StartsAtOrigin);
        }
예제 #28
0
    public static ParticleSystem Create(ContentManager contentManager)
    {
      ParticleSystem ps = new ParticleSystem
      {
        Name = "Smoke",
        MaxNumberOfParticles = 200,
      };

      // All particles should live for 5 seconds.
      ps.Parameters.AddUniform<float>(ParticleParameterNames.Lifetime).DefaultValue = 5;

      // Add an effector that emits particles at a constant rate.
      ps.Effectors.Add(new StreamEmitter
      {
        DefaultEmissionRate = 30,
      });

      // The reference frame can be either "Local" or "World" (Default).
      // - "Local" means that the particle positions, directions, velocities, etc.
      //   are relative to the ParticleSystemNode in the scene graph.
      // - "World" means that those values are given in world space. The position
      //   of the ParticleSystemNode in the scene graph does not affect the particles. 
      // (For more information check out sample "11-ReferenceFrame".)
      ps.ReferenceFrame = ParticleReferenceFrame.Local;

      // Particle positions start in the center of the particle system.
      ps.Parameters.AddVarying<Vector3F>(ParticleParameterNames.Position);
      ps.Effectors.Add(new StartPositionEffector
      {
        Parameter = ParticleParameterNames.Position,
        DefaultValue = Vector3F.Zero,
      });

      // Particles move in the up direction with a random deviation of 0.5 radians and a 
      // random speed.
      ps.Parameters.AddVarying<Vector3F>(ParticleParameterNames.Direction);
      ps.Effectors.Add(new StartDirectionEffector
      {
        Parameter = ParticleParameterNames.Direction,
        Distribution = new DirectionDistribution { Deviation = 0.5f, Direction = Vector3F.Up },
      });
      ps.Parameters.AddVarying<float>(ParticleParameterNames.LinearSpeed);
      ps.Effectors.Add(new StartValueEffector<float>
      {
        Parameter = ParticleParameterNames.LinearSpeed,
        Distribution = new UniformDistributionF(0.5f, 1),
      });

      // The LinearVelocityEffector uses the Direction and LinearSpeed to update the Position
      // of particles.
      ps.Effectors.Add(new LinearVelocityEffector
      {
        // Following parameters are equal to the default values. No need to set them.
        //PositionParameter = ParticleParameterNames.Position,
        //DirectionParameter = ParticleParameterNames.Direction,
        //SpeedParameter = ParticleParameterNames.LinearSpeed,
      });

      // To create a wind effect, we apply an acceleration to all particles.
      ps.Parameters.AddUniform<Vector3F>(ParticleParameterNames.LinearAcceleration).DefaultValue =
        new Vector3F(0.2f, -0.1f, 0);

      ps.Effectors.Add(new LinearAccelerationEffector
      {
        // Following parameters are equal to the default values. No need to set them.
        //AccelerationParameter = ParticleParameterNames.LinearAcceleration,
        //DirectionParameter = ParticleParameterNames.Direction,
        //SpeedParameter = ParticleParameterNames.LinearSpeed,        
      });

      // Each particle starts with a random rotation angle and a random angular speed.
      ps.Parameters.AddVarying<float>(ParticleParameterNames.Angle);
      ps.Effectors.Add(new StartValueEffector<float>
      {
        Parameter = ParticleParameterNames.Angle,
        Distribution = new UniformDistributionF(-ConstantsF.Pi, ConstantsF.Pi),
      });
      ps.Parameters.AddVarying<float>(ParticleParameterNames.AngularSpeed);
      ps.Effectors.Add(new StartValueEffector<float>
      {
        Parameter = ParticleParameterNames.AngularSpeed,
        Distribution = new UniformDistributionF(-2, 2),
      });
      // The AngularVelocityEffector uses the AngularSpeed to update the particle Angle.
      ps.Effectors.Add(new AngularVelocityEffector
      {
        // Following parameters are equal to the default values. No need to set them.
        //AngleParameter = ParticleParameterNames.Angle,
        //SpeedParameter = ParticleParameterNames.AngularSpeed,
      });

      ps.Parameters.AddVarying<float>("StartSize");
      ps.Effectors.Add(new StartValueEffector<float>
      {
        Parameter = "StartSize",
        Distribution = new UniformDistributionF(0.1f, 0.5f),
      });

      ps.Parameters.AddVarying<float>("EndSize");
      ps.Effectors.Add(new StartValueEffector<float>
      {
        Parameter = "EndSize",
        Distribution = new UniformDistributionF(2, 4),
      });

      ps.Parameters.AddVarying<float>(ParticleParameterNames.Size);
      ps.Effectors.Add(new SingleLerpEffector
      {
        ValueParameter = ParticleParameterNames.Size,
        StartParameter = "StartSize",
        EndParameter = "EndSize",
      });

      // Particle alpha fades in to a target value of 1 and then back out to 0.
      ps.Parameters.AddVarying<float>(ParticleParameterNames.Alpha);
      ps.Parameters.AddUniform<float>("TargetAlpha").DefaultValue = 1f;
      ps.Effectors.Add(new SingleFadeEffector
      {
        ValueParameter = ParticleParameterNames.Alpha,
        TargetValueParameter = "TargetAlpha",
        FadeInStart = 0f,
        FadeInEnd = 0.2f,
        FadeOutStart = 0.7f,
        FadeOutEnd = 1f,
      });

      ps.Parameters.AddUniform<Texture2D>(ParticleParameterNames.Texture).DefaultValue =
        contentManager.Load<Texture2D>("Particles/Smoke");

      ParticleSystemValidator.Validate(ps);

      return ps;
    }
예제 #29
0
    public static ParticleSystem Create(ContentManager contentManager)
    {
      var ps = new ParticleSystem
      {
        Name = "Ribbon",
        MaxNumberOfParticles = 50,
      };

      // Ribbons are enabled by setting the "Type" to ParticleType.Ribbon. Consecutive 
      // living particles are connected and rendered as ribbons (quad strips). At least 
      // two living particles are required to create a ribbon. Dead particles 
      // ("NormalizedAge" ≥ 1) can be used as delimiters to terminate one ribbon and 
      // start the next ribbon. 
      ps.Parameters.AddUniform<ParticleType>(ParticleParameterNames.Type).DefaultValue =
        ParticleType.Ribbon;

      ps.Parameters.AddUniform<float>(ParticleParameterNames.Lifetime).DefaultValue = 1;

      ps.Parameters.AddVarying<Vector3F>(ParticleParameterNames.Position);
      ps.Effectors.Add(new StartPositionEffector());

      // The parameter "Axis" determines the orientation of the ribbon. 
      // We could use a fixed orientation. It is also possible to "twist" the ribbon
      // by using a varying parameter.
      //ps.Parameters.AddUniform<Vector3F>(ParticleParameterNames.Axis).DefaultValue =
      //  Vector3F.Up;

      ps.Effectors.Add(new RibbonEffector());
      ps.Effectors.Add(new ReserveParticleEffector { Reserve = 1 });

      ps.Parameters.AddUniform<float>(ParticleParameterNames.Size).DefaultValue = 1;

      ps.Parameters.AddVarying<Vector3F>(ParticleParameterNames.Color);
      ps.Effectors.Add(new StartValueEffector<Vector3F>
      {
        Parameter = ParticleParameterNames.Color,
        Distribution = new BoxDistribution { MinValue = new Vector3F(0.5f, 0.5f, 0.5f), MaxValue = new Vector3F(1, 1, 1) }
      });

      ps.Parameters.AddVarying<float>(ParticleParameterNames.Alpha);
      ps.Effectors.Add(new FuncEffector<float, float>
      {
        InputParameter = ParticleParameterNames.NormalizedAge,
        OutputParameter = ParticleParameterNames.Alpha,
        Func = age => 6.7f * age * (1 - age) * (1 - age),
      });

      ps.Parameters.AddUniform<Texture2D>(ParticleParameterNames.Texture).DefaultValue =
        contentManager.Load<Texture2D>("Particles/Ribbon");

      // The parameter "TextureTiling" defines how the texture spreads across the ribbon.
      // 0 ... no tiling, 
      // 1 ... repeat every particle, 
      // n ... repeat every n-th particle
      ps.Parameters.AddUniform<int>(ParticleParameterNames.TextureTiling).DefaultValue =
        1;

      ps.Parameters.AddUniform<float>(ParticleParameterNames.BlendMode).DefaultValue = 0;

      ParticleSystemValidator.Validate(ps);

      return ps;
    }
예제 #30
0
 //--------------------------------------------------------------
 /// <summary>
 /// Initializes a new instance of the <see cref="ParticleSystemData" /> class.
 /// </summary>
 /// <param name="particleSystem">The particle system.</param>
 public ParticleSystemData(ParticleSystem particleSystem)
 {
     RequeryParameters(particleSystem);
       Particles = new ArrayList<Particle>(Math.Max(particleSystem.NumberOfActiveParticles, 8));
 }