/// <inheritdoc/> protected override void OnInitializeParticles(int startIndex, int count, object emitter) { if (_linearSpeedParameter == null || _directionParameter == null || _biasVelocityParameter == null) { return; } Vector3[] directions = _directionParameter.Values; float[] speeds = _linearSpeedParameter.Values; Vector3[] biases = _biasVelocityParameter.Values; if (directions != null && speeds != null && biases != null) { // Optimized case: Direction, Speed, and Acceleration are varying parameters. for (int i = startIndex; i < startIndex + count; i++) { Vector3 velocity = directions[i] * speeds[i]; velocity += biases[i] * Strength; speeds[i] = velocity.Length; if (!Numeric.IsZero(speeds[i])) { directions[i] = velocity / speeds[i]; } } } else if (directions != null && speeds != null) { // Optimized case: Direction and Speed are varying parameters, Bias is uniform. Vector3 bias = _biasVelocityParameter.DefaultValue * Strength; for (int i = startIndex; i < startIndex + count; i++) { Vector3 velocity = directions[i] * speeds[i]; velocity += bias; speeds[i] = velocity.Length; if (!Numeric.IsZero(speeds[i])) { directions[i] = velocity / speeds[i]; } } } else if (directions != null || speeds != null) { // General case: Either Direction or Speed is varying parameter. // This path does not make sense much sense. - But maybe someone has an idea how to use it. Vector3 bias = _biasVelocityParameter.DefaultValue * Strength; for (int i = startIndex; i < startIndex + count; i++) { Vector3 velocity = _directionParameter.GetValue(i) * _linearSpeedParameter.GetValue(i); velocity += bias; var newSpeed = velocity.Length; _linearSpeedParameter.SetValue(i, newSpeed); if (!Numeric.IsZero(newSpeed)) { _directionParameter.SetValue(i, velocity / newSpeed); } } } }
// This method is called each frame to update particles. protected override void OnUpdateParticles(TimeSpan deltaTime, int startIndex, int count) { // Abort if we are missing particle parameters. if (_positionParameter == null || _linearSpeedParameter == null || _directionParameter == null) { return; } // Get the direction and linear speed particle parameter arrays. for (int i = startIndex; i < startIndex + count; i++) { // Get the particle position and check if the position is behind the plane. Vector3 position = _positionParameter.GetValue(i); if (Vector3.Dot(position, _plane.Normal) > _plane.DistanceFromOrigin) { continue; } // Get the linear velocity of the particle. Vector3 velocity = _directionParameter.GetValue(i) * _linearSpeedParameter.GetValue(i); // Check if the particle is moving into the plane or away. float normalSpeed = Vector3.Dot(velocity, _plane.Normal); if (normalSpeed > 0) { continue; } // Get the restitution. If there is no restitution particle parameter, we use a default value. float restitution = (_restitutionParameter != null) ? _restitutionParameter.GetValue(i) : 0.5f; // Change the velocity to let the particle bounce off. velocity = velocity - (1 + restitution) * _plane.Normal * normalSpeed; // Update LinearSpeed and Direction from the velocity vector. // The speed is the magnitude of the velocity vector. var newSpeed = velocity.Length; _linearSpeedParameter.SetValue(i, newSpeed); // Direction stores the normalized direction of the velocity vector. if (!Numeric.IsZero(newSpeed)) { _directionParameter.SetValue(i, velocity / newSpeed); } } }
/// <inheritdoc/> protected override void OnUpdateParticles(TimeSpan deltaTime, int startIndex, int count) { if (_linearSpeedParameter == null || _directionParameter == null || _linearAccelerationParameter == null) { return; } // Update varying parameters. Vector3[] directions = _directionParameter.Values; float[] speeds = _linearSpeedParameter.Values; Vector3[] accelerations = _linearAccelerationParameter.Values; float dt = (float)deltaTime.TotalSeconds; if (directions != null && speeds != null && accelerations != null) { // Optimized case: Direction, Speed, and Acceleration are varying parameters. for (int i = startIndex; i < startIndex + count; i++) { Vector3 velocity = directions[i] * speeds[i]; velocity += accelerations[i] * dt; speeds[i] = velocity.Length; if (!Numeric.IsZero(speeds[i])) { directions[i] = velocity / speeds[i]; } } } else if (directions != null && speeds != null) { // Optimized case: Direction and Speed are varying parameters, Acceleration is uniform. Vector3 acceleration = _linearAccelerationParameter.DefaultValue; for (int i = startIndex; i < startIndex + count; i++) { Vector3 velocity = directions[i] * speeds[i]; velocity += acceleration * dt; speeds[i] = velocity.Length; if (!Numeric.IsZero(speeds[i])) { directions[i] = velocity / speeds[i]; } } } else if (directions != null || speeds != null) { // General case: Either Direction or Speed is varying parameter. // This path does not make sense much sense. - But maybe someone has an idea how to use it. Vector3 acceleration = _linearAccelerationParameter.DefaultValue; for (int i = startIndex; i < startIndex + count; i++) { Vector3 velocity = _directionParameter.GetValue(i) * _linearSpeedParameter.GetValue(i); velocity += acceleration * dt; var newSpeed = velocity.Length; _linearSpeedParameter.SetValue(i, newSpeed); if (!Numeric.IsZero(newSpeed)) { _directionParameter.SetValue(i, velocity / newSpeed); } } } }