public static void SolveClusters(AlignedSoftBodyArray bodies) { btSoftBody_solveClusters(bodies._native); }
// Create a sequence of flag objects and add them to the world. void CreateFlag(int width, int height, out AlignedSoftBodyArray flags) { flags = new AlignedSoftBodyArray(); // First create a triangle mesh to represent a flag // Allocate a simple mesh consisting of a vertex array and a triangle index array IndexedMesh mesh = new IndexedMesh(); mesh.NumVertices = width * height; mesh.NumTriangles = 2 * (width - 1) * (height - 1); Vector3Array vertexArray = new Vector3Array(mesh.NumVertices); mesh.Vertices = vertexArray; mesh.VertexStride = Vector3.SizeInBytes; IntArray triangleVertexIndexArray = new IntArray(3 * mesh.NumTriangles); mesh.TriangleIndices = triangleVertexIndexArray; mesh.TriangleIndexStride = sizeof(int) * 3; // Generate normalised object space vertex coordinates for a rectangular flag Matrix defaultScale = Matrix.Scaling(5, 20, 1); for (int y = 0; y < height; ++y) { float yCoordinate = y * 2.0f / (float)height - 1.0f; for (int x = 0; x < width; ++x) { float xCoordinate = x * 2.0f / (float)width - 1.0f; Vector3 vertex = new Vector3(xCoordinate, yCoordinate, 0.0f); vertexArray[y * width + x] = Vector3.TransformCoordinate(vertex, defaultScale); } } // Generate vertex indices for triangles for (int y = 0; y < (height - 1); ++y) { for (int x = 0; x < (width - 1); ++x) { // Triangle 0 // Top left of square on mesh { int vertex0 = y * width + x; int vertex1 = vertex0 + 1; int vertex2 = vertex0 + width; int triangleIndex = 2 * (y * (width - 1) + x); triangleVertexIndexArray[(mesh.TriangleIndexStride * triangleIndex) / sizeof(int)] = vertex0; triangleVertexIndexArray[(mesh.TriangleIndexStride * triangleIndex + 1) / sizeof(int) + 1] = vertex1; triangleVertexIndexArray[(mesh.TriangleIndexStride * triangleIndex + 2) / sizeof(int) + 2] = vertex2; } // Triangle 1 // Bottom right of square on mesh { int vertex0 = y * width + x + 1; int vertex1 = vertex0 + width; int vertex2 = vertex1 - 1; int triangleIndex = 2 * y * (width - 1) + 2 * x + 1; triangleVertexIndexArray[(mesh.TriangleIndexStride * triangleIndex) / sizeof(int)] = vertex0; triangleVertexIndexArray[(mesh.TriangleIndexStride * triangleIndex) / sizeof(int) + 1] = vertex1; triangleVertexIndexArray[(mesh.TriangleIndexStride * triangleIndex) / sizeof(int) + 2] = vertex2; } } } Matrix defaultRotateAndScale = Matrix.RotationX(0.5f); // Construct the sequence flags applying a slightly different translation to each one to arrange them // appropriately in the scene. for (int i = 0; i < numFlags; ++i) { float zTranslate = flagSpacing * (i - numFlags / 2); Vector3 defaultTranslate = new Vector3(0, 20, zTranslate); Matrix transform = defaultRotateAndScale * Matrix.Translation(defaultTranslate); SoftBody softBody = CreateFromIndexedMesh(vertexArray, triangleVertexIndexArray, true); for (int j = 0; j < mesh.NumVertices; ++j) { softBody.SetMass(j, 10.0f / mesh.NumVertices); } softBody.SetMass((height - 1) * width, 0); softBody.SetMass((height - 1) * width + width - 1, 0); softBody.SetMass((height - 1) * width + width / 2, 0); softBody.Cfg.Collisions = FCollisions.CLSS | FCollisions.CLRS; softBody.Cfg.LF = 0.0005f; softBody.Cfg.VCF = 0.001f; softBody.Cfg.DP = 0.0f; softBody.Cfg.DG = 0.0f; flags.Add(softBody); softBody.Transform(transform); SoftWorld.AddSoftBody(softBody); } //delete [] vertexArray; //delete [] triangleVertexIndexArray; }
protected override void OnHandleInput() { base.OnHandleInput(); if (Input.MousePressed == MouseButtons.Right) { results.Fraction = 1; if (pickConstraint == null) { Vector3 rayFrom = Freelook.Eye; Vector3 rayTo = GetRayTo(Input.MousePoint, Freelook.Eye, Freelook.Target, FieldOfView); Vector3 rayDir = (rayTo - rayFrom); rayDir.Normalize(); AlignedSoftBodyArray sbs = ((SoftRigidDynamicsWorld)PhysicsContext.World).SoftBodyArray; for (int ib = 0; ib < sbs.Count; ++ib) { SoftBody psb = sbs[ib]; SRayCast res = new SRayCast(); if (psb.RayTest(rayFrom, rayTo, res)) { results = res; } } if (results.Fraction < 1) { impact = rayFrom + (rayTo - rayFrom) * results.Fraction; drag = !(PhysicsContext as Physics).cutting; lastMousePos = Input.MousePoint; node = null; switch (results.Feature) { case EFeature.Tetra: { Tetra tet = results.Body.Tetras[results.Index]; node = tet.Nodes[0]; for (int i = 1; i < 4; ++i) { if ((node.X - impact).LengthSquared() > (tet.Nodes[i].X - impact).LengthSquared()) { node = tet.Nodes[i]; } } break; } case EFeature.Face: { Face f = results.Body.Faces[results.Index]; node = f.N[0]; for (int i = 1; i < 3; ++i) { if ((node.X - impact).LengthSquared() > (f.N[i].X - impact).LengthSquared()) { node = f.N[i]; } } } break; } if (node != null) { goal = node.X; } //return; } } } else if (Input.MouseReleased == MouseButtons.Right) { if ((!drag) && (PhysicsContext as Physics).cutting && (results.Fraction < 1)) { ImplicitSphere isphere = new ImplicitSphere(impact, 1); results.Body.Refine(isphere, 0.0001f, true); } results.Fraction = 1; drag = false; } // Mouse movement if (Input.MouseDown == MouseButtons.Right) { if (node != null && (results.Fraction < 1)) { if (!drag) { int x = Input.MousePoint.X - lastMousePos.X; int y = Input.MousePoint.Y - lastMousePos.Y; if ((x * x) + (y * y) > 6) { drag = true; } } if (drag) { lastMousePos = Input.MousePoint; } } } (PhysicsContext as Physics).HandleInput(Input, FrameDelta); }