private bool CheckCollision(ClothParticle p) { bool collision = false; foreach (ClothCollider c in colliders) { if (clothType == ClothType.spring) { if (collision) { c.CheckCollision(p, true, this); } else { collision = c.CheckCollision(p, true, this); } } else { c.CheckCollision(p, false, this); } } return(collision); }
public ClothSpring(ClothParticle particle1, ClothParticle particle2, float Stiffness) { this.particle1 = particle1; this.particle2 = particle2; this.length = (particle1.pos - particle2.pos).magnitude; this.inverseLength = 1.0f / length; this.springTension = Stiffness; }
private void VerletTimeStep(ClothParticle p) { Vector3 temp = p.pos; p.pos = p.pos + (p.pos - p.oldPos) * (1 - damp) + p.acceleration * Time.fixedDeltaTime; p.oldPos = temp; p.acceleration = Vector3.zero; }
private void AddWind(ClothParticle p1, ClothParticle p2, ClothParticle p3, Vector3 windForce) { Vector3 normal = GetTriangleNormal(p1, p2, p3); Vector3 dir = normal.normalized; Vector3 force = normal * (Vector3.Dot(dir, windForce)); p1.acceleration += (force * (1 / p1.mass)) * Time.fixedDeltaTime; p2.acceleration += (force * (1 / p2.mass)) * Time.fixedDeltaTime; p3.acceleration += (force * (1 / p3.mass)) * Time.fixedDeltaTime; }
// Update is called once per frame void Update() { if (Input.GetMouseButtonDown(0)) { Vector3 mousePos = Input.mousePosition; float distance = (Camera.main.WorldToScreenPoint(particles[0, 0].pos) - mousePos).magnitude; ClothParticle temp = particles[0, 0]; foreach (ClothParticle p in particles) { if ((Camera.main.WorldToScreenPoint(p.pos) - mousePos).magnitude < distance) { distance = (Camera.main.WorldToScreenPoint(p.pos) - mousePos).magnitude; temp = p; } } if (temp != null) { selectedParticle = temp; } tConnections.text = selectedParticle.constraints.Count.ToString(); } if (Input.GetMouseButton(1)) { selectedParticle.moving = true; selectedParticle.pos += Camera.main.transform.right * ((Input.mousePosition.x - oldMousePos.x) * particleMoveSpeed * (selectedParticle.pos - Camera.main.transform.position).magnitude); selectedParticle.pos += Camera.main.transform.up * ((Input.mousePosition.y - oldMousePos.y) * particleMoveSpeed * (selectedParticle.pos - Camera.main.transform.position).magnitude); } if (Input.GetMouseButtonUp(1)) { selectedParticle.moving = false; if (clothType == ClothType.spring) { selectedParticle.acceleration = Vector3.zero; } } if (Input.GetKeyDown(KeyCode.P)) { selectedParticle.posLocked = !selectedParticle.posLocked; if (clothType == ClothType.spring) { selectedParticle.acceleration = Vector3.zero; } } oldMousePos = Input.mousePosition; }
private Vector3 GetTriangleNormal(ClothParticle p1, ClothParticle p2, ClothParticle p3) { Vector3 pos1 = p1.pos; Vector3 pos2 = p2.pos; Vector3 pos3 = p3.pos; Vector3 v1 = pos2 - pos1; Vector3 v2 = pos3 - pos1; return(Vector3.Cross(v1, v2)); }
public override bool CheckCollision(ClothParticle p, bool elastic, ClothSim cloth) { Vector3 dir = p.pos - transform.position; if (p.pos.y < transform.position.y) { p.pos = new Vector3(p.pos.x, transform.position.y, p.pos.z); //p.acceleration = Vector3.zero; return(true); } return(false); }
public override bool CheckCollision(ClothParticle p, bool elastic, ClothSim cloth) { Vector3 dif = p.pos - transform.position; if (dif.magnitude < radius) { Vector3 dir = dif.normalized; dir *= (radius + 0.001f); p.pos = dir + transform.position; p.acceleration = Vector3.zero; return(true); } return(false); }
public override bool CheckCollision(ClothParticle p, bool elastic, ClothSim cloth) { Vector3 dir = p.pos - transform.position; if (p.pos.x < transform.position.x + (boundingBox.x / 2) && p.pos.x > transform.position.x - (boundingBox.x / 2) && p.pos.y < transform.position.y + (boundingBox.y / 2) && p.pos.y > transform.position.y - (boundingBox.y / 2) && p.pos.z < transform.position.z + (boundingBox.z / 2) && p.pos.z > transform.position.z - (boundingBox.z / 2)) { //dir.Normalize(); p.acceleration = Vector3.zero; return(true); } return(false); }
public abstract bool CheckCollision(ClothParticle p, bool elastic, ClothSim cloth);
public ClothConstraint(ClothParticle particle1, ClothParticle particle2) { this.particle1 = particle1; this.particle2 = particle2; this.restLegth = (particle1.pos - particle2.pos).magnitude; }
public void Reset() { constraints.Clear(); springs.Clear(); clothAvarage = Vector3.zero; gridSize = gridSizeInit; particles = new ClothParticle[gridSize, gridSize]; float x = 0; for (int i = 0; i < particles.GetLength(0); i++) { float z = 0; for (int j = 0; j < particles.GetLength(1); j++) { ClothParticle p = new ClothParticle(new Vector3(x, 0, z), particleMass, particleCollider); particles[i, j] = p; z = z + radius; clothAvarage += new Vector3(0, -(radius / (gridSize) / 2), radius / gridSize); } x = x + radius; clothAvarage += new Vector3(radius / 2, 0, 0); } for (int i = 0; i < particles.GetLength(0); i++) { for (int j = 0; j < particles.GetLength(1); j++) { ClothParticle mainParticle = particles[i, j]; ClothParticle subParticle; if (i < particles.GetLength(0) - 1) { subParticle = particles[i + 1, j]; ClothSpring s1 = new ClothSpring(mainParticle, subParticle, tenstion); springs.Add(s1); ClothConstraint c1 = new ClothConstraint(mainParticle, subParticle); constraints.Add(c1); mainParticle.constraints.Add(c1); subParticle.constraints.Add(c1); } if (j < particles.GetLength(1) - 1) { subParticle = particles[i, j + 1]; ClothSpring s2 = new ClothSpring(mainParticle, subParticle, tenstion); springs.Add(s2); ClothConstraint c2 = new ClothConstraint(mainParticle, subParticle); constraints.Add(c2); mainParticle.constraints.Add(c2); subParticle.constraints.Add(c2); } if (sheerGrid) { if (j < particles.GetLength(0) - 1 && i < particles.GetLength(1) - 1) { subParticle = particles[i + 1, j + 1]; ClothSpring s3 = new ClothSpring(mainParticle, subParticle, tenstion); springs.Add(s3); ClothConstraint c3 = new ClothConstraint(mainParticle, subParticle); constraints.Add(c3); mainParticle.constraints.Add(c3); subParticle.constraints.Add(c3); } if (j > 0 && i < particles.GetLength(1) - 1) { subParticle = particles[i + 1, j - 1]; ClothSpring s4 = new ClothSpring(mainParticle, subParticle, tenstion); springs.Add(s4); ClothConstraint c4 = new ClothConstraint(mainParticle, subParticle); constraints.Add(c4); mainParticle.constraints.Add(c4); subParticle.constraints.Add(c4); } } if (bendGrid) { if (i < particles.GetLength(0) - 2) { subParticle = particles[i + 2, j]; ClothSpring s5 = new ClothSpring(mainParticle, subParticle, tenstion); springs.Add(s5); ClothConstraint c5 = new ClothConstraint(mainParticle, subParticle); constraints.Add(c5); mainParticle.constraints.Add(c5); subParticle.constraints.Add(c5); } if (j < particles.GetLength(1) - 2) { subParticle = particles[i, j + 2]; ClothSpring s6 = new ClothSpring(mainParticle, subParticle, tenstion); springs.Add(s6); ClothConstraint c6 = new ClothConstraint(mainParticle, subParticle); constraints.Add(c6); mainParticle.constraints.Add(c6); subParticle.constraints.Add(c6); } if (j < particles.GetLength(0) - 2 && i < particles.GetLength(1) - 2) { subParticle = particles[i + 2, j + 2]; ClothSpring s7 = new ClothSpring(mainParticle, subParticle, tenstion); springs.Add(s7); ClothConstraint c7 = new ClothConstraint(mainParticle, subParticle); constraints.Add(c7); mainParticle.constraints.Add(c7); subParticle.constraints.Add(c7); } if (j > 1 && i < particles.GetLength(1) - 2) { subParticle = particles[i + 2, j - 2]; ClothSpring s8 = new ClothSpring(mainParticle, subParticle, tenstion); springs.Add(s8); ClothConstraint c8 = new ClothConstraint(mainParticle, subParticle); constraints.Add(c8); mainParticle.constraints.Add(c8); subParticle.constraints.Add(c8); } } } } particles[0, gridSize - 1].posLocked = true; particles[0, gridSize - 1].startPos = particles[0, gridSize - 1].pos; particles[gridSize - 1, gridSize - 1].posLocked = true; particles[gridSize - 1, gridSize - 1].startPos = particles[gridSize - 1, gridSize - 1].pos; selectedParticle = particles[gridSize - 1, gridSize - 1]; filter.mesh = GenerateMesh(); CreateWireframe(); }
public static Cloth CreateQuad(ClothQuadDefinition def) { var resX = def.ResX; var resY = def.ResY; var pts = new ClothParticle[resX * resY]; for (var y = 0; y < resY; y++) { var fy = y / (float)(resY - 1); var p0 = Vector3.Lerp(def.V00, def.V01, fy); var p1 = Vector3.Lerp(def.V10, def.V11, fy); for (var x = 0; x < resX; x++) { var fx = x / (float)(resX - 1); var p = new ClothParticle { Position = Vector3.Lerp(p0, p1, fx), Velocity = Vector3.Zero, Tension = Vector3.Zero, Uv = new Vector2(fx, fy) }; pts[y * resX + x] = p; } } #region Pin Particles foreach (var pin in def.Pins) { pts[pin.Y * resX + pin.X].Pinned = true; } #endregion #region Calculate Particle Masses from Area var totalArea = 0f; for (var y = 0; y < resY; y++) { for (var x = 0; x < resX; x++) { var idx = y * resX + x; var pos = pts[idx].Position; var normal = Vector3.One; var area = 0f; if (x < resX - 1 && y < resY - 1) { area += (normal = Vector3.Cross(pts[idx + 1].Position - pos, pts[idx + resX].Position - pos)).Length() / 2; } if (x < resX - 1 && y > 0) { area += (normal = Vector3.Cross(pts[idx + 1].Position - pos, pts[idx - resX].Position - pos)).Length() / 2; } if (x > 0 && y < resY - 1) { area += (normal = Vector3.Cross(pts[idx - 1].Position - pos, pts[idx + resX].Position - pos)).Length() / 2; } if (x > 0 && y > 0) { area += (normal = Vector3.Cross(pts[idx - 1].Position - pos, pts[idx - resX].Position - pos)).Length() / 2; } normal.Normalize(); pts[idx].Normal = normal; pts[idx].Area = area; pts[idx].InverseMass = def.Mass * area; totalArea += area; } } for (var i = 0; i < pts.Length; i++) { pts[i].InverseMass = 1 / (pts[i].InverseMass / totalArea); } #endregion var springs = new List <ClothSpring>(resX * (resY - 1) + (resX - 1) * resY + (resX - 1) * (resY - 1) + (resX - 2) * (resY - 1) + (resX - 1) * (resY - 2)); #region Create Springs // + X for (var y = 0; y < resY; y++) { for (var x = 0; x < resX - 1; x++) { var idx = y * resX + x; springs.Add(new ClothSpring { P0 = idx, P1 = idx + 1, Stiffness = def.TensionStrength }); } } // + Y for (var y = 0; y < resY - 1; y++) { for (var x = 0; x < resX; x++) { var idx = y * resX + x; springs.Add(new ClothSpring { P0 = idx, P1 = idx + resX, Stiffness = def.TensionStrength }); } } // + X, +Y if (def.ShearStrength > 0) { for (var y = 0; y < resY - 1; y++) { for (var x = 0; x < resX - 1; x++) { var idx = y * resX + x; springs.Add(new ClothSpring { P0 = idx, P1 = idx + resX + 1, Stiffness = def.ShearStrength }); } } } if (def.StructuralStrength > 0) { // + 2X, +Y for (var y = 0; y < resY - 1; y++) { for (var x = 0; x < resX - 2; x++) { var idx = y * resX + x; springs.Add(new ClothSpring { P0 = idx, P1 = idx + resX + 2, Stiffness = def.StructuralStrength }); } } // +X, +2Y for (var y = 0; y < resY - 2; y++) { for (var x = 0; x < resX - 1; x++) { var idx = y * resX + x; springs.Add(new ClothSpring { P0 = idx, P1 = idx + resX * 2 + 1, Stiffness = def.StructuralStrength }); } } } #endregion #region Fill Spring Lengths for (var i = 0; i < springs.Count; i++) { var s = springs[i]; var len = Vector3.Distance(pts[s.P0].Position, pts[s.P1].Position); s.Length = len; s.InvLength = 1 / len; springs[i] = s; } #endregion var quadStream = new int[4 * (resX - 1) * (resY - 1)]; #region Create Quad Stream var quadOffset = 0; for (var y = 0; y < resY - 1; y++) { for (var x = 0; x < resX - 1; x++) { var idx = y * resX + x; quadStream[quadOffset++] = idx; quadStream[quadOffset++] = idx + 1; quadStream[quadOffset++] = idx + 1 + resX; quadStream[quadOffset++] = idx + resX; } } #endregion var cloth = new Cloth(pts, springs.ToArray(), quadStream) { Damping = def.Damping }; return(cloth); }