// Update is called once per frame void Update() { Debug.DrawLine(new Vector3(0, 0), new Vector3(x, 0)); Debug.DrawLine(new Vector3(0, 0), new Vector3(0, y)); Debug.DrawLine(new Vector3(x, 0), new Vector3(x, y)); Debug.DrawLine(new Vector3(0, y), new Vector3(x, y)); // Spatial hashing SpatialHash2D sh2d = new SpatialHash2D(x, y, h); foreach (Point point in listPoint) { sh2d.Insert(point); } PVFS(listPoint, sh2d, g, Y, x, y, k, knear, pnear, h, r0, foutside); }
public static void PVFS(List <Point> listPoint, SpatialHash2D sh2d, float g, Vector3 Y, float boundaryX, float boundaryY, float k, float knear, float pnear, float h, float r0, float foutside) { foreach (Point point in listPoint) { // Apply gravity point.pos = point.transform.position; point.v = Vdt(point.m, g, point.cd, Y, point.v); // save previous position point.prevPos = point.pos; // advance to predicted position point.pos = Pdt(point.v, point.pos); } // modify velocities with pairwise viscosity impulses // applyViscosity // add and remove springs, change rest lengths // adjustSprings // modify positions according to springs, // double density relaxation, and collisions // applySpringDisplacements // doubleDensityRelaxation foreach (Point pointI in listPoint) { float r = 0; float rnear = 0; float p; float q; Vector3 dirIJ; // compute density and near-density List <Point> neighborhood = sh2d.GetNearby(pointI); foreach (Point pointJ in neighborhood) { dirIJ = pointJ.pos - pointI.pos; q = dirIJ.magnitude / h; if (q < 1) { r += Mathf.Pow(1 - q, 2); rnear += Mathf.Pow(1 - q, 3); } } // compute pressure and near-pressure p = k * (r - r0); pnear = knear * rnear; Vector3 dx = Vector3.zero; foreach (Point pointJ in neighborhood) { dirIJ = pointJ.pos - pointI.pos; q = dirIJ.magnitude / h; if (q < 1) { Vector3 D = (Time.fixedDeltaTime * Time.fixedDeltaTime) / pointI.m * (p * (1 - q) + pnear * Mathf.Pow(1 - q, 2)) * dirIJ.normalized; pointJ.pos += D / 2; dx = dx - D / 2; } } pointI.pos += dx; } //resolveCollisions // use previous position to compute next velocity foreach (Point pointI in listPoint) { // Clamp if (pointI.pos.y < 0) { pointI.pos += Vector3.up * (new Vector3(pointI.pos.x, 0) - pointI.pos).magnitude * foutside * (Time.fixedDeltaTime * Time.fixedDeltaTime) / pointI.m; } if (pointI.pos.y > boundaryY) { pointI.pos += Vector3.down * (new Vector3(pointI.pos.x, boundaryY) - pointI.pos).magnitude * foutside * (Time.fixedDeltaTime * Time.fixedDeltaTime) / pointI.m; } if (pointI.pos.x < 0) { pointI.pos += Vector3.right * (new Vector3(0, pointI.pos.y) - pointI.pos).magnitude * foutside * (Time.fixedDeltaTime * Time.fixedDeltaTime) / pointI.m; } if (pointI.pos.x > boundaryX) { pointI.pos += Vector3.left * (new Vector3(boundaryX, pointI.pos.y) - pointI.pos).magnitude * foutside * (Time.fixedDeltaTime * Time.fixedDeltaTime) / pointI.m; } pointI.transform.position = pointI.pos; pointI.v = (pointI.pos - pointI.prevPos) / Time.fixedDeltaTime; } }