private static void SetupParticles(EngineContext engineContext) { // Create particle system var particleSystem = new SiliconStudio.Xenko.Particles.ParticleSystem(); // Set particle default size to 10.0f particleSystem.GetOrCreateFieldWithDefault(ParticleFields.Size, 10.0f); // Add particle plugins particleSystem.Plugins.Add(new ResetAcceleration()); particleSystem.Plugins.Add(new SimpleEmitter()); particleSystem.Plugins.Add(new RemoveOldParticles(10.0f)); particleSystem.Plugins.Add(new Gravity()); particleSystem.Plugins.Add(new UpdateVelocity()); // Create particle system mesh for rendering. var particleEffect = engineContext.RenderContext.Effects.First(x => x.Name == "DefaultParticle"); var particleMesh = new EffectMesh(particleEffect); particleMesh.Parameters.Set(ParticleRendererPlugin.ParticleSystemKey, particleSystem); // Load particle texture var smokeVolTexture = (Texture2D)engineContext.AssetManager.Load <Texture>("/global_data/gdc_demo/fx/smokevol.dds"); particleMesh.Parameters.Set(TexturingKeys.DiffuseTexture, smokeVolTexture); // Register it to rendering engineContext.RenderContext.GlobalMeshes.AddMesh(particleMesh); }
public unsafe void Update(ParticleSystem particleSystem, float dt) { var accelerationField = particleSystem.GetOrCreateField(ParticleFields.Acceleration); foreach (var particle in particleSystem) { var acceleration = (Vector3*)particle[accelerationField]; *acceleration += GravityForce; } }
public void Update(ParticleSystem particleSystem, float dt) { var velocityField = particleSystem.GetOrCreateField(ParticleFields.Velocity); // No more than 1000 particles if (particleSystem.ParticleCount < 1000) { var particle = particleSystem.AddParticle(); // Default random velocity, going upward particle.Set(velocityField, new Vector3((float)rand.NextDouble() * 30.0f - 15.0f, (float)rand.NextDouble() * 30.0f - 15.0f, (float)rand.NextDouble() * 50.0f)); } }
public unsafe void Update(ParticleSystem particleSystem, float dt) { var lifetimeField = particleSystem.GetOrCreateField(LifetimeField); // Iterate over particles var particleEnumerator = particleSystem.GetEnumerator(); while (particleEnumerator.MoveNext()) { var particle = particleEnumerator.Current; var lifetime = (float*)particle[lifetimeField]; // Remove particle through enumerator. // Enumerator will be valid again in next loop. if ((*lifetime += dt) > Lifetime) particleEnumerator.RemoveParticle(); } }
/// <summary> /// Updates the location matrices of all elements. Needs to be called even when the particle system is paused for updating the render positions /// </summary> /// <param name="parentSystem"><see cref="ParticleSystem"/> containing this emitter</param> private void UpdateLocations(ParticleSystem parentSystem) { drawTransform.Position = parentSystem.Translation; drawTransform.Rotation = parentSystem.Rotation; drawTransform.ScaleUniform = parentSystem.UniformScale; drawTransform.SetParentTransform(null); if (simulationSpace == EmitterSimulationSpace.World) { // Update sub-systems initialDefaultFields.SetParentTRS(ref parentSystem.Translation, ref parentSystem.Rotation, parentSystem.UniformScale); foreach (var initializer in Initializers) { initializer.SetParentTRS(drawTransform, parentSystem); } foreach (var updater in Updaters) { updater.SetParentTRS(drawTransform, parentSystem); } } else { var posIdentity = new Vector3(0, 0, 0); var rotIdentity = Quaternion.Identity; // Update sub-systems initialDefaultFields.SetParentTRS(ref posIdentity, ref rotIdentity, 1f); foreach (var initializer in Initializers) { initializer.SetParentTRS(identityTransform, parentSystem); } foreach (var updater in Updaters) { updater.SetParentTRS(identityTransform, parentSystem); } } }
/// <summary> /// Some parameters should be initialized when the emitter first runs, rather than in the constructor /// </summary> protected unsafe void DelayedInitialization(ParticleSystem parentSystem) { if (hasBeenInitialized) return; hasBeenInitialized = true; // RandomNumberGenerator creation { uint rngSeed = 0; // EmitterRandomSeedMethod.Fixed if (randomSeedMethod == EmitterRandomSeedMethod.Time) { // Stopwatch has maximum possible frequency, so rngSeeds initialized at different times will be different rngSeed = unchecked((uint)Stopwatch.GetTimestamp()); } else if (randomSeedMethod == EmitterRandomSeedMethod.Position) { // Different float have different uint representation so randomness should be good // The only problem occurs when the three position components are the same var posX = parentSystem.Translation.X; var posY = parentSystem.Translation.Y; var posZ = parentSystem.Translation.Z; var uintX = *((uint*)(&posX)); var uintY = *((uint*)(&posY)); var uintZ = *((uint*)(&posZ)); // Add some randomness to prevent glitches when positions are the same (diagonal) uintX ^= (uintX >> 19); uintY ^= (uintY >> 8); rngSeed = uintX ^ uintY ^ uintZ; } RandomSeedGenerator = new ParticleRandomSeedGenerator(rngSeed); } }
/// <summary> /// Updates the emitter and all its particles, and applies all updaters and spawners. /// </summary> /// <param name="dt">Delta time, elapsed time since the last call, in seconds</param> /// <param name="parentSystem">The parent <see cref="ParticleSystem"/> containing this emitter</param> public void Update(float dt, ParticleSystem parentSystem) { cachedParentSystem = parentSystem; if (!hasBeenInitialized) { DelayedInitialization(parentSystem); } UpdateLocations(parentSystem); EnsurePoolCapacity(); MoveAndDeleteParticles(dt); ApplyParticleUpdaters(dt); SpawnNewParticles(dt); ApplyParticlePostUpdaters(dt); }
/// <summary> /// Call this update when the <see cref="ParticleSystem"/> is paused to only update the renreding information /// </summary> /// <param name="parentSystem">The parent <see cref="ParticleSystem"/> containing this emitter</param> public void UpdatePaused(ParticleSystem parentSystem) { cachedParentSystem = parentSystem; UpdateLocations(parentSystem); }
private static void SetupParticles(EngineContext engineContext) { // Create particle system var particleSystem = new SiliconStudio.Xenko.Particles.ParticleSystem(); // Set particle default size to 10.0f particleSystem.GetOrCreateFieldWithDefault(ParticleFields.Size, 10.0f); // Add particle plugins particleSystem.Plugins.Add(new ResetAcceleration()); particleSystem.Plugins.Add(new SimpleEmitter()); particleSystem.Plugins.Add(new RemoveOldParticles(10.0f)); particleSystem.Plugins.Add(new Gravity()); particleSystem.Plugins.Add(new UpdateVelocity()); // Create particle system mesh for rendering. var particleEffect = engineContext.RenderContext.Effects.First(x => x.Name == "DefaultParticle"); var particleMesh = new EffectMesh(particleEffect); particleMesh.Parameters.Set(ParticleRendererPlugin.ParticleSystemKey, particleSystem); // Load particle texture var smokeVolTexture = (Texture2D)engineContext.AssetManager.Load<Texture>("/global_data/gdc_demo/fx/smokevol.dds"); particleMesh.Parameters.Set(TexturingKeys.DiffuseTexture, smokeVolTexture); // Register it to rendering engineContext.RenderContext.GlobalMeshes.AddMesh(particleMesh); }
/// <summary> /// Sets the parent (particle system's) translation, rotation and scale (uniform) /// The module can choose to inherit, use or ignore any of the elements /// </summary> /// <param name="transform"><see cref="ParticleSystem"/>'s transform (from the Transform component) or identity if local space is used</param> /// <param name="parent">The parent <see cref="ParticleSystem"/></param> public virtual void SetParentTRS(ParticleTransform transform, ParticleSystem parent) { SetParentTransform(transform); }
public unsafe void Update(ParticleSystem particleSystem, float dt) { var accelerationField = particleSystem.GetOrCreateField(ParticleFields.Acceleration); var velocityField = particleSystem.GetOrCreateField(ParticleFields.Velocity); foreach (var particle in particleSystem) { var position = (Vector3*)particle[particleSystem.Position]; var acceleration = (Vector3*)particle[accelerationField]; var velocity = (Vector3*)particle[velocityField]; *velocity += *acceleration * dt; *position += *velocity * dt; } }