void AddCenteredRect(float coverage, float densityFull) { int xH = GetXH(coverage); int yH = GetYH(coverage); int offsetX = GetOffsetX(xH); int offsetY = GetOffsetY(yH); float fill = ((N * M) / (xH * yH)) * densityFull; for (int i = offsetX; i <= offsetX + xH - 1; i++) { for (int j = offsetY; j <= offsetY + yH - 1; j++) { dS[FluidMath.IX(N, i, j)] = fill; } } }
void Draw(SKSurface surface, int width, int height) { Stopwatch sw = new Stopwatch(); if (canRender) { var canvas = surface.Canvas; canvas.Clear(SKColors.White); sw.Restart(); using (var paint = new SKPaint()) { paint.Style = SKPaintStyle.Fill; SKRect rect = new SKRect(); Color densityColor; float xCord = 0; float yCord = 0; float xInc, yInc; float colorScale = 1.0f; float density; xInc = width / (float)N; yInc = height / (float)M; // Loop through, match simulation format of first cell (0,0) at bottom left. for (int i = 1; i <= N; i++) { yCord = height; for (int j = 1; j <= M; j++) { // Set bounds of rectangle. rect.Left = xCord; rect.Top = yCord - yInc; rect.Right = xCord + xInc; rect.Bottom = yCord; // Read from corresponding cell to set color based on density. Note bottom left in simulation is index 1,1. density = d[FluidMath.IX(N, i, j)]; colorScale = colorScaleFactor * Math.Max(1.0f, Math.Min(1.0f, (1 / density))); if (density > 0.05) { densityColor = new Color(baseColor.R * colorScale, baseColor.G * colorScale, baseColor.B * colorScale, baseColor.A * Math.Pow(density, 1 - Math.Min(1.0, density))); paint.Color = densityColor.ToSKColor(); canvas.DrawRect(rect, paint); } // Decrement y for next rectangle. yCord -= yInc; } // Increment x for next rectangle. xCord += xInc; } canvas.Flush(); } var drawTime = sw.ElapsedMilliseconds; if (drawTime > 10) { #if DEBUG Debug.WriteLine("Slow render time: {0} milliseconds.", drawTime); #endif } } }
void Spin() { float cellVelocity = 0, addU = 0, addV = 0; int xH = GetXH(SPIN_FORCE_COVERAGE); int yH = GetYH(SPIN_FORCE_COVERAGE); int average = (xH + yH) / 2; xH = average; yH = average; int offsetX = GetOffsetX(xH); int offsetY = GetOffsetY(yH); float gravity = this.gravity * 1.2f; // Extra force for spin. // Normalize and reverse X & Y direction. MotionVector normalizedMotion = new MotionVector(); normalizedMotion.X = (double)N / (N + M) * (N + M / 30); normalizedMotion.Y = (double)M / (N + M) * (N + M / 30); switch (spin) { case 0: normalizedMotion.X *= 1; normalizedMotion.Y *= 1; break; case 1: normalizedMotion.X *= 1; normalizedMotion.Y *= -1; break; case 2: normalizedMotion.X *= -1; normalizedMotion.Y *= -1; break; case 3: normalizedMotion.X *= -1; normalizedMotion.Y *= 1; break; } if (lastSpin.ElapsedMilliseconds >= 120 || !lastSpin.IsRunning) { lastSpin.Restart(); spin += 1; if (spin > 3) { spin = 0; } } if (lastSpinMove.ElapsedMilliseconds >= 1920 || !lastSpinMove.IsRunning) { lastSpinMove.Restart(); // Find random spot where there is some fluid (>10% density). do { spinOffsetAddX = spinRandom.Next(-(N - xH - 2) / 2, (N - xH - 2) / 2); spinOffsetAddY = spinRandom.Next(-(M - yH - 2) / 2, (M - yH - 2) / 2); } while (d[FluidMath.IX(N, offsetX + spinOffsetAddX, offsetY + spinOffsetAddY)] < 0.10f); } offsetX += spinOffsetAddX; offsetY += spinOffsetAddY; for (int i = offsetX; i <= offsetX + xH - 1; i++) { for (int j = offsetY; j <= offsetY + yH - 1; j++) { if (d[FluidMath.IX(N, i, j)] > 0) { addU = gravity * (float)normalizedMotion.X * d[FluidMath.IX(N, i, j)]; addV = gravity * (float)normalizedMotion.Y * d[FluidMath.IX(N, i, j)]; } else { addU = gravity * (float)normalizedMotion.X; addV = gravity * (float)normalizedMotion.Y; } uS[FluidMath.IX(N, i, j)] = addU; vS[FluidMath.IX(N, i, j)] = addV; // Set u. cellVelocity = u[FluidMath.IX(N, i, j)] + addU; if (cellVelocity < -terminalVelocity) { uS[FluidMath.IX(N, i, j)] = addU - (cellVelocity - -terminalVelocity); } else if (cellVelocity > terminalVelocity) { uS[FluidMath.IX(N, i, j)] = addU - (cellVelocity - terminalVelocity); } else { uS[FluidMath.IX(N, i, j)] = addU; } // Set v. cellVelocity = v[FluidMath.IX(N, i, j)] + addV; if (cellVelocity < -terminalVelocity) { vS[FluidMath.IX(N, i, j)] = addV - (cellVelocity - -terminalVelocity);; } else if (cellVelocity > terminalVelocity) { vS[FluidMath.IX(N, i, j)] = addV - (cellVelocity - terminalVelocity); } else { vS[FluidMath.IX(N, i, j)] = addV; } } } }
void AddForces() { float cellVelocity = 0, addU = 0, addV = 0; int xH = GetXH(FORCE_COVERAGE); int yH = GetYH(FORCE_COVERAGE); int average = (xH + yH) / 2; xH = average; yH = average; int offsetX = GetOffsetX(xH); int offsetY = GetOffsetY(yH); // Normalize and reverse X & Y direction. MotionVector normalizedMotion = new MotionVector(); double normal = 1.0d; //; Math.Sqrt(Math.Pow(deviceMotion.X, 2) + Math.Pow(deviceMotion.Y, 2) + Math.Pow(deviceMotion.Z, 2)); normalizedMotion.X = deviceMotion.X / -normal; normalizedMotion.Y = deviceMotion.Y / -normal; for (int i = offsetX; i <= offsetX + xH - 1; i++) { for (int j = offsetY; j <= offsetY + yH - 1; j++) { if (d[FluidMath.IX(N, i, j)] > 0) { addU = gravity * (float)normalizedMotion.X * d[FluidMath.IX(N, i, j)]; addV = gravity * (float)normalizedMotion.Y * d[FluidMath.IX(N, i, j)]; } else { addU = gravity * (float)normalizedMotion.X; addV = gravity * (float)normalizedMotion.Y; } uS[FluidMath.IX(N, i, j)] = addU; vS[FluidMath.IX(N, i, j)] = addV; // Set u. cellVelocity = u[FluidMath.IX(N, i, j)] + addU; if (cellVelocity < -terminalVelocity) { uS[FluidMath.IX(N, i, j)] = addU - (cellVelocity - -terminalVelocity); } else if (cellVelocity > terminalVelocity) { uS[FluidMath.IX(N, i, j)] = addU - (cellVelocity - terminalVelocity); } else { uS[FluidMath.IX(N, i, j)] = addU; } // Set v. cellVelocity = v[FluidMath.IX(N, i, j)] + addV; if (cellVelocity < -terminalVelocity) { vS[FluidMath.IX(N, i, j)] = addV - (cellVelocity - -terminalVelocity);; } else if (cellVelocity > terminalVelocity) { vS[FluidMath.IX(N, i, j)] = addV - (cellVelocity - terminalVelocity); } else { vS[FluidMath.IX(N, i, j)] = addV; } } } }