public void Destroy() { baseAmplitude = amplitude = 0.0f; isAlive = false; if (leftNeighbour != null) { leftNeighbour.rightNeighbour = rightNeighbour; leftNeighbour.disallowSubdivision = true; } if (rightNeighbour != null) { rightNeighbour.leftNeighbour = leftNeighbour; rightNeighbour.disallowSubdivision = true; if (leftNeighbour == null) { group.leftParticle = rightNeighbour; } } leftNeighbour = null; rightNeighbour = null; }
private void UpdateSpawnPoints(float deltaTime) { deltaTime *= emissionFrequencyScale; for (int i = 0; i < spawnPoints.Length; ++i) { var spawnPoint = spawnPoints[i]; spawnPoint.timeLeft -= deltaTime; if (spawnPoint.timeLeft < 0) { float waveLength = 2.0f * Mathf.PI / spawnPoint.frequency; float preferredParticleCount = (span * 0.3f) / waveLength; int minParticles = Mathf.Max(2, Mathf.RoundToInt(preferredParticleCount * 0.7f)); int maxParticles = Mathf.Max(2, Mathf.RoundToInt(preferredParticleCount * 1.429f)); spawnPoint.timeLeft += spawnPoint.timeInterval; Vector2 position = spawnPoint.position + new Vector2(spawnPoint.direction.y, -spawnPoint.direction.x) * Random.Range(-span * 0.35f, span * 0.35f); var particle = WaveParticle.Create(position, spawnPoint.direction, spawnPoint.frequency, spawnPoint.amplitude, lifetime, shoreWaves); if (particle != null) { wavesParticleSystem.Spawn(particle, Random.Range(minParticles, maxParticles), waveShapeIrregularity); particle.Destroy(); particle.AddToCache(); } } } }
/// <summary> /// Ensures that whole wave is either expanding or contracting. /// </summary> /// <param name="left"></param> /// <param name="right"></param> /// <param name="waveLength"></param> private void FilterRefractedDirections(WaveParticle left, WaveParticle right, int waveLength) { WaveParticle p = left; int halfLength = waveLength / 2; Vector2 leftDirection = new Vector2(); for (int i = 0; i < halfLength; ++i) { leftDirection += p.direction; p = p.rightNeighbour; } Vector2 rightDirection = new Vector2(); for (int i = halfLength; i < waveLength; ++i) { rightDirection += p.direction; p = p.rightNeighbour; } leftDirection.Normalize(); rightDirection.Normalize(); p = left; for (int i = 0; i < waveLength; ++i) { p.direction = Vector2.Lerp(leftDirection, rightDirection, i / (waveLength - 1)); p = p.rightNeighbour; } }
public bool Spawn(WaveParticle particle, int clones, float waveShapeIrregularity) { if (particle == null || particles.FreeSpace < clones * 2 + 1) { return(false); } particle.group = new WaveParticlesGroup(simulationTime); particle.baseAmplitude *= water.UniformWaterScale; particle.baseFrequency /= water.UniformWaterScale; WaveParticle previousParticle = null; float minAmplitude = 1.0f / waveShapeIrregularity; for (int i = -clones; i <= clones; ++i) { var p = particle.Clone(particle.position + new Vector2(particle.direction.y, -particle.direction.x) * (i * 1.48f / particle.baseFrequency)); if (p == null) { continue; } p.baseAmplitude *= Random.Range(minAmplitude, 1.0f); p.leftNeighbour = previousParticle; if (previousParticle != null) { previousParticle.rightNeighbour = p; if (i == clones) { p.disallowSubdivision = true; // it's a last particle of the group } } else { p.group.leftParticle = p; // it's a first particle of the group p.disallowSubdivision = true; } if (!particles.AddElement(p)) { return(previousParticle != null); } previousParticle = p; } return(true); }
public bool Spawn(WaveParticle particle) { if (particle != null) { particle.group = new WaveParticlesGroup(simulationTime); particle.group.leftParticle = particle; return(particles.AddElement(particle)); } else { return(false); } }
public void Update(float time) { WaveParticle particle = leftParticle; float deltaTime = time - lastUpdateTime; lastUpdateTime = time; float step = deltaTime < 1.0f ? deltaTime : 1.0f; float invStep = 1.0f - step; do { var p = particle; particle = particle.rightNeighbour; p.Update(deltaTime, step, invStep); }while(particle != null); }
static public WaveParticle Create(Vector2 position, Vector2 direction, float baseFrequency, float baseAmplitude, float lifetime, bool isShoreWave) { WaveParticle particle; if (waveParticlesCache.Count != 0) { particle = waveParticlesCache.Pop(); particle.position = position; particle.direction = direction; particle.baseFrequency = baseFrequency; particle.baseAmplitude = baseAmplitude; particle.fadeFactor = 0.0f; particle.isShoreWave = isShoreWave; particle.baseSpeed = 3.2f * Mathf.Sqrt(9.81f / baseFrequency); particle.amplitude = baseAmplitude; particle.frequency = baseFrequency; particle.targetSpeed = 1.0f; particle.invkh = 1.0f; particle.targetInvKh = 1.0f; particle.energyBalance = 0.0f; particle.shoaling = 0.0f; particle.speed = 0.0f; particle.lifetime = lifetime; particle.amplitudeModifiers = 0.0f; particle.expansionEnergyLoss = 0.0f; particle.isAlive = true; particle.disallowSubdivision = false; if (particle.leftNeighbour != null || particle.rightNeighbour != null) { particle.leftNeighbour = null; // WYWALIC particle.rightNeighbour = null; } particle.CostlyUpdate(null, 0.1f); } else { particle = new WaveParticle(position, direction, baseFrequency, baseAmplitude, lifetime, isShoreWave); } return(particle.baseAmplitude != 0.0f ? particle : null); }
private void Subdivide(WaveParticlesQuadtree quadtree, WaveParticle left, WaveParticle right, ref int numSubdivisions) { Vector2 diff = left.position - right.position; float distance = diff.magnitude; if (distance * frequency > 1.0f && distance > 1.0f && quadtree.FreeSpace != 0) // don't subdivide below 1m on CPU { var newParticle = Create(right.position + diff * 0.5f, (left.direction + right.direction) * 0.5f, (left.baseFrequency + right.baseFrequency) * 0.5f, (left.baseAmplitude + right.baseAmplitude) * 0.5f, (left.lifetime + right.lifetime) * 0.5f, left.isShoreWave); if (newParticle != null) { newParticle.group = left.group; newParticle.amplitude = (left.amplitude + right.amplitude) * 0.5f; newParticle.frequency = (left.frequency + right.frequency) * 0.5f; newParticle.speed = (left.speed + right.speed) * 0.5f; newParticle.targetSpeed = (left.targetSpeed + right.targetSpeed) * 0.5f; newParticle.energyBalance = (left.energyBalance + right.energyBalance) * 0.5f; newParticle.shoaling = (left.shoaling + right.shoaling) * 0.5f; if (quadtree.AddElement(newParticle)) { /*const float subdivideEnergyLoss = 0.94f; * * left.baseAmplitude *= subdivideEnergyLoss; * left.amplitude *= subdivideEnergyLoss; * right.baseAmplitude *= subdivideEnergyLoss; * right.amplitude *= subdivideEnergyLoss; * newParticle.baseAmplitude *= subdivideEnergyLoss; * newParticle.amplitude *= subdivideEnergyLoss;*/ newParticle.leftNeighbour = left; newParticle.rightNeighbour = right; left.rightNeighbour = newParticle; right.leftNeighbour = newParticle; } ++numSubdivisions; } } }
public void CostlyUpdate(WaveParticlesQuadtree quadtree, float time) { WaveParticle particle = leftParticle; float deltaTime = time - lastCostlyUpdateTime; lastCostlyUpdateTime = time; int numSubdivisions = 0; do { var p = particle; particle = particle.rightNeighbour; numSubdivisions += p.CostlyUpdate(numSubdivisions < 30 ? quadtree : null, deltaTime); }while(particle != null); particle = leftParticle; WaveParticle firstParticleInWave = particle; int waveLength = 0; do { var p = particle; particle = particle.rightNeighbour; ++waveLength; if (p != firstParticleInWave && (p.disallowSubdivision || particle == null)) { if (waveLength > 3) { FilterRefractedDirections(firstParticleInWave, p, waveLength); } firstParticleInWave = particle; waveLength = 0; } }while(particle != null); }
public void UpdateParticles(float time, float deltaTime) { if (!isActiveAndEnabled) { return; } switch (wavesSource) { case WavesSource.CustomWaveFrequency: { if (time > nextSpawnTime) { Vector3 position = transform.position; Vector3 direction = transform.forward; var particle = WaveParticle.Create( new Vector2(position.x, position.z), new Vector2(direction.x, direction.z).normalized, 2.0f * Mathf.PI / wavelength, amplitude, lifetime, shoreWaves ); if (particle != null) { wavesParticleSystem.Spawn(particle, width, waveShapeIrregularity); particle.Destroy(); particle.AddToCache(); } nextSpawnTime += timeStep; } break; } } }