/// <seealso cref="Silver.Weight.Raw.Collide.Collider.Collide(Silver.Weight.Raw.Contact[], Silver.Weight.Raw.Body, Silver.Weight.Raw.Body)">
        /// </seealso>
        public override int Collide(Contact[] contacts, Body bodyA, Body bodyB)
        {
            Polygon polyA = (Polygon) bodyA.Shape;
            Circle circle = (Circle) bodyB.Shape;

            // TODO: this can be optimized using matrix multiplications and moving only the circle
            Vector2f[] vertsA = polyA.GetVertices(bodyA.GetPosition(), bodyA.Rotation);

            Vector2f centroidA = new Vector2f(polyA.GetCentroid());
            centroidA.Add(bodyA.GetPosition());

            int[][] collPairs = GetCollisionCandidates(vertsA, centroidA, circle.Radius, bodyB.GetPosition());

            int noContacts = 0;
            for (int i = 0; i < collPairs.Length; i++)
            {
                if (noContacts >= contacts.Length)
                    return contacts.Length;

                Vector2f lineStartA = vertsA[collPairs[i][0]];
                Vector2f lineEndA = vertsA[(collPairs[i][0] + 1) % vertsA.Length];
                Line line = new Line(lineStartA, lineEndA);

                float dis2 = line.distanceSquared(bodyB.GetPosition());
                float r2 = circle.Radius * circle.Radius;

                if (dis2 < r2)
                {
                    Vector2f pt = new Vector2f();

                    line.getClosestPoint(bodyB.GetPosition(), pt);
                    Vector2f normal = new Vector2f(bodyB.GetPosition());
                    normal.Sub(pt);
                    float sep = circle.Radius - normal.Length();
                    normal.Normalise();

                    contacts[noContacts].Separation = - sep;
                    contacts[noContacts].Position = pt;
                    contacts[noContacts].Normal = normal;
                    contacts[noContacts].Feature = new FeaturePair();
                    noContacts++;
                }
            }

            return noContacts;
        }
Пример #2
0
        /// <summary> Configure the line
        /// 
        /// </summary>
        /// <param name="start">The start point of the line
        /// </param>
        /// <param name="end">The end point of the line
        /// </param>
        public virtual void Reconfigure(ROVector2f start, ROVector2f end)
        {
            this.start = start;
            this.end = end;

            vec = new Vector2f(end);
            vec.Sub(start);

            lenSquared = vec.Length();
            lenSquared *= lenSquared;
        }
Пример #3
0
        /// <summary> Precaculate everything and apply initial impulse before the
        /// simulation Step takes place
        /// 
        /// </summary>
        /// <param name="invDT">The amount of time the simulation is being stepped by
        /// </param>
        public virtual void PreStep(float invDT)
        {
            // calculate the spring's vector (pointing from body1 to body2) and Length
            spring = new Vector2f(body2.GetPosition());
            spring.Add(r2);
            spring.Sub(body1.GetPosition());
            spring.Sub(r1);
            springLength = spring.Length();

            // the spring vector needs to be normalized for ApplyImpulse as well!
            spring.Normalise();

            // calculate the spring's forces
            // note that although theoretically invDT could never be 0
            // but here it can
            float springConst;

            if (springLength < minSpringSize || springLength > maxSpringSize)
            {
                // Pre-compute anchors, mass matrix, and bias.
                Matrix2f rot1 = new Matrix2f(body1.Rotation);
                Matrix2f rot2 = new Matrix2f(body2.Rotation);

                r1 = MathUtil.Mul(rot1, localAnchor1);
                r2 = MathUtil.Mul(rot2, localAnchor2);

                // the mass normal or 'k'
                float rn1 = r1.Dot(spring);
                float rn2 = r2.Dot(spring);
                float kNormal = body1.InvMass + body2.InvMass;
                kNormal += body1.InvI * (r1.Dot(r1) - rn1 * rn1) + body2.InvI * (r2.Dot(r2) - rn2 * rn2);
                massNormal = 1 / kNormal;

                // The spring is broken so apply force to correct it
                // note that we use biased velocities for this
                float springImpulse = invDT != 0?brokenSpringConst * (springLength - springSize) / invDT:0;

                Vector2f impulse = MathUtil.Scale(spring, springImpulse);
                body1.AdjustBiasedVelocity(MathUtil.Scale(impulse, body1.InvMass));
                body1.AdjustBiasedAngularVelocity((body1.InvI * MathUtil.Cross(r1, impulse)));

                body2.AdjustBiasedVelocity(MathUtil.Scale(impulse, - body2.InvMass));
                body2.AdjustBiasedAngularVelocity(- (body2.InvI * MathUtil.Cross(r2, impulse)));

                isBroken = true;
                return ;
            }
            else if (springLength < springSize)
            {
                springConst = compressedSpringConst;
                isBroken = false;
            }
            else
            {
                // if ( springLength >= springSize )
                springConst = stretchedSpringConst;
                isBroken = false;
            }

            float springImpulse2 = invDT != 0?springConst * (springLength - springSize) / invDT:0;

            // apply the spring's forces
            Vector2f impulse2 = MathUtil.Scale(spring, springImpulse2);
            body1.AdjustVelocity(MathUtil.Scale(impulse2, body1.InvMass));
            body1.AdjustAngularVelocity((body1.InvI * MathUtil.Cross(r1, impulse2)));

            body2.AdjustVelocity(MathUtil.Scale(impulse2, - body2.InvMass));
            body2.AdjustAngularVelocity(- (body2.InvI * MathUtil.Cross(r2, impulse2)));
        }
Пример #4
0
        /// <summary> Resolve the collision math around an end point
        /// 
        /// </summary>
        /// <param name="pos">The position of the contact
        /// </param>
        /// <param name="bodyA">The first body in the collision
        /// </param>
        /// <param name="bodyB">The second body in the collision
        /// </param>
        /// <param name="leftLine">The line to the left of the vertex of collision
        /// </param>
        /// <param name="rightLine">The line to the right of the vertex of collision
        /// </param>
        /// <param name="contact">The contact to populate
        /// </param>
        /// <param name="norm">The normal determined for the line
        /// </param>
        /// <param name="i">The index of teh face we're resolving for feature ID
        /// </param>
        private void ResolveEndPointCollision(Vector2f pos, Body bodyA, Body bodyB, Vector2f norm, Line leftLine, Line rightLine, Contact contact, int i)
        {
            Vector2f start = new Vector2f(pos);
            Vector2f end = new Vector2f(start);
            end.Add(norm);

            rightLine.move(bodyA.GetPosition());
            leftLine.move(bodyA.GetPosition());
            Line normLine = new Line(start, end);
            Vector2f rightPoint = normLine.intersect(rightLine);
            Vector2f leftPoint = normLine.intersect(leftLine);

            float dis1 = System.Single.MaxValue;
            if (rightPoint != null)
            {
                dis1 = rightPoint.Distance(start) - norm.Length();
            }
            float dis2 = System.Single.MaxValue;
            if (leftPoint != null)
            {
                dis2 = leftPoint.Distance(start) - norm.Length();
            }

            norm.Normalise();
            float dis = System.Math.Min(dis1, dis2);

            contact.Separation = - dis;
            contact.Position = pos;
            contact.Normal = norm;
            contact.Feature = new FeaturePair(i);
        }
Пример #5
0
        /// <summary> Create a joint holding two bodies together
        /// 
        /// </summary>
        /// <param name="b1">The first body attached to the joint
        /// </param>
        /// <param name="b2">The second body attached to the joint
        /// </param>
        /// <param name="anchor1">The location of the attachment to the first body, in absolute coordinates.
        /// </param>
        /// <param name="anchor2">The location of the attachment to the second body, in absolute coordinates.
        /// </param>
        public SpringJoint(Body b1, Body b2, ROVector2f anchor1, ROVector2f anchor2)
        {
            id = NEXT_ID++;

            stretchedSpringConst = 100;
            compressedSpringConst = 100;
            brokenSpringConst = 100;

            Vector2f spring = new Vector2f(anchor1);
            spring.Sub(anchor2);
            springSize = spring.Length();
            minSpringSize = 0;
            maxSpringSize = 2 * springSize;

            Reconfigure(b1, b2, anchor1, anchor2);
        }