/// <inheritdoc/> public override unsafe void Update(float dt, ParticlePool pool) { if (!pool.FieldExists(ParticleFields.Position) || !pool.FieldExists(ParticleFields.Velocity)) { return; } var posField = pool.GetField(ParticleFields.Position); var velField = pool.GetField(ParticleFields.Velocity); var lifeField = pool.GetField(ParticleFields.Life); foreach (var particle in pool) { var surfacePoint = new Vector3(0, 0, 0); var surfaceNormal = new Vector3(0, 1, 0); var particlePos = (*((Vector3 *)particle[posField])); var particleVel = (*((Vector3 *)particle[velField])); var isInside = false; if (FieldShape != null) { FieldShape.PreUpdateField(WorldPosition, WorldRotation, WorldScale); isInside = FieldShape.IsPointInside(particlePos, out surfacePoint, out surfaceNormal); } if (IsHollow != isInside) { if (IsHollow) { surfaceNormal *= -1; } // The particle is on the wrong side of the collision shape and must collide (*((Vector3 *)particle[posField])) = surfacePoint; var verIncidentCoef = Vector3.Dot(surfaceNormal, particleVel); var verticalIncidentVelocity = verIncidentCoef * surfaceNormal; var horizontalIncidentVelocity = particleVel - verticalIncidentVelocity; particleVel = horizontalIncidentVelocity * (1 - Friction) + verticalIncidentVelocity * ((verIncidentCoef > 0) ? Restitution : -Restitution); (*((Vector3 *)particle[velField])) = particleVel; // TODO Maybe set some collision flags if other calculations depend on them // Possibly kill the particle if (KillParticles) { // Don't set the particle's life directly to 0 just yet - it might need to spawn other particles on impact (*((float *)particle[lifeField])) = MathUtil.ZeroTolerance; } } } }
/// <inheritdoc /> public override unsafe void Update(float dt, ParticlePool pool) { // The force field operates over position and velocity. If the particles don't have such fields we can't run this update if (!pool.FieldExists(ParticleFields.Position) || !pool.FieldExists(ParticleFields.Velocity)) { return; } var posField = pool.GetField(ParticleFields.Position); var velField = pool.GetField(ParticleFields.Velocity); // Depending on our settings some of the energy will be lost (it directly translates to changes in position) // and some of the energy will be preserved (it translates to changes in velocity) var directToPosition = 1f - EnergyConservation; foreach (var particle in pool) { var alongAxis = new Vector3(0, 1, 0); var awayAxis = new Vector3(0, 0, 1); var aroundAxis = new Vector3(1, 0, 0); var particlePos = (*((Vector3 *)particle[posField])); var particleVel = (*((Vector3 *)particle[velField])); var forceMagnitude = 1f; if (FieldShape != null) { FieldShape.PreUpdateField(WorldPosition, WorldRotation, WorldScale); forceMagnitude = FieldShape.GetDistanceToCenter(particlePos, particleVel, out alongAxis, out aroundAxis, out awayAxis); forceMagnitude = FieldFalloff.GetStrength(forceMagnitude); } forceMagnitude *= dt * parentScale; var totalForceVector = ForceFixed + alongAxis * ForceDirected + aroundAxis * ForceVortex + awayAxis * ForceRepulsive; totalForceVector *= forceMagnitude; // Force contribution to velocity - conserved energy var vectorContribution = totalForceVector * EnergyConservation; (*((Vector3 *)particle[velField])) += vectorContribution; // Force contribution to position - lost energy vectorContribution = (vectorContribution * (dt * 0.5f)) + (totalForceVector * directToPosition); (*((Vector3 *)particle[posField])) += vectorContribution; } }
public override unsafe void Update(float dt, ParticlePool pool) { if (!pool.FieldExists(ParticleFields.Position) || !pool.FieldExists(ParticleFields.Velocity)) { return; } var posField = pool.GetField(ParticleFields.Position); var velField = pool.GetField(ParticleFields.Velocity); // var colField = pool.GetField(ParticleFields.Color); var directToPosition = 1f - EnergyConservation; foreach (var particle in pool) { var alongAxis = new Vector3(0, 1, 0); var awayAxis = new Vector3(0, 0, 1); var aroundAxis = new Vector3(1, 0, 0); var particlePos = (*((Vector3 *)particle[posField])); var particleVel = (*((Vector3 *)particle[velField])); var forceMagnitude = 1f; if (FieldShape != null) { FieldShape.PreUpdateField(WorldPosition, WorldRotation, WorldScale); forceMagnitude = FieldShape.GetDistanceToCenter(particlePos, particleVel, out alongAxis, out aroundAxis, out awayAxis); forceMagnitude = FieldFalloff.GetStrength(forceMagnitude); } forceMagnitude *= dt * parentScale; var totalForceVector = ForceFixed + alongAxis * ForceDirected + aroundAxis * ForceVortex + awayAxis * ForceRepulsive; totalForceVector *= forceMagnitude; // Force contribution to velocity - conserved energy var vectorContribution = totalForceVector * EnergyConservation; (*((Vector3 *)particle[velField])) += vectorContribution; // Force contribution to position - lost energy vectorContribution = (vectorContribution * (dt * 0.5f)) + (totalForceVector * directToPosition); (*((Vector3 *)particle[posField])) += vectorContribution; } }