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); }
public ClothSection(MyObjectBuilder_ClothSquaresComponentDefinition.ClothSquare sq) { Def = new ClothQuadDefinition(sq); Bindings = sq.Pins.Where(x => !string.IsNullOrWhiteSpace(x.Bone)).Select(x => new Binding(x)).ToArray(); }