Пример #1
0
        // Solve A * x = b
        public b2Vec3 Solve33(b2Vec3 outV, float bX, float bY, float bZ)
        {
            float a11 = col1.x;
            float a21 = col1.y;
            float a31 = col1.z;
            float a12 = col2.x;
            float a22 = col2.y;
            float a32 = col2.z;
            float a13 = col3.x;
            float a23 = col3.y;
            float a33 = col3.z;
            //float32 det = b2Dot(col1, b2Cross(col2, col3));
            float det = a11 * (a22 * a33 - a32 * a23) +
                        a21 * (a32 * a13 - a12 * a33) +
                        a31 * (a12 * a23 - a22 * a13);

            if (det != 0.0f)
            {
                det = 1.0f / det;
            }
            //out.x = det * b2Dot(b, b2Cross(col2, col3));
            outV.x = det * (bX * (a22 * a33 - a32 * a23) +
                            bY * (a32 * a13 - a12 * a33) +
                            bZ * (a12 * a23 - a22 * a13));
            //out.y = det * b2Dot(col1, b2Cross(b, col3));
            outV.y = det * (a11 * (bY * a33 - bZ * a23) +
                            a21 * (bZ * a13 - bX * a33) +
                            a31 * (bX * a23 - bY * a13));
            //out.z = det * b2Dot(col1, b2Cross(col2, b));
            outV.z = det * (a11 * (a22 * bZ - a32 * bY) +
                            a21 * (a32 * bX - a12 * bZ) +
                            a31 * (a12 * bY - a22 * bX));
            return(outV);
        }
Пример #2
0
 public b2Mat33(b2Vec3 c1, b2Vec3 c2, b2Vec3 c3) : this(Box2DPINVOKE.new_b2Mat33__SWIG_1(b2Vec3.getCPtr(c1), b2Vec3.getCPtr(c2), b2Vec3.getCPtr(c3)), true)
 {
     if (Box2DPINVOKE.SWIGPendingException.Pending)
     {
         throw Box2DPINVOKE.SWIGPendingException.Retrieve();
     }
 }
Пример #3
0
 public void MinusEqual(b2Vec3 v)
 {
     Box2dPINVOKE.b2Vec3_MinusEqual(swigCPtr, b2Vec3.getCPtr(v));
     if (Box2dPINVOKE.SWIGPendingException.Pending)
     {
         throw Box2dPINVOKE.SWIGPendingException.Retrieve();
     }
 }
Пример #4
0
        public override void SolveVelocityConstraints(b2SolverData data)
        {
            b2Vec2 vA = m_bodyA.InternalVelocity.v;
            float  wA = m_bodyA.InternalVelocity.w;
            b2Vec2 vB = m_bodyB.InternalVelocity.v;
            float  wB = m_bodyB.InternalVelocity.w;

            float mA = m_invMassA, mB = m_invMassB;
            float iA = m_invIA, iB = m_invIB;

            if (m_frequencyHz > 0.0f)
            {
                float Cdot2 = wB - wA;

                float impulse2 = -m_mass.ez.z * (Cdot2 + m_bias + m_gamma * m_impulse.z);
                m_impulse.z += impulse2;

                wA -= iA * impulse2;
                wB += iB * impulse2;

                b2Vec2 Cdot1 = vB + b2Math.b2Cross(wB, ref m_rB) - vA - b2Math.b2Cross(wA, ref m_rA);

                b2Vec2 impulse1 = -b2Math.b2Mul22(m_mass, Cdot1);
                m_impulse.x += impulse1.x;
                m_impulse.y += impulse1.y;

                b2Vec2 P = impulse1;

                vA -= mA * P;
                wA -= iA * b2Math.b2Cross(ref m_rA, ref P);

                vB += mB * P;
                wB += iB * b2Math.b2Cross(ref m_rB, ref P);
            }
            else
            {
                b2Vec2 Cdot1 = vB + b2Math.b2Cross(wB, ref m_rB) - vA - b2Math.b2Cross(wA, ref m_rA);
                float  Cdot2 = wB - wA;
                b2Vec3 Cdot  = new b2Vec3(Cdot1.x, Cdot1.y, Cdot2);

                b2Vec3 impulse = -b2Math.b2Mul(m_mass, Cdot);
                m_impulse += impulse;

                b2Vec2 P = b2Vec2.Zero;
                P.Set(impulse.x, impulse.y);

                vA -= mA * P;
                wA -= iA * (b2Math.b2Cross(ref m_rA, ref P) + impulse.z);

                vB += mB * P;
                wB += iB * (b2Math.b2Cross(ref m_rB, ref P) + impulse.z);
            }

            m_bodyA.InternalVelocity.v = vA;
            m_bodyA.InternalVelocity.w = wA;
            m_bodyB.InternalVelocity.v = vB;
            m_bodyB.InternalVelocity.w = wB;
        }
Пример #5
0
        public b2Vec3 Solve33(b2Vec3 b)
        {
            b2Vec3 ret = new b2Vec3(Box2DPINVOKE.b2Mat33_Solve33(swigCPtr, b2Vec3.getCPtr(b)), true);

            if (Box2DPINVOKE.SWIGPendingException.Pending)
            {
                throw Box2DPINVOKE.SWIGPendingException.Retrieve();
            }
            return(ret);
        }
Пример #6
0
        public static b2Vec3 Multiply(float s, b2Vec3 a)
        {
            b2Vec3 ret = new b2Vec3(Box2dPINVOKE.Multiply__SWIG_1(s, b2Vec3.getCPtr(a)), true);

            if (Box2dPINVOKE.SWIGPendingException.Pending)
            {
                throw Box2dPINVOKE.SWIGPendingException.Retrieve();
            }
            return(ret);
        }
Пример #7
0
        public static float b2Dot(b2Vec3 a, b2Vec3 b)
        {
            float ret = Box2dPINVOKE.b2Dot__SWIG_1(b2Vec3.getCPtr(a), b2Vec3.getCPtr(b));

            if (Box2dPINVOKE.SWIGPendingException.Pending)
            {
                throw Box2dPINVOKE.SWIGPendingException.Retrieve();
            }
            return(ret);
        }
Пример #8
0
        public static b2Vec3 b2Cross(b2Vec3 a, b2Vec3 b)
        {
            b2Vec3 ret = new b2Vec3(Box2dPINVOKE.b2Cross__SWIG_3(b2Vec3.getCPtr(a), b2Vec3.getCPtr(b)), true);

            if (Box2dPINVOKE.SWIGPendingException.Pending)
            {
                throw Box2dPINVOKE.SWIGPendingException.Retrieve();
            }
            return(ret);
        }
Пример #9
0
        public static b2Vec3 b2Mul(b2Mat33 A, b2Vec3 v)
        {
            b2Vec3 ret = new b2Vec3(Box2DPINVOKE.b2Mul__SWIG_2(b2Mat33.getCPtr(A), b2Vec3.getCPtr(v)), true);

            if (Box2DPINVOKE.SWIGPendingException.Pending)
            {
                throw Box2DPINVOKE.SWIGPendingException.Retrieve();
            }
            return(ret);
        }
Пример #10
0
 public b2Mat33(b2Vec3 c1 = null, b2Vec3 c2 = null, b2Vec3 c3 = null)
 {
     if (c1 == null && c2 == null && c3 == null)
     {
         col1.SetZero();
         col2.SetZero();
         col3.SetZero();
     }
     else
     {
         col1.SetV(c1);
         col2.SetV(c2);
         col3.SetV(c3);
     }
 }
Пример #11
0
    /// Solve A * x = b, where b is a column vector. This is more efficient
    /// than computing the inverse in one-shot cases.

    /// Solve A * x = b, where b is a column vector. This is more efficient
    /// than computing the inverse in one-shot cases.
    public b2Vec3 Solve33(b2Vec3 b)
    {
        float det = Utils.b2Dot(ex, Utils.b2Cross(ey, ez));

        if (det != 0.0f)
        {
            det = 1.0f / det;
        }

        b2Vec3 x = new b2Vec3();

        x.x = det * Utils.b2Dot(b, Utils.b2Cross(ey, ez));
        x.y = det * Utils.b2Dot(ex, Utils.b2Cross(b, ez));
        x.z = det * Utils.b2Dot(ex, Utils.b2Cross(ey, b));
        return(x);
    }
Пример #12
0
 public void Add(b2Vec3 v)
 {
     x += v.x; y += v.y; z += v.z;
 }
Пример #13
0
 public void SetV(b2Vec3 v)
 {
     x = v.x;
     y = v.y;
     z = v.z;
 }
Пример #14
0
        public override bool SolvePositionConstraints(float baumgarte)
        {
            //B2_NOT_USED(baumgarte);


            float limitC;
            float oldLimitImpulse;

            b2Body bA = m_bodyA;
            b2Body bB = m_bodyB;

            b2Vec2 c1 = bA.m_sweep.c;
            float  a1 = bA.m_sweep.a;

            b2Vec2 c2 = bB.m_sweep.c;
            float  a2 = bB.m_sweep.a;

            b2Mat22 tMat;
            float   tX;

            float m1;
            float m2;
            float i1;
            float i2;

            // Solve linear limit constraint
            float linearError  = 0.0f;
            float angularError = 0.0f;
            bool  active       = false;
            float C2           = 0.0f;

            b2Mat22 R1 = b2Mat22.FromAngle(a1);
            b2Mat22 R2 = b2Mat22.FromAngle(a2);

            //b2Vec2 r1 = b2Mul(R1, m_localAnchor1 - m_localCenterA);
            tMat = R1;
            float r1X = m_localAnchor1.x - m_localCenterA.x;
            float r1Y = m_localAnchor1.y - m_localCenterA.y;

            tX  = (tMat.col1.x * r1X + tMat.col2.x * r1Y);
            r1Y = (tMat.col1.y * r1X + tMat.col2.y * r1Y);
            r1X = tX;
            //b2Vec2 r2 = b2Mul(R2, m_localAnchor2 - m_localCenterB);
            tMat = R2;
            float r2X = m_localAnchor2.x - m_localCenterB.x;
            float r2Y = m_localAnchor2.y - m_localCenterB.y;

            tX  = (tMat.col1.x * r2X + tMat.col2.x * r2Y);
            r2Y = (tMat.col1.y * r2X + tMat.col2.y * r2Y);
            r2X = tX;

            float dX = c2.x + r2X - c1.x - r1X;
            float dY = c2.y + r2Y - c1.y - r1Y;

            if (m_enableLimit)
            {
                m_axis = b2Math.MulMV(R1, m_localXAxis1);

                //m_a1 = b2Math.b2Cross(d + r1, m_axis);
                m_a1 = (dX + r1X) * m_axis.y - (dY + r1Y) * m_axis.x;
                //m_a2 = b2Math.b2Cross(r2, m_axis);
                m_a2 = r2X * m_axis.y - r2Y * m_axis.x;

                float translation = m_axis.x * dX + m_axis.y * dY;
                if (b2Math.Abs(m_upperTranslation - m_lowerTranslation) < 2.0f * b2Settings.b2_linearSlop)
                {
                    // Prevent large angular corrections.
                    C2          = b2Math.Clamp(translation, -b2Settings.b2_maxLinearCorrection, b2Settings.b2_maxLinearCorrection);
                    linearError = b2Math.Abs(translation);
                    active      = true;
                }
                else if (translation <= m_lowerTranslation)
                {
                    // Prevent large angular corrections and allow some slop.
                    C2          = b2Math.Clamp(translation - m_lowerTranslation + b2Settings.b2_linearSlop, -b2Settings.b2_maxLinearCorrection, 0.0f);
                    linearError = m_lowerTranslation - translation;
                    active      = true;
                }
                else if (translation >= m_upperTranslation)
                {
                    // Prevent large angular corrections and allow some slop.
                    C2          = b2Math.Clamp(translation - m_upperTranslation + b2Settings.b2_linearSlop, 0.0f, b2Settings.b2_maxLinearCorrection);
                    linearError = translation - m_upperTranslation;
                    active      = true;
                }
            }

            m_perp = b2Math.MulMV(R1, m_localYAxis1);

            //m_s1 = b2Cross(d + r1, m_perp);
            m_s1 = (dX + r1X) * m_perp.y - (dY + r1Y) * m_perp.x;
            //m_s2 = b2Cross(r2, m_perp);
            m_s2 = r2X * m_perp.y - r2Y * m_perp.x;

            b2Vec3 impulse = new b2Vec3();
            float  C1X     = m_perp.x * dX + m_perp.y * dY;
            float  C1Y     = a2 - a1 - m_refAngle;

            linearError  = b2Math.Max(linearError, b2Math.Abs(C1X));
            angularError = b2Math.Abs(C1Y);

            if (active)
            {
                m1 = m_invMassA;
                m2 = m_invMassB;
                i1 = m_invIA;
                i2 = m_invIB;

                m_K.col1.x = m1 + m2 + i1 * m_s1 * m_s1 + i2 * m_s2 * m_s2;
                m_K.col1.y = i1 * m_s1 + i2 * m_s2;
                m_K.col1.z = i1 * m_s1 * m_a1 + i2 * m_s2 * m_a2;
                m_K.col2.x = m_K.col1.y;
                m_K.col2.y = i1 + i2;
                m_K.col2.z = i1 * m_a1 + i2 * m_a2;
                m_K.col3.x = m_K.col1.z;
                m_K.col3.y = m_K.col2.z;
                m_K.col3.z = m1 + m2 + i1 * m_a1 * m_a1 + i2 * m_a2 * m_a2;

                m_K.Solve33(impulse, -C1X, -C1Y, -C2);
            }
            else
            {
                m1 = m_invMassA;
                m2 = m_invMassB;
                i1 = m_invIA;
                i2 = m_invIB;

                float k11 = m1 + m2 + i1 * m_s1 * m_s1 + i2 * m_s2 * m_s2;
                float k12 = i1 * m_s1 + i2 * m_s2;
                float k22 = i1 + i2;

                m_K.col1.Set(k11, k12, 0.0f);
                m_K.col2.Set(k12, k22, 0.0f);

                b2Vec2 impulse1 = m_K.Solve22(new b2Vec2(), -C1X, -C1Y);
                impulse.x = impulse1.x;
                impulse.y = impulse1.y;
                impulse.z = 0.0f;
            }

            float PX = impulse.x * m_perp.x + impulse.z * m_axis.x;
            float PY = impulse.x * m_perp.y + impulse.z * m_axis.y;
            float L1 = impulse.x * m_s1 + impulse.y + impulse.z * m_a1;
            float L2 = impulse.x * m_s2 + impulse.y + impulse.z * m_a2;

            c1.x -= m_invMassA * PX;
            c1.y -= m_invMassA * PY;
            a1   -= m_invIA * L1;

            c2.x += m_invMassB * PX;
            c2.y += m_invMassB * PY;
            a2   += m_invIB * L2;

            // TODO_ERIN remove need for this
            //bA.m_sweep.c = c1;	//Already done by reference
            bA.m_sweep.a = a1;
            //bB.m_sweep.c = c2;	//Already done by reference
            bB.m_sweep.a = a2;
            bA.SynchronizeTransform();
            bB.SynchronizeTransform();

            return(linearError <= b2Settings.b2_linearSlop && angularError <= b2Settings.b2_angularSlop);
        }
Пример #15
0
        public override void SolveVelocityConstraints(b2TimeStep step)
        {
            b2Body bA = m_bodyA;
            b2Body bB = m_bodyB;

            b2Vec2 v1 = bA.m_linearVelocity;
            float  w1 = bA.m_angularVelocity;
            b2Vec2 v2 = bB.m_linearVelocity;
            float  w2 = bB.m_angularVelocity;

            float PX;
            float PY;
            float L1;
            float L2;

            // Solve linear motor constraint
            if (m_enableMotor && m_limitState != e_equalLimits)
            {
                //float32 Cdot = b2Dot(m_axis, v2 - v1) + m_a2 * w2 - m_a1 * w1;
                float Cdot       = m_axis.x * (v2.x - v1.x) + m_axis.y * (v2.y - v1.y) + m_a2 * w2 - m_a1 * w1;
                float impulse    = m_motorMass * (m_motorSpeed - Cdot);
                float oldImpulse = m_motorImpulse;
                float maxImpulse = step.dt * m_maxMotorForce;
                m_motorImpulse = b2Math.Clamp(m_motorImpulse + impulse, -maxImpulse, maxImpulse);
                impulse        = m_motorImpulse - oldImpulse;

                PX = impulse * m_axis.x;
                PY = impulse * m_axis.y;
                L1 = impulse * m_a1;
                L2 = impulse * m_a2;

                v1.x -= m_invMassA * PX;
                v1.y -= m_invMassA * PY;
                w1   -= m_invIA * L1;

                v2.x += m_invMassB * PX;
                v2.y += m_invMassB * PY;
                w2   += m_invIB * L2;
            }

            //Cdot1.x = b2Dot(m_perp, v2 - v1) + m_s2 * w2 - m_s1 * w1;
            float Cdot1X = m_perp.x * (v2.x - v1.x) + m_perp.y * (v2.y - v1.y) + m_s2 * w2 - m_s1 * w1;
            float Cdot1Y = w2 - w1;

            if (m_enableLimit && m_limitState != e_inactiveLimit)
            {
                // Solve prismatic and limit constraint in block form
                //Cdot2 = b2Dot(m_axis, v2 - v1) + m_a2 * w2 - m_a1 * w1;
                float Cdot2 = m_axis.x * (v2.x - v1.x) + m_axis.y * (v2.y - v1.y) + m_a2 * w2 - m_a1 * w1;

                b2Vec3 f1 = m_impulse.Copy();
                b2Vec3 df = m_K.Solve33(new b2Vec3(), -Cdot1X, -Cdot1Y, -Cdot2);

                m_impulse.Add(df);

                if (m_limitState == e_atLowerLimit)
                {
                    m_impulse.z = b2Math.Max(m_impulse.z, 0.0f);
                }
                else if (m_limitState == e_atUpperLimit)
                {
                    m_impulse.z = b2Math.Min(m_impulse.z, 0.0f);
                }

                // f2(1:2) = invK(1:2,1:2) * (-Cdot3\(1:2) - K(1:2,3) * (f2(3) - f1(3))) + f1(1:2)
                //b2Vec2 b = -Cdot1 - (m_impulse.z - f1.z) * b2Vec2(m_K.col3.x, m_K.col3.y);
                float  bX  = -Cdot1X - (m_impulse.z - f1.z) * m_K.col3.x;
                float  bY  = -Cdot1Y - (m_impulse.z - f1.z) * m_K.col3.y;
                b2Vec2 f2r = m_K.Solve22(new b2Vec2(), bX, bY);
                f2r.x      += f1.x;
                f2r.y      += f1.y;
                m_impulse.x = f2r.x;
                m_impulse.y = f2r.y;

                df.x = m_impulse.x - f1.x;
                df.y = m_impulse.y - f1.y;
                df.z = m_impulse.z - f1.z;

                PX = df.x * m_perp.x + df.z * m_axis.x;
                PY = df.x * m_perp.y + df.z * m_axis.y;
                L1 = df.x * m_s1 + df.y + df.z * m_a1;
                L2 = df.x * m_s2 + df.y + df.z * m_a2;

                v1.x -= m_invMassA * PX;
                v1.y -= m_invMassA * PY;
                w1   -= m_invIA * L1;

                v2.x += m_invMassB * PX;
                v2.y += m_invMassB * PY;
                w2   += m_invIB * L2;
            }
            else
            {
                // Limit is inactive, just solve the prismatic constraint in block form.
                b2Vec2 df2 = m_K.Solve22(new b2Vec2(), -Cdot1X, -Cdot1Y);
                m_impulse.x += df2.x;
                m_impulse.y += df2.y;

                PX = df2.x * m_perp.x;
                PY = df2.x * m_perp.y;
                L1 = df2.x * m_s1 + df2.y;
                L2 = df2.x * m_s2 + df2.y;

                v1.x -= m_invMassA * PX;
                v1.y -= m_invMassA * PY;
                w1   -= m_invIA * L1;

                v2.x += m_invMassB * PX;
                v2.y += m_invMassB * PY;
                w2   += m_invIB * L2;
            }

            bA.m_linearVelocity.SetV(v1);
            bA.m_angularVelocity = w1;
            bB.m_linearVelocity.SetV(v2);
            bB.m_angularVelocity = w2;
        }
Пример #16
0
        private void GenerateTerrain(bool hardcore)
        {
            const int GRASS = 0, STUMP = 1, STAIRS = 2, PIT = 3, _STATES_ = 4;

            int   state    = GRASS;
            float velocity = 0.0f;
            float y        = TERRAIN_HEIGHT;
            int   counter  = TERRAIN_STARTPAD;
            bool  oneshot  = false;

            terrain_poly.Clear();
            terrain.Clear();
            terrain_x.Clear();
            terrain_y.Clear();

            float original_y   = 0;
            float stair_height = 0;
            int   stair_width  = 0;
            int   stair_steps  = 0;

            for (int i = 0; i < TERRAIN_LENGTH; ++i)
            {
                float x = i * TERRAIN_STEP;
                terrain_x.Add(x);

                if (state == GRASS && !oneshot)
                {
                    velocity = 0.8f * velocity + 0.01f * Neuro.Tools.Sign(TERRAIN_HEIGHT - y);
                    if (i > TERRAIN_STARTPAD)
                    {
                        velocity += (float)Rng.NextFloat(-1, 1) / SCALE;   //1
                    }
                    y += velocity;
                }
                else if (state == PIT && oneshot)
                {
                    counter = Rng.Next(3, 5);
                    var poly = new []
                    {
                        new b2Vec2(x, y),
                        new b2Vec2(x + TERRAIN_STEP, y),
                        new b2Vec2(x + TERRAIN_STEP, y - 4 * TERRAIN_STEP),
                        new b2Vec2(x, y - 4 * TERRAIN_STEP)
                    };
                    (fd_polygon.shape as b2PolygonShape).Set(poly);

                    var t = World.CreateStaticBody(fd_polygon);

                    t.SetUserData(new CustomBodyData()
                    {
                        Color1 = new b2Vec3(1, 1, 1), Color2 = new b2Vec3(0.6f, 0.6f, 0.6f)
                    });
                    terrain.Add(t);

                    (fd_polygon.shape as b2PolygonShape).Set(poly.Select(p => new b2Vec2(p.x + TERRAIN_STEP * counter, p.y)).ToArray());

                    t = World.CreateStaticBody(fd_polygon);

                    t.SetUserData(new CustomBodyData()
                    {
                        Color1 = new b2Vec3(1, 1, 1), Color2 = new b2Vec3(0.6f, 0.6f, 0.6f)
                    });
                    terrain.Add(t);
                    counter   += 2;
                    original_y = y;
                }
                else if (state == PIT && !oneshot)
                {
                    y = original_y;
                    if (counter > 1)
                    {
                        y -= 4 * TERRAIN_STEP;
                    }
                }
                else if (state == STUMP && oneshot)
                {
                    counter = Rng.Next(1, 3);
                    var poly = new[]
                    {
                        new b2Vec2(x, y),
                        new b2Vec2(x + counter * TERRAIN_STEP, y),
                        new b2Vec2(x + counter * TERRAIN_STEP, y + counter * TERRAIN_STEP),
                        new b2Vec2(x, y + counter * TERRAIN_STEP)
                    };
                    (fd_polygon.shape as b2PolygonShape).Set(poly);
                    var t = World.CreateStaticBody(fd_polygon);
                    t.SetUserData(new CustomBodyData()
                    {
                        Color1 = new b2Vec3(1, 1, 1), Color2 = new b2Vec3(0.6f, 0.6f, 0.6f)
                    });
                    terrain.Add(t);
                }
                else if (state == STAIRS && oneshot)
                {
                    stair_height = Rng.NextDouble() > 0.5 ? 1 : -1;
                    stair_width  = Rng.Next(4, 5);
                    stair_steps  = Rng.Next(3, 5);
                    original_y   = y;
                    for (int s = 0; s < stair_steps; ++s)
                    {
                        var poly = new[]
                        {
                            new b2Vec2(x + (s * stair_width) * TERRAIN_STEP, y + (s * stair_height) * TERRAIN_STEP),
                            new b2Vec2(x + ((1 + s) * stair_width) * TERRAIN_STEP, y + (s * stair_height) * TERRAIN_STEP),
                            new b2Vec2(x + ((1 + s) * stair_width) * TERRAIN_STEP, y + (-1 + s * stair_height) * TERRAIN_STEP),
                            new b2Vec2(x + (s * stair_width) * TERRAIN_STEP, y + (-1 + s * stair_height) * TERRAIN_STEP),
                        };
                        (fd_polygon.shape as b2PolygonShape).Set(poly);
                        var t = World.CreateStaticBody(fd_polygon);
                        t.SetUserData(new CustomBodyData()
                        {
                            Color1 = new b2Vec3(1, 1, 1), Color2 = new b2Vec3(0.6f, 0.6f, 0.6f)
                        });
                        terrain.Add(t);
                    }

                    counter = stair_steps * stair_width;
                }
                else if (state == STAIRS && !oneshot)
                {
                    var s = stair_steps * stair_width - counter - stair_height;
                    var n = s / stair_width;
                    y = original_y + (n * stair_height) * TERRAIN_STEP;
                }

                oneshot = false;
                terrain_y.Add(y);
                counter -= 1;
                if (counter == 0)
                {
                    counter = Rng.Next(TERRAIN_GRASS / 2, TERRAIN_GRASS);
                    if (state == GRASS && hardcore)
                    {
                        state   = Rng.Next(1, _STATES_);
                        oneshot = true;
                    }
                    else
                    {
                        state   = GRASS;
                        oneshot = true;
                    }
                }
            }

            for (int i = 0; i < TERRAIN_LENGTH - 1; ++i)
            {
                var poly = new[]
                {
                    new b2Vec2(terrain_x[i], terrain_y[i]),
                    new b2Vec2(terrain_x[i + 1], terrain_y[i + 1])
                };
                (fd_edge.shape as b2EdgeShape).m_vertex1 = poly[0];
                (fd_edge.shape as b2EdgeShape).m_vertex2 = poly[1];
                var t     = World.CreateStaticBody(fd_edge);
                var color = new b2Vec3(0.3f, i % 2 == 0 ? 1.0f : 0.8f, 0.3f);
                t.SetUserData(new CustomBodyData()
                {
                    Color1 = color, Color2 = color
                });
                terrain.Add(t);
                color = new b2Vec3(0.4f, 0.6f, 0.3f);
                var poly_extended = new List <float[]>
                {
                    new float[] { poly[0].x, poly[0].y },
                    new float[] { poly[1].x, poly[1].y },
                    new float[] { poly[1].x, 0 },
                    new float[] { poly[0].x, 0 }
                };
                terrain_poly.Add(new Tuple <List <float[]>, b2Vec3> (poly_extended, color));
            }

            terrain.Reverse();
        }
Пример #17
0
        public override void InitVelocityConstraints(b2SolverData data)
        {
            m_indexA       = m_bodyA.IslandIndex;
            m_indexB       = m_bodyB.IslandIndex;
            m_localCenterA = m_bodyA.Sweep.localCenter;
            m_localCenterB = m_bodyB.Sweep.localCenter;
            m_invMassA     = m_bodyA.InvertedMass;
            m_invMassB     = m_bodyB.InvertedMass;
            m_invIA        = m_bodyA.InvertedI;
            m_invIB        = m_bodyB.InvertedI;

            b2Vec2 cA = m_bodyA.InternalPosition.c;
            float  aA = m_bodyA.InternalPosition.a;
            b2Vec2 vA = m_bodyA.InternalVelocity.v;
            float  wA = m_bodyA.InternalVelocity.w;

            b2Vec2 cB = m_bodyB.InternalPosition.c;
            float  aB = m_bodyB.InternalPosition.a;
            b2Vec2 vB = m_bodyB.InternalVelocity.v;
            float  wB = m_bodyB.InternalVelocity.w;

            b2Rot qA = new b2Rot(aA);
            b2Rot qB = new b2Rot(aB);

            m_rA = b2Math.b2Mul(qA, m_localAnchorA - m_localCenterA);
            m_rB = b2Math.b2Mul(qB, m_localAnchorB - m_localCenterB);

            // J = [-I -r1_skew I r2_skew]
            //     [ 0       -1 0       1]
            // r_skew = [-ry; rx]

            // Matlab
            // K = [ mA+r1y^2*iA+mB+r2y^2*iB,  -r1y*iA*r1x-r2y*iB*r2x,          -r1y*iA-r2y*iB]
            //     [  -r1y*iA*r1x-r2y*iB*r2x, mA+r1x^2*iA+mB+r2x^2*iB,           r1x*iA+r2x*iB]
            //     [          -r1y*iA-r2y*iB,           r1x*iA+r2x*iB,                   iA+iB]

            float mA = m_invMassA, mB = m_invMassB;
            float iA = m_invIA, iB = m_invIB;

            bool   fixedRotation = (iA + iB == 0.0f);
            b2Vec3 ex            = new b2Vec3();
            b2Vec3 ey            = new b2Vec3();
            b2Vec3 ez            = new b2Vec3();

            ex.x   = mA + mB + m_rA.y * m_rA.y * iA + m_rB.y * m_rB.y * iB;
            ey.x   = -m_rA.y * m_rA.x * iA - m_rB.y * m_rB.x * iB;
            ez.x   = -m_rA.y * iA - m_rB.y * iB;
            ex.y   = ey.x;
            ey.y   = mA + mB + m_rA.x * m_rA.x * iA + m_rB.x * m_rB.x * iB;
            ez.y   = m_rA.x * iA + m_rB.x * iB;
            ex.z   = ez.x;
            ey.z   = ez.y;
            ez.z   = iA + iB;
            m_mass = new b2Mat33(ex, ey, ez);

            m_motorMass = iA + iB;
            if (m_motorMass > 0.0f)
            {
                m_motorMass = 1.0f / m_motorMass;
            }

            if (m_enableMotor == false || fixedRotation)
            {
                m_motorImpulse = 0.0f;
            }

            if (m_enableLimit && fixedRotation == false)
            {
                float jointAngle = aB - aA - m_referenceAngle;
                if (b2Math.b2Abs(m_upperAngle - m_lowerAngle) < 2.0f * b2Settings.b2_angularSlop)
                {
                    m_limitState = b2LimitState.e_equalLimits;
                }
                else if (jointAngle <= m_lowerAngle)
                {
                    if (m_limitState != b2LimitState.e_atLowerLimit)
                    {
                        m_impulse.z = 0.0f;
                    }
                    m_limitState = b2LimitState.e_atLowerLimit;
                }
                else if (jointAngle >= m_upperAngle)
                {
                    if (m_limitState != b2LimitState.e_atUpperLimit)
                    {
                        m_impulse.z = 0.0f;
                    }
                    m_limitState = b2LimitState.e_atUpperLimit;
                }
                else
                {
                    m_limitState = b2LimitState.e_inactiveLimit;
                    m_impulse.z  = 0.0f;
                }
            }
            else
            {
                m_limitState = b2LimitState.e_inactiveLimit;
            }

            if (data.step.warmStarting)
            {
                // Scale impulses to support a variable time step.
                m_impulse      *= data.step.dtRatio;
                m_motorImpulse *= data.step.dtRatio;

                b2Vec2 P = new b2Vec2(m_impulse.x, m_impulse.y);

                vA -= mA * P;
                wA -= iA * (b2Math.b2Cross(m_rA, P) + m_motorImpulse + m_impulse.z);

                vB += mB * P;
                wB += iB * (b2Math.b2Cross(m_rB, P) + m_motorImpulse + m_impulse.z);
            }
            else
            {
                m_impulse.SetZero();
                m_motorImpulse = 0.0f;
            }

            m_bodyA.InternalVelocity.v = vA;
            m_bodyA.InternalVelocity.w = wA;
            m_bodyB.InternalVelocity.v = vB;
            m_bodyB.InternalVelocity.w = wB;
        }
Пример #18
0
        public override void SolveVelocityConstraints(b2SolverData data)
        {
            b2Vec2 vA = data.velocities[m_indexA].v;
            float  wA = data.velocities[m_indexA].w;
            b2Vec2 vB = data.velocities[m_indexB].v;
            float  wB = data.velocities[m_indexB].w;

            float mA = InvertedMassA, mB = InvertedMassB;
            float iA = InvertedIA, iB = InvertedIB;

            // Solve linear motor constraint.
            if (m_enableMotor && m_limitState != b2LimitState.e_equalLimits)
            {
                float Cdot       = b2Math.b2Dot(m_axis, vB - vA) + m_a2 * wB - m_a1 * wA;
                float impulse    = m_motorMass * (m_motorSpeed - Cdot);
                float oldImpulse = m_motorImpulse;
                float maxImpulse = data.step.dt * m_maxMotorForce;
                m_motorImpulse = b2Math.b2Clamp(m_motorImpulse + impulse, -maxImpulse, maxImpulse);
                impulse        = m_motorImpulse - oldImpulse;

                b2Vec2 P  = impulse * m_axis;
                float  LA = impulse * m_a1;
                float  LB = impulse * m_a2;

                vA -= mA * P;
                wA -= iA * LA;

                vB += mB * P;
                wB += iB * LB;
            }

            b2Vec2 Cdot1 = new b2Vec2();

            Cdot1.x = b2Math.b2Dot(m_perp, vB - vA) + m_s2 * wB - m_s1 * wA;
            Cdot1.y = wB - wA;

            if (m_enableLimit && m_limitState != b2LimitState.e_inactiveLimit)
            {
                // Solve prismatic and limit constraint in block form.
                float Cdot2;
                Cdot2 = b2Math.b2Dot(m_axis, vB - vA) + m_a2 * wB - m_a1 * wA;
                b2Vec3 Cdot = new b2Vec3(Cdot1.x, Cdot1.y, Cdot2);

                b2Vec3 f1 = m_impulse;
                b2Vec3 df = m_K.Solve33(-Cdot);
                m_impulse += df;

                if (m_limitState == b2LimitState.e_atLowerLimit)
                {
                    m_impulse.z = Math.Max(m_impulse.z, 0.0f);
                }
                else if (m_limitState == b2LimitState.e_atUpperLimit)
                {
                    m_impulse.z = Math.Min(m_impulse.z, 0.0f);
                }

                // f2(1:2) = invK(1:2,1:2) * (-Cdot(1:2) - K(1:2,3) * (f2(3) - f1(3))) + f1(1:2)
                b2Vec2 b   = -Cdot1 - (m_impulse.z - f1.z) * (new b2Vec2(m_K.ez.x, m_K.ez.y));
                b2Vec2 f2r = m_K.Solve22(b) + (new b2Vec2(f1.x, f1.y));
                m_impulse.x = f2r.x;
                m_impulse.y = f2r.y;

                df = m_impulse - f1;

                b2Vec2 P  = df.x * m_perp + df.z * m_axis;
                float  LA = df.x * m_s1 + df.y + df.z * m_a1;
                float  LB = df.x * m_s2 + df.y + df.z * m_a2;

                vA -= mA * P;
                wA -= iA * LA;

                vB += mB * P;
                wB += iB * LB;
            }
            else
            {
                // Limit is inactive, just solve the prismatic constraint in block form.
                b2Vec2 df = m_K.Solve22(-Cdot1);
                m_impulse.x += df.x;
                m_impulse.y += df.y;

                b2Vec2 P  = df.x * m_perp;
                float  LA = df.x * m_s1 + df.y;
                float  LB = df.x * m_s2 + df.y;

                vA -= mA * P;
                wA -= iA * LA;

                vB += mB * P;
                wB += iB * LB;

                b2Vec2 Cdot10 = Cdot1;

                Cdot1.x = b2Math.b2Dot(m_perp, vB - vA) + m_s2 * wB - m_s1 * wA;
                Cdot1.y = wB - wA;

                if (b2Math.b2Abs(Cdot1.x) > 0.01f || b2Math.b2Abs(Cdot1.y) > 0.01f)
                {
                    b2Vec2 test = b2Math.b2Mul22(m_K, df);
                    Cdot1.x += 0.0f;
                }
            }

            data.velocities[m_indexA].v = vA;
            data.velocities[m_indexA].w = wA;
            data.velocities[m_indexB].v = vB;
            data.velocities[m_indexB].w = wB;
        }
Пример #19
0
        public override void InitVelocityConstraints(b2SolverData data)
        {
            m_indexA       = m_bodyA.IslandIndex;
            m_indexB       = m_bodyB.IslandIndex;
            m_localCenterA = m_bodyA.Sweep.localCenter;
            m_localCenterB = m_bodyB.Sweep.localCenter;
            m_invMassA     = m_bodyA.InvertedMass;
            m_invMassB     = m_bodyB.InvertedMass;
            m_invIA        = m_bodyA.InvertedI;
            m_invIB        = m_bodyB.InvertedI;

            b2Vec2 cA = data.positions[m_indexA].c;
            float  aA = data.positions[m_indexA].a;
            b2Vec2 vA = data.velocities[m_indexA].v;
            float  wA = data.velocities[m_indexA].w;

            b2Vec2 cB = data.positions[m_indexB].c;
            float  aB = data.positions[m_indexB].a;
            b2Vec2 vB = data.velocities[m_indexB].v;
            float  wB = data.velocities[m_indexB].w;

            b2Rot qA = new b2Rot(aA);
            b2Rot qB = new b2Rot(aB);

            m_rA = b2Math.b2Mul(qA, m_localAnchorA - m_localCenterA);
            m_rB = b2Math.b2Mul(qB, m_localAnchorB - m_localCenterB);

            // J = [-I -r1_skew I r2_skew]
            //     [ 0       -1 0       1]
            // r_skew = [-ry; rx]

            // Matlab
            // K = [ mA+r1y^2*iA+mB+r2y^2*iB,  -r1y*iA*r1x-r2y*iB*r2x,          -r1y*iA-r2y*iB]
            //     [  -r1y*iA*r1x-r2y*iB*r2x, mA+r1x^2*iA+mB+r2x^2*iB,           r1x*iA+r2x*iB]
            //     [          -r1y*iA-r2y*iB,           r1x*iA+r2x*iB,                   iA+iB]

            float mA = m_invMassA, mB = m_invMassB;
            float iA = m_invIA, iB = m_invIB;

            b2Vec3 ex = new b2Vec3();
            b2Vec3 ey = new b2Vec3();
            b2Vec3 ez = new b2Vec3();

            ex.x = mA + mB + m_rA.y * m_rA.y * iA + m_rB.y * m_rB.y * iB;
            ey.x = -m_rA.y * m_rA.x * iA - m_rB.y * m_rB.x * iB;
            ez.x = -m_rA.y * iA - m_rB.y * iB;
            ex.y = ey.x;
            ey.y = mA + mB + m_rA.x * m_rA.x * iA + m_rB.x * m_rB.x * iB;
            ez.y = m_rA.x * iA + m_rB.x * iB;
            ex.z = ez.x;
            ey.z = ez.y;
            ez.z = iA + iB;
            b2Mat33 K = new b2Mat33(ex, ey, ez);

            if (m_frequencyHz > 0.0f)
            {
                m_mass = K.GetInverse22(m_mass);

                float invM = iA + iB;
                float m    = invM > 0.0f ? 1.0f / invM : 0.0f;

                float C = aB - aA - m_referenceAngle;

                // Frequency
                float omega = 2.0f * b2Settings.b2_pi * m_frequencyHz;

                // Damping coefficient
                float d = 2.0f * m * m_dampingRatio * omega;

                // Spring stiffness
                float k = m * omega * omega;

                // magic formulas
                float h = data.step.dt;
                m_gamma = h * (d + h * k);
                m_gamma = m_gamma != 0.0f ? 1.0f / m_gamma : 0.0f;
                m_bias  = C * h * k * m_gamma;

                invM      += m_gamma;
                m_mass.ezz = invM != 0.0f ? 1.0f / invM : 0.0f;
            }
            else
            {
                m_mass  = K.GetSymInverse33(m_mass);
                m_gamma = 0.0f;
                m_bias  = 0.0f;
            }

            if (data.step.warmStarting)
            {
                // Scale impulses to support a variable time step.
                m_impulse *= data.step.dtRatio;

                b2Vec2 P = new b2Vec2(m_impulse.x, m_impulse.y);

                vA -= mA * P;
                wA -= iA * (b2Math.b2Cross(m_rA, P) + m_impulse.z);

                vB += mB * P;
                wB += iB * (b2Math.b2Cross(m_rB, P) + m_impulse.z);
            }
            else
            {
                m_impulse.SetZero();
            }

            data.velocities[m_indexA].v = vA;
            data.velocities[m_indexA].w = wA;
            data.velocities[m_indexB].v = vB;
            data.velocities[m_indexB].w = wB;
        }
Пример #20
0
        public override bool SolvePositionConstraints(b2SolverData data)
        {
            b2Vec2 cA = data.positions[m_indexA].c;
            float  aA = data.positions[m_indexA].a;
            b2Vec2 cB = data.positions[m_indexB].c;
            float  aB = data.positions[m_indexB].a;

            b2Rot qA = new b2Rot(aA);
            b2Rot qB = new b2Rot(aB);

            float mA = m_invMassA, mB = m_invMassB;
            float iA = m_invIA, iB = m_invIB;

            b2Vec2 rA = b2Math.b2Mul(qA, m_localAnchorA - m_localCenterA);
            b2Vec2 rB = b2Math.b2Mul(qB, m_localAnchorB - m_localCenterB);

            float positionError, angularError;

            b2Vec3 ex = new b2Vec3();
            b2Vec3 ey = new b2Vec3();
            b2Vec3 ez = new b2Vec3();

            ex.x = mA + mB + rA.y * rA.y * iA + rB.y * rB.y * iB;
            ey.x = -rA.y * rA.x * iA - rB.y * rB.x * iB;
            ez.x = -rA.y * iA - rB.y * iB;
            ex.y = ey.x;
            ey.y = mA + mB + rA.x * rA.x * iA + rB.x * rB.x * iB;
            ez.y = rA.x * iA + rB.x * iB;
            ex.z = ez.x;
            ey.z = ez.y;
            ez.z = iA + iB;
            b2Mat33 K = new b2Mat33(ex, ey, ez);

            if (m_frequencyHz > 0.0f)
            {
                b2Vec2 C1 = cB + rB - cA - rA;

                positionError = C1.Length();
                angularError  = 0.0f;

                b2Vec2 P = -K.Solve22(C1);

                cA -= mA * P;
                aA -= iA * b2Math.b2Cross(rA, P);

                cB += mB * P;
                aB += iB * b2Math.b2Cross(rB, P);
            }
            else
            {
                b2Vec2 C1 = cB + rB - cA - rA;
                float  C2 = aB - aA - m_referenceAngle;

                positionError = C1.Length();
                angularError  = b2Math.b2Abs(C2);

                b2Vec3 C = new b2Vec3(C1.x, C1.y, C2);

                b2Vec3 impulse = -K.Solve33(C);
                b2Vec2 P       = new b2Vec2(impulse.x, impulse.y);

                cA -= mA * P;
                aA -= iA * (b2Math.b2Cross(rA, P) + impulse.z);

                cB += mB * P;
                aB += iB * (b2Math.b2Cross(rB, P) + impulse.z);
            }

            data.positions[m_indexA].c = cA;
            data.positions[m_indexA].a = aA;
            data.positions[m_indexB].c = cB;
            data.positions[m_indexB].a = aB;

            return(positionError <= b2Settings.b2_linearSlop && angularError <= b2Settings.b2_angularSlop);
        }
Пример #21
0
 public void SetVVV(b2Vec3 c1, b2Vec3 c2, b2Vec3 c3)
 {
     col1.SetV(c1);
     col2.SetV(c2);
     col3.SetV(c3);
 }
Пример #22
0
 /// Construct this matrix using columns.
 public b2Mat33(b2Vec3 c1, b2Vec3 c2, b2Vec3 c3)
 {
     ex = c1;
     ey = c2;
     ez = c3;
 }
Пример #23
0
        public b2Vec3 Minus()
        {
            b2Vec3 ret = new b2Vec3(Box2dPINVOKE.b2Vec3_Minus(swigCPtr), true);

            return(ret);
        }
Пример #24
0
 internal static global::System.Runtime.InteropServices.HandleRef getCPtr(b2Vec3 obj)
 {
     return((obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr);
 }
Пример #25
0
        public override void SolveVelocityConstraints(b2SolverData data)
        {
            b2Vec2 vA = m_bodyA.InternalVelocity.v;
            float  wA = m_bodyA.InternalVelocity.w;
            b2Vec2 vB = m_bodyB.InternalVelocity.v;
            float  wB = m_bodyB.InternalVelocity.w;

            float mA = m_invMassA, mB = m_invMassB;
            float iA = m_invIA, iB = m_invIB;

            bool fixedRotation = (iA + iB == 0.0f);

            // Solve motor constraint.
            if (m_enableMotor && m_limitState != b2LimitState.e_equalLimits && fixedRotation == false)
            {
                float Cdot       = wB - wA - m_motorSpeed;
                float impulse    = -m_motorMass * Cdot;
                float oldImpulse = m_motorImpulse;
                float maxImpulse = data.step.dt * m_maxMotorTorque;
                m_motorImpulse = b2Math.b2Clamp(m_motorImpulse + impulse, -maxImpulse, maxImpulse);
                impulse        = m_motorImpulse - oldImpulse;

                wA -= iA * impulse;
                wB += iB * impulse;
            }

            // Solve limit constraint.
            if (m_enableLimit && m_limitState != b2LimitState.e_inactiveLimit && fixedRotation == false)
            {
                b2Vec2 Cdot1 = vB + b2Math.b2Cross(wB, ref m_rB) - vA - b2Math.b2Cross(wA, ref m_rA);
                float  Cdot2 = wB - wA;
                b2Vec3 Cdot  = new b2Vec3(Cdot1.x, Cdot1.y, Cdot2);

                b2Vec3 impulse = -m_mass.Solve33(Cdot);

                if (m_limitState == b2LimitState.e_equalLimits)
                {
                    m_impulse += impulse;
                }
                else if (m_limitState == b2LimitState.e_atLowerLimit)
                {
                    float newImpulse = m_impulse.z + impulse.z;
                    if (newImpulse < 0.0f)
                    {
                        b2Vec2 rhs     = -Cdot1 + m_impulse.z * (new b2Vec2(m_mass.ez.x, m_mass.ez.y));
                        b2Vec2 reduced = m_mass.Solve22(rhs);
                        impulse.x    = reduced.x;
                        impulse.y    = reduced.y;
                        impulse.z    = -m_impulse.z;
                        m_impulse.x += reduced.x;
                        m_impulse.y += reduced.y;
                        m_impulse.z  = 0.0f;
                    }
                    else
                    {
                        m_impulse += impulse;
                    }
                }
                else if (m_limitState == b2LimitState.e_atUpperLimit)
                {
                    float newImpulse = m_impulse.z + impulse.z;
                    if (newImpulse > 0.0f)
                    {
                        b2Vec2 rhs     = -Cdot1 + m_impulse.z * (new b2Vec2(m_mass.ez.x, m_mass.ez.y));
                        b2Vec2 reduced = m_mass.Solve22(rhs);
                        impulse.x    = reduced.x;
                        impulse.y    = reduced.y;
                        impulse.z    = -m_impulse.z;
                        m_impulse.x += reduced.x;
                        m_impulse.y += reduced.y;
                        m_impulse.z  = 0.0f;
                    }
                    else
                    {
                        m_impulse += impulse;
                    }
                }

                b2Vec2 P = new b2Vec2(impulse.x, impulse.y);

                vA -= mA * P;
                wA -= iA * (b2Math.b2Cross(m_rA, P) + impulse.z);

                vB += mB * P;
                wB += iB * (b2Math.b2Cross(m_rB, P) + impulse.z);
            }
            else
            {
                // Solve point-to-point constraint
                b2Vec2 Cdot    = vB + b2Math.b2Cross(wB, ref m_rB) - vA - b2Math.b2Cross(wA, ref m_rA);
                b2Vec2 impulse = m_mass.Solve22(-Cdot);

                m_impulse.x += impulse.x;
                m_impulse.y += impulse.y;

                vA -= mA * impulse;
                wA -= iA * b2Math.b2Cross(ref m_rA, ref impulse);

                vB += mB * impulse;
                wB += iB * b2Math.b2Cross(ref m_rB, ref impulse);
            }

            m_bodyA.InternalVelocity.v = vA;
            m_bodyA.InternalVelocity.w = wA;
            m_bodyB.InternalVelocity.v = vB;
            m_bodyB.InternalVelocity.w = wB;
        }
Пример #26
0
 public void Subtract(b2Vec3 v)
 {
     x -= v.x; y -= v.y; z -= v.z;
 }
Пример #27
0
        public override void InitVelocityConstraints(b2SolverData data)
        {
            m_indexA       = m_bodyA.IslandIndex;
            m_indexB       = m_bodyB.IslandIndex;
            m_localCenterA = m_bodyA.Sweep.localCenter;
            m_localCenterB = m_bodyB.Sweep.localCenter;
            InvertedMassA  = m_bodyA.InvertedMass;
            InvertedMassB  = m_bodyB.InvertedMass;
            InvertedIA     = m_bodyA.InvertedI;
            InvertedIB     = m_bodyB.InvertedI;

            b2Vec2 cA = data.positions[m_indexA].c;
            float  aA = data.positions[m_indexA].a;
            b2Vec2 vA = data.velocities[m_indexA].v;
            float  wA = data.velocities[m_indexA].w;

            b2Vec2 cB = data.positions[m_indexB].c;
            float  aB = data.positions[m_indexB].a;
            b2Vec2 vB = data.velocities[m_indexB].v;
            float  wB = data.velocities[m_indexB].w;

            b2Rot qA = new b2Rot(aA);
            b2Rot qB = new b2Rot(aB);

            // Compute the effective masses.
            b2Vec2 rA = b2Math.b2Mul(qA, m_localAnchorA - m_localCenterA);
            b2Vec2 rB = b2Math.b2Mul(qB, m_localAnchorB - m_localCenterB);
            b2Vec2 d  = (cB - cA) + rB - rA;

            float mA = InvertedMassA, mB = InvertedMassB;
            float iA = InvertedIA, iB = InvertedIB;

            // Compute motor Jacobian and effective mass.
            {
                m_axis = b2Math.b2Mul(qA, m_localXAxisA);
                m_a1   = b2Math.b2Cross(d + rA, m_axis);
                m_a2   = b2Math.b2Cross(rB, m_axis);

                m_motorMass = mA + mB + iA * m_a1 * m_a1 + iB * m_a2 * m_a2;
                if (m_motorMass > 0.0f)
                {
                    m_motorMass = 1.0f / m_motorMass;
                }
            }

            // Prismatic constraint.
            {
                m_perp = b2Math.b2Mul(qA, m_localYAxisA);

                m_s1 = b2Math.b2Cross(d + rA, m_perp);
                m_s2 = b2Math.b2Cross(rB, m_perp);

                float k11 = mA + mB + iA * m_s1 * m_s1 + iB * m_s2 * m_s2;
                float k12 = iA * m_s1 + iB * m_s2;
                float k13 = iA * m_s1 * m_a1 + iB * m_s2 * m_a2;
                float k22 = iA + iB;
                if (k22 == 0.0f)
                {
                    // For bodies with fixed rotation.
                    k22 = 1.0f;
                }
                float k23 = iA * m_a1 + iB * m_a2;
                float k33 = mA + mB + iA * m_a1 * m_a1 + iB * m_a2 * m_a2;

                m_K.ex.Set(k11, k12, k13);
                m_K.ey.Set(k12, k22, k23);
                m_K.ez.Set(k13, k23, k33);
            }

            // Compute motor and limit terms.
            if (m_enableLimit)
            {
                float jointTranslation = b2Math.b2Dot(m_axis, d);
                if (b2Math.b2Abs(m_upperTranslation - m_lowerTranslation) < 2.0f * b2Settings.b2_linearSlop)
                {
                    m_limitState = b2LimitState.e_equalLimits;
                }
                else if (jointTranslation <= m_lowerTranslation)
                {
                    if (m_limitState != b2LimitState.e_atLowerLimit)
                    {
                        m_limitState = b2LimitState.e_atLowerLimit;
                        m_impulse.z  = 0.0f;
                    }
                }
                else if (jointTranslation >= m_upperTranslation)
                {
                    if (m_limitState != b2LimitState.e_atUpperLimit)
                    {
                        m_limitState = b2LimitState.e_atUpperLimit;
                        m_impulse.z  = 0.0f;
                    }
                }
                else
                {
                    m_limitState = b2LimitState.e_inactiveLimit;
                    m_impulse.z  = 0.0f;
                }
            }
            else
            {
                m_limitState = b2LimitState.e_inactiveLimit;
                m_impulse.z  = 0.0f;
            }

            if (m_enableMotor == false)
            {
                m_motorImpulse = 0.0f;
            }

            if (data.step.warmStarting)
            {
                // Account for variable time step.
                m_impulse      *= data.step.dtRatio;
                m_motorImpulse *= data.step.dtRatio;

                b2Vec2 P  = m_impulse.x * m_perp + (m_motorImpulse + m_impulse.z) * m_axis;
                float  LA = m_impulse.x * m_s1 + m_impulse.y + (m_motorImpulse + m_impulse.z) * m_a1;
                float  LB = m_impulse.x * m_s2 + m_impulse.y + (m_motorImpulse + m_impulse.z) * m_a2;

                vA -= mA * P;
                wA -= iA * LA;

                vB += mB * P;
                wB += iB * LB;
            }
            else
            {
                m_impulse.SetZero();
                m_motorImpulse = 0.0f;
            }

            data.velocities[m_indexA].v = vA;
            data.velocities[m_indexA].w = wA;
            data.velocities[m_indexB].v = vB;
            data.velocities[m_indexB].w = wB;
        }
Пример #28
0
 /// <summary>
 /// Perform the cross product on two vectors.
 /// </summary>
 public static b2Vec3 Cross(b2Vec3 a, b2Vec3 b)
 {
     return(new b2Vec3(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x));
 }
Пример #29
0
        public override bool SolvePositionConstraints(b2SolverData data)
        {
            b2Vec2 cA = data.positions[m_indexA].c;
            float  aA = data.positions[m_indexA].a;
            b2Vec2 cB = data.positions[m_indexB].c;
            float  aB = data.positions[m_indexB].a;

            b2Rot qA = new b2Rot(aA);
            b2Rot qB = new b2Rot(aB);

            float mA = InvertedMassA, mB = InvertedMassB;
            float iA = InvertedIA, iB = InvertedIB;

            // Compute fresh Jacobians
            b2Vec2 rA = b2Math.b2Mul(qA, m_localAnchorA - m_localCenterA);
            b2Vec2 rB = b2Math.b2Mul(qB, m_localAnchorB - m_localCenterB);
            b2Vec2 d  = cB + rB - cA - rA;

            b2Vec2 axis = b2Math.b2Mul(qA, m_localXAxisA);
            float  a1   = b2Math.b2Cross(d + rA, axis);
            float  a2   = b2Math.b2Cross(rB, axis);
            b2Vec2 perp = b2Math.b2Mul(qA, m_localYAxisA);

            float s1 = b2Math.b2Cross(d + rA, perp);
            float s2 = b2Math.b2Cross(rB, perp);

            b2Vec3 impulse;
            b2Vec2 C1 = new b2Vec2();

            C1.x = b2Math.b2Dot(perp, d);
            C1.y = aB - aA - m_referenceAngle;

            float linearError  = b2Math.b2Abs(C1.x);
            float angularError = b2Math.b2Abs(C1.y);

            bool  active = false;
            float C2     = 0.0f;

            if (m_enableLimit)
            {
                float translation = b2Math.b2Dot(axis, d);
                if (b2Math.b2Abs(m_upperTranslation - m_lowerTranslation) < 2.0f * b2Settings.b2_linearSlop)
                {
                    // Prevent large angular corrections
                    C2          = b2Math.b2Clamp(translation, -b2Settings.b2_maxLinearCorrection, b2Settings.b2_maxLinearCorrection);
                    linearError = Math.Max(linearError, b2Math.b2Abs(translation));
                    active      = true;
                }
                else if (translation <= m_lowerTranslation)
                {
                    // Prevent large linear corrections and allow some slop.
                    C2          = b2Math.b2Clamp(translation - m_lowerTranslation + b2Settings.b2_linearSlop, -b2Settings.b2_maxLinearCorrection, 0.0f);
                    linearError = Math.Max(linearError, m_lowerTranslation - translation);
                    active      = true;
                }
                else if (translation >= m_upperTranslation)
                {
                    // Prevent large linear corrections and allow some slop.
                    C2          = b2Math.b2Clamp(translation - m_upperTranslation - b2Settings.b2_linearSlop, 0.0f, b2Settings.b2_maxLinearCorrection);
                    linearError = Math.Max(linearError, translation - m_upperTranslation);
                    active      = true;
                }
            }

            if (active)
            {
                float k11 = mA + mB + iA * s1 * s1 + iB * s2 * s2;
                float k12 = iA * s1 + iB * s2;
                float k13 = iA * s1 * a1 + iB * s2 * a2;
                float k22 = iA + iB;
                if (k22 == 0.0f)
                {
                    // For fixed rotation
                    k22 = 1.0f;
                }
                float k23 = iA * a1 + iB * a2;
                float k33 = mA + mB + iA * a1 * a1 + iB * a2 * a2;

                b2Mat33 K = new b2Mat33(
                    new b2Vec3(k11, k12, k13),
                    new b2Vec3(k12, k22, k23),
                    new b2Vec3(k13, k23, k33));

                b2Vec3 C = new b2Vec3(C1.x, C1.y, C2);

                impulse = K.Solve33(-C);
            }
            else
            {
                float k11 = mA + mB + iA * s1 * s1 + iB * s2 * s2;
                float k12 = iA * s1 + iB * s2;
                float k22 = iA + iB;
                if (k22 == 0.0f)
                {
                    k22 = 1.0f;
                }

                b2Mat22 K = new b2Mat22();
                K.ex.Set(k11, k12);
                K.ey.Set(k12, k22);

                b2Vec2 impulse1 = K.Solve(-C1);
                impulse   = new b2Vec3();
                impulse.x = impulse1.x;
                impulse.y = impulse1.y;
                impulse.z = 0.0f;
            }

            b2Vec2 P  = impulse.x * perp + impulse.z * axis;
            float  LA = impulse.x * s1 + impulse.y + impulse.z * a1;
            float  LB = impulse.x * s2 + impulse.y + impulse.z * a2;

            cA -= mA * P;
            aA -= iA * LA;
            cB += mB * P;
            aB += iB * LB;

            data.positions[m_indexA].c = cA;
            data.positions[m_indexA].a = aA;
            data.positions[m_indexB].c = cB;
            data.positions[m_indexB].a = aB;

            return(linearError <= b2Settings.b2_linearSlop && angularError <= b2Settings.b2_angularSlop);
        }
Пример #30
0
 /// <summary>
 /// Perform the dot product on two vectors.
 /// </summary>
 public static float Dot(b2Vec3 a, b2Vec3 b)
 {
     return(a.x * b.x + a.y * b.y + a.z * b.z);
 }