private void CreateFlowField() { t_flowField = new Engine.Calc.Vector[t_imageSource.Width, t_imageSource.Height]; for (int y = 0; y < t_imageSource.Height; y++) { for (int x = 0; x < t_imageSource.Width; x++) { // initialize vectors with basic to-the-right direction t_flowField[x, y] = new Engine.Calc.Vector(1, 0); } } }
/*public static Engine.Calc.Vector ExpressiveForce(this Engine.Effects.Particles.Attractor attractor, * Engine.Effects.Particles.ForceParticle p) * { * float G = 4f; * * Engine.Calc.Vector relDistance = attractor.Distance(p); * * float distance = relDistance.Norm; // Norm seems the magnitude in Processing * * float force = G / distance; * * force = Engine.Calc.Math.Sigmoid(force); * * relDistance.Normalize(); * Engine.Calc.Vector.Multiply(relDistance, force); * * return relDistance; * }*/ /// <summary> /// /// </summary> /// <param name="attractor"></param> /// <param name="p"></param> /// <param name="G">The "Gravitational constant" of the force (suggested value 1.3)</param> /// <param name="expansion">Allows the force to be stronger or weaker on longer distances while remaining weak at very short distances. /// suggested value 2.8</param> /// <param name="direction">the direction of the force. positive makes the force attraction, negative makes the force repulsion. suggested value 0.5 or -0.5</param> /// <returns></returns> public static Engine.Calc.Vector ModularForce(this Engine.Effects.Particles.Attractor attractor, Engine.Effects.Particles.ForceParticle p) { Engine.Calc.Vector relDistance = attractor.Distance(p); double distance = System.Math.Sqrt(relDistance.X * relDistance.X + relDistance.Y * relDistance.Y); double force = (attractor.Intensity * attractor.Force * distance) - 10d / System.Math.Pow(attractor.Expression, -1 * (distance / attractor.Force)); relDistance.Normalize(); relDistance *= force; return(relDistance); }
public void CalculateAveragePressure(Engine.Effects.Particles.FlowField flowField, int startX, int startY) { t_pressure = new Calc.Vector(0, 0); for (int y = 0; y < t_height; y++) { for (int x = 0; x < t_width; x++) { Engine.Calc.Vector v = flowField.GetVector(x + startX, y + startY); t_pressure += v; } } //t_pressure.Normalize(Calc.CalculationStyles.Accord); }
/// <summary> /// /// </summary> /// <param name="x"></param> private int ParticleFlow() { Engine.Color.ColorVariance cv = new Color.ColorVariance(t_particles[0].Pixel); cv.SetFrequencies(500); cv.SetRanges(30); double life = 0; do { cv.Step(); life = 0; for (int y = 0; y < t_particles.Length; y++) { t_particles[y].Pixel = cv.ColorVariation; t_particles[y].Draw(t_imageSource); if (t_particles[y].Life < 0) { continue; } Engine.Calc.Vector pos = t_particles[y].Position; if (pos.X < 0 || pos.X >= t_imageSource.Width) { t_particles[y].Die(); life += 0; continue; } if (pos.Y < 0 || pos.Y >= t_imageSource.Height) { t_particles[y].Die(); life += 0; continue; } t_particles[y].Move(t_flowField[(int)t_particles[y].Position.X, (int)t_particles[y].Position.Y]); life += t_particles[y].Life; } } while (life > t_particleLife); return(0); }
/// <summary> /// /// </summary> private int ParticleFlow(int start, int end, Engine.Threading.ParamList lst) { Engine.Color.ColorVariance cv = new Color.ColorVariance(t_particles[0].Pixel); cv.SetFrequencies(500); cv.SetRanges(30); double life = 0; do { life = 0; for (int i = start; i < end; i++) { t_particles[i].Pixel = cv.ColorVariation; t_particles[i].Draw(t_imageProcessed); if (t_particles[i].Life < 0) { continue; } Engine.Calc.Vector pos = t_particles[i].Position; if (pos.X < 0 || pos.X >= t_imageProcessed.Width) { t_particles[i].Die(); continue; } if (pos.Y < 0 || pos.Y >= t_imageProcessed.Height) { t_particles[i].Die(); continue; } t_particles[i].Move(t_flowField[(int)t_particles[i].Position.X, (int)t_particles[i].Position.Y]); life += t_particles[i].Life; } } while (life > t_particleLife); return(0); }
public void VelocityFriction(double a, double b, double c) { // The force of pressure affects velocity for (int iterate = 0; iterate < 1; iterate++) { // NOTE: We include the border cells in global friction for (int x = 0; x < t_width; x++) { for (int y = 0; y < t_height; y++) { int cell = CellOffset(x, y, t_width); Engine.Calc.Vector v = new Engine.Calc.Vector(mp_xv0[cell], mp_yv0[cell]); double len2 = v.MagnitudeSquared(); double len = System.Math.Sqrt(len2); if (len < 0.0f) { len = -len; } len -= m_dt * (a * len2 + b * len + c); if (len < 0.0d) { len = 0.0d; } if (len < 0.0f) { len = 0.0f; } v.Normalize(); v.SetMagnitude(len); mp_xv0[cell] = v.X; mp_yv0[cell] = v.Y; } } } }
internal override void Draw(MousePoint p) { if (!t_skipper.Skip()) { return; } if (t_imageSource.IsOutOfBounds(p.X, p.Y)) { return; } Engine.Color.Cell col; t_colorVariance.Step(); if (t_useColorFromImage) { col = t_imageSource.GetPixel(p.X, p.Y, PixelRetrievalOptions.ReturnEdgePixel); t_colorVariance.SetColor(col); col = t_colorVariance.ColorVariation; col.Alpha = t_alpha; } else { col = t_colorVariance.ColorVariation; col.Alpha = t_alpha; } // particles must follow the pen between each call to draw int[] delta = MousePoint.Delta(t_previousPoint, p); Engine.Calc.Vector d = new Engine.Calc.Vector(delta[0], delta[1]); foreach (Engine.Effects.Particles.Obsolete.PixelParticle_O px in t_particles) { px.Move(d); px.Draw(t_imageSource, col); } t_previousPoint = p; }
private int Threaded_CreateFlowField(int start, int end, Engine.Threading.ParamList paramList) { for (int y = start; y < end; y++) { for (int x = 0; x < t_imageSource.Width; x++) { // initialize vectors with basic to-the-right direction t_flowField[x, y] = new Engine.Calc.Vector(1, 0); Engine.Color.Cell c = t_imagePerlin.GetPixel(x, y, Surface.PixelRetrievalOptions.ReturnEdgePixel); double lum = (double)Engine.Calc.Color.Luminance(c); double angle = (lum * 360 / 255); double rad = angle * Engine.Calc.Math.DEG_TO_RAD; t_flowField[x, y].X = (float)System.Math.Cos(rad); t_flowField[x, y].Y = (float)System.Math.Sin(rad); } } return(0); }
public override void Move(Engine.Calc.Vector direction) { if (t_life <= 0) { // particle is dead return; } double previousX = t_position.X; double previousY = t_position.Y; Engine.Calc.Vector tempDir = direction + t_direction; t_position += tempDir; double deltaX = System.Math.Abs(t_position.X - previousX); double deltaY = System.Math.Abs(t_position.Y - previousY); double distance = System.Math.Sqrt(deltaX * deltaX + deltaY * deltaY); t_life -= distance; }
/// <summary> /// Draws a filled circle at the specified coordinates using the specified color. /// </summary> /// <param name="canvas">the target image onto which to draw a circle</param> /// <param name="position">where on the target image the center of the cicle is to be located.</param> /// <param name="size">the diameter of the circle to draw</param> /// <param name="color">the color of the circle line</param> /// <remarks>Implements the Bresenham's circle argorithm, most of the code found at : https://rosettacode.org/wiki/Bitmap/Midpoint_circle_algorithm#C.23 </remarks> public static void DrawCircle(Engine.Surface.Canvas canvas, Engine.Calc.Vector position, int size, Engine.Color.Cell color) { int centerX = (int)System.Math.Round(position.X); int centerY = (int)System.Math.Round(position.Y); int radius = (int)System.Math.Round((double)size / 2); int d = (5 - radius * 4) / 4; int x = 0; int y = radius; do { // ensure index is in range before setting (depends on your image implementation) // in this case we check if the pixel location is within the bounds of the image before setting the pixel canvas.SetPixel(color, centerX + x, centerY + y, Surface.PixelSetOptions.Ignore); canvas.SetPixel(color, centerX + x, centerY - y, Surface.PixelSetOptions.Ignore); canvas.SetPixel(color, centerX - x, centerY + y, Surface.PixelSetOptions.Ignore); canvas.SetPixel(color, centerX - x, centerY - y, Surface.PixelSetOptions.Ignore); canvas.SetPixel(color, centerX + y, centerY + x, Surface.PixelSetOptions.Ignore); canvas.SetPixel(color, centerX + y, centerY - x, Surface.PixelSetOptions.Ignore); canvas.SetPixel(color, centerX - y, centerY + x, Surface.PixelSetOptions.Ignore); canvas.SetPixel(color, centerX - y, centerY - x, Surface.PixelSetOptions.Ignore); if (d < 0) { d += 2 * x + 1; } else { d += 2 * (x - y) + 1; y--; } x++; } while (x <= y); }
private int Threaded_GetParticles(int start, int end, Threading.ParamList paramlist) { Engine.Effects.Code.Particles.AutonomousParticle[] particles = (Engine.Effects.Code.Particles.AutonomousParticle[])paramlist.Get("particles").Value; for (int x = start; x < end; x++) { for (int y = 0; y < t_cells.GetLength(1); y++) { int offset = Engine.Surface.Ops.GetGridOffset(x, y, t_cells.GetLength(0), t_cells.GetLength(1)); particles[offset] = new Effects.Code.Particles.AutonomousParticle(new Engine.Calc.Vector((x * t_gridCellWidth) + (t_gridCellWidth / 2), (y * t_gridCellHeight) + (t_gridCellHeight / 2))); Engine.Calc.Vector vel = t_cells[x, y].Pressure; vel.Normalize(); vel.SetMagnitude(2); particles[offset].Velocity = vel; //t_cells[x, y].CalculateAveragePressure(t_flowField, x * t_gridCellWidth, y * t_gridCellHeight); } } return(0); }
public void Update() { t_position += t_velocity; }
/// <summary> /// Updates the position of the particule according to its own position, velocity, and the force (and location) of the /// specified attractor. /// </summary> /// <param name="attractor"></param> public void Update(Engine.Effects.Particles.Attractor attractor) { //t_acceleration = attractor.ExpressiveForce(this); t_acceleration = attractor.ModularForce(this); Update(); }
public override void Move(Engine.Calc.Vector direction) { throw new InvalidOperationException("In ForceParticle.Move(), use any overload of the Update() method instead."); }
public static Engine.Calc.Vector Distance(this Engine.Effects.Particles.Attractor attractor, Engine.Effects.Particles.BaseParticle p) { Engine.Calc.Vector distance = attractor.Position - p.Position; return(distance); }
/// <summary> /// /// </summary> /// <param name="position"></param> /// <param name="G">The base value of the force of "gravity". G must be greater than 0. If not, value defaults to 0.1d. /// Suggested value 1.2d.</param> /// <param name="expression">A parameter that influences the intensity curve of the calculated gravity force. Cannot be less /// than 0. Sugested value 1.3d. The higher the value, the less intense the gravity curve is.</param> /// <param name="intensity">A positive value means attraction, a negative value means repulsion.</param> public Attractor(Engine.Calc.Vector position, double G, double expression, double intensity) : base(position) { Force = G > 0 ? G : 0.1d; Expression = expression > 0 ? expression : 0.1d; Intensity = intensity; }
public Attractor(Engine.Calc.Vector position, double G) : base(position) { Force = G; }
public Attractor(Engine.Calc.Vector position) : base(position) { }
public ForceParticle(Engine.Calc.Vector position) : base(position) { t_previousPoint = new Point((int)position.X, (int)position.Y); }
public ForceParticle(int x, int y, float velX, float velY) { t_previousPoint = new Point(x, y); t_position = new Engine.Calc.Vector(x, y); t_velocity = new Engine.Calc.Vector(velX, velY); }
public ForceParticle(Engine.Calc.Vector position, Engine.Calc.Vector velocity) : base(position) { t_previousPoint = new Point((int)position.X, (int)position.Y); t_velocity = velocity; }
public PixelParticle_O(Engine.Color.Cell c, int x, int y) : this(c) { t_position = new Engine.Calc.Vector((float)x, (float)y); }
public PixelParticle_O(Engine.Color.Cell c, float x, float y) : this(c) { t_position = new Engine.Calc.Vector(x, y); }
public BaseParticle(Engine.Calc.Vector position) { t_position = new Engine.Calc.Vector(position.X, position.Y); }
public AutonomousParticle(Engine.Calc.Vector position) : base(position) { //t_position.Normalize(Calc.CalculationStyles.Accord); t_direction = new Calc.Vector(0, 0); }
public AutonomousParticle() { t_direction = new Calc.Vector(0, 0); }
public virtual void Move(Engine.Calc.Vector direction) { t_position += direction; }
private void SetField() { t_field = new List <List <Engine.Calc.Vector> >(); for (int i = 0; i < t_imageSource.Width; i++) { t_field.Add(new List <Engine.Calc.Vector>()); } double[] lums = new double[t_imageSource.Height * t_imageSource.Width]; int[] reds = new int[t_imageSource.Height * t_imageSource.Width]; int[] greens = new int[t_imageSource.Height * t_imageSource.Width]; int[] blues = new int[t_imageSource.Height * t_imageSource.Width]; int offset = 0; for (int y = 0; y < t_imageSource.Height; y++) { for (int x = 0; x < t_imageSource.Width; x++) { Engine.Color.Cell c = t_imageSource.GetPixel(x, y, Surface.PixelRetrievalOptions.ReturnNeutralGray); c.InArray(ref blues, ref greens, ref reds, offset); offset++; } } Engine.EngineCppLibrary.Luminance s_luminance = (Engine.EngineCppLibrary.Luminance)Marshal.GetDelegateForFunctionPointer( Engine.EngineCppLibrary.Pointer_luminance, typeof(Engine.EngineCppLibrary.Luminance)); s_luminance(t_imageSource.Height * t_imageSource.Width, blues, greens, reds, lums); offset = 0; for (int y = 0; y < t_imageSource.Height; y++) { for (int x = 0; x < t_imageSource.Width; x++) { double lum = lums[offset]; /* * surrounding cell config * 0 1 2 * * 7 x 3 * * 6 5 4 * */ double[] localLums = new double[8]; localLums[0] = GetLum(lums, x - 1, y - 1); localLums[1] = GetLum(lums, x, y - 1); localLums[2] = GetLum(lums, x + 1, y - 1); localLums[3] = GetLum(lums, x + 1, y); localLums[4] = GetLum(lums, x + 1, y + 1); localLums[5] = GetLum(lums, x, y + 1); localLums[6] = GetLum(lums, x - 1, y + 1); localLums[7] = GetLum(lums, x - 1, y); if (t_invertLuminance) { lum = 255 - lum; localLums[0] = 255 - localLums[0]; localLums[1] = 255 - localLums[1]; localLums[2] = 255 - localLums[2]; localLums[3] = 255 - localLums[3]; localLums[4] = 255 - localLums[4]; localLums[5] = 255 - localLums[5]; localLums[6] = 255 - localLums[6]; localLums[7] = 255 - localLums[7]; } double[] lumDiffs = new double[8]; for (int i = 0; i < lumDiffs.Length; i++) { lumDiffs[i] = lum - localLums[i]; } Engine.Calc.Vector[] vs = new Calc.Vector[lumDiffs.Length]; vs[0] = new Engine.Calc.Vector(-1, -1); vs[1] = new Engine.Calc.Vector(0, -1); vs[2] = new Engine.Calc.Vector(1, -1); vs[3] = new Engine.Calc.Vector(1, 0); vs[4] = new Engine.Calc.Vector(1, 1); vs[5] = new Engine.Calc.Vector(0, 1); vs[6] = new Engine.Calc.Vector(-1, 1); vs[7] = new Engine.Calc.Vector(-1, 0); Engine.Calc.Vector v_this = new Engine.Calc.Vector(0, 0); for (int i = 0; i < vs.Length; i++) { vs[i].SetMagnitude(lumDiffs[i]); v_this += vs[i]; } //v_this.Normalize(Calc.CalculationStyles.Accord); t_field[x].Add(v_this); offset++; } } }