void CPhysicsDragController::Tick(btScalar dt)
{
    for(int i = 0; i < m_ents.Size(); i++)
    {
        CPhysicsObject * object = (CPhysicsObject *)m_ents[i];

        Vector dragLinearFinal(0,0,0);
        AngularImpulse dragAngularFinal(0,0,0);

        Vector vel;
        AngularImpulse ang;
        object->GetVelocity(&vel, &ang);

        btVector3 bull_vel;

        ConvertPosToBull(vel, bull_vel);

        float dragForce = -0.5 * object->GetDragInDirection( &bull_vel ) * m_airDensity * dt;
        if ( dragForce < -1.0f )
        {
            dragForce = -1.0f;
        }
        if ( dragForce < 0 )
        {
            Vector dragLinearFinal = vel * dragForce;
        }
        btVector3 bull_angimpulse;
        ConvertAngularImpulseToBull(ang, bull_angimpulse);

        float angDragForce = -object->GetAngularDragInDirection(&bull_angimpulse) * m_airDensity * dt;
        if ( angDragForce < -1.0f )
        {
            angDragForce = -1.0f;
        }
        if( angDragForce < 0)
        {
            dragAngularFinal = ang * angDragForce;
        }
        object->AddVelocity(&dragLinearFinal, &dragAngularFinal);
    }
}
Пример #2
0
void ProjectileHandler::DoImpulse(CExplosion* & exp)
{
	//todo: get a brilliant idea and rewrite all this 
	for (int i = 0; i < objectVector->size(); i++)
	{
		CPhysicsObject* obj = objectVector->at(i);
		int ySurface;

		if (obj->pos[1] + obj->GetHeight() < exp->impulseCentre[1])
		{
			//object is above impulse center, act on bottom surface
			ySurface = 0;
		}
		else if (obj->pos[1] > exp->impulseCentre[1])
		{
			//object is below impulse center, act on top surface
			ySurface = 1;
		}
		else
		{
			ySurface = 2;
			// object surfaces are on both sides of impulse, act on centre.
		}
		int distanceX;
		int distanceY;
		float distanceMultiplier;
		if (obj->pos[0] + obj->GetWidth() < exp->impulseCentre[0])
		{

			//obj is left of impulse center
			switch (ySurface)
			{
			case 0:
				//object is above impulse center, act on bottom surface
				distanceX = obj->pos[0] + obj->GetWidth() - exp->impulseCentre[0];
				if (distanceX > -1 * exp->radius)
				{
					distanceY = obj->pos[1] - exp->impulseCentre[1];
					if (distanceY > -1 * exp->radius && distanceY <= 0)
					{
						distanceMultiplier = sqrt(distanceX*distanceX + distanceY*distanceY);
						distanceMultiplier /= exp->radius;
						distanceMultiplier = 1 - distanceMultiplier;
						distanceMultiplier /= obj->weight;
						double multiplier = (float)(distanceY) / (float)(distanceX);
						CVector2f imp(-1 * (float)exp->impulse / (1 + 1 * abs(multiplier))*distanceMultiplier, -1 * (exp->impulse - exp->impulse / (1 + 1 * abs(multiplier)))*distanceMultiplier);
						obj->AddVelocity(imp);
					}
				}
				break;
			case 1:
				//object is below impulse center, act on top surface
				distanceX = obj->pos[0] + obj->GetWidth() - exp->impulseCentre[0];
				if (distanceX > -1 * exp->radius)
				{
					distanceY = obj->pos[1] - exp->impulseCentre[1];
					if (distanceY < exp->radius && distanceY >= 0)
					{
						distanceMultiplier = sqrt(distanceX*distanceX + distanceY*distanceY);
						distanceMultiplier /= exp->radius;
						distanceMultiplier = 1 - distanceMultiplier;
						distanceMultiplier /= obj->weight;
						double multiplier = (float)(distanceY) / (float)(distanceX);
						CVector2f imp(-1 * (float)exp->impulse / (1 + 1 * abs(multiplier))*distanceMultiplier, (exp->impulse - (float)exp->impulse / (1 + 1 * abs(multiplier)))*distanceMultiplier);
						obj->AddVelocity(imp);
					}
				}
				break;
			case 2:
				// object surfaces are on both sides of impulse, act on centre.
				distanceX = obj->pos[0] + obj->GetWidth() - exp->impulseCentre[0];
				if (distanceX > -1 * exp->radius)
				{
					distanceY = obj->pos[1] + (obj->GetHeight() / 2) - exp->impulseCentre[1];
					if (distanceY > -1 * exp->radius && distanceY <= 0)
					{
						distanceMultiplier = sqrt(distanceX*distanceX + distanceY*distanceY);
						distanceMultiplier /= exp->radius;
						distanceMultiplier = 1 - distanceMultiplier;
						distanceMultiplier /= obj->weight;
						double multiplier = (float)(distanceY) / (float)(distanceX);
						CVector2f imp(-1 * (float)exp->impulse / (1 + 1 * abs(multiplier))*distanceMultiplier, -1 * (exp->impulse - exp->impulse / (1 + 1 * abs(multiplier)))*distanceMultiplier);
						obj->AddVelocity(imp);
					}
					else if (distanceY < exp->radius && distanceY >= 0)
					{
						distanceMultiplier = sqrt(distanceX*distanceX + distanceY*distanceY);
						distanceMultiplier /= exp->radius;
						distanceMultiplier = 1 - distanceMultiplier;
						distanceMultiplier /= obj->weight;
						double multiplier = (float)(distanceY) / (float)(distanceX);
						CVector2f imp(-1 * (float)exp->impulse / (1 + 1 * abs(multiplier))*distanceMultiplier, exp->impulse - (exp->impulse / (1 + 1 * abs(multiplier)))*distanceMultiplier);
						obj->AddVelocity(imp);
					}
				}
				break;
			}
		}
		else if (obj->pos[0] > exp->impulseCentre[0])
		{//obj is right of impulse center
			switch (ySurface)
			{
			case 0:
				//object is above impulse center, act on bottom surface
				distanceX = obj->pos[0] - exp->impulseCentre[0];
				if (distanceX < exp->radius)
				{
					distanceY = obj->pos[1] + obj->GetHeight() - exp->impulseCentre[1];
					if (distanceY > -1 * exp->radius && distanceY <= 0)
					{
						distanceMultiplier = sqrt(distanceX*distanceX + distanceY*distanceY);
						distanceMultiplier /= exp->radius;
						distanceMultiplier = 1 - distanceMultiplier;
						distanceMultiplier /= obj->weight;
						double multiplier = (float)(distanceY) / (float)(distanceX);
						CVector2f imp(exp->impulse / (1 + 1 * abs(multiplier))*distanceMultiplier, -1 * (exp->impulse - exp->impulse / (1 + 1 * abs(multiplier)))*distanceMultiplier);
						obj->AddVelocity(imp);
					}
				}
				break;
			case 1:
				//object is below impulse center, act on top surface
				distanceX = obj->pos[0] - exp->impulseCentre[0];
				if (distanceX < exp->radius)
				{
					distanceY = obj->pos[1] - exp->impulseCentre[1];
					if (distanceY < exp->radius && distanceY >= 0)
					{
						distanceMultiplier = sqrt(distanceX*distanceX + distanceY*distanceY);
						distanceMultiplier /= exp->radius;
						distanceMultiplier = 1 - distanceMultiplier;
						distanceMultiplier /= obj->weight;
						double multiplier = (float)(distanceY) / (float)(distanceX);
						CVector2f imp(exp->impulse / (1 + 1 * abs(multiplier))*distanceMultiplier, exp->impulse - (exp->impulse / (1 + 1 * abs(multiplier)))*distanceMultiplier);
						obj->AddVelocity(imp);
					}
				}
				break;
			case 2:
				// object surfaces are on both sides of impulse, act on centre.
				distanceX = obj->pos[0] - exp->impulseCentre[0];
				if (distanceX < exp->radius)
				{
					distanceY = obj->pos[1] + (obj->GetHeight() / 2) - exp->impulseCentre[1];
					if (distanceY > -1 * exp->radius && distanceY <= 0)
					{
						distanceMultiplier = sqrt(distanceX*distanceX + distanceY*distanceY);
						distanceMultiplier /= exp->radius;
						distanceMultiplier = 1 - distanceMultiplier;
						distanceMultiplier /= obj->weight;
						double multiplier = (float)(distanceY) / (float)(distanceX);
						CVector2f imp(exp->impulse / (1 + 1 * abs(multiplier))*distanceMultiplier, -1 * (exp->impulse - exp->impulse / (1 + 1 * abs(multiplier)))*distanceMultiplier);
						obj->AddVelocity(imp);
					}
					else if (distanceY < exp->radius && distanceY >= 0)
					{
						distanceMultiplier = sqrt(distanceX*distanceX + distanceY*distanceY);
						distanceMultiplier /= exp->radius;
						distanceMultiplier = 1 - distanceMultiplier;
						distanceMultiplier /= obj->weight;
						double multiplier = (float)(distanceY) / (float)(distanceX);
						CVector2f imp(exp->impulse / (1 + 1 * abs(multiplier))*distanceMultiplier, (exp->impulse - exp->impulse / (1 + 1 * abs(multiplier)))*distanceMultiplier);
						obj->AddVelocity(imp);
					}
				}
				break;
			}
		}
		else
		{// object X-surfaces are on both sides of impulse, act on centre.
			switch (ySurface)
			{
			case 0:
				//object is above impulse center, act on bottom surface
				distanceX = obj->pos[0] + (obj->GetWidth() / 2) - exp->impulseCentre[0];
				if (distanceX < exp->radius && distanceX >= 0)
				{
					distanceY = obj->pos[1] + obj->GetHeight() - exp->impulseCentre[1];
					if (distanceY > -1 * exp->radius && distanceY <= 0)
					{
						distanceMultiplier = sqrt(distanceX*distanceX + distanceY*distanceY);
						distanceMultiplier /= exp->radius;
						distanceMultiplier = 1 - distanceMultiplier;
						distanceMultiplier /= obj->weight;
						double multiplier = (float)(distanceY) / (float)(distanceX);
						CVector2f imp(exp->impulse / (1 + 1 * abs(multiplier))*distanceMultiplier, -1 * (exp->impulse - exp->impulse / (1 + 1 * abs(multiplier)))*distanceMultiplier);
						obj->AddVelocity(imp);
					}
				}
				else if (distanceX > -1 * exp->radius && distanceX <= 0)
				{
					distanceY = obj->pos[1] + obj->GetHeight() - exp->impulseCentre[1];
					if (distanceY > -1 * exp->radius && distanceY <= 0)
					{
						distanceMultiplier = sqrt(distanceX*distanceX + distanceY*distanceY);
						distanceMultiplier /= exp->radius;
						distanceMultiplier = 1 - distanceMultiplier;
						distanceMultiplier /= obj->weight;
						double multiplier = (float)(distanceY) / (float)(distanceX);
						CVector2f imp(-1 * (exp->impulse / (1 + 1 * abs(multiplier)))*distanceMultiplier, -1 * (exp->impulse - exp->impulse / (1 + 1 * abs(multiplier)))*distanceMultiplier);
						obj->AddVelocity(imp);
					}
				}
				break;
			case 1:
				//object is below impulse center, act on top surface
				distanceX = obj->pos[0] + (obj->GetWidth() / 2) - exp->impulseCentre[0];
				if (distanceX < exp->radius && distanceX >= 0)
				{
					distanceY = obj->pos[1] - exp->impulseCentre[1];
					if (distanceY < exp->radius && distanceY >= 0)
					{
						distanceMultiplier = sqrt(distanceX*distanceX + distanceY*distanceY);
						distanceMultiplier /= exp->radius;
						distanceMultiplier = 1 - distanceMultiplier;
						distanceMultiplier /= obj->weight;
						double multiplier = (float)(distanceY) / (float)(distanceX);
						CVector2f imp(exp->impulse / (1 + 1 * abs(multiplier))*distanceMultiplier, exp->impulse - (exp->impulse / (1 + 1 * abs(multiplier)))*distanceMultiplier);
						obj->AddVelocity(imp);
					}
				}
				else if (distanceX > -1 * exp->radius && distanceX <= 0)
				{
					distanceY = obj->pos[1] - exp->impulseCentre[1];
					if (distanceY < exp->radius && distanceY >= 0)
					{
						distanceMultiplier = sqrt(distanceX*distanceX + distanceY*distanceY);
						distanceMultiplier /= exp->radius;
						distanceMultiplier = 1 - distanceMultiplier;
						distanceMultiplier /= obj->weight;
						double multiplier = (float)(distanceY) / (float)(distanceX);
						CVector2f imp(-1 * (exp->impulse / (1 + 1 * abs(multiplier))*distanceMultiplier), exp->impulse - (exp->impulse / (1 + 1 * abs(multiplier)))*distanceMultiplier);
						obj->AddVelocity(imp);
					}
				}

				break;
			case 2:
				// object surfaces are on both sides of impulse, act on centre.
				distanceX = obj->pos[0] + (obj->GetWidth() / 2) - exp->impulseCentre[0];
				if (distanceX < exp->radius && distanceX >= 0)
				{
					distanceY = obj->pos[1] + (obj->GetHeight() / 2) - exp->impulseCentre[1];
					if (distanceY > -1 * exp->radius && distanceY <= 0)
					{
						distanceMultiplier = sqrt(distanceX*distanceX + distanceY*distanceY);
						distanceMultiplier /= exp->radius;
						distanceMultiplier = 1 - distanceMultiplier;
						distanceMultiplier /= obj->weight;
						double multiplier = (float)(distanceY) / (float)(distanceX);
						CVector2f imp(exp->impulse / (1 + 1 * abs(multiplier))*distanceMultiplier, -1 * (exp->impulse - exp->impulse / (1 + 1 * abs(multiplier)))*distanceMultiplier);
						obj->AddVelocity(imp);
					}
					else if (distanceY < exp->radius && distanceY >= 0)
					{
						distanceMultiplier = sqrt(distanceX*distanceX + distanceY*distanceY);
						distanceMultiplier /= exp->radius;
						distanceMultiplier = 1 - distanceMultiplier;
						distanceMultiplier /= obj->weight;
						double multiplier = (float)(distanceY) / (float)(distanceX);
						CVector2f imp(exp->impulse / (1 + 1 * abs(multiplier))*distanceMultiplier, (exp->impulse - exp->impulse / (1 + 1 * abs(multiplier)))*distanceMultiplier);
						obj->AddVelocity(imp);
					}

				}
				else if (distanceX > -1 * exp->radius && distanceX <= 0)
				{
					distanceY = obj->pos[1] + (obj->GetHeight() / 2) - exp->impulseCentre[1];
					if (distanceY > -1 * exp->radius && distanceY <= 0)
					{
						distanceMultiplier = sqrt(distanceX*distanceX + distanceY*distanceY);
						distanceMultiplier /= exp->radius;
						distanceMultiplier = 1 - distanceMultiplier;
						distanceMultiplier /= obj->weight;
						double multiplier = (float)(distanceY) / (float)(distanceX);
						CVector2f imp(-1 * (exp->impulse / (1 + 1 * abs(multiplier)))*distanceMultiplier, -1 * (exp->impulse - exp->impulse / (1 + 1 * abs(multiplier)))*distanceMultiplier);
						obj->AddVelocity(imp);
					}
					else if (distanceY < exp->radius && distanceY >= 0)
					{
						distanceMultiplier = sqrt(distanceX*distanceX + distanceY*distanceY);
						distanceMultiplier /= exp->radius;
						distanceMultiplier = 1 - distanceMultiplier;
						distanceMultiplier /= obj->weight;
						double multiplier = (float)(distanceY) / (float)(distanceX);
						CVector2f imp(-1 * (exp->impulse / (1 + 1 * abs(multiplier)))*distanceMultiplier, (exp->impulse - exp->impulse / (1 + 1 * abs(multiplier)))*distanceMultiplier);
						obj->AddVelocity(imp);
					}
				}
				break;
			}
		}
	}
}