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); } }
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; } } } }