Ejemplo n.º 1
0
 public static void mulTransToOutUnsafe(Transform A, Transform B,
                                        Transform out_)
 {
     Rot.mulTransUnsafe(A.q, B.q, out_.q);
     pool.set(B.p).subLocal(A.p);
     Rot.mulTransUnsafe(A.q, pool, out_.p);
 }
Ejemplo n.º 2
0
        public double evaluate(int indexA, int indexB, double t)
        {
            m_sweepA.getTransform(xfa, t);
            m_sweepB.getTransform(xfb, t);

            switch (m_type)
            {
            case Type.POINTS:
            {
                Rot.mulTransUnsafe(xfa.q, m_axis, axisA);
                Rot.mulTransUnsafe(xfb.q, m_axis.negateLocal(), axisB);
                m_axis.negateLocal();

                localPointA.set(m_proxyA.getVertex(indexA));
                localPointB.set(m_proxyB.getVertex(indexB));

                Transform.mulToOutUnsafe(xfa, localPointA, pointA);
                Transform.mulToOutUnsafe(xfb, localPointB, pointB);

                double separation = Vec2.dot(pointB.subLocal(pointA), m_axis);
                return(separation);
            }

            case Type.FACE_A:
            {
                // System.out.printf("We're faceA");
                Rot.mulToOutUnsafe(xfa.q, m_axis, normal);
                Transform.mulToOutUnsafe(xfa, m_localPoint, pointA);

                Rot.mulTransUnsafe(xfb.q, normal.negateLocal(), axisB);
                normal.negateLocal();

                localPointB.set(m_proxyB.getVertex(indexB));
                Transform.mulToOutUnsafe(xfb, localPointB, pointB);
                double separation = Vec2.dot(pointB.subLocal(pointA), normal);
                return(separation);
            }

            case Type.FACE_B:
            {
                // System.out.printf("We're faceB");
                Rot.mulToOutUnsafe(xfb.q, m_axis, normal);
                Transform.mulToOutUnsafe(xfb, m_localPoint, pointB);

                Rot.mulTransUnsafe(xfa.q, normal.negateLocal(), axisA);
                normal.negateLocal();

                localPointA.set(m_proxyA.getVertex(indexA));
                Transform.mulToOutUnsafe(xfa, localPointA, pointA);

                double separation = Vec2.dot(pointA.subLocal(pointB), normal);
                return(separation);
            }

            default:
                return(0d);
            }
        }
Ejemplo n.º 3
0
        public static Transform mulTrans(Transform A, Transform B)
        {
            var C = new Transform();

            Rot.mulTransUnsafe(A.q, B.q, C.q);
            pool.set(B.p).subLocal(A.p);
            Rot.mulTransUnsafe(A.q, pool, C.p);
            return(C);
        }
Ejemplo n.º 4
0
 public void getLocalVectorToOutUnsafe(Vec2 worldVector, Vec2 out_)
 {
     Rot.mulTransUnsafe(m_xf.q, worldVector, out_);
 }
Ejemplo n.º 5
0
        // double FindMinSeparation(int* indexA, int* indexB, double t) const
        public double findMinSeparation(int[] indexes, double t)
        {
            m_sweepA.getTransform(xfa, t);
            m_sweepB.getTransform(xfb, t);

            switch (m_type)
            {
            case Type.POINTS:
            {
                Rot.mulTransUnsafe(xfa.q, m_axis, axisA);
                Rot.mulTransUnsafe(xfb.q, m_axis.negateLocal(), axisB);
                m_axis.negateLocal();

                indexes[0] = m_proxyA.getSupport(axisA);
                indexes[1] = m_proxyB.getSupport(axisB);

                localPointA.set(m_proxyA.getVertex(indexes[0]));
                localPointB.set(m_proxyB.getVertex(indexes[1]));

                Transform.mulToOutUnsafe(xfa, localPointA, pointA);
                Transform.mulToOutUnsafe(xfb, localPointB, pointB);

                double separation = Vec2.dot(pointB.subLocal(pointA), m_axis);
                return(separation);
            }

            case Type.FACE_A:
            {
                Rot.mulToOutUnsafe(xfa.q, m_axis, normal);
                Transform.mulToOutUnsafe(xfa, m_localPoint, pointA);

                Rot.mulTransUnsafe(xfb.q, normal.negateLocal(), axisB);
                normal.negateLocal();

                indexes[0] = -1;
                indexes[1] = m_proxyB.getSupport(axisB);

                localPointB.set(m_proxyB.getVertex(indexes[1]));
                Transform.mulToOutUnsafe(xfb, localPointB, pointB);

                double separation = Vec2.dot(pointB.subLocal(pointA), normal);
                return(separation);
            }

            case Type.FACE_B:
            {
                Rot.mulToOutUnsafe(xfb.q, m_axis, normal);
                Transform.mulToOutUnsafe(xfb, m_localPoint, pointB);

                Rot.mulTransUnsafe(xfa.q, normal.negateLocal(), axisA);
                normal.negateLocal();

                indexes[1] = -1;
                indexes[0] = m_proxyA.getSupport(axisA);

                localPointA.set(m_proxyA.getVertex(indexes[0]));
                Transform.mulToOutUnsafe(xfa, localPointA, pointA);

                double separation = Vec2.dot(pointA.subLocal(pointB), normal);
                return(separation);
            }

            default:
                indexes[0] = -1;
                indexes[1] = -1;
                return(0d);
            }
        }
Ejemplo n.º 6
0
        /**
         * Compute the closest points between two shapes. Supports any combination of: CircleShape and
         * PolygonShape. The simplex cache is input/output. On the first call set SimplexCache.count to
         * zero.
         *
         * @param output
         * @param cache
         * @param input
         */

        public void distance(DistanceOutput output, SimplexCache cache,
                             DistanceInput input)
        {
            GJK_CALLS++;

            DistanceProxy proxyA = input.proxyA;
            DistanceProxy proxyB = input.proxyB;

            Transform transformA = input.transformA;
            Transform transformB = input.transformB;

            // Initialize the simplex.
            simplex.readCache(cache, proxyA, transformA, proxyB, transformB);

            // Get simplex vertices as an array.
            SimplexVertex[] vertices = simplex.vertices;

            // These store the vertices of the last simplex so that we
            // can check for duplicates and prevent cycling.
            // (pooled above)
            int saveCount = 0;

            simplex.getClosestPoint(closestPoint);
            double distanceSqr1 = closestPoint.lengthSquared();
            double distanceSqr2 = distanceSqr1;

            // Main iteration loop
            int iter = 0;

            while (iter < GJK_MAX_ITERS)
            {
                // Copy simplex so we can identify duplicates.
                saveCount = simplex.m_count;
                for (int i = 0; i < saveCount; i++)
                {
                    saveA[i] = vertices[i].indexA;
                    saveB[i] = vertices[i].indexB;
                }

                switch (simplex.m_count)
                {
                case 1:
                    break;

                case 2:
                    simplex.solve2();
                    break;

                case 3:
                    simplex.solve3();
                    break;
                }

                // If we have 3 points, then the origin is in the corresponding triangle.
                if (simplex.m_count == 3)
                {
                    break;
                }

                // Compute closest point.
                simplex.getClosestPoint(closestPoint);
                distanceSqr2 = closestPoint.lengthSquared();

                // ensure progress
                if (distanceSqr2 >= distanceSqr1)
                {
                    // break;
                }
                distanceSqr1 = distanceSqr2;

                // get search direction;
                simplex.getSearchDirection(d);

                // Ensure the search direction is numerically fit.
                if (d.lengthSquared() < Settings.EPSILON * Settings.EPSILON)
                {
                    // The origin is probably contained by a line segment
                    // or triangle. Thus the shapes are overlapped.

                    // We can't return zero here even though there may be overlap.
                    // In case the simplex is a point, segment, or triangle it is difficult
                    // to determine if the origin is contained in the CSO or very close to it.
                    break;
                }

                /*
                 * SimplexVertex* vertex = vertices + simplex.m_count; vertex.indexA =
                 * proxyA.GetSupport(MulT(transformA.R, -d)); vertex.wA = Mul(transformA,
                 * proxyA.GetVertex(vertex.indexA)); Vec2 wBLocal; vertex.indexB =
                 * proxyB.GetSupport(MulT(transformB.R, d)); vertex.wB = Mul(transformB,
                 * proxyB.GetVertex(vertex.indexB)); vertex.w = vertex.wB - vertex.wA;
                 */

                // Compute a tentative new simplex vertex using support points.
                SimplexVertex vertex = vertices[simplex.m_count];

                Rot.mulTransUnsafe(transformA.q, d.negateLocal(), temp);
                vertex.indexA = proxyA.getSupport(temp);
                Transform.mulToOutUnsafe(transformA, proxyA.getVertex(vertex.indexA), vertex.wA);
                // Vec2 wBLocal;
                Rot.mulTransUnsafe(transformB.q, d.negateLocal(), temp);
                vertex.indexB = proxyB.getSupport(temp);
                Transform.mulToOutUnsafe(transformB, proxyB.getVertex(vertex.indexB), vertex.wB);
                vertex.w.set(vertex.wB).subLocal(vertex.wA);

                // Iteration count is equated to the number of support point calls.
                ++iter;
                ++GJK_ITERS;

                // Check for duplicate support points. This is the main termination criteria.
                bool duplicate = false;
                for (int i = 0; i < saveCount; ++i)
                {
                    if (vertex.indexA == saveA[i] && vertex.indexB == saveB[i])
                    {
                        duplicate = true;
                        break;
                    }
                }

                // If we found a duplicate support point we must exit to avoid cycling.
                if (duplicate)
                {
                    break;
                }

                // New vertex is ok and needed.
                ++simplex.m_count;
            }

            GJK_MAX_ITERS = MathUtils.max(GJK_MAX_ITERS, iter);

            // Prepare output.
            simplex.getWitnessPoints(output.pointA, output.pointB);
            output.distance   = MathUtils.distance(output.pointA, output.pointB);
            output.iterations = iter;

            // Cache the simplex.
            simplex.writeCache(cache);

            // Apply radii if requested.
            if (input.useRadii)
            {
                double rA = proxyA.m_radius;
                double rB = proxyB.m_radius;

                if (output.distance > rA + rB && output.distance > Settings.EPSILON)
                {
                    // Shapes are still no overlapped.
                    // Move the witness points to the out_er surface.
                    output.distance -= rA + rB;
                    normal.set(output.pointB).subLocal(output.pointA);
                    normal.normalize();
                    temp.set(normal).mulLocal(rA);
                    output.pointA.addLocal(temp);
                    temp.set(normal).mulLocal(rB);
                    output.pointB.subLocal(temp);
                }
                else
                {
                    // Shapes are overlapped when radii are considered.
                    // Move the witness points to the middle.
                    // Vec2 p = 0.5d * (output.pointA + output.pointB);
                    output.pointA.addLocal(output.pointB).mulLocal(.5d);
                    output.pointB.set(output.pointA);
                    output.distance = 0.0d;
                }
            }
        }
Ejemplo n.º 7
0
        public override bool solvePositionConstraints(SolverData data)
        {
            Vec2   cA = data.positions[m_indexA].c;
            double aA = data.positions[m_indexA].a;
            Vec2   cB = data.positions[m_indexB].c;
            double aB = data.positions[m_indexB].a;
            Vec2   cC = data.positions[m_indexC].c;
            double aC = data.positions[m_indexC].a;
            Vec2   cD = data.positions[m_indexD].c;
            double aD = data.positions[m_indexD].a;

            Rot qA = pool.popRot(), qB = pool.popRot(), qC = pool.popRot(), qD = pool.popRot();

            qA.set(aA);
            qB.set(aB);
            qC.set(aC);
            qD.set(aD);

            double linearError = 0.0d;

            double coordinateA, coordinateB;

            Vec2   temp = pool.popVec2();
            Vec2   JvAC = pool.popVec2();
            Vec2   JvBD = pool.popVec2();
            double JwA, JwB, JwC, JwD;
            double mass = 0.0d;

            if (m_typeA == JointType.REVOLUTE)
            {
                JvAC.setZero();
                JwA   = 1.0d;
                JwC   = 1.0d;
                mass += m_iA + m_iC;

                coordinateA = aA - aC - m_referenceAngleA;
            }
            else
            {
                Vec2 rC = pool.popVec2();
                Vec2 rA = pool.popVec2();
                Vec2 pC = pool.popVec2();
                Vec2 pA = pool.popVec2();
                Rot.mulToOutUnsafe(qC, m_localAxisC, JvAC);
                Rot.mulToOutUnsafe(qC, temp.set(m_localAnchorC).subLocal(m_lcC), rC);
                Rot.mulToOutUnsafe(qA, temp.set(m_localAnchorA).subLocal(m_lcA), rA);
                JwC   = Vec2.cross(rC, JvAC);
                JwA   = Vec2.cross(rA, JvAC);
                mass += m_mC + m_mA + m_iC * JwC * JwC + m_iA * JwA * JwA;

                pC.set(m_localAnchorC).subLocal(m_lcC);
                Rot.mulTransUnsafe(qC, temp.set(rA).addLocal(cA).subLocal(cC), pA);
                coordinateA = Vec2.dot(pA.subLocal(pC), m_localAxisC);
                pool.pushVec2(4);
            }

            if (m_typeB == JointType.REVOLUTE)
            {
                JvBD.setZero();
                JwB   = m_ratio;
                JwD   = m_ratio;
                mass += m_ratio * m_ratio * (m_iB + m_iD);

                coordinateB = aB - aD - m_referenceAngleB;
            }
            else
            {
                Vec2 u  = pool.popVec2();
                Vec2 rD = pool.popVec2();
                Vec2 rB = pool.popVec2();
                Vec2 pD = pool.popVec2();
                Vec2 pB = pool.popVec2();
                Rot.mulToOutUnsafe(qD, m_localAxisD, u);
                Rot.mulToOutUnsafe(qD, temp.set(m_localAnchorD).subLocal(m_lcD), rD);
                Rot.mulToOutUnsafe(qB, temp.set(m_localAnchorB).subLocal(m_lcB), rB);
                JvBD.set(u).mulLocal(m_ratio);
                JwD   = Vec2.cross(rD, u);
                JwB   = Vec2.cross(rB, u);
                mass += m_ratio * m_ratio * (m_mD + m_mB) + m_iD * JwD * JwD + m_iB * JwB * JwB;

                pD.set(m_localAnchorD).subLocal(m_lcD);
                Rot.mulTransUnsafe(qD, temp.set(rB).addLocal(cB).subLocal(cD), pB);
                coordinateB = Vec2.dot(pB.subLocal(pD), m_localAxisD);
                pool.pushVec2(5);
            }

            double C = (coordinateA + m_ratio * coordinateB) - m_constant;

            double impulse = 0.0d;

            if (mass > 0.0d)
            {
                impulse = -C / mass;
            }
            pool.pushVec2(3);
            pool.pushRot(4);

            cA.x += (m_mA * impulse) * JvAC.x;
            cA.y += (m_mA * impulse) * JvAC.y;
            aA   += m_iA * impulse * JwA;

            cB.x += (m_mB * impulse) * JvBD.x;
            cB.y += (m_mB * impulse) * JvBD.y;
            aB   += m_iB * impulse * JwB;

            cC.x -= (m_mC * impulse) * JvAC.x;
            cC.y -= (m_mC * impulse) * JvAC.y;
            aC   -= m_iC * impulse * JwC;

            cD.x -= (m_mD * impulse) * JvBD.x;
            cD.y -= (m_mD * impulse) * JvBD.y;
            aD   -= m_iD * impulse * JwD;

            // data.positions[m_indexA].c = cA;
            data.positions[m_indexA].a = aA;
            // data.positions[m_indexB].c = cB;
            data.positions[m_indexB].a = aB;
            // data.positions[m_indexC].c = cC;
            data.positions[m_indexC].a = aC;
            // data.positions[m_indexD].c = cD;
            data.positions[m_indexD].a = aD;

            // TODO_ERIN not implemented
            return(linearError < Settings.linearSlop);
        }
Ejemplo n.º 8
0
        public GearJoint(IWorldPool argWorldPool, GearJointDef def)
            : base(argWorldPool, def)
        {
            m_joint1 = def.joint1;
            m_joint2 = def.joint2;

            m_typeA = m_joint1.getType();
            m_typeB = m_joint2.getType();


            double coordinateA, coordinateB;

            // TODO_ERIN there might be some problem with the joint edges in Joint.

            m_bodyC = m_joint1.getBodyA();
            m_bodyA = m_joint1.getBodyB();

            // Get geometry of joint1
            Transform xfA = m_bodyA.m_xf;
            double    aA  = m_bodyA.m_sweep.a;
            Transform xfC = m_bodyC.m_xf;
            double    aC  = m_bodyC.m_sweep.a;

            if (m_typeA == JointType.REVOLUTE)
            {
                var revolute = (RevoluteJoint)def.joint1;
                m_localAnchorC.set(revolute.m_localAnchorA);
                m_localAnchorA.set(revolute.m_localAnchorB);
                m_referenceAngleA = revolute.m_referenceAngle;
                m_localAxisC.setZero();

                coordinateA = aA - aC - m_referenceAngleA;
            }
            else
            {
                Vec2 pA        = pool.popVec2();
                Vec2 temp      = pool.popVec2();
                var  prismatic = (PrismaticJoint)def.joint1;
                m_localAnchorC.set(prismatic.m_localAnchorA);
                m_localAnchorA.set(prismatic.m_localAnchorB);
                m_referenceAngleA = prismatic.m_referenceAngle;
                m_localAxisC.set(prismatic.m_localXAxisA);

                Vec2 pC = m_localAnchorC;
                Rot.mulToOutUnsafe(xfA.q, m_localAnchorA, temp);
                temp.addLocal(xfA.p).subLocal(xfC.p);
                Rot.mulTransUnsafe(xfC.q, temp, pA);
                coordinateA = Vec2.dot(pA.subLocal(pC), m_localAxisC);
                pool.pushVec2(2);
            }

            m_bodyD = m_joint2.getBodyA();
            m_bodyB = m_joint2.getBodyB();

            // Get geometry of joint2
            Transform xfB = m_bodyB.m_xf;
            double    aB  = m_bodyB.m_sweep.a;
            Transform xfD = m_bodyD.m_xf;
            double    aD  = m_bodyD.m_sweep.a;

            if (m_typeB == JointType.REVOLUTE)
            {
                var revolute = (RevoluteJoint)def.joint2;
                m_localAnchorD.set(revolute.m_localAnchorA);
                m_localAnchorB.set(revolute.m_localAnchorB);
                m_referenceAngleB = revolute.m_referenceAngle;
                m_localAxisD.setZero();

                coordinateB = aB - aD - m_referenceAngleB;
            }
            else
            {
                Vec2 pB        = pool.popVec2();
                Vec2 temp      = pool.popVec2();
                var  prismatic = (PrismaticJoint)def.joint2;
                m_localAnchorD.set(prismatic.m_localAnchorA);
                m_localAnchorB.set(prismatic.m_localAnchorB);
                m_referenceAngleB = prismatic.m_referenceAngle;
                m_localAxisD.set(prismatic.m_localXAxisA);

                Vec2 pD = m_localAnchorD;
                Rot.mulToOutUnsafe(xfB.q, m_localAnchorB, temp);
                temp.addLocal(xfB.p).subLocal(xfD.p);
                Rot.mulTransUnsafe(xfD.q, temp, pB);
                coordinateB = Vec2.dot(pB.subLocal(pD), m_localAxisD);
                pool.pushVec2(2);
            }

            m_ratio = def.ratio;

            m_constant = coordinateA + m_ratio * coordinateB;

            m_impulse = 0.0d;
        }