예제 #1
0
        /// <summary>
        /// Create a verlet cluster.
        /// </summary>
        /// <param name="world">Verlet world</param>
        /// <param name="centerPosition">Center position</param>
        /// <param name="pointCount">Point count</param>
        /// <param name="diameter">Cluster diameter</param>
        /// <param name="gravityScale">Gravity scale</param>
        /// <param name="tearSensitivityFactor">Distance factor required to break the cloth. Use `-1` to create an unbreakable cloth.</param>
        /// <param name="stiffness">Stiffness of the cloth</param>
        /// <param name="drawPoints">Draw points</param>
        /// <param name="pointRadius">Verlet point radius</param>
        public VerletCluster(VerletWorld world, Vector2 centerPosition, int pointCount, float diameter, float gravityScale = 1, float tearSensitivityFactor = -1, float stiffness = 0.1f, bool drawPoints = true, float pointRadius = 10f)
        {
            Points = new List <VerletPoint>();

            for (int i = 0; i < pointCount; ++i)
            {
                var position = centerPosition + new Vector2((float)GD.RandRange(-1, 1), (float)GD.RandRange(-1, 1));
                var point    = world.CreatePoint();
                point.GravityScale = gravityScale;
                point.Radius       = pointRadius;
                point.Visible      = drawPoints;
                point.MoveToPosition(position);
                Points.Add(point);
            }

            for (int i = 0; i < Points.Count - 1; ++i)
            {
                for (int j = i + 1; j < Points.Count; ++j)
                {
                    var a = Points[i];
                    var b = Points[j];

                    var link = world.CreateLink(a, b);
                    link.RestingDistance = diameter;
                    link.TearSensitivity = diameter * tearSensitivityFactor;
                    link.Stiffness       = stiffness;
                }
            }
        }
 /// <summary>
 /// Create a verlet chain builder.
 /// </summary>
 /// <param name="world">Verlet world</param>
 /// <param name="pinFirst">Pin first chain point</param>
 /// <param name="pinLast">Pin last chain point</param>
 /// <param name="drawIntermediatePoints">Draw chain intermediate points</param>
 public VerletChainBuilder(VerletWorld world, bool pinFirst = true, bool pinLast = false, bool drawIntermediatePoints = false)
 {
     this.world    = world;
     this.pinFirst = pinFirst;
     this.pinLast  = pinLast;
     this.drawIntermediatePoints = drawIntermediatePoints;
     points = new List <VerletPoint>();
 }
예제 #3
0
        /// <summary>
        /// Create a verlet ragdoll.
        /// </summary>
        /// <param name="world">Verlet world</param>
        /// <param name="centerPosition">Center position</param>
        /// <param name="height">Body height</param>
        /// <param name="gravityScale">Gravity scale</param>
        /// <param name="tearSensitivityFactor">Distance factor required to break links. Use '-1' to create an unbreakable ragdoll</param>
        /// <param name="pointRadius">Point radius</param>
        /// <param name="drawIntermediatePoints">Draw all ragdoll points</param>
        /// <param name="drawSupportLinks">Draw support links</param>
        public VerletRagdoll(VerletWorld world, Vector2 centerPosition, float height, float gravityScale = 1, float tearSensitivityFactor = -1, float pointRadius = 10f, bool drawIntermediatePoints = false, bool drawSupportLinks = false)
        {
            Vector2 genPos()
            {
                return(centerPosition + MathUtils.RandVector2(-5, 5, -5, 5));
            }

            VerletPoint createPoint(float mass, float?radius = null, bool?visible = null)
            {
                var point = world.CreatePoint(genPos(), mass: mass, radius: radius ?? pointRadius, visible: visible ?? drawIntermediatePoints);

                point.GravityScale = gravityScale;
                return(point);
            }

            var headSize   = pointRadius * 3;
            var handSize   = pointRadius * 2;
            var footSize   = pointRadius * 1.5f;
            var headLength = height / 7.5f;

            head     = createPoint(4, radius: headSize, visible: true);
            shoulder = createPoint(26);
            world.CreateLink(head, shoulder, restingDistance: 5 / 4 * headLength, tearSensitivityFactor: tearSensitivityFactor, stiffness: 1);

            elbowLeft  = createPoint(2);
            elbowRight = createPoint(2);
            world.CreateLink(elbowLeft, shoulder, restingDistance: 3 / 2 * headLength, tearSensitivityFactor: tearSensitivityFactor, stiffness: 1);
            world.CreateLink(elbowRight, shoulder, restingDistance: 3 / 2 * headLength, tearSensitivityFactor: tearSensitivityFactor, stiffness: 1);

            handLeft  = createPoint(2, radius: handSize, visible: true);
            handRight = createPoint(2, radius: handSize, visible: true);
            world.CreateLink(handLeft, elbowLeft, restingDistance: 2 * headLength, tearSensitivityFactor: tearSensitivityFactor, stiffness: 1);
            world.CreateLink(handRight, elbowRight, restingDistance: 2 * headLength, tearSensitivityFactor: tearSensitivityFactor, stiffness: 1);

            pelvis = createPoint(15);
            world.CreateLink(pelvis, shoulder, restingDistance: 3.5f * headLength, tearSensitivityFactor: tearSensitivityFactor, stiffness: 0.8f);
            world.CreateLink(pelvis, head, restingDistance: 4.75f * headLength, tearSensitivityFactor: tearSensitivityFactor, stiffness: 0.02f, visible: drawSupportLinks, color: Colors.LightBlue.WithAlpha(64));

            kneeLeft  = createPoint(10);
            kneeRight = createPoint(10);
            world.CreateLink(kneeLeft, pelvis, restingDistance: 2 * headLength, tearSensitivityFactor: tearSensitivityFactor, stiffness: 1);
            world.CreateLink(kneeRight, pelvis, restingDistance: 2 * headLength, tearSensitivityFactor: tearSensitivityFactor, stiffness: 1);

            footLeft  = createPoint(20, radius: footSize, visible: true);
            footRight = createPoint(20, radius: footSize, visible: true);
            world.CreateLink(footLeft, kneeLeft, restingDistance: 2 * headLength, tearSensitivityFactor: tearSensitivityFactor, stiffness: 1);
            world.CreateLink(footRight, kneeRight, restingDistance: 2 * headLength, tearSensitivityFactor: tearSensitivityFactor, stiffness: 1);
            world.CreateLink(footLeft, shoulder, restingDistance: 7.5f * headLength, tearSensitivityFactor: tearSensitivityFactor, stiffness: 0.001f, visible: drawSupportLinks, color: Colors.LightBlue.WithAlpha(64));
            world.CreateLink(footRight, shoulder, restingDistance: 7.5f * headLength, tearSensitivityFactor: tearSensitivityFactor, stiffness: 0.001f, visible: drawSupportLinks, color: Colors.LightBlue.WithAlpha(64));
        }
예제 #4
0
        /// <summary>
        /// Create a simple verlet link.
        /// </summary>
        /// <param name="world">World</param>
        /// <param name="a">Point A</param>
        /// <param name="b">Point B</param>
        public VerletLink(VerletWorld world, VerletPoint a, VerletPoint b)
        {
            A          = a;
            B          = b;
            this.world = world;

            PositionA = A.GlobalPosition;
            PositionB = B.GlobalPosition;

            if (RestingDistance == 0)
            {
                // Calculate resting distance from points position
                RestingDistance = (PositionB - PositionA).Length();
            }
        }
예제 #5
0
 /// <summary>
 /// Create an uninitialized verlet link.
 /// </summary>
 public VerletLink()
 {
     this.world = null;
 }
예제 #6
0
        /// <summary>
        /// Create a verlet cloth.
        /// </summary>
        /// <param name="world">Verlet world</param>
        /// <param name="topLeftPosition">Top-left position</param>
        /// <param name="pointCount">X/Y point count</param>
        /// <param name="separation">Separation</param>
        /// <param name="pinMode">Pin mode</param>
        /// <param name="tearSensitivityFactor">Distance factor required to break the cloth. Use `-1` to create an unbreakable cloth.</param>
        /// <param name="stiffness">Stiffness of the cloth</param>
        /// <param name="drawPoints">Draw verlet points</param>
        /// <param name="pointRadius">Verlet point radius</param>
        public VerletCloth(VerletWorld world, Vector2 topLeftPosition, Vector2 pointCount, float separation, PinModeEnum pinMode = PinModeEnum.TopCorners, float tearSensitivityFactor = 2, float stiffness = 1, bool drawPoints = false, float pointRadius = 10f)
        {
            points = new List <VerletPoint>();

            for (int j = 0; j < pointCount.y; ++j)
            {
                for (int i = 0; i < pointCount.x; ++i)
                {
                    var position = topLeftPosition + new Vector2(separation * i, separation * j);
                    var point    = world.CreatePoint();
                    point.Radius  = pointRadius;
                    point.Visible = drawPoints;
                    point.MoveToPosition(position);

                    if (pinMode == PinModeEnum.AllCorners)
                    {
                        if ((j == 0 || j == pointCount.y - 1) && (i == 0 || i == pointCount.x - 1))
                        {
                            point.PinToCurrentPosition();
                        }
                    }
                    else if (pinMode == PinModeEnum.TopCorners)
                    {
                        if (j == 0 && (i == 0 || i == pointCount.x - 1))
                        {
                            point.PinToCurrentPosition();
                        }
                    }
                    else if (pinMode == PinModeEnum.Top)
                    {
                        if (j == 0)
                        {
                            point.PinToCurrentPosition();
                        }
                    }

                    points.Add(point);
                }
            }

            if (points.Count == 0)
            {
                GD.PrintErr("Bad points length for cloth. Need to be > 0");
                return;
            }

            for (int j = 0; j < pointCount.y; ++j)
            {
                for (int i = 0; i < pointCount.x; ++i)
                {
                    if (i > 0)
                    {
                        // Right to left
                        int pAIdx = i - 1 + (j * (int)pointCount.x);
                        int pBIdx = i + (j * (int)pointCount.x);

                        var link = world.CreateLink(points[pAIdx], points[pBIdx]);
                        link.RestingDistance = separation;
                        link.TearSensitivity = separation * tearSensitivityFactor;
                        link.Stiffness       = stiffness;
                    }

                    if (j > 0)
                    {
                        // Bottom to top
                        int pAIdx = i + ((j - 1) * (int)pointCount.x);
                        int pBIdx = i + (j * (int)pointCount.x);

                        var link = world.CreateLink(points[pAIdx], points[pBIdx]);
                        link.RestingDistance = separation;
                        link.TearSensitivity = separation * tearSensitivityFactor;
                        link.Stiffness       = stiffness;
                    }
                }
            }
        }