public static SoftBody CreateRope(SoftBodyWorldInfo worldInfo, Vector3 from, Vector3 to, int resolution, int fixedTips) { // Create nodes int numLinks = resolution + 2; var positions = new Vector3[numLinks]; var masses = new double[numLinks]; for (int i = 0; i < numLinks; i++) { Vector3.Lerp(ref from, ref to, i / (double)(numLinks - 1), out positions[i]); masses[i] = 1; } var body = new SoftBody(worldInfo, numLinks, positions, masses); if ((fixedTips & 1) != 0) { body.SetMass(0, 0); } if ((fixedTips & 2) != 0) { body.SetMass(numLinks - 1, 0); } // Create links for (int i = 1; i < numLinks; i++) { body.AppendLink(i - 1, i); } return(body); }
public static SoftBody CreateRope(SoftBodyWorldInfo worldInfo, Vector3 from, Vector3 to, int res, int fixeds) { // Create nodes int r = res + 2; Vector3[] x = new Vector3[r]; float[] m = new float[r]; for (int i = 0; i < r; i++) { Vector3.Lerp(ref from, ref to, i / (float)(r - 1), out x[i]); m[i] = 1; } SoftBody psb = new SoftBody(worldInfo, r, x, m); if ((fixeds & 1) != 0) { psb.SetMass(0, 0); } if ((fixeds & 2) != 0) { psb.SetMass(r - 1, 0); } // Create links for (int i = 1; i < r; i++) { psb.AppendLink(i - 1, i); } return(psb); }
void Init_Bending() { const float s = 4; Vector3[] x = new Vector3[] { new Vector3(-s, 0, -s), new Vector3(+s, 0, -s), new Vector3(+s, 0, +s), new Vector3(-s, 0, +s) }; float[] m = new float[] { 0, 0, 0, 1 }; SoftBody psb = new SoftBody(softBodyWorldInfo, 4, x, m); psb.AppendLink(0, 1); psb.AppendLink(1, 2); psb.AppendLink(2, 3); psb.AppendLink(3, 0); psb.AppendLink(0, 2); SoftWorld.AddSoftBody(psb); }
// Helper to test and add links correctly. // Records links that have already been generated static bool TestAndAddLink(AlignedIntArray trianglesForLinks, SoftBody softBody, int triangle, IntArray triangleVertexIndexArray, int numVertices, int vertex0, int vertex1, int nonLinkVertex, Material structuralMaterial, bool createBendLinks, Material bendMaterial) { if (trianglesForLinks[numVertices * vertex0 + vertex1] >= 0 && createBendLinks) { // Already have link so find other triangle and generate cross link int otherTriangle = trianglesForLinks[numVertices * vertex0 + vertex1]; int[] otherIndices = new int[] { triangleVertexIndexArray[otherTriangle * 3], triangleVertexIndexArray[otherTriangle * 3 + 1], triangleVertexIndexArray[otherTriangle * 3 + 2] }; int nodeA = 0; // Test all links of the other triangle against this link. The one that's not part of it is what we want. if (otherIndices[0] != vertex0 && otherIndices[0] != vertex1) { nodeA = otherIndices[0]; } if (otherIndices[1] != vertex0 && otherIndices[1] != vertex1) { nodeA = otherIndices[1]; } if (otherIndices[2] != vertex0 && otherIndices[2] != vertex1) { nodeA = otherIndices[2]; } softBody.AppendLink(nodeA, nonLinkVertex, bendMaterial); } else { // Don't yet have link so create it softBody.AppendLink(vertex0, vertex1, structuralMaterial); // If we added a new link, set the triangle array trianglesForLinks[numVertices * vertex0 + vertex1] = triangle; trianglesForLinks[numVertices * vertex1 + vertex0] = triangle; } return(true); }
protected override SoftBody CreateSoftBody(SoftBodyWorldInfo si) { si.SparseSdf.Reset(); SoftBody sb = new SoftBody(si, vertices, mass); int pairs = this.indices.Length / 2; for (int i = 0; i < pairs; i++) { sb.AppendLink(indices[i * 2], indices[i * 2 + 1]); } sb.RandomizeConstraints(); this.SetConfig(sb); return(sb); }
public static SoftBody CreateFromTriMesh(SoftBodyWorldInfo worldInfo, Vector3[] vertices, int[] triangles, bool randomizeConstraints = true) { int numTriangleIndices = triangles.Length; int numTriangles = numTriangleIndices / 3; int maxIndex = 0; // triangles.Max() + 1; for (int i = 0; i < numTriangleIndices; i++) { if (triangles[i] > maxIndex) { maxIndex = triangles[i]; } } maxIndex++; var psb = new SoftBody(worldInfo, maxIndex, vertices, null); BitArray chks = new BitArray(maxIndex * maxIndex); for (int i = 0; i < numTriangleIndices; i += 3) { int[] idx = new int[] { triangles[i], triangles[i + 1], triangles[i + 2] }; for (int j = 2, k = 0; k < 3; j = k++) { int chkIndex = maxIndex * idx[k] + idx[j]; if (!chks[chkIndex]) { chks[chkIndex] = true; chks[maxIndex * idx[j] + idx[k]] = true; psb.AppendLink(idx[j], idx[k]); } } psb.AppendFace(idx[0], idx[1], idx[2]); } if (randomizeConstraints) { psb.RandomizeConstraints(); } return(psb); }
public static SoftBody CreatePatch(SoftBodyWorldInfo worldInfo, Vector3 corner00, Vector3 corner10, Vector3 corner01, Vector3 corner11, int resolutionX, int resolutionY, int fixedCorners, bool generateDiagonals) { // Create nodes if ((resolutionX < 2) || (resolutionY < 2)) { return(null); } int rx = resolutionX; int ry = resolutionY; int total = rx * ry; var positions = new Vector3[total]; var masses = new double[total]; for (int y = 0; y < ry; y++) { double ty = y / (double)(ry - 1); Vector3 py0, py1; Vector3.Lerp(ref corner00, ref corner01, ty, out py0); Vector3.Lerp(ref corner10, ref corner11, ty, out py1); for (int ix = 0; ix < rx; ix++) { double tx = ix / (double)(rx - 1); int index = rx * y + ix; Vector3.Lerp(ref py0, ref py1, tx, out positions[index]); masses[index] = 1; } } var body = new SoftBody(worldInfo, total, positions, masses); if ((fixedCorners & 1) != 0) { body.SetMass(0, 0); } if ((fixedCorners & 2) != 0) { body.SetMass(rx - 1, 0); } if ((fixedCorners & 4) != 0) { body.SetMass(rx * (ry - 1), 0); } if ((fixedCorners & 8) != 0) { body.SetMass(rx * (ry - 1) + rx - 1, 0); } // Create links and faces for (int y = 0; y < ry; ++y) { for (int x = 0; x < rx; ++x) { int ixy = rx * y + x; int ix1y = ixy + 1; int ixy1 = rx * (y + 1) + x; bool mdx = (x + 1) < rx; bool mdy = (y + 1) < ry; if (mdx) { body.AppendLink(ixy, ix1y); } if (mdy) { body.AppendLink(ixy, ixy1); } if (mdx && mdy) { int ix1y1 = ixy1 + 1; if (((x + y) & 1) != 0) { body.AppendFace(ixy, ix1y, ix1y1); body.AppendFace(ixy, ix1y1, ixy1); if (generateDiagonals) { body.AppendLink(ixy, ix1y1); } } else { body.AppendFace(ixy1, ixy, ix1y); body.AppendFace(ixy1, ix1y, ix1y1); if (generateDiagonals) { body.AppendLink(ix1y, ixy1); } } } } } return(body); }
public static SoftBody CreateFromTetGenData(SoftBodyWorldInfo worldInfo, string ele, string face, string node, bool faceLinks, bool tetraLinks, bool facesFromTetras) { CultureInfo culture = CultureInfo.InvariantCulture; char[] separator = new[] { ' ' }; Vector3[] pos; using (var nodeReader = new StringReader(node)) { string[] nodeHeader = nodeReader.ReadLine().Split(separator, StringSplitOptions.RemoveEmptyEntries); int numNodes = int.Parse(nodeHeader[0]); //int numDims = int.Parse(nodeHeader[1]); //int numAttrs = int.Parse(nodeHeader[2]); //bool hasBounds = !nodeHeader[3].Equals("0"); pos = new Vector3[numNodes]; for (int n = 0; n < numNodes; n++) { string[] nodeLine = nodeReader.ReadLine().Split(separator, StringSplitOptions.RemoveEmptyEntries); pos[int.Parse(nodeLine[0])] = new Vector3( double.Parse(nodeLine[1], culture), double.Parse(nodeLine[2], culture), double.Parse(nodeLine[3], culture)); } } var psb = new SoftBody(worldInfo, pos.Length, pos, null); /* * if (!string.IsNullOrEmpty(face)) * { * throw new NotImplementedException(); * } */ if (!string.IsNullOrEmpty(ele)) { using (var eleReader = new StringReader(ele)) { string[] eleHeader = eleReader.ReadLine().Split(separator, StringSplitOptions.RemoveEmptyEntries); int numTetras = int.Parse(eleHeader[0]); //int numCorners = int.Parse(eleHeader[1]); //int numAttrs = int.Parse(eleHeader[2]); for (int n = 0; n < numTetras; n++) { string[] eleLine = eleReader.ReadLine().Split(separator, StringSplitOptions.RemoveEmptyEntries); //int index = int.Parse(eleLine[0], culture); int ni0 = int.Parse(eleLine[1], culture); int ni1 = int.Parse(eleLine[2], culture); int ni2 = int.Parse(eleLine[3], culture); int ni3 = int.Parse(eleLine[4], culture); psb.AppendTetra(ni0, ni1, ni2, ni3); if (tetraLinks) { psb.AppendLink(ni0, ni1, null, true); psb.AppendLink(ni1, ni2, null, true); psb.AppendLink(ni2, ni0, null, true); psb.AppendLink(ni0, ni3, null, true); psb.AppendLink(ni1, ni3, null, true); psb.AppendLink(ni2, ni3, null, true); } } } } //Console.WriteLine("Nodes: {0}", psb.Nodes.Count); //Console.WriteLine("Links: {0}", psb.Links.Count); //Console.WriteLine("Faces: {0}", psb.Faces.Count); //Console.WriteLine("Tetras: {0}", psb.Tetras.Count); return(psb); }
public static SoftBody CreatePatch(SoftBodyWorldInfo worldInfo, Vector3 corner00, Vector3 corner10, Vector3 corner01, Vector3 corner11, int resx, int resy, int fixeds, bool gendiags) { // Create nodes if ((resx < 2) || (resy < 2)) { return(null); } int rx = resx; int ry = resy; int tot = rx * ry; Vector3[] x = new Vector3[tot]; float[] m = new float[tot]; for (int iy = 0; iy < ry; iy++) { float ty = iy / (float)(ry - 1); Vector3 py0, py1; Vector3.Lerp(ref corner00, ref corner01, ty, out py0); Vector3.Lerp(ref corner10, ref corner11, ty, out py1); for (int ix = 0; ix < rx; ix++) { float tx = ix / (float)(rx - 1); int index = rx * iy + ix; Vector3.Lerp(ref py0, ref py1, tx, out x[index]); m[index] = 1; } } SoftBody psb = new SoftBody(worldInfo, tot, x, m); if ((fixeds & 1) != 0) { psb.SetMass(0, 0); } if ((fixeds & 2) != 0) { psb.SetMass(rx - 1, 0); } if ((fixeds & 4) != 0) { psb.SetMass(rx * (ry - 1), 0); } if ((fixeds & 8) != 0) { psb.SetMass(rx * (ry - 1) + rx - 1, 0); } // Create links and faces for (int iy = 0; iy < ry; ++iy) { for (int ix = 0; ix < rx; ++ix) { int ixy = rx * iy + ix; int ix1y = ixy + 1; int ixy1 = rx * (iy + 1) + ix; bool mdx = (ix + 1) < rx; bool mdy = (iy + 1) < ry; if (mdx) { psb.AppendLink(ixy, ix1y); } if (mdy) { psb.AppendLink(ixy, ixy1); } if (mdx && mdy) { int ix1y1 = ixy1 + 1; if (((ix + iy) & 1) != 0) { psb.AppendFace(ixy, ix1y, ix1y1); psb.AppendFace(ixy, ix1y1, ixy1); if (gendiags) { psb.AppendLink(ixy, ix1y1); } } else { psb.AppendFace(ixy1, ixy, ix1y); psb.AppendFace(ixy1, ix1y, ix1y1); if (gendiags) { psb.AppendLink(ix1y, ixy1); } } } } } return(psb); }
public static SoftBody CreateFromVtkFile(SoftBodyWorldInfo worldInfo, string fileName) { List <Vector3> points = new List <Vector3>(0); List <int[]> cells = new List <int[]>(0); using (var reader = new StreamReader(fileName)) { bool readingPoints = false; bool readingCells = false; string line; while ((line = reader.ReadLine()) != null) { if (line.Length == 0) { continue; } string[] lineParts = line.Split(' '); if (lineParts[0] == "POINTS") { readingPoints = true; readingCells = false; points.Capacity = int.Parse(lineParts[1]); } else if (lineParts[0] == "CELLS") { readingPoints = false; readingCells = true; cells.Capacity = int.Parse(lineParts[1]); } else if (lineParts[0] == "CELL_TYPES") { readingPoints = false; readingCells = false; } else if (readingPoints) { Vector3 point = new Vector3( (float)ParseDouble(lineParts[0]), (float)ParseDouble(lineParts[1]), (float)ParseDouble(lineParts[2])); points.Add(point); } else if (readingCells) { int numPoints = int.Parse(lineParts[0]); int[] cell = new int[numPoints]; for (int i = 0; i < numPoints; i++) { cell[i] = int.Parse(lineParts[i + 1]); } cells.Add(cell); } } } SoftBody body = new SoftBody(worldInfo, points.Count, points.ToArray(), null); foreach (int[] cell in cells) { body.AppendTetra(cell[0], cell[1], cell[2], cell[3]); body.AppendLink(cell[0], cell[1], null, true); body.AppendLink(cell[1], cell[2], null, true); body.AppendLink(cell[2], cell[0], null, true); body.AppendLink(cell[0], cell[3], null, true); body.AppendLink(cell[1], cell[3], null, true); body.AppendLink(cell[2], cell[3], null, true); } GenerateBoundaryFaces(body); body.InitializeDmInverse(); body.TetraScratches.Resize(body.Tetras.Count); body.TetraScratchesTn.Resize(body.Tetras.Count); //Console.WriteLine($"Nodes: {body.Nodes.Count}"); //Console.WriteLine($"Links: {body.Links.Count}"); //Console.WriteLine($"Faces: {body.Faces.Count}"); //Console.WriteLine($"Tetras: {body.Tetras.Count}"); return(body); }
SoftBody CreateVolumetricSoftbody(SoftBodyWorldInfo worldInfo, BulletSharp.Math.Vector3[] vertices) { int vertexcount = vertices.Length; psb = new SoftBody(worldInfo, vertexcount, vertices, null); for (int x = 3; vertexcount > x; x += 4) { int n0 = x - 3; int n1 = x - 2; int n2 = x - 1; int n3 = x - 0; psb.AppendTetra(n0, n1, n2, n3); psb.AppendLink(n0, n1); linkdata.Add(true); brokenlinks.Add(false); psb.AppendLink(n1, n2); linkdata.Add(true); brokenlinks.Add(false); psb.AppendLink(n2, n0); linkdata.Add(true); brokenlinks.Add(false); psb.AppendLink(n0, n3); linkdata.Add(true); brokenlinks.Add(false); psb.AppendLink(n1, n3); linkdata.Add(true); brokenlinks.Add(false); psb.AppendLink(n2, n3); linkdata.Add(true); brokenlinks.Add(false); ValidTetras.Add(true); } instances = GetInstances(vertices); //List<bool> ValidCuts = CutTest3(vertices); for (int x = 0; instances.Count > x; x++) { //if (ValidCuts[x] == false) { // continue; } for (int i = 1; instances[x].Count > i; i++) { int i1 = instances[x][i - 1]; int i2 = instances[x][i - 0]; psb.AppendLink(i1, i2); linkdata.Add(false); brokenlinks.Add(false); } } return(psb); }