예제 #1
0
        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);
        }
예제 #3
0
        void InitSticks()
        {
            const int   n   = 16;
            const int   sg  = 4;
            const float sz  = 5;
            const float hg  = 4;
            const float inf = 1 / (float)(n - 1);

            for (int y = 0; y < n; ++y)
            {
                for (int x = 0; x < n; ++x)
                {
                    Vector3 org = new Vector3(-sz + sz * 2 * x * inf,
                                              -10, -sz + sz * 2 * y * inf);

                    SoftBody psb = SoftBodyHelpers.CreateRope(softBodyWorldInfo, org,
                                                              org + new Vector3(hg * 0.001f, hg, 0), sg, 1);

                    psb.Cfg.DP  = 0.005f;
                    psb.Cfg.Chr = 0.1f;
                    for (int i = 0; i < 3; ++i)
                    {
                        psb.GenerateBendingConstraints(2 + i);
                    }
                    psb.SetMass(1, 0);
                    psb.SetTotalMass(0.01f);
                    SoftWorld.AddSoftBody(psb);
                }
            }
            CreateBigBall(new Vector3(0, 13, 0));
        }
예제 #4
0
        internal override bool _BuildCollisionObject()
        {
            if (meshSettings.numPointsInRope < 2)
            {
                Debug.LogError("There must be at least two points in the rope");
                return(false);
            }
            if (SoftBodySettings.totalMass <= 0f)
            {
                Debug.LogError("The rope must have a positive mass");
                return(false);
            }

            SoftBody m_BSoftBody = SoftBodyHelpers.CreateRope(World.WorldInfo,
                                                              meshSettings.startPoint.ToBullet(), meshSettings.endPoint.ToBullet(), meshSettings.numPointsInRope, 0);

            m_collisionObject = m_BSoftBody;

            verts = new Vector3[m_BSoftBody.Nodes.Count];
            norms = new Vector3[m_BSoftBody.Nodes.Count];

            for (int i = 0; i < m_BSoftBody.Nodes.Count; i++)
            {
                verts[i] = m_BSoftBody.Nodes[i].Position.ToUnity();
                norms[i] = m_BSoftBody.Nodes[i].Normal.ToUnity();
            }

            //Set SB settings
            SoftBodySettings.ConfigureSoftBody(m_BSoftBody);

            foreach (RopeAnchor anchor in ropeAnchors)
            {
                //anchorNode point 0 to 1, rounds to node #
                int node = (int)Mathf.Floor(Mathf.Lerp(0, m_BSoftBody.Nodes.Count - 1, anchor.anchorNodePoint));

                if (anchor.body != null)
                {
                    m_BSoftBody.AppendAnchor(node, (BulletSharp.RigidBody)anchor.body.GetCollisionObject());
                }
                else
                {
                    m_BSoftBody.SetMass(node, 0);  //setting node mass to 0 fixes it in space apparently
                }
            }

            //TODO: lr, Doesnt always work in editor
            LineRenderer lr = GetComponent <LineRenderer>();

            lr.useWorldSpace = false;

            lr.SetVertexCount(verts.Length);
            lr.SetWidth(meshSettings.width, meshSettings.width);
            lr.SetColors(meshSettings.startColor, meshSettings.endColor);

            //Set SB position to GO position
            //m_BSoftBody.Rotate(transform.rotation.ToBullet());
            //m_BSoftBody.Translate(transform.position.ToBullet());
            //m_BSoftBody.Scale(transform.localScale.ToBullet());

            UpdateMesh();
            return(true);
        }
예제 #5
0
        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 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);
        }
예제 #7
0
        // 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;
        }
예제 #8
0
        private void OnSceneGUI()
        {
            if (!EditorApplication.isPlaying)
            {
                Handles.BeginGUI();
                GUILayout.Label("Viewing nodes only supported while playing.");
                Handles.EndGUI();
                return;
            }

            SoftBody softBody = bSoftBodyTarget.GetCollisionObject() as SoftBody;

            if (softBody == null)
            {
                Handles.BeginGUI();
                GUILayout.Label("Seems like the CollisionObject has not been generated.");
                Handles.EndGUI();
                return;
            }

            bool             clickedNode = false;
            AlignedNodeArray nodes       = softBody.Nodes;
            float            highestMass = 0;

            for (int i = 0; i < nodes.Count; i++)
            {
                float invMass = nodes[i].InverseMass;
                if (invMass > 0 && 1 / invMass > highestMass)
                {
                    highestMass = 1 / invMass;
                }
            }
            for (int i = 0; i < nodes.Count; i++)
            {
                float mass = softBody.GetMass(i);
                if (_currentSelectedNode == i)
                {
                    Handles.BeginGUI();
                    EditorGUI.BeginChangeCheck();
                    EditorGUILayout.LabelField(string.Format("id: {0}", i));
                    mass = EditorGUILayout.Slider("Mass", mass, 0, Mathf.Clamp(mass * 10, 1, 100), GUILayout.Width(500));
                    if (EditorGUI.EndChangeCheck())
                    {
                        softBody.SetMass(i, mass);
                        nodes[i].Velocity = BulletSharp.Math.Vector3.Zero;
                        nodes[i].Force    = BulletSharp.Math.Vector3.Zero;
                    }
                    Handles.EndGUI();
                    Handles.color = Color.green;
                }
                else
                {
                    Color usedColor;
                    if (mass > 0)
                    {
                        usedColor = Color.Lerp(Color.white, Color.gray, mass / highestMass);
                    }
                    else
                    {
                        usedColor = Color.blue;
                    }

                    Handles.color = usedColor;
                }
                Vector3 position = nodes[i].Position.ToUnity();
                float   size     = HandleUtility.GetHandleSize(position) * 0.5f;
                if (Handles.Button(position, Quaternion.identity, size, size, Handles.SphereHandleCap))
                {
                    clickedNode          = true;
                    _currentSelectedNode = i;
                }
            }

            if (!clickedNode && Input.GetMouseButton(0))
            {
                _currentSelectedNode = -1;
            }
        }