Example #1
0
void Joint::PreStep(float inv_dt)
{
	// Pre-compute anchors, mass matrix, and bias.
	Mat22 Rot1(body1->rotation);
	Mat22 Rot2(body2->rotation);

	r1 = Rot1 * localAnchor1;
	r2 = Rot2 * localAnchor2;

	// deltaV = deltaV0 + K * impulse
	// invM = [(1/m1 + 1/m2) * eye(2) - skew(r1) * invI1 * skew(r1) - skew(r2) * invI2 * skew(r2)]
	//      = [1/m1+1/m2     0    ] + invI1 * [r1.y*r1.y -r1.x*r1.y] + invI2 * [r1.y*r1.y -r1.x*r1.y]
	//        [    0     1/m1+1/m2]           [-r1.x*r1.y r1.x*r1.x]           [-r1.x*r1.y r1.x*r1.x]
	Mat22 K1;
	K1.col1.x = body1->invMass + body2->invMass;	K1.col2.x = 0.0f;
	K1.col1.y = 0.0f;								K1.col2.y = body1->invMass + body2->invMass;

	Mat22 K2;
	K2.col1.x =  body1->invI * r1.y * r1.y;		K2.col2.x = -body1->invI * r1.x * r1.y;
	K2.col1.y = -body1->invI * r1.x * r1.y;		K2.col2.y =  body1->invI * r1.x * r1.x;

	Mat22 K3;
	K3.col1.x =  body2->invI * r2.y * r2.y;		K3.col2.x = -body2->invI * r2.x * r2.y;
	K3.col1.y = -body2->invI * r2.x * r2.y;		K3.col2.y =  body2->invI * r2.x * r2.x;

	Mat22 K = K1 + K2 + K3;
	K.col1.x += softness;
	K.col2.y += softness;

	M = K.Invert();

	Vec2 p1 = body1->position + r1;
	Vec2 p2 = body2->position + r2;
	Vec2 dp = p2 - p1;

	if (World::positionCorrection)
	{
		bias = -biasFactor * inv_dt * dp;
	}
	else
	{
		bias.Set(0.0f, 0.0f);
	}

	if (World::warmStarting)
	{
		// Apply accumulated impulse.
		body1->velocity -= body1->invMass * P;
		body1->angularVelocity -= body1->invI * Cross(r1, P);

		body2->velocity += body2->invMass * P;
		body2->angularVelocity += body2->invI * Cross(r2, P);
	}
	else
	{
		P.Set(0.0f, 0.0f);
	}
}
Example #2
0
bool SATCollide(SimBody *body1, SimBody *body2, float2 &N, f32 &t)
{
	SimBody &a = *body1;
	SimBody &b = *body2;

	if(a.vertices.size() < 2 && b.vertices.size() < 2) return false;

	Mat22 OA = Mat22::RotationMatrix(a.rotation_in_rads);
	Mat22 OB = Mat22::RotationMatrix(b.rotation_in_rads);
	Mat22 OB_T = OB.Transpose();

	Mat22 xOrient = OA * OB_T;
	float2 xOffset = (a.position - b.position) * OB_T;

	const u32 MAX_SEPERATING_AXIS = 16; 
	float2 xAxis[MAX_SEPERATING_AXIS];
	f32 taxis[MAX_SEPERATING_AXIS];
	u32 axisCount = 0;

	for(u32 i=0;i<a.seperatingAxis.size();++i)
	{
		xAxis[axisCount] = a.seperatingAxis[i] * xOrient;
		if(!IntervalIntersect(a.vertices, b.vertices, xAxis[axisCount],
			xOffset, xOrient, taxis[axisCount], t))
		{
			return false;
		}
		++axisCount;
	};
	for(u32 i=0;i<b.seperatingAxis.size();++i)
	{
		xAxis[axisCount] = b.seperatingAxis[i];
		if(!IntervalIntersect(a.vertices, b.vertices, xAxis[axisCount],
			xOffset, xOrient, taxis[axisCount], t))
		{
			return false;
		}
		++axisCount;
	};

	if(!GetMinimumTranslationVector(xAxis, taxis, axisCount, N, t))
	{
		return false;
	}

	f32 D = N.dot(xOffset);
	N =  D < 0.0f ? -N : N;

	N = N * OB;

	return true;
};
Example #3
0
static void ComputeIncidentEdge(ClipVertex c[2], const Vec2& h, const Vec2& pos,
								const Mat22& Rot, const Vec2& normal)
{
	// The normal is from the reference box. Convert it
	// to the incident boxe's frame and flip sign.
	Mat22 RotT = Rot.Transpose();
	Vec2 n = -(RotT * normal);
	Vec2 nAbs = Abs(n);

	if (nAbs.x > nAbs.y)
	{
		if (Sign(n.x) > 0.0f)
		{
			c[0].v.Set(h.x, -h.y);
			c[0].fp.e.inEdge2 = EDGE3;
			c[0].fp.e.outEdge2 = EDGE4;

			c[1].v.Set(h.x, h.y);
			c[1].fp.e.inEdge2 = EDGE4;
			c[1].fp.e.outEdge2 = EDGE1;
		}
		else
		{
			c[0].v.Set(-h.x, h.y);
			c[0].fp.e.inEdge2 = EDGE1;
			c[0].fp.e.outEdge2 = EDGE2;

			c[1].v.Set(-h.x, -h.y);
			c[1].fp.e.inEdge2 = EDGE2;
			c[1].fp.e.outEdge2 = EDGE3;
		}
	}
	else
	{
		if (Sign(n.y) > 0.0f)
		{
			c[0].v.Set(h.x, h.y);
			c[0].fp.e.inEdge2 = EDGE4;
			c[0].fp.e.outEdge2 = EDGE1;

			c[1].v.Set(-h.x, h.y);
			c[1].fp.e.inEdge2 = EDGE1;
			c[1].fp.e.outEdge2 = EDGE2;
		}
		else
		{
			c[0].v.Set(-h.x, -h.y);
			c[0].fp.e.inEdge2 = EDGE2;
			c[0].fp.e.outEdge2 = EDGE3;

			c[1].v.Set(h.x, -h.y);
			c[1].fp.e.inEdge2 = EDGE3;
			c[1].fp.e.outEdge2 = EDGE4;
		}
	}

	c[0].v = pos + Rot * c[0].v;
	c[1].v = pos + Rot * c[1].v;
}
Example #4
0
bool IntervalIntersect(const std::vector<float2> &aVertices,
		const std::vector<float2> &bVertices, const float2 &axis, const float2 &relPos,
		const Mat22 &xOrient, f32 &taxis, f32 tmax)
{
	SATProjection proj0 = GetInterval(aVertices, axis * xOrient.Transpose());
	SATProjection proj1 = GetInterval(bVertices, axis);
	
	f32 h = relPos.dot(axis);
	proj0.min += h;
	proj0.max += h;

	f32 d0 = proj0.min - proj1.max;
	f32 d1 = proj1.min - proj0.max;

	if(d0 > 0.0f || d1 > 0.0f)
	{
		return false;
	}

	taxis = d0 > d1 ? d0 : d1;
	return true;
};
Example #5
0
// The normal points from A to B
int Collide(Contact* contacts, Body* bodyA, Body* bodyB)
{
	// Setup
	Vec2 hA = 0.5f * bodyA->width;
	Vec2 hB = 0.5f * bodyB->width;

	Vec2 posA = bodyA->position;
	Vec2 posB = bodyB->position;

	Mat22 RotA(bodyA->rotation), RotB(bodyB->rotation);

	Mat22 RotAT = RotA.Transpose();
	Mat22 RotBT = RotB.Transpose();

	Vec2 a1 = RotA.col1, a2 = RotA.col2;
	Vec2 b1 = RotB.col1, b2 = RotB.col2;

	Vec2 dp = posB - posA;
	Vec2 dA = RotAT * dp;
	Vec2 dB = RotBT * dp;

	Mat22 C = RotAT * RotB;
	Mat22 absC = Abs(C);
	Mat22 absCT = absC.Transpose();

	// Box A faces
	Vec2 faceA = Abs(dA) - hA - absC * hB;
	if (faceA.x > 0.0f || faceA.y > 0.0f)
		return 0;

	// Box B faces
	Vec2 faceB = Abs(dB) - absCT * hA - hB;
	if (faceB.x > 0.0f || faceB.y > 0.0f)
		return 0;

	// Find best axis
	Axis axis;
	float separation;
	Vec2 normal;

	// Box A faces
	axis = FACE_A_X;
	separation = faceA.x;
	normal = dA.x > 0.0f ? RotA.col1 : -RotA.col1;

	const float relativeTol = 0.95f;
	const float absoluteTol = 0.01f;

	if (faceA.y > relativeTol * separation + absoluteTol * hA.y)
	{
		axis = FACE_A_Y;
		separation = faceA.y;
		normal = dA.y > 0.0f ? RotA.col2 : -RotA.col2;
	}

	// Box B faces
	if (faceB.x > relativeTol * separation + absoluteTol * hB.x)
	{
		axis = FACE_B_X;
		separation = faceB.x;
		normal = dB.x > 0.0f ? RotB.col1 : -RotB.col1;
	}

	if (faceB.y > relativeTol * separation + absoluteTol * hB.y)
	{
		axis = FACE_B_Y;
		separation = faceB.y;
		normal = dB.y > 0.0f ? RotB.col2 : -RotB.col2;
	}

	// Setup clipping plane data based on the separating axis
	Vec2 frontNormal, sideNormal;
	ClipVertex incidentEdge[2];
	float front, negSide, posSide;
	char negEdge, posEdge;

	// Compute the clipping lines and the line segment to be clipped.
	switch (axis)
	{
	case FACE_A_X:
		{
			frontNormal = normal;
			front = Dot(posA, frontNormal) + hA.x;
			sideNormal = RotA.col2;
			float side = Dot(posA, sideNormal);
			negSide = -side + hA.y;
			posSide =  side + hA.y;
			negEdge = EDGE3;
			posEdge = EDGE1;
			ComputeIncidentEdge(incidentEdge, hB, posB, RotB, frontNormal);
		}
		break;

	case FACE_A_Y:
		{
			frontNormal = normal;
			front = Dot(posA, frontNormal) + hA.y;
			sideNormal = RotA.col1;
			float side = Dot(posA, sideNormal);
			negSide = -side + hA.x;
			posSide =  side + hA.x;
			negEdge = EDGE2;
			posEdge = EDGE4;
			ComputeIncidentEdge(incidentEdge, hB, posB, RotB, frontNormal);
		}
		break;

	case FACE_B_X:
		{
			frontNormal = -normal;
			front = Dot(posB, frontNormal) + hB.x;
			sideNormal = RotB.col2;
			float side = Dot(posB, sideNormal);
			negSide = -side + hB.y;
			posSide =  side + hB.y;
			negEdge = EDGE3;
			posEdge = EDGE1;
			ComputeIncidentEdge(incidentEdge, hA, posA, RotA, frontNormal);
		}
		break;

	case FACE_B_Y:
		{
			frontNormal = -normal;
			front = Dot(posB, frontNormal) + hB.y;
			sideNormal = RotB.col1;
			float side = Dot(posB, sideNormal);
			negSide = -side + hB.x;
			posSide =  side + hB.x;
			negEdge = EDGE2;
			posEdge = EDGE4;
			ComputeIncidentEdge(incidentEdge, hA, posA, RotA, frontNormal);
		}
		break;
	}

	// clip other face with 5 box planes (1 face plane, 4 edge planes)

	ClipVertex clipPoints1[2];
	ClipVertex clipPoints2[2];
	int np;

	// Clip to box side 1
	np = ClipSegmentToLine(clipPoints1, incidentEdge, -sideNormal, negSide, negEdge);

	if (np < 2)
		return 0;

	// Clip to negative box side 1
	np = ClipSegmentToLine(clipPoints2, clipPoints1,  sideNormal, posSide, posEdge);

	if (np < 2)
		return 0;

	// Now clipPoints2 contains the clipping points.
	// Due to roundoff, it is possible that clipping removes all points.

	int numContacts = 0;
	for (int i = 0; i < 2; ++i)
	{
		float separation = Dot(frontNormal, clipPoints2[i].v) - front;

		if (separation <= 0)
		{
			contacts[numContacts].separation = separation;
			contacts[numContacts].normal = normal;
			// slide contact point onto reference face (easy to cull)
			contacts[numContacts].position = clipPoints2[i].v - separation * frontNormal;
			contacts[numContacts].feature = clipPoints2[i].fp;
			if (axis == FACE_B_X || axis == FACE_B_Y)
				Flip(contacts[numContacts].feature);
			++numContacts;
		}
	}

	return numContacts;
}
Example #6
0
//Vec2 offset;//((float)(uWidth / 2), (float)(uHeight / 5));
void DrawJoint(Joint* joint)
{
    float factor = 10.0f;
    iS32 Point[2][2];
//iLog("Start DrawJoint ");
    switch ( demoIndex )
    {
    case 2:
        factor = 12.0f;
        break;
    case 6:
        factor = 15.0f;
        break;
    default:
        return;
    }

    Body* b1 = joint->body1;
    Body* b2 = joint->body2;

    R1.Mat22_1(b1->rotation);
    R2.Mat22_1(b2->rotation);

    x1 = b1->position;
    p1 = x1 + R1 * joint->localAnchor1;

    x2 = b2->position;
    p2 = x2 + R2 * joint->localAnchor2;
//#if 1

    iU16 *pScrBuffer;
    iU16 uWidth=240, uHeight=320;
	if( i51AdeMmiGetScreenScale ( &uWidth , &uHeight ) == 0 ) return;
    //GetFullScreenBuffer( &pScrBuffer, &uWidth, &uHeight );

    offset.Set((float)(uWidth / 2), (float)(uHeight / 5));

    x1 *= factor;
    p1 *= factor;
    x2 *= factor;
    p2 *= factor;

    x1 += offset;
    p1 += offset;
    x2 += offset;
    p2 += offset;

    x1.y = uHeight - x1.y;
    p1.y = uHeight - p1.y;
    x2.y = uHeight - x2.y;
    p2.y = uHeight - p2.y;


// 	GUI_BEGIN(pScrBuffer, uWidth, uHeight);
// 	DrawLine((int16)x1.x, (int16)x1.y, (int16)p1.x, (int16)p1.y, MEX_COLOR_RED);
// 	DrawLine((int16)x2.x, (int16)x2.y, (int16)p2.x, (int16)p2.y, MEX_COLOR_RED);
// 	GUI_END();
//#endif
	Point[0][0] = (iS32)x1.x;
	Point[0][1] = (iS32)x1.y;
	Point[1][0] = (iS32)p1.x;
	Point[1][1] = (iS32)p1.y;
	i51KitG2DrawLine(Point, 0XFF00);
	Point[0][0] = (iS32)x2.x;
	Point[0][1] = (iS32)x2.y;
	Point[1][0] = (iS32)p2.x;
	Point[1][1] = (iS32)p2.y;
	i51KitG2DrawLine(Point, 0XFF00);
//iLog("End DrawJoint ");
}
Example #7
0
void DrawBody(Body* body)
{
// 	uint16 *pScrBuffer;
// 	uint16 uWidth, uHeight;
// 	GetFullScreenBuffer( &pScrBuffer, &uWidth, &uHeight );
	iU16 *pScrBuffer;
	iU16 uWidth=0, uHeight=0;
	iS32 Point[2][2];
	if( i51AdeMmiGetScreenScale ( &uWidth , &uHeight ) == 0 ) return;

//	GetFullScreenBuffer( &pScrBuffer, &uWidth, &uHeight );

//iLog("Start DrawBody ");
    R.Mat22_1(body->rotation);
    x = body->position;
    h = 0.5f * body->width;

    offset.Set((float)(uWidth / 2), (float)(uHeight / 5));

    v1 = x + R * Vec2(-h.x, -h.y);
    v2 = x + R * Vec2( h.x, -h.y);
    v3 = x + R * Vec2( h.x,  h.y);
    v4 = x + R * Vec2(-h.x,  h.y);
//#if 1
    float factor = 10.0f;
    switch ( demoIndex )
    {
    case 1:
        factor = 30.0f;
        break;
    case 2:
        factor = 12.0f;
        break;
    case 5:
        factor = 15.0f;
        break;
    case 6:
        factor = 15.0f;
        break;
    case 9:
        factor = 6.0f;
        break;
    default:
        factor = 10.0f;
        break;
    }

    v1 *= factor;
    v2 *= factor;
    v3 *= factor;
    v4 *= factor;

    v1 += offset;
    v2 += offset;
    v3 += offset;
    v4 += offset;

    v1.y = uHeight - v1.y;
    v2.y = uHeight - v2.y;
    v3.y = uHeight - v3.y;
    v4.y = uHeight - v4.y;

    //log(MEX_LOG_APP0, "(%d, %d), (%d, %d)", (int16)v1.x, (int16)v1.y, (int16)v2.x, (int16)v2.y);
    //log(MEX_LOG_APP0, "(%d, %d), (%d, %d)", (int16)v2.x, (int16)v2.y, (int16)v3.x, (int16)v3.y);
    //log(MEX_LOG_APP0, "(%d, %d), (%d, %d)", (int16)v3.x, (int16)v3.y, (int16)v4.x, (int16)v4.y);
    //log(MEX_LOG_APP0, "(%d, %d), (%d, %d)", (int16)v4.x, (int16)v4.y, (int16)v1.x, (int16)v1.y);
// 
// 	GUI_BEGIN(pScrBuffer, uWidth, uHeight);
// 	DrawLine((int16)v1.x, (int16)v1.y, (int16)v2.x, (int16)v2.y, MEX_COLOR_WHITE);
// 	DrawLine((int16)v2.x, (int16)v2.y, (int16)v3.x, (int16)v3.y, MEX_COLOR_WHITE);
// 	DrawLine((int16)v3.x, (int16)v3.y, (int16)v4.x, (int16)v4.y, MEX_COLOR_WHITE);
// 	DrawLine((int16)v4.x, (int16)v4.y, (int16)v1.x, (int16)v1.y, MEX_COLOR_WHITE);
// 	GUI_END();
//	GUI_BEGIN(pScrBuffer, uWidth, uHeight);
//#endif
	Point[0][0] = (iS32)v1.x;
	Point[0][1] = (iS32)v1.y;
	Point[1][0] = (iS32)v2.x;
	Point[1][1] = (iS32)v2.y;
	i51KitG2DrawLine(Point, 0XFF00);
	Point[0][0] = (iS32)v2.x;
	Point[0][1] = (iS32)v2.y;
	Point[1][0] = (iS32)v3.x;
	Point[1][1] = (iS32)v3.y;
	i51KitG2DrawLine(Point, 0XFF00);
	Point[0][0] = (iS32)v3.x;
	Point[0][1] = (iS32)v3.y;
	Point[1][0] = (iS32)v4.x;
	Point[1][1] = (iS32)v4.y;
	i51KitG2DrawLine(Point, 0XFF00);
	Point[0][0] = (iS32)v4.x;
	Point[0][1] = (iS32)v4.y;
	Point[1][0] = (iS32)v1.x;
	Point[1][1] = (iS32)v1.y;
	i51KitG2DrawLine(Point, 0XFF00);
//iLog("End DrawBody ");
}
Example #8
0
void MouseJoint::InitVelocityConstraints(const SolverData& data)
{
	m_indexB = m_bodyB->m_islandIndex;
	m_localCenterB = m_bodyB->m_sweep.localCenter;
	m_invMassB = m_bodyB->m_invMass;
	m_invIB = m_bodyB->m_invI;

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

	Rot qB(aB);

	float32 mass = m_bodyB->GetMass();

	// Frequency
	float32 omega = 2.0f * pi * m_frequencyHz;

	// Damping coefficient
	float32 d = 2.0f * mass * m_dampingRatio * omega;

	// Spring stiffness
	float32 k = mass * (omega * omega);

	// magic formulas
	// gamma has units of inverse mass.
	// beta has units of inverse time.
	float32 h = data.step.dt;
	assert(d + h * k > epsilon);
	m_gamma = h * (d + h * k);
	if (m_gamma != 0.0f)
	{
		m_gamma = 1.0f / m_gamma;
	}
	m_beta = h * k * m_gamma;

	// Compute the effective mass matrix.
	m_rB = Mul(qB, m_localAnchorB - m_localCenterB);

	// K    = [(1/m1 + 1/m2) * eye(2) - skew(r1) * invI1 * skew(r1) - skew(r2) * invI2 * skew(r2)]
	//      = [1/m1+1/m2     0    ] + invI1 * [r1.y*r1.y -r1.x*r1.y] + invI2 * [r1.y*r1.y -r1.x*r1.y]
	//        [    0     1/m1+1/m2]           [-r1.x*r1.y r1.x*r1.x]           [-r1.x*r1.y r1.x*r1.x]
	Mat22 K;
	K.ex.x = m_invMassB + m_invIB * m_rB.y * m_rB.y + m_gamma;
	K.ex.y = -m_invIB * m_rB.x * m_rB.y;
	K.ey.x = K.ex.y;
	K.ey.y = m_invMassB + m_invIB * m_rB.x * m_rB.x + m_gamma;

	m_mass = K.GetInverse();

	m_C = cB + m_rB - m_targetA;
	m_C *= m_beta;

	// Cheat with some damping
	wB *= 0.98f;

	if (data.step.warmStarting)
	{
		m_impulse *= data.step.dtRatio;
		vB += m_invMassB * m_impulse;
		wB += m_invIB * Cross(m_rB, m_impulse);
	}
	else
	{
		m_impulse.SetZero();
	}

	data.velocities[m_indexB].v = vB;
	data.velocities[m_indexB].w = wB;
}