コード例 #1
0
void WindModificator::applyImpulse (b2Body* body, b2Vec2 contactPoint, float force) const
{
	const b2Vec2 direction = body->GetPosition() - getPos();
	const float distance = 0.1f * b2Distance(body->GetPosition(), getPos());
	const float impulseMag = std::min(70.0f, force * _modificatorSize / distance);
	body->ApplyLinearImpulse(impulseMag * direction, contactPoint, true);
}
コード例 #2
0
ファイル: b2Rope.cpp プロジェクト: 1vanK/Urho3D
void b2Rope::Initialize(const b2RopeDef* def)
{
	b2Assert(def->count >= 3);
	m_count = def->count;
	m_ps = (b2Vec2*)b2Alloc(m_count * sizeof(b2Vec2));
	m_p0s = (b2Vec2*)b2Alloc(m_count * sizeof(b2Vec2));
	m_vs = (b2Vec2*)b2Alloc(m_count * sizeof(b2Vec2));
	m_ims = (float32*)b2Alloc(m_count * sizeof(float32));

	for (int32 i = 0; i < m_count; ++i)
	{
		m_ps[i] = def->vertices[i];
		m_p0s[i] = def->vertices[i];
		m_vs[i].SetZero();

		float32 m = def->masses[i];
		if (m > 0.0f)
		{
			m_ims[i] = 1.0f / m;
		}
		else
		{
			m_ims[i] = 0.0f;
		}
	}

	int32 count2 = m_count - 1;
	int32 count3 = m_count - 2;
	m_Ls = (float32*)b2Alloc(count2 * sizeof(float32));
	m_as = (float32*)b2Alloc(count3 * sizeof(float32));

	for (int32 i = 0; i < count2; ++i)
	{
		b2Vec2 p1 = m_ps[i];
		b2Vec2 p2 = m_ps[i+1];
		m_Ls[i] = b2Distance(p1, p2);
	}

	for (int32 i = 0; i < count3; ++i)
	{
		b2Vec2 p1 = m_ps[i];
		b2Vec2 p2 = m_ps[i + 1];
		b2Vec2 p3 = m_ps[i + 2];

		b2Vec2 d1 = p2 - p1;
		b2Vec2 d2 = p3 - p2;

		float32 a = b2Cross(d1, d2);
		float32 b = b2Dot(d1, d2);

		m_as[i] = b2Atan2(a, b);
	}

	m_gravity = def->gravity;
	m_damping = def->damping;
	m_k2 = def->k2;
	m_k3 = def->k3;
}
コード例 #3
0
ファイル: uniteaerienne.cpp プロジェクト: xabufr/pixelwars
void UniteAerienne::Update()
{
    if(m_timerSurfauffe.getElapsedTime().asSeconds()>=m_maxShootTime&&!m_surchauffe&&m_fire)
    {
        m_surchauffe=true;
        m_timerSurfauffe.restart();
    }
    else if(m_surchauffe && m_timerSurfauffe.getElapsedTime().asSeconds()>=m_maxShootTime*3)
    {
        m_surchauffe=false;
        m_timerSurfauffe.restart();
    }
    if(m_body->GetPosition().y>150)
        m_body->SetGravityScale(5);
    else if(b2Distance(m_body->GetLinearVelocity(), b2Vec2(0,0))<m_minVelocity||(!m_forces.avant&&!m_forces.arriere))
        m_body->SetGravityScale(1);
    else
        m_body->SetGravityScale(0);
    b2Vec2 vec(0,0);
    if(m_forces.avant)
    {
        sf::Transform tr;
        tr.rotate(Trigo::ToDeg(m_body->GetAngle()));
        sf::Vector2f v;
        if(m_sens==1)
        {
            v=tr.transformPoint(m_acceleration, 0);
            m_AddTrainee();
        }
        else
            v=tr.transformPoint(m_acceleration*0.05, 0);

        vec.Set(v.x, v.y);
        m_body->ApplyForceToCenter(vec);
    }
    if(m_forces.arriere)
    {
        sf::Transform tr;
        tr.rotate(Trigo::ToDeg(m_body->GetAngle()));
        sf::Vector2f v;
        if(m_sens==-1)
        {
            v=tr.transformPoint(-m_acceleration, 0);
            m_AddTrainee();
        }
        else
            v=tr.transformPoint(-m_acceleration*0.05, 0);
        vec.Set(v.x, v.y);
        m_body->ApplyForceToCenter(vec);
    }
    if(m_forces.monte)
        m_body->ApplyAngularImpulse(m_rotationVelocity);
    else if(m_forces.descend)
        m_body->ApplyAngularImpulse(-m_rotationVelocity);
    Unite::Update();
}
コード例 #4
0
ファイル: b2Collision.cpp プロジェクト: FrancisVarga/wck
bool b2TestOverlap(const b2Shape* shapeA, const b2Shape* shapeB,
				   const b2Transform& xfA, const b2Transform& xfB)
{
	b2DistanceInput input;
	input.proxyA.Set(shapeA);
	input.proxyB.Set(shapeB);
	input.transformA = xfA;
	input.transformB = xfB;
	input.useRadii = true;

	b2SimplexCache cache;
	cache.count = 0;

	b2DistanceOutput output;

	b2Distance(&output, &cache, &input);

	return output.distance < 10.0f * b2_epsilon;
}
コード例 #5
0
// this function returns -1 if two objects has collision
// And otherwise returns the distance
float PlanningProblem::distToObstacle(Station A, const Obstacle &ob, b2Vec2& A_point, b2Vec2& ob_point)
{        
    b2DistanceProxy state_proxy, ob_proxy;
    state_proxy.Set(agent->shape, 0);
    ob_proxy.Set(ob.shape, 1);
    b2DistanceInput dist_in;
    dist_in.proxyA = state_proxy;
    dist_in.proxyB = ob_proxy;
    dist_in.transformA = b2Transform(A.getPosition().toB2vec2(),
                                    b2Rot(A.getPosition().Teta()));
    dist_in.transformB = ob.transform;
    b2SimplexCache dist_cache;
    dist_cache.count = 0;
    b2DistanceOutput dis_out;
    b2Distance(&dis_out, &dist_cache, &dist_in);
    A_point = dis_out.pointA;
    ob_point = dis_out.pointB;    
    if(hasCollision(A, ob)) {
        return -1;
    }
    return dis_out.distance;
}
コード例 #6
0
ファイル: b2Distance.cpp プロジェクト: layzerar/box2dlib
    float32 GetMetric() const
    {
        switch (m_count)
        {
        case 0:
            b2Assert(false);
            return 0.0;

        case 1:
            return 0.0f;

        case 2:
            return b2Distance(m_v1.w, m_v2.w);

        case 3:
            return b2Cross(m_v2.w - m_v1.w, m_v3.w - m_v1.w);

        default:
            b2Assert(false);
            return 0.0f;
        }
    }
コード例 #7
0
ファイル: VRope.cpp プロジェクト: SongCF/game-LostStar
void VRope::initWithBodysAndRopeLenght(b2World* world, b2Body *body1, b2Body *body2, cocos2d::CCSpriteBatchNode *spriteSheetArg, float ropeLength){
    bodyA = body1;
    bodyB = body2;
    mWorld = world;
    
	float length =  ropeLength; //
	if (length < 0)
		length = b2Distance(body1->GetPosition(), body2->GetPosition());
    //创建关节
    b2RopeJointDef jd;
    jd.bodyA=bodyA;
    jd.bodyB=bodyB;
    jd.localAnchorA = b2Vec2(0,0);
    jd.localAnchorB = b2Vec2(0,0);
    jd.maxLength= length;
    mJoint = (b2RopeJoint*)mWorld->CreateJoint(&jd);
    
    
    CCPoint pointA = ccp(bodyA->GetPosition().x*PTM_RATIO,bodyA->GetPosition().y*PTM_RATIO);
    CCPoint pointB = ccp(bodyB->GetPosition().x*PTM_RATIO,bodyB->GetPosition().y*PTM_RATIO);
    spriteSheet = spriteSheetArg;
    createRope(pointA, pointB, (length+0.1)*PTM_RATIO);
}
コード例 #8
0
void VehicleMonitor::WriteCSV(double elapsedTime)
{
	std::ostringstream row;
	//events
	if (m_IsColliding == true)
		row << "C:" << m_obstacleName << ";";
	else
		row << ",";

	row << elapsedTime << ",";
	row << m_simObject->GetPosition().x << ",";
	row << m_simObject->GetPosition().y << ",";
	row << ((Vehicle*)m_simObject)->m_body->GetAngle() << ",";
	//internal data
	for (auto& datum : ((Vehicle*)m_simObject)->GetInternalData())
	{
		row << datum.second << ",";
	}
	row.str().pop_back();
	m_csvStream << row.str() << "\n";

	m_dist_travelled += b2Distance(prevPos, m_simObject->GetPosition());
	prevPos = m_simObject->GetPosition();
}
コード例 #9
0
ファイル: VRope.cpp プロジェクト: SongCF/game-LostStar
void VRope::initWithBodys(b2World* world, b2Body *body1, b2Body *body2, CCSpriteBatchNode *spriteSheetArg) {
    initWithBodysAndRopeLenght(world, body1, body2, spriteSheetArg, b2Distance(body1->GetPosition(), body2->GetPosition()));
}
コード例 #10
0
ファイル: b2Distance.cpp プロジェクト: layzerar/box2dlib
void b2Distance(b2DistanceOutput* output,
                b2SimplexCache* cache,
                const b2DistanceInput* input)
{
    ++b2_gjkCalls;

    const b2DistanceProxy* proxyA = &input->proxyA;
    const b2DistanceProxy* proxyB = &input->proxyB;

    b2Transform transformA = input->transformA;
    b2Transform transformB = input->transformB;

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

    // Get simplex vertices as an array.
    b2SimplexVertex* vertices = &simplex.m_v1;
    const int32 k_maxIters = 20;

    // These store the vertices of the last simplex so that we
    // can check for duplicates and prevent cycling.
    int32 saveA[3], saveB[3];
    int32 saveCount = 0;

    b2Vec2 closestPoint = simplex.GetClosestPoint();
    float32 distanceSqr1 = closestPoint.LengthSquared();
    float32 distanceSqr2 = distanceSqr1;

    // Main iteration loop.
    int32 iter = 0;
    while (iter < k_maxIters)
    {
        // Copy simplex so we can identify duplicates.
        saveCount = simplex.m_count;
        for (int32 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;

        default:
            b2Assert(false);
        }

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

        // Compute closest point.
        b2Vec2 p = simplex.GetClosestPoint();
        distanceSqr2 = p.LengthSquared();

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

        // Get search direction.
        b2Vec2 d = simplex.GetSearchDirection();

        // Ensure the search direction is numerically fit.
        if (d.LengthSquared() < b2_epsilon * b2_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;
        }

        // Compute a tentative new simplex vertex using support points.
        b2SimplexVertex* vertex = vertices + simplex.m_count;
        vertex->indexA = proxyA->GetSupport(b2MulT(transformA.q, -d));
        vertex->wA = b2Mul(transformA, proxyA->GetVertex(vertex->indexA));
        b2Vec2 wBLocal;
        vertex->indexB = proxyB->GetSupport(b2MulT(transformB.q, d));
        vertex->wB = b2Mul(transformB, proxyB->GetVertex(vertex->indexB));
        vertex->w = vertex->wB - vertex->wA;

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

        // Check for duplicate support points. This is the main termination criteria.
        bool duplicate = false;
        for (int32 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;
    }

    b2_gjkMaxIters = b2Max(b2_gjkMaxIters, iter);

    // Prepare output.
    simplex.GetWitnessPoints(&output->pointA, &output->pointB);
    output->distance = b2Distance(output->pointA, output->pointB);
    output->iterations = iter;

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

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

        if (output->distance > rA + rB && output->distance > b2_epsilon)
        {
            // Shapes are still no overlapped.
            // Move the witness points to the outer surface.
            output->distance -= rA + rB;
            b2Vec2 normal = output->pointB - output->pointA;
            normal.Normalize();
            output->pointA += rA * normal;
            output->pointB -= rB * normal;
        }
        else
        {
            // Shapes are overlapped when radii are considered.
            // Move the witness points to the middle.
            b2Vec2 p = 0.5f * (output->pointA + output->pointB);
            output->pointA = p;
            output->pointB = p;
            output->distance = 0.0f;
        }
    }
}
コード例 #11
0
ファイル: b2Island.cpp プロジェクト: 2085020/titanium_modules
void b2Island::SolveTOI(const b2TimeStep& subStep, int32 toiIndexA, int32 toiIndexB)
{
	b2Assert(toiIndexA < m_bodyCount);
	b2Assert(toiIndexB < m_bodyCount);

	// Initialize the body state.
	for (int32 i = 0; i < m_bodyCount; ++i)
	{
		b2Body* b = m_bodies[i];
		m_positions[i].c = b->m_sweep.c;
		m_positions[i].a = b->m_sweep.a;
		m_velocities[i].v = b->m_linearVelocity;
		m_velocities[i].w = b->m_angularVelocity;
	}

	b2ContactSolverDef contactSolverDef;
	contactSolverDef.contacts = m_contacts;
	contactSolverDef.count = m_contactCount;
	contactSolverDef.allocator = m_allocator;
	contactSolverDef.step = subStep;
	contactSolverDef.positions = m_positions;
	contactSolverDef.velocities = m_velocities;
	b2ContactSolver contactSolver(&contactSolverDef);

	// Solve position constraints.
	for (int32 i = 0; i < subStep.positionIterations; ++i)
	{
		bool contactsOkay = contactSolver.SolveTOIPositionConstraints(toiIndexA, toiIndexB);
		if (contactsOkay)
		{
			break;
		}
	}

#if 0
	// Is the new position really safe?
	for (int32 i = 0; i < m_contactCount; ++i)
	{
		b2Contact* c = m_contacts[i];
		b2Fixture* fA = c->GetFixtureA();
		b2Fixture* fB = c->GetFixtureB();

		b2Body* bA = fA->GetBody();
		b2Body* bB = fB->GetBody();

		int32 indexA = c->GetChildIndexA();
		int32 indexB = c->GetChildIndexB();

		b2DistanceInput input;
		input.proxyA.Set(fA->GetShape(), indexA);
		input.proxyB.Set(fB->GetShape(), indexB);
		input.transformA = bA->GetTransform();
		input.transformB = bB->GetTransform();
		input.useRadii = false;

		b2DistanceOutput output;
		b2SimplexCache cache;
		cache.count = 0;
		b2Distance(&output, &cache, &input);

		if (output.distance == 0 || cache.count == 3)
		{
			cache.count += 0;
		}
	}
#endif

	// Leap of faith to new safe state.
	m_bodies[toiIndexA]->m_sweep.c0 = m_positions[toiIndexA].c;
	m_bodies[toiIndexA]->m_sweep.a0 = m_positions[toiIndexA].a;
	m_bodies[toiIndexB]->m_sweep.c0 = m_positions[toiIndexB].c;
	m_bodies[toiIndexB]->m_sweep.a0 = m_positions[toiIndexB].a;

	// No warm starting is needed for TOI events because warm
	// starting impulses were applied in the discrete solver.
	contactSolver.InitializeVelocityConstraints();

	// Solve velocity constraints.
	for (int32 i = 0; i < subStep.velocityIterations; ++i)
	{
		contactSolver.SolveVelocityConstraints();
	}

	// Don't store the TOI contact forces for warm starting
	// because they can be quite large.

	float32 h = subStep.dt;

	// Integrate positions
	for (int32 i = 0; i < m_bodyCount; ++i)
	{
		b2Vec2 c = m_positions[i].c;
		float32 a = m_positions[i].a;
		b2Vec2 v = m_velocities[i].v;
		float32 w = m_velocities[i].w;

		// Check for large velocities
		b2Vec2 translation = h * v;
		if (b2Dot(translation, translation) > b2_maxTranslationSquared)
		{
			float32 ratio = b2_maxTranslation / translation.Length();
			v *= ratio;
		}

		float32 rotation = h * w;
		if (rotation * rotation > b2_maxRotationSquared)
		{
			float32 ratio = b2_maxRotation / b2Abs(rotation);
			w *= ratio;
		}

		// Integrate
		c += h * v;
		a += h * w;

		m_positions[i].c = c;
		m_positions[i].a = a;
		m_velocities[i].v = v;
		m_velocities[i].w = w;

		// Sync bodies
		b2Body* body = m_bodies[i];
		body->m_sweep.c = c;
		body->m_sweep.a = a;
		body->m_linearVelocity = v;
		body->m_angularVelocity = w;
		body->SynchronizeTransform();
	}

	Report(contactSolver.m_velocityConstraints);
}
コード例 #12
0
float32 b2TimeOfImpact(const b2TOIInput* input, const TA* shapeA, const TB* shapeB)
{
	b2Sweep sweepA = input->sweepA;
	b2Sweep sweepB = input->sweepB;

	float32 r1 = input->sweepRadiusA;
	float32 r2 = input->sweepRadiusB;

	float32 tolerance = input->tolerance;

	float32 radius = shapeA->m_radius + shapeB->m_radius;

	b2Assert(sweepA.t0 == sweepB.t0);
	b2Assert(1.0f - sweepA.t0 > B2_FLT_EPSILON);

	b2Vec2 v1 = sweepA.c - sweepA.c0;
	b2Vec2 v2 = sweepB.c - sweepB.c0;
	float32 omega1 = sweepA.a - sweepA.a0;
	float32 omega2 = sweepB.a - sweepB.a0;

	float32 alpha = 0.0f;

	b2DistanceInput distanceInput;
	distanceInput.useRadii = false;
	b2SimplexCache cache;
	cache.count = 0;

	b2Vec2 p1, p2;
	const int32 k_maxIterations = 1000;	// TODO_ERIN b2Settings
	int32 iter = 0;
	b2Vec2 normal = b2Vec2_zero;
	float32 distance = 0.0f;
	float32 targetDistance = 0.0f;
	for(;;)
	{
		b2XForm xf1, xf2;
		sweepA.GetTransform(&xf1, alpha);
		sweepB.GetTransform(&xf2, alpha);

		// Get the distance between shapes.
		distanceInput.transformA = xf1;
		distanceInput.transformB = xf2;
		b2DistanceOutput distanceOutput;
		b2Distance(&distanceOutput, &cache, &distanceInput, shapeA, shapeB);
		distance = distanceOutput.distance;
		p1 = distanceOutput.pointA;
		p2 = distanceOutput.pointB;

		if (iter == 0)
		{
			// Compute a reasonable target distance to give some breathing room
			// for conservative advancement.
			if (distance > radius)
			{
				targetDistance = b2Max(radius - tolerance, 0.75f * radius);
			}
			else
			{
				targetDistance = b2Max(distance - tolerance, 0.02f * radius);
			}
		}

		if (distance - targetDistance < 0.5f * tolerance || iter == k_maxIterations)
		{
			break;
		}

		normal = p2 - p1;
		normal.Normalize();

		// Compute upper bound on remaining movement.
		float32 approachVelocityBound = b2Dot(normal, v1 - v2) + b2Abs(omega1) * r1 + b2Abs(omega2) * r2;
		if (b2Abs(approachVelocityBound) < B2_FLT_EPSILON)
		{
			alpha = 1.0f;
			break;
		}

		// Get the conservative time increment. Don't advance all the way.
		float32 dAlpha = (distance - targetDistance) / approachVelocityBound;
		//float32 dt = (distance - 0.5f * b2_linearSlop) / approachVelocityBound;
		float32 newAlpha = alpha + dAlpha;

		// The shapes may be moving apart or a safe distance apart.
		if (newAlpha < 0.0f || 1.0f < newAlpha)
		{
			alpha = 1.0f;
			break;
		}

		// Ensure significant advancement.
		if (newAlpha < (1.0f + 100.0f * B2_FLT_EPSILON) * alpha)
		{
			break;
		}

		alpha = newAlpha;

		++iter;
	}

	b2_maxToiIters = b2Max(iter, b2_maxToiIters);

	return alpha;
}
コード例 #13
0
ファイル: b2Island.cpp プロジェクト: brigosx/pybox2d-android
void b2Island::SolveTOI(const b2TimeStep& subStep, const b2Body* bodyA, const b2Body* bodyB)
{
	b2ContactSolverDef solverDef;
	solverDef.contacts = m_contacts;
	solverDef.count = m_contactCount;
	solverDef.allocator = m_allocator;
	solverDef.impulseRatio = subStep.dtRatio;
	solverDef.warmStarting = subStep.warmStarting;
	b2ContactSolver contactSolver(&solverDef);

	// Solve position constraints.
	const float32 k_toiBaumgarte = 0.75f;
	for (int32 i = 0; i < subStep.positionIterations; ++i)
	{
		bool contactsOkay = contactSolver.SolveTOIPositionConstraints(k_toiBaumgarte, bodyA, bodyB);
		if (contactsOkay)
		{
			break;
		}

		if (i == subStep.positionIterations - 1)
		{
			i += 0;
		}
	}

#if 0
	// Is the new position really safe?
	for (int32 i = 0; i < m_contactCount; ++i)
	{
		b2Contact* c = m_contacts[i];
		b2Fixture* fA = c->GetFixtureA();
		b2Fixture* fB = c->GetFixtureB();

		b2Body* bA = fA->GetBody();
		b2Body* bB = fB->GetBody();

		int32 indexA = c->GetChildIndexA();
		int32 indexB = c->GetChildIndexB();

		b2DistanceInput input;
		input.proxyA.Set(fA->GetShape(), indexA);
		input.proxyB.Set(fB->GetShape(), indexB);
		input.transformA = bA->GetTransform();
		input.transformB = bB->GetTransform();
		input.useRadii = false;

		b2DistanceOutput output;
		b2SimplexCache cache;
		cache.count = 0;
		b2Distance(&output, &cache, &input);

		if (output.distance == 0 || cache.count == 3)
		{
			cache.count += 0;
		}
	}
#endif

	// Leap of faith to new safe state.
	for (int32 i = 0; i < m_bodyCount; ++i)
	{
		m_bodies[i]->m_sweep.a0 = m_bodies[i]->m_sweep.a;
		m_bodies[i]->m_sweep.c0 = m_bodies[i]->m_sweep.c;
	}

	// No warm starting is needed for TOI events because warm
	// starting impulses were applied in the discrete solver.
	contactSolver.InitializeVelocityConstraints();

	// Solve velocity constraints.
	for (int32 i = 0; i < subStep.velocityIterations; ++i)
	{
		contactSolver.SolveVelocityConstraints();
	}

	// Don't store the TOI contact forces for warm starting
	// because they can be quite large.

	// Integrate positions.
	for (int32 i = 0; i < m_bodyCount; ++i)
	{
		b2Body* b = m_bodies[i];

		if (b->GetType() == b2_staticBody)
		{
			continue;
		}

		// Check for large velocities.
		b2Vec2 translation = subStep.dt * b->m_linearVelocity;
		if (b2Dot(translation, translation) > b2_maxTranslationSquared)
		{
			translation.Normalize();
			b->m_linearVelocity = (b2_maxTranslation * subStep.inv_dt) * translation;
		}

		float32 rotation = subStep.dt * b->m_angularVelocity;
		if (rotation * rotation > b2_maxRotationSquared)
		{
			if (rotation < 0.0)
			{
				b->m_angularVelocity = -subStep.inv_dt * b2_maxRotation;
			}
			else
			{
				b->m_angularVelocity = subStep.inv_dt * b2_maxRotation;
			}
		}

		// Integrate
		b->m_sweep.c += subStep.dt * b->m_linearVelocity;
		b->m_sweep.a += subStep.dt * b->m_angularVelocity;

		// Compute new transform
		b->SynchronizeTransform();

		// Note: shapes are synchronized later.
	}

	Report(contactSolver.m_constraints);
}
コード例 #14
0
ファイル: b2TimeOfImpact.cpp プロジェクト: 4ian/GD
// CCD via the local separating axis method. This seeks progression
// by computing the largest time at which separation is maintained.
void b2TimeOfImpact(b2TOIOutput* output, const b2TOIInput* input)
{
	++b2_toiCalls;

	output->state = b2TOIOutput::e_unknown;
	output->t = input->tMax;

	const b2DistanceProxy* proxyA = &input->proxyA;
	const b2DistanceProxy* proxyB = &input->proxyB;

	b2Sweep sweepA = input->sweepA;
	b2Sweep sweepB = input->sweepB;

	// Large rotations can make the root finder fail, so we normalize the
	// sweep angles.
	sweepA.Normalize();
	sweepB.Normalize();

	float32 tMax = input->tMax;

	float32 totalRadius = proxyA->m_radius + proxyB->m_radius;
	float32 target = b2Max(b2_linearSlop, totalRadius - 3.0f * b2_linearSlop);
	float32 tolerance = 0.25f * b2_linearSlop;
	b2Assert(target > tolerance);

	float32 t1 = 0.0f;
	const int32 k_maxIterations = 20;	// TODO_ERIN b2Settings
	int32 iter = 0;

	// Prepare input for distance query.
	b2SimplexCache cache;
	cache.count = 0;
	b2DistanceInput distanceInput;
	distanceInput.proxyA = input->proxyA;
	distanceInput.proxyB = input->proxyB;
	distanceInput.useRadii = false;

	// The outer loop progressively attempts to compute new separating axes.
	// This loop terminates when an axis is repeated (no progress is made).
	for(;;)
	{
		b2Transform xfA, xfB;
		sweepA.GetTransform(&xfA, t1);
		sweepB.GetTransform(&xfB, t1);

		// Get the distance between shapes. We can also use the results
		// to get a separating axis.
		distanceInput.transformA = xfA;
		distanceInput.transformB = xfB;
		b2DistanceOutput distanceOutput;
		b2Distance(&distanceOutput, &cache, &distanceInput);

		// If the shapes are overlapped, we give up on continuous collision.
		if (distanceOutput.distance <= 0.0f)
		{
			// Failure!
			output->state = b2TOIOutput::e_overlapped;
			output->t = 0.0f;
			break;
		}

		if (distanceOutput.distance < target + tolerance)
		{
			// Victory!
			output->state = b2TOIOutput::e_touching;
			output->t = t1;
			break;
		}

		// Initialize the separating axis.
		b2SeparationFunction fcn;
		fcn.Initialize(&cache, proxyA, sweepA, proxyB, sweepB);
#if 0
		// Dump the curve seen by the root finder
		{
			const int32 N = 100;
			float32 dx = 1.0f / N;
			float32 xs[N+1];
			float32 fs[N+1];

			float32 x = 0.0f;

			for (int32 i = 0; i <= N; ++i)
			{
				sweepA.GetTransform(&xfA, x);
				sweepB.GetTransform(&xfB, x);
				float32 f = fcn.Evaluate(xfA, xfB) - target;

				printf("%g %g\n", x, f);

				xs[i] = x;
				fs[i] = f;

				x += dx;
			}
		}
#endif

		// Compute the TOI on the separating axis. We do this by successively
		// resolving the deepest point. This loop is bounded by the number of vertices.
		bool done = false;
		float32 t2 = tMax;
		int32 pushBackIter = 0;
		for (;;)
		{
			// Find the deepest point at t2. Store the witness point indices.
			int32 indexA, indexB;
			float32 s2 = fcn.FindMinSeparation(&indexA, &indexB, t2);

			// Is the final configuration separated?
			if (s2 > target + tolerance)
			{
				// Victory!
				output->state = b2TOIOutput::e_separated;
				output->t = tMax;
				done = true;
				break;
			}

			// Has the separation reached tolerance?
			if (s2 > target - tolerance)
			{
				// Advance the sweeps
				t1 = t2;
				break;
			}

			// Compute the initial separation of the witness points.
			float32 s1 = fcn.Evaluate(indexA, indexB, t1);

			// Check for initial overlap. This might happen if the root finder
			// runs out of iterations.
			if (s1 < target - tolerance)
			{
				output->state = b2TOIOutput::e_failed;
				output->t = t1;
				done = true;
				break;
			}

			// Check for touching
			if (s1 <= target + tolerance)
			{
				// Victory! t1 should hold the TOI (could be 0.0).
				output->state = b2TOIOutput::e_touching;
				output->t = t1;
				done = true;
				break;
			}

			// Compute 1D root of: f(x) - target = 0
			int32 rootIterCount = 0;
			float32 a1 = t1, a2 = t2;
			for (;;)
			{
				// Use a mix of the secant rule and bisection.
				float32 t;
				if (rootIterCount & 1)
				{
					// Secant rule to improve convergence.
					t = a1 + (target - s1) * (a2 - a1) / (s2 - s1);
				}
				else
				{
					// Bisection to guarantee progress.
					t = 0.5f * (a1 + a2);
				}

				float32 s = fcn.Evaluate(indexA, indexB, t);

				if (b2Abs(s - target) < tolerance)
				{
					// t2 holds a tentative value for t1
					t2 = t;
					break;
				}

				// Ensure we continue to bracket the root.
				if (s > target)
				{
					a1 = t;
					s1 = s;
				}
				else
				{
					a2 = t;
					s2 = s;
				}

				++rootIterCount;
				++b2_toiRootIters;

				if (rootIterCount == 50)
				{
					break;
				}
			}

			b2_toiMaxRootIters = b2Max(b2_toiMaxRootIters, rootIterCount);

			++pushBackIter;

			if (pushBackIter == b2_maxPolygonVertices)
			{
				break;
			}
		}

		++iter;
		++b2_toiIters;

		if (done)
		{
			break;
		}

		if (iter == k_maxIterations)
		{
			// Root finder got stuck. Semi-victory.
			output->state = b2TOIOutput::e_failed;
			output->t = t1;
			break;
		}
	}

	b2_toiMaxIters = b2Max(b2_toiMaxIters, iter);
}
コード例 #15
0
float32 b2TimeOfImpact(const b2TOIInput* input, const TA* shapeA, const TB* shapeB)
{
	b2Sweep sweepA = input->sweepA;
	b2Sweep sweepB = input->sweepB;

	b2Assert(sweepA.t0 == sweepB.t0);
	b2Assert(1.0f - sweepA.t0 > B2_FLT_EPSILON);

	float32 radius = shapeA->m_radius + shapeB->m_radius;
	float32 tolerance = input->tolerance;

	float32 alpha = 0.0f;

	const int32 k_maxIterations = 1000;	// TODO_ERIN b2Settings
	int32 iter = 0;
	float32 target = 0.0f;

	// Prepare input for distance query.
	b2SimplexCache cache;
	cache.count = 0;
	b2DistanceInput distanceInput;
	distanceInput.useRadii = false;

	for(;;)
	{
		b2XForm xfA, xfB;
		sweepA.GetTransform(&xfA, alpha);
		sweepB.GetTransform(&xfB, alpha);

		// Get the distance between shapes.
		distanceInput.transformA = xfA;
		distanceInput.transformB = xfB;
		b2DistanceOutput distanceOutput;
		b2Distance(&distanceOutput, &cache, &distanceInput, shapeA, shapeB);

		if (distanceOutput.distance <= 0.0f)
		{
			alpha = 1.0f;
			break;
		}

		b2SeparationFunction<TA, TB> fcn;
		fcn.Initialize(&cache, shapeA, xfA, shapeB, xfB);

		float32 separation = fcn.Evaluate(xfA, xfB);
		if (separation <= 0.0f)
		{
			alpha = 1.0f;
			break;
		}

		if (iter == 0)
		{
			// Compute a reasonable target distance to give some breathing room
			// for conservative advancement. We take advantage of the shape radii
			// to create additional clearance.
			if (separation > radius)
			{
				target = b2Max(radius - tolerance, 0.75f * radius);
			}
			else
			{
				target = b2Max(separation - tolerance, 0.02f * radius);
			}
		}

		if (separation - target < 0.5f * tolerance)
		{
			if (iter == 0)
			{
				alpha = 1.0f;
				break;
			}

			break;
		}

#if 0
		// Dump the curve seen by the root finder
		{
			const int32 N = 100;
			float32 dx = 1.0f / N;
			float32 xs[N+1];
			float32 fs[N+1];

			float32 x = 0.0f;

			for (int32 i = 0; i <= N; ++i)
			{
				sweepA.GetTransform(&xfA, x);
				sweepB.GetTransform(&xfB, x);
				float32 f = fcn.Evaluate(xfA, xfB) - target;

				printf("%g %g\n", x, f);

				xs[i] = x;
				fs[i] = f;

				x += dx;
			}
		}
#endif

		// Compute 1D root of: f(x) - target = 0
		float32 newAlpha = alpha;
		{
			float32 x1 = alpha, x2 = 1.0f;

			float32 f1 = separation;

			sweepA.GetTransform(&xfA, x2);
			sweepB.GetTransform(&xfB, x2);
			float32 f2 = fcn.Evaluate(xfA, xfB);

			// If intervals don't overlap at t2, then we are done.
			if (f2 >= target)
			{
				alpha = 1.0f;
				break;
			}

			// Determine when intervals intersect.
			int32 rootIterCount = 0;
			for (;;)
			{
				// Use a mix of the secant rule and bisection.
				float32 x;
				if (rootIterCount & 1)
				{
					// Secant rule to improve convergence.
					x = x1 + (target - f1) * (x2 - x1) / (f2 - f1);
				}
				else
				{
					// Bisection to guarantee progress.
					x = 0.5f * (x1 + x2);
				}

				sweepA.GetTransform(&xfA, x);
				sweepB.GetTransform(&xfB, x);

				float32 f = fcn.Evaluate(xfA, xfB);

				if (b2Abs(f - target) < 0.025f * tolerance)
				{
					newAlpha = x;
					break;
				}

				// Ensure we continue to bracket the root.
				if (f > target)
				{
					x1 = x;
					f1 = f;
				}
				else
				{
					x2 = x;
					f2 = f;
				}

				++rootIterCount;

				//b2Assert(rootIterCount < 50);
				if (rootIterCount >= 50 )
				{
					break;
				}
			}

			b2_maxToiRootIters = b2Max(b2_maxToiRootIters, rootIterCount);
		}

		// Ensure significant advancement.
		if (newAlpha < (1.0f + 100.0f * B2_FLT_EPSILON) * alpha)
		{
			break;
		}

		alpha = newAlpha;

		++iter;

		if (iter == k_maxIterations)
		{
			break;
		}
	}

	b2_maxToiIters = b2Max(b2_maxToiIters, iter);

	return alpha;
}
コード例 #16
0
ファイル: b2Conservative.cpp プロジェクト: DrakonPL/jge
bool b2Conservative(b2Shape* shape1, b2Shape* shape2)
{
	b2Body* body1 = shape1->GetBody();
	b2Body* body2 = shape2->GetBody();

	b2Vec2 v1 = body1->m_position - body1->m_position0;
	float32 omega1 = body1->m_rotation - body1->m_rotation0;
	b2Vec2 v2 = body2->m_position - body2->m_position0;
	float32 omega2 = body2->m_rotation - body2->m_rotation0;

	float32 r1 = shape1->GetMaxRadius();
	float32 r2 = shape2->GetMaxRadius();

	b2Vec2 p1Start = body1->m_position0;
	float32 a1Start = body1->m_rotation0;

	b2Vec2 p2Start = body2->m_position0;
	float32 a2Start = body2->m_rotation0;

	b2Vec2 p1 = p1Start;
	float32 a1 = a1Start;
	b2Vec2 p2 = p2Start;
	float32 a2 = a2Start;

	b2Mat22 R1(a1), R2(a2);

	shape1->QuickSync(p1, R1);
	shape2->QuickSync(p2, R2);

	float32 s1 = 0.0f;
	const int32 maxIterations = 10;
	b2Vec2 d;
	float32 invRelativeVelocity = 0.0f;
	bool hit = true;
	b2Vec2 x1, x2;
	for (int32 iter = 0; iter < maxIterations; ++iter)
	{
		// Get the accurate distance between shapes.
		float32 distance = b2Distance(&x1, &x2, shape1, shape2);
		if (distance < b2_linearSlop)
		{
			if (iter == 0)
			{
				hit = false;
			}
			else
			{
				hit = true;
			}
			break;
		}

		if (iter == 0)
		{
			b2Vec2 d = x2 - x1;
			d.Normalize();
			float32 relativeVelocity = b2Dot(d, v1 - v2) + b2Abs(omega1) * r1 + b2Abs(omega2) * r2;
			if (b2Abs(relativeVelocity) < FLT_EPSILON)
			{
				hit = false;
				break;
			}

			invRelativeVelocity = 1.0f / relativeVelocity;
		}

		// Get the conservative movement.
		float32 ds = distance * invRelativeVelocity;
		float32 s2 = s1 + ds;

		if (s2 < 0.0f || 1.0f < s2)
		{
			hit = false;
			break;
		}

		if (s2 < (1.0f + 100.0f * FLT_EPSILON) * s1)
		{
			hit = true;
			break;
		}

		s1 = s2;

		// Move forward conservatively.
		p1 = p1Start + s1 * v1;
		a1 = a1Start + s1 * omega1;
		p2 = p2Start + s1 * v2;
		a2 = a2Start + s1 * omega2;

		R1.Set(a1);
		R2.Set(a2);
		shape1->QuickSync(p1, R1);
		shape2->QuickSync(p2, R2);
	}

	if (hit)
	{
		// Hit, move bodies to safe position and re-sync shapes.
		b2Vec2 d = x2 - x1;
		float32 length = d.Length();
		if (length > FLT_EPSILON)
		{
			d *= b2_linearSlop / length;
		}

		if (body1->IsStatic())
		{
			body1->m_position = p1;
		}
		else
		{
			body1->m_position = p1 - d;
		}
		body1->m_rotation = a1;
		body1->m_R.Set(a1);
		body1->QuickSyncShapes();

		if (body2->IsStatic())
		{
			body2->m_position = p2;
		}
		else
		{
			body2->m_position = p2 + d;
		}
		body2->m_position = p2 + d;
		body2->m_rotation = a2;
		body2->m_R.Set(a2);
		body2->QuickSyncShapes();

		return true;
	}

	// No hit, restore shapes.
	shape1->QuickSync(body1->m_position, body1->m_R);
	shape2->QuickSync(body2->m_position, body2->m_R);
	return false;
}
コード例 #17
0
ファイル: EngineBase.cpp プロジェクト: EVA-08/littlegame
DirectSprite* EngineBase::add_sprite(int model, float x, float y, void* userdata)
{
	DirectSprite* sp = new DirectSprite;


	//animations
	sp->set_num = SpriteModel::instance()->Models[model].subset_num;
	sp->animes = SpriteModel::instance()->Models[model].animes;
	//sp->texco_trans = { XMFLOAT2(0, 0), XMFLOAT2(1, 1) };
	if (!sp->animes.empty())
	{
		sp->anime_active = true;
		sp->current_anim = SpriteModel::instance()->Models[model].defanime;
		sp->distH = SpriteModel::instance()->Models[model].disth;
		sp->distV = SpriteModel::instance()->Models[model].distv;
		sp->_interval = SpriteModel::instance()->Models[model].interval;

		Animated_Sprites.push_back(sp);
	}
	else
	{
		sp->anime_active = false;
	}
	
	//box2d
	{
		b2BodyDef bdef;
		bdef.position.Set(x * tometer, y * tometer);
		bdef.type = SpriteModel::instance()->Models[model].bodytype;
		sp->body = tworld->CreateBody(&bdef);
	}
	{
		b2FixtureDef fdef;
		fdef.density = 1;
		fdef.friction = 1;
		if (SpriteModel::instance()->Models[model].shapetype.size() !=
			SpriteModel::instance()->Models[model].vert_colli.size())
		{
			MessageBox(0, "error fixture num!", 0, 0);
			return nullptr;
		}
		for (int i = 0; i < SpriteModel::instance()->Models[model].shapetype.size(); i++)
		{
			if (SpriteModel::instance()->Models[model].shapetype[i] == b2Shape::Type::e_polygon)
			{
				b2PolygonShape shape;
				vector<b2Vec2> vert = SpriteModel::instance()->Models[model].vert_colli[i];
				for (int ii = 0; ii < vert.size(); ii++)
				{
					vert[ii] = tometer * vert[ii];
				}
				shape.Set(&vert[0], vert.size());
				fdef.shape = &shape;
				sp->body->CreateFixture(&fdef);
			}
			else if (SpriteModel::instance()->Models[model].shapetype[i] == b2Shape::Type::e_closeedge)
			{
				b2EdgeShape shape;
				vector<b2Vec2> vert = SpriteModel::instance()->Models[model].vert_colli[i];
				for (int ii = 0; ii < vert.size(); ii++)
				{
					vert[ii] = tometer * vert[ii];
				}
				for (int ii = 0; ii < vert.size(); ii++)
				{
					int v0 = ii - 1 < 0 ? vert.size() - 1 : ii - 1;
					int v1 = ii;
					int v2 = ii + 1 >= vert.size() ? 0 : ii + 1;
					int v3 = v2 + 1 >= vert.size() ? 0 : v2 + 1;

					shape.Set(vert[v1], vert[v2]);
					shape.m_hasVertex0 = true;
					shape.m_hasVertex3 = true;
					shape.m_vertex0 = vert[v0];
					shape.m_vertex3 = vert[v3];
					fdef.shape = &shape;
					sp->body->CreateFixture(&fdef);
				}
			}
			else if (SpriteModel::instance()->Models[model].shapetype[i] == b2Shape::Type::e_edge)
			{
				b2EdgeShape shape;
				vector<b2Vec2> vert = SpriteModel::instance()->Models[model].vert_colli[i];
				for (int ii = 0; ii < vert.size(); ii++)
				{
					vert[ii] = tometer * vert[ii];
				}
				for (int ii = 0; ii < vert.size(); ii++)
				{
					int v0 = ii - 1 < 0 ? vert.size() - 1 : ii - 1;
					int v1 = ii;
					int v2 = ii + 1 >= vert.size() ? 0 : ii + 1;
					int v3 = v2 + 1 >= vert.size() ? 0 : v2 + 1;
					
					if (ii == 0)
					{
						shape.Set(vert[v1], vert[v2]);
						shape.m_hasVertex3 = true;
						shape.m_vertex3 = vert[v3];
						fdef.shape = &shape;
						sp->body->CreateFixture(&fdef);
					}
					else if (ii == vert.size() - 1)
					{
						shape.Set(vert[v1], vert[v2]);
						shape.m_hasVertex0 = true;
						shape.m_vertex0 = vert[v0];
						fdef.shape = &shape;
						sp->body->CreateFixture(&fdef);
					}
					else
					{
						shape.Set(vert[v1], vert[v2]);
						shape.m_hasVertex0 = true;
						shape.m_hasVertex3 = true;
						shape.m_vertex0 = vert[v0];
						shape.m_vertex3 = vert[v3];
						fdef.shape = &shape;
						sp->body->CreateFixture(&fdef);
					}
				}
			}
			else if (SpriteModel::instance()->Models[model].shapetype[i] == b2Shape::Type::e_circle)
			{
				b2CircleShape shape;
				shape.m_p = b2Vec2(0, 0);
				shape.m_radius = tometer * b2Distance(
					b2Vec2(
						SpriteModel::instance()->Models[model].vert_colli[i][0].x,
						SpriteModel::instance()->Models[model].vert_colli[i][0].y),
					b2Vec2(
						SpriteModel::instance()->Models[model].vert_colli[i][1].x,
						SpriteModel::instance()->Models[model].vert_colli[i][1].y));
				fdef.shape = &shape;
				sp->body->CreateFixture(&fdef);
			}
		}
	}
	if (userdata != nullptr)
	{
		sp->body->SetUserData(userdata);
	}
	//update world matrix!
	sp->update_world_matrix();

	if (sp->body->GetType() == b2BodyType::b2_staticBody)		//kinematic body can also be static! fix this! don't forget!
	{
		Static_Sprites.push_back(sp);
	}
	else
	{
		Dynamic_Sprites.push_back(sp);
	}

	return sp;
}
コード例 #18
0
ファイル: uniteaerienne.cpp プロジェクト: xabufr/pixelwars
bool UniteAerienne::SubirDegatsTerrain()
{
    if(b2Distance(m_body->GetLinearVelocity(), b2Vec2(0,0))>20)
        SubirDegats(100000);
    return EstVivant();
}
コード例 #19
0
ファイル: b2TimeOfImpact.cpp プロジェクト: vHanda/Survival
// This algorithm uses conservative advancement to compute the time of
// impact (TOI) of two shapes.
// Refs: Bullet, Young Kim
float32 b2TimeOfImpact(const b2Shape* shape1, const b2Sweep& sweep1,
					   const b2Shape* shape2, const b2Sweep& sweep2)
{
	float32 r1 = shape1->GetSweepRadius();
	float32 r2 = shape2->GetSweepRadius();

	b2Assert(sweep1.t0 == sweep2.t0);
	b2Assert(1.0f - sweep1.t0 > B2_FLT_EPSILON);

	float32 t0 = sweep1.t0;
	b2Vec2 v1 = sweep1.c - sweep1.c0;
	b2Vec2 v2 = sweep2.c - sweep2.c0;
	float32 omega1 = sweep1.a - sweep1.a0;
	float32 omega2 = sweep2.a - sweep2.a0;

	float32 alpha = 0.0f;

	b2Vec2 p1, p2;
	const int32 k_maxIterations = 20;	// TODO_ERIN b2Settings
	int32 iter = 0;
	b2Vec2 normal = b2Vec2_zero;
	float32 distance = 0.0f;
	float32 targetDistance = 0.0f;
	for(;;)
	{
		float32 t = (1.0f - alpha) * t0 + alpha;
		b2XForm xf1, xf2;
		sweep1.GetXForm(&xf1, t);
		sweep2.GetXForm(&xf2, t);

		// Get the distance between shapes.
		distance = b2Distance(&p1, &p2, shape1, xf1, shape2, xf2);

		if (iter == 0)
		{
			// Compute a reasonable target distance to give some breathing room
			// for conservative advancement.
			if (distance > 2.0f * b2_toiSlop)
			{
				targetDistance = 1.5f * b2_toiSlop;
			}
			else
			{
				targetDistance = b2Max(0.05f * b2_toiSlop, distance - 0.5f * b2_toiSlop);
			}
		}

		if (distance - targetDistance < 0.05f * b2_toiSlop || iter == k_maxIterations)
		{
			break;
		}

		normal = p2 - p1;
		normal.Normalize();

		// Compute upper bound on remaining movement.
		float32 approachVelocityBound = b2Dot(normal, v1 - v2) + b2Abs(omega1) * r1 + b2Abs(omega2) * r2;
		if (b2Abs(approachVelocityBound) < B2_FLT_EPSILON)
		{
			alpha = 1.0f;
			break;
		}

		// Get the conservative time increment. Don't advance all the way.
		float32 dAlpha = (distance - targetDistance) / approachVelocityBound;
		//float32 dt = (distance - 0.5f * b2_linearSlop) / approachVelocityBound;
		float32 newAlpha = alpha + dAlpha;

		// The shapes may be moving apart or a safe distance apart.
		if (newAlpha < 0.0f || 1.0f < newAlpha)
		{
			alpha = 1.0f;
			break;
		}

		// Ensure significant advancement.
		if (newAlpha < (1.0f + 100.0f * B2_FLT_EPSILON) * alpha)
		{
			break;
		}

		alpha = newAlpha;

		++iter;
	}

	return alpha;
}
コード例 #20
0
ファイル: MainScene.cpp プロジェクト: ChaitanyaGP/SensorTest
void MainScene::CreateAsteroids()
{
   Vec2 center(0,0);
   
   const string names[] =
   {
      "Asteroid_01",
      "Asteroid_02",
      "Asteroid_03",
      "Asteroid_04",
      "Asteroid_05",
      "Asteroid_06",
      "Asteroid_07",
      //       "Asteroid_08",
   };
   
   const int MAX_NAMES = sizeof(names)/sizeof(names[0]);
   
   typedef struct
   {
      float32 radius;
      uint32 asteroids;
   } RING_DATA_T;
   
   RING_DATA_T ringData[] =
   {
      {1, 1},
      {9, 3},
      {17, 7},
      {25, 13},
      {35, 20},
   };
   
   const int MAX_RINGS = sizeof(ringData)/sizeof(ringData[0]);
   
   float32 angleRads = 0;
   uint32 nameIdx = 0;
   
   
   for(int ring = 0; ring < MAX_RINGS; ring++)
   {
      // Inner ring asteroids
      float32 targetRadius = ringData[ring].radius;
      uint32 asteroids = ringData[ring].asteroids;
      
      for(int idx = 0; idx < asteroids; idx++)
      {
         Vec2 offset =  Vec2::FromPolar(targetRadius, angleRads);
         Vec2 position = center + offset;
         Asteroid* asteroid = new Asteroid();
         asteroid->Create(*_world,
                          names[nameIdx%MAX_NAMES],
                          position,
                          9.0 + RanNumGen::RandFloat(-1.0, 1.0));
         
         asteroid->GetBody()->SetDebugDraw(false);
         
         EntityManager::Instance().Register(asteroid);
         _asteroids.push_back(asteroid);
         
         
         // All asteroids have a distance joint to the anchor
         // Now create the joint.
         b2RopeJointDef jointDef;
         jointDef.bodyA = _anchor;
         jointDef.bodyB = asteroid->GetBody();
         jointDef.maxLength = b2Distance(jointDef.bodyA->GetPosition(), jointDef.bodyB->GetPosition());
         jointDef.collideConnected = true;
         _world->CreateJoint(&jointDef);
         
         nameIdx++;
         angleRads += (2*M_PI)/asteroids + RanNumGen::RandFloat(-M_PI/(12*asteroids), M_PI/(12*asteroids));
      }
   }
   
   
   for(int idx = 0;idx < _asteroids.size(); idx++)
   {
      _asteroidLayer->AddSprite(_asteroids[idx]->GetSprite());
      EntityScheduler::Instance().Register(_asteroids[idx]);
      // Give it at least one update to start.
      _asteroids[idx]->Update();
   }
}