public void SimulateOneTimeStep(float dt) { #region Apply External Force for (int v = 0; v < totalVerts; v++) { Vector3 force = Vector3.zero; Vector3 corr; // add gravity acceleration (f = ma) force += gravity * meshData.particles[v].mass; if (PBD.ExternalForce( dt, meshData.particles[v].predictedPos, meshData.particles[v].velocity, meshData.particles[v].invMass, force, damping, out corr)) { meshData.particles[v].predictedPos += corr; } } #endregion #region Apply Wind Force float dirX = wind.GetComponentInParent <Transform>().eulerAngles.x % 360 / 360; float dirY = wind.GetComponentInParent <Transform>().eulerAngles.y % 360 / 360; float dirZ = wind.GetComponentInParent <Transform>().eulerAngles.z % 360 / 360; // TODO: change this to real direction the arrow is pointing Vector3 windDir = new Vector3(dirX, dirY, dirZ); float windForce = wind.windMain; for (int t = 0; t < totalTriangles; t++) { Triangle tri = meshData.triangles[t]; Vector3 p0 = meshData.particles[tri.p0].predictedPos; Vector3 p1 = meshData.particles[tri.p1].predictedPos; Vector3 p2 = meshData.particles[tri.p2].predictedPos; float w0 = meshData.particles[tri.p0].invMass; float w1 = meshData.particles[tri.p1].invMass; float w2 = meshData.particles[tri.p2].invMass; Vector3 corr0, corr1, corr2; PBD.WindForce( dt, p0, w0, p1, w1, p2, w2, windDir, windForce, out corr0, out corr1, out corr2); meshData.particles[tri.p0].predictedPos += corr0; meshData.particles[tri.p1].predictedPos += corr1; meshData.particles[tri.p2].predictedPos += corr2; } #endregion #region Collision Constraints SH sh = new SH(gridSize, invGridSize, tableSize); SPHash[] spHash = new SPHash[tableSize]; for (int v = 0; v < totalVerts; v++) { int hash = Mathf.Abs(sh.Hash(meshData.particles[v].predictedPos)); if (spHash[hash].indices == null) { spHash[hash].indices = new List <int>(); } spHash[hash].indices.Add(meshData.particles[v].idx); } for (int t = 0; t < totalTriangles; t++) { Triangle tri = meshData.triangles[t]; Vector3 p0 = meshData.particles[tri.p0].predictedPos; Vector3 p1 = meshData.particles[tri.p1].predictedPos; Vector3 p2 = meshData.particles[tri.p2].predictedPos; float w0 = meshData.particles[tri.p0].invMass; float w1 = meshData.particles[tri.p1].invMass; float w2 = meshData.particles[tri.p2].invMass; List <int> hashes = sh.TriangleBoundingBoxHashes(p0, p1, p2); for (int h = 0; h < hashes.Count; h++) { if (spHash[h].indices != null) { for (int sph = 0; sph < spHash[h].indices.Count; sph++) { int idx = spHash[h].indices[sph]; if ( idx != meshData.particles[tri.p0].idx && idx != meshData.particles[tri.p1].idx && idx != meshData.particles[tri.p2].idx) { Vector3 p = meshData.particles[idx].predictedPos; float w = meshData.particles[idx].invMass; Vector3 corr, corr0, corr1, corr2; if (PBD.TrianglePointDistanceConstraint( p, w, p0, w0, p1, w1, p2, w2, thickness, 1f, 0.0f, out corr, out corr0, out corr1, out corr2)) { meshData.particles[idx].predictedPos += corr; meshData.particles[tri.p0].predictedPos += corr0; meshData.particles[tri.p1].predictedPos += corr1; meshData.particles[tri.p2].predictedPos += corr2; } } } } } } #endregion #region Project Constraints for (int iter = 0; iter < iterationSteps; iter++) { #region Distance Constraint for (int e = 0; e < totalEdges; e++) { Vector3 corr0, corr1; Edge edge = meshData.edges[e]; Vector3 p0 = meshData.particles[edge.p0].predictedPos; Vector3 p1 = meshData.particles[edge.p1].predictedPos; float w0 = meshData.particles[edge.p0].invMass; float w1 = meshData.particles[edge.p1].invMass; if (PBD.DistanceConstraint( p0, w0, p1, w1, edge.restLength, stretchStiffness, compressionStiffness, out corr0, out corr1)) { meshData.particles[edge.p0].predictedPos += corr0; meshData.particles[edge.p1].predictedPos += corr1; } } #endregion #region Dihedral Constraint for (int n = 0; n < totalNeighborTriangles; n++) { Vector3 corr0, corr1, corr2, corr3; NeighborTriangles neighbor = meshData.neighborTriangles[n]; Vector3 p0 = meshData.particles[neighbor.p0].predictedPos; Vector3 p1 = meshData.particles[neighbor.p1].predictedPos; Vector3 p2 = meshData.particles[neighbor.p2].predictedPos; Vector3 p3 = meshData.particles[neighbor.p3].predictedPos; float w0 = meshData.particles[neighbor.p0].invMass; float w1 = meshData.particles[neighbor.p1].invMass; float w2 = meshData.particles[neighbor.p2].invMass; float w3 = meshData.particles[neighbor.p3].invMass; if (PBD.DihedralConstraint( p0, w0, p1, w1, p2, w2, p3, w3, neighbor.restAngle, bendingStiffness, out corr0, out corr1, out corr2, out corr3)) { meshData.particles[neighbor.p0].predictedPos += corr0; meshData.particles[neighbor.p1].predictedPos += corr1; meshData.particles[neighbor.p2].predictedPos += corr2; meshData.particles[neighbor.p3].predictedPos += corr3; } } #endregion } #endregion }