public void calcViscosityForce(Sphere p) { Vector3 f = new Vector3(0, 0, 0); int[] closePointInds = Game.neighborsIndicesConcatenated(p.Position); for (int i = 0; i < closePointInds.Length; i++) { int index = (int)((Game.getDistance(p.Position, Game.particles[closePointInds[i]].Position) * 100) / d); float lap = 0; if (index <= 100 && index >= 0) { lap = laplacianLookup[index]; } else { lap = Poly6WeightKernel(p.Position, Game.particles[closePointInds[i]].Position); } f += viscosity * Game.particles[closePointInds[i]].Mass * ((Game.particles[closePointInds[i]].Velocity - p.Velocity) / Game.particles[closePointInds[i]].Density) * lap; } // Console.WriteLine("viscosity force: " + f); if (p.verbose) { Console.WriteLine("Viscocity: " + f); } p.NetForce += f; }
/** * Kernels: the following functions are the kernels used to calculate the distance weighting of particles * as well as the effect that graident of the vector field has on the particles for each force. * * Sources used to find these kernels: * https://www8.cs.umu.se/kurser/TDBD24/VT06/lectures/sphsurvivalkit.pdf * https://nccastaff.bournemouth.ac.uk/jmacey/MastersProjects/MSc15/06Burak/BurakErtekinMScThesis.pdf **/ //Poly6 kernel for distance weighting. used in calculating a particle's density public float Poly6WeightKernel(Vector3 x1, Vector3 x2) { float r = Game.getDistance(x1, x2); if (r > d) { return(0.0f); } return((315 / (64 * (float)Math.PI * (float)Math.Pow(d, 9))) * (float)Math.Pow(d * d - r * r, 3)); }
//Laplacian kernel for distance weighitng and vector gradient. used forcalculating viscosit force public float laplacianKernel(Vector3 x1, Vector3 x2) { float r = Game.getDistance(x1, x2); if (r > d) { return(0.0f); } return((45 / ((float)Math.PI * (float)Math.Pow(d, 6))) * (d - r)); }
//Spiky kernel for distance weighitng and vector gradient. used for calculating pressure force public Vector3 spikyPressureKernel(Vector3 x1, Vector3 x2) { float r = Game.getDistance(x1, x2); if (r > d) { return(new Vector3(0, 0, 0)); } return(-1.0f * (45 / ((float)Math.PI * (float)Math.Pow(d, 6))) * (float)Math.Pow(d - r, 2) * (x1 - x2)); }
public Vector3 Poly6GradientKernel(Vector3 x1, Vector3 x2) { float r = Game.getDistance(x1, x2); if (r < 1.0f) { r = 0.1f; } if (r > d) { return(new Vector3(0, 0, 0)); } return((-945 / (32 * (float)Math.PI * (float)Math.Pow(d, 9))) * ((x1 - x2) * (float)Math.Pow(d * d - r * r, 2))); }
public float CohesionKernel(Vector3 x1, Vector3 x2) { float r = Game.getDistance(x1, x2); float constant = (float)(32 / (Math.PI * Math.Pow(d, 9))); if (2 * r > d && r <= d) { //Console.WriteLine(1); return(constant * (float)Math.Pow((d - r), 3) * (float)Math.Pow(r, 3)); } else if (r > 0.0001 && 2 * r <= d) { //Console.WriteLine(2); return(constant * 2 * (float)Math.Pow((d - r), 3) * (float)Math.Pow(r, 3) - (float)Math.Pow(d, 6) / 64); } //Console.WriteLine(3); return(0.0f); }
public void calcSurfaceTension(Sphere p) { if (p.normal.Length < gradientFieldThreshold) { return; } Vector3 f = new Vector3(0, 0, 0); Vector3 cNormal = new Vector3(0, 0, 0); Vector3 cCurvature = new Vector3(0, 0, 0); float K = p.Density; int[] closePointInds = Game.neighborsIndicesConcatenated(p.Position); for (int i = 0; i < closePointInds.Length; i++) { Vector3 r = p.Position - Game.particles[closePointInds[i]].Position; if (Game.getDistance(p.Position, Game.particles[closePointInds[i]].Position) > 0) { cNormal += Game.particles[closePointInds[i]].Mass * CohesionKernel(p.Position, Game.particles[closePointInds[i]].Position) * (r / r.Length); cCurvature += p.normal - Game.particles[closePointInds[i]].normal; K += Game.particles[closePointInds[i]].Density; } } cNormal *= p.Mass * -sigma; cCurvature *= p.Mass * -sigma; if (K > 0.0001) { K = 2 * p0 / K; } else { K = 0; } f = K * (cNormal + cCurvature); if (p.verbose) { Console.WriteLine("Surface: " + f); } p.NetForce += f; }
/** * The following functions are implementations of the langrangian fluid equations provided here: * https://www.cs.ubc.ca/~rbridson/fluidsimulation/fluids_notes.pdf * * This source was linked by Amir on the game physics course page **/ public void calcDensity(Sphere p) { float dense = 1f; int[] closePointInds = Game.neighborsIndicesConcatenated(p.Position); for (int i = 0; i < closePointInds.Length; i++) { int index = (int)((Game.getDistance(p.Position, Game.particles[closePointInds[i]].Position) * 100) / d); float poly = 0; if (false) { poly = poly6Lookup[index]; } else { poly = Poly6WeightKernel(p.Position, Game.particles[closePointInds[i]].Position); } dense += Game.particles[closePointInds[i]].Mass * poly; } p.Density = dense; }