Beispiel #1
0
void ClassicMode::SlideResolution()
{
	if (0 != MyScene.GetSelectedObjectId() && bModelMovedByUser)
	{
		bool bCollisionExists = CheckForCollision();

		// Snap back
		if (!bCollisionExists)
		{
			SnapPersp(Back);
			bCollisionExists = CheckForCollision();
		}

		// Snap front
		if (bCollisionExists)
		{
			int nIterations = 3;

			do SnapPersp(Front);
			while ((bCollisionExists = CheckForCollision()) && nIterations-- > 0);
		}

		if (!bCollisionExists)
			bModelMovedByUser = false;
	}
}
bool MenuCheckBox::HoldOnCollision(int fingerid, float x, float y, bool releaseifnottouching, bool fingerwentdown)
{
    if( m_FingerHolding != -1 )
        return true;

    if( CheckForCollision( x, y ) )
    {
        PlaySound();
        //LOGInfo( LOGTag, "CheckBox Held\n" );

        m_FingerHolding = fingerid;
        m_State = MCBS_HeldDown;
        return true;
    }
    else if( releaseifnottouching )
    {
        //if( m_FingerHolding != -1 )
        //    LOGInfo( LOGTag, "CheckBox releaseifnottouching\n" );

        m_FingerHolding = -1;
        m_State = MCBS_Idle;
    }

    return false;
}
void DIYPhysicScene::Update(float dt)
{
	CheckForCollision();
	for (PhysicsObject* po : actors)
	{
		po->Update(gravity, dt);
	}
}
// Spiele Logik hier
void Spiel::Update()
{
	if(_steinNeu->GetStatus())
	{
		if(!CheckForCollision())
			_steinNeu->Fallen();
	}
	else
	{
		_spielSteine.push_back(*_steinNeu);
		_steinNeu = new Stein(RandomStein(), _viewNeu);
	}
}
Beispiel #5
0
// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CLightCycleMgr::Update
//
//	PURPOSE:	Updates the light cycle mgr
//
// ----------------------------------------------------------------------- //
void CLightCycleMgr::Update()
{
	if(!m_bUpdating)
		return;

	// Vars
	LTVector vPos;
	LTVector vOldForward;
	LIGHT_CYCLIST* pCyclist;
	LIGHT_CYCLE_TRAIL *pTrail;
	std::vector<LIGHT_CYCLIST*>::iterator iter;

	// Walk the list
	for(iter=m_collCyclists.begin();iter!=m_collCyclists.end();iter++)
	{
		pCyclist = (*iter);
		if(pCyclist->bUpdating)
		{
			// Update his trail
			ASSERT(pCyclist->hObject);
			g_pLTServer->GetObjectPos(pCyclist->hObject,&vPos);

			pTrail = pCyclist->pCurTrail;

			// Check to see if we have a trail
			if(pTrail)
			{
				vOldForward = pCyclist->vForward;

				// Update the trail
				UpdateLightCycleTrail(pCyclist, vPos);
			}
			else
			{
				// Simple case: We're starting a new trail
				BeginLightCycleTrail(pCyclist,vPos);
			}

			// Now we check to see if this guy collided
			LightCycleCollisionInfo info;
			if(CheckForCollision(pCyclist,info))
			{
				// Uh-oh. We have a crash. And crashing is bad, m'kay?
				HandleCollision(pCyclist,info);
			}
		}
	}
}
int MenuCheckBox::TriggerOnCollision(int fingerid, float x, float y, bool careifheld, bool releaseifnocollision)
{
    if( careifheld && m_FingerHolding != fingerid )
        return -1;

    if( CheckForCollision( x, y ) )
    {
        PlaySound();
        //LOGInfo( LOGTag, "CheckBox TriggerOnCollision\n" );
        m_Checked = !m_Checked;

        return m_Action;
    }

    return -1;
}
float MenuCheckBox::TestCollision(int fingerid, float x, float y, bool fingerwentdown)
{
    //if( m_FingerHolding != -1 )
    //    return true;

    if( CheckForCollision( x, y ) )
    {
        float posx = m_Transform.m41;
        float posy = m_Transform.m42;

        float dist = (posx - x)*(posx - x) + (posy - y)*(posy - y);
        return dist;
    }

    return -1;
}
bool MenuCheckBox::ReleaseOnNoCollision(int fingerid, float x, float y)
{
    if( m_FingerHolding != fingerid )
        return false;

    if( CheckForCollision( x, y ) )
    {
        return false;
    }
    else
    {
        if( m_State == MCBS_HeldDown )
        {
            PlaySound();
            //LOGInfo( LOGTag, "CheckBox ReleaseOnNoCollision\n" );

            m_FingerHolding = -1;
            m_State = MCBS_Idle;
            return true;
        }
    }

    return false;
}
Beispiel #9
0
void CAirMoveType::UpdateFighterAttack(void)
{
	float3 &pos = owner->pos;
	SyncedFloat3 &rightdir = owner->rightdir;
	SyncedFloat3 &frontdir = owner->frontdir;
	SyncedFloat3 &updir = owner->updir;
	float3 &speed = owner->speed;

	float speedf = owner->speed.Length();
	if (speedf < 0.01f) {
		UpdateAirPhysics(0, 0, 0, 1, owner->frontdir);
		return;
	}

	if (!((gs->frameNum + owner->id) & 3))
		CheckForCollision();

	bool groundTarget = !owner->userTarget || !owner->userTarget->unitDef->canfly || owner->userTarget->unitDef->hoverAttack;
	bool airTarget = owner->userTarget && owner->userTarget->unitDef->canfly && !owner->userTarget->unitDef->hoverAttack;	//only "real" aircrafts (non gunship)
	if (groundTarget) {
		if (frontdir.dot(goalPos - pos) < 0 && (pos - goalPos).SqLength() < turnRadius * turnRadius * (loopbackAttack ? 4 : 1)) {
			float3 dif = pos - goalPos;
			dif.y = 0;
			dif.Normalize();
			goalPos = goalPos + dif * turnRadius * 4;
		} else if (loopbackAttack && !airTarget) {
			bool hasFired = false;
			if (!owner->weapons.empty() && owner->weapons[0]->reloadStatus > gs->frameNum && owner->weapons[0]->salvoLeft == 0)
				hasFired = true;
			if (frontdir.dot(goalPos - pos) < owner->maxRange * (hasFired ? 1.0f : 0.7f))
				maneuver = 1;
		} else if (frontdir.dot(goalPos - pos) < owner->maxRange * 0.7f) {
			goalPos += exitVector * (owner->userTarget ? owner->userTarget->radius + owner->radius + 10 : owner->radius + 40);
		}
	}
	float3 tgp = goalPos + (goalPos - oldGoalPos) * 8;
	oldGoalPos = goalPos;
	goalPos = tgp;

	float goalLength = (goalPos - pos).Length();
	float3 goalDir =
		(goalLength > 0.0f)?
		(goalPos - pos) / goalLength:
		ZeroVector;

	float aileron = 0;
	float rudder = 0;
	float elevator = 0;
	float engine = 0;
	float gHeight = ground->GetHeight(pos.x, pos.z);

	float goalDotRight = rightdir.dot(goalDir);
	float goalDotFront = goalDir.dot(frontdir) * 0.5f + 0.501f;

	if (goalDotFront != 0.0f) {
		goalDotRight /= goalDotFront;
	}


	if (goalDir.dot(frontdir) < -0.2f + inefficientAttackTime * 0.002f && frontdir.y > -0.2f && speedf > 2.0f && gs->randFloat() > 0.996f)
		maneuver = 1;

	if (goalDir.dot(frontdir) < -0.2f + inefficientAttackTime * 0.002f && fabs(frontdir.y) < 0.2f && gs->randFloat() > 0.996f && gHeight + 400 < pos.y) {
		maneuver = 2;
		maneuverSubState = 0;
	}

	// roll
	if (speedf > 0.45f && pos.y + owner->speed.y * 60 * fabs(frontdir.y) + std::min(0.0f, float(updir.y)) * 150 > gHeight + 60 + fabs(rightdir.y) * 150) {
		float goalBankDif = goalDotRight + rightdir.y * 0.2f;
		if (goalBankDif > maxAileron * speedf * 4.0f) {
			aileron = 1;
		} else if (goalBankDif < -maxAileron * speedf * 4.0f) {
			aileron = -1;
		} else {
			aileron = goalBankDif / (maxAileron * speedf * 4.0f);
		}
	} else {
		if (rightdir.y > 0.0f) {
			if (rightdir.y > maxAileron * speedf || frontdir.y < -0.7f) {
				aileron = 1;
			} else {
				if (speedf > 0.0f) {
					aileron = rightdir.y / (maxAileron * speedf);
				}
			}
		} else {
			if (rightdir.y < -maxAileron * speedf || frontdir.y < -0.7f) {
				aileron = -1;
			} else {
				if (speedf > 0.0f) {
					aileron = rightdir.y / (maxAileron * speedf);
				}
			}
		}
	}

	// yaw
	if (pos.y > gHeight + 30) {
		if (goalDotRight < -maxRudder * speedf) {
			rudder = -1;
		} else if (goalDotRight > maxRudder * speedf) {
			rudder = 1;
		} else {
			if (speedf > 0.0f) {
				rudder = goalDotRight / (maxRudder * speedf);
			}
		}
	}

	float upside = 1;
	if (updir.y < -0.3f)
		upside = -1;

	// pitch
	if (speedf < 1.5f) {
		if (frontdir.y < 0.0f) {
			elevator = upside;
		} else if (frontdir.y > 0.0f) {
			elevator = -upside;
		}
	} else {
		float gHeight2 = ground->GetHeight(pos.x + speed.x * 40, pos.z + speed.z * 40);
		float hdif = std::max(gHeight, gHeight2) + 60 - pos.y - frontdir.y * speedf * 20;
		float minPitch = 1.0f; // min(1.0f, hdif / (maxElevator * speedf * speedf * 20));

		if (hdif < -(maxElevator * speedf * speedf * 20)) {
			minPitch = -1;
		} else if (hdif > (maxElevator * speedf * speedf * 20)) {
			minPitch = 1;
		} else {
			minPitch = hdif / (maxElevator * speedf * speedf * 20);
		}
//	} else {
		if (lastColWarning && lastColWarningType == 2 && frontdir.dot(lastColWarning->pos + lastColWarning->speed * 20 - pos-owner->speed * 20) < 0) {
			/*
			float pitchMod = (updir.y > 0.0f)? 1: -1;
			if (lastColWarning->pos.y > pos.y)
				elevator = -pitchMod;
			else
				elevator = pitchMod;
			*/

			elevator = (updir.dot(lastColWarning->midPos - owner->midPos) > 0.0f)? -1 : 1;
		} else {
			float hdif = goalDir.dot(updir);
			if (hdif < -maxElevator * speedf) {
				elevator = -1;
			} else if (hdif > maxElevator * speedf) {
				elevator = 1;
			} else {
				elevator = hdif / (maxElevator * speedf);
			}
		}
		if (elevator * upside < minPitch)
			elevator = minPitch * upside;
	}
#ifdef DEBUG_AIRCRAFT
	GML_RECMUTEX_LOCK(sel); // UpdateFighterAttack

	if (selectedUnits.selectedUnits.find(this) != selectedUnits.selectedUnits.end()){
		logOutput.Print("FAttack %.1f %.1f %.2f", pos.y - gHeight, goalLength, goalDir.dot(frontdir));
	}
#endif

	if (groundTarget)
		engine = 1;
	else
		engine = std::min(1.f, (float)(goalLength / owner->maxRange + 1 - goalDir.dot(frontdir) * 0.7f));

	UpdateAirPhysics(rudder, aileron, elevator, engine, owner->frontdir);
}
Beispiel #10
0
Datei: check.c Projekt: kahrs/cda
void CheckSignalNet(struct signal *signalPointer)
{
	struct pin *pinPointer;
	char *signal_name;
	int pinType;
	char signalPins[MAXPERNET];

	inputPinCount = 0;
	outputPinCount = 0;
	sinkPinCount = 0;
	sourcePinCount = 0;
	analogPinCount = 0;
	undeclaredPinCount = 0;
	totalPinCount = 0;

	signal_name = signalPointer -> bucket -> name;
	if (cFlag)
	{
		fprintf(stdout, "%s:", signal_name);
		if (xFlag) printf("\n");
		else
		if (signalPointer -> pin_count > MAXPERNET)
			Bug("signal net too large in CheckSignalNet");
	} /* end if */
	for (pinPointer = signalPointer -> first_pin;
	     pinPointer != NULL_STRUCT(pin);
	     pinPointer = pinPointer -> instance_chain)
	{
		(void) CheckForCollision(signalPointer, pinPointer);
		pinType = PinType(pinPointer, cFlag & xFlag);
		if (cFlag & !xFlag)
			signalPins[totalPinCount] = pinType;
		else
			(void) DoPinType(pinPointer, signalPointer, pinType);
		totalPinCount++;
	} /* end for */
	if (cFlag)
	{
		if (!xFlag)
		{
			signalPins[totalPinCount] = '\0';
			fprintf(stdout, "\t%s\n", signalPins);
		} /* end if */
		if (pFlag) fprintf(stdout, "\t\t\t\t%di,%do,%ds,%dS,%da,%du\n",
					inputPinCount, outputPinCount,
					sinkPinCount, sourcePinCount,
					analogPinCount, undeclaredPinCount);
		return;
	} /* end if */
	if ((sinkPinCount > 0) && (sourcePinCount == 0) &&
	    (!PowerGroundNet(signalPointer)) && (!AnalogNet(signalPointer)))
		if (OpenCollectorNet(signalPointer))
			(void) ParanoidSignalWarning(signalPointer, "no o.c. pullup");
		else
			(void) ParanoidSignalWarning(signalPointer, "no source");
	if ((!PowerGroundNet(signalPointer)) && (inputPinCount > 0) && (outputPinCount == 0))
		(void) ParanoidSignalWarning(signalPointer, "no outputs");
	if ((!PowerGroundNet(signalPointer)) && (outputPinCount > 0) && (inputPinCount == 0))
		(void) ParanoidSignalWarning(signalPointer, "no inputs");
	(void) CheckSignalPins(signalPointer);
} /* end CheckSignalNet */
Beispiel #11
0
Datei: check.c Projekt: kahrs/cda
void CheckSignal(struct signal *signalPointer)
{
	int pins;
	int pinType;
	char message[STRLEN];
	char *pinName;
	struct pin *thePin;
	struct pin_definitions *pinDefinitions;
	if (tFlag) printf("%s: #%d\n", signalPointer -> bucket -> name,
				signalPointer -> pin_count);
	pins = signalPointer -> pin_count;
	if (signalPointer -> type & IGNORE_SIGNAL) return;
	if (pins == 0) (void) Warning("net %s has no pins?", signalPointer -> bucket -> name);
	else
	if (pins == 1)
	{
		if (signalPointer -> type & MACRO_SIGNAL & mFlag)
			return;
		thePin = signalPointer -> first_pin;
		if (LFlag && (signalPointer -> bucket -> name[0] == '$'))
			return; /* ignore local nets */
		pinDefinitions = thePin -> instance -> chip -> pin_definitions;
		if (cFlag) return;
		if (xFlag)
		{
			pinName = "";
			pinType = NO_TYPE;
			if ((pinDefinitions != NULL_STRUCT(pin_definitions)) &&
			    (pinDefinitions -> pin_names) &&
			    (pinDefinitions -> pin_names[(thePin -> pin_number) - 1]))
			{
				pinName = pinDefinitions -> pin_names[(thePin -> pin_number) - 1];
				pinType = TypePin(pinDefinitions -> pin_types[(thePin -> pin_number) - 1]);
			}
			if (wFlag)
			    (void) sprintf(message, "lone%s pin at %s.%d (%s.%s) [%s]",
			    pinDirectionString[PinDirection(pinType)],
			    thePin -> instance -> bucket -> name,
			    thePin -> pin_number,
			    thePin -> instance -> chip -> bucket -> name,
			    pinName,
			    wFiles[thePin -> fileindex]);
			else
			    (void) sprintf(message, "lone%s pin at %s.%d (%s.%s)",
			    pinDirectionString[PinDirection(pinType)],
			    thePin -> instance -> bucket -> name,
			    thePin -> pin_number,
			    thePin -> instance -> chip -> bucket -> name,
			    pinName);
		} /* end if */
		else
			(void) sprintf(message, "lone%s pin at %s.%d",
			pinDirectionString[PinDirection(pinType)],
			thePin -> instance -> bucket -> name,
			thePin -> pin_number);
		(void) SignalWarning(signalPointer, FULL_PIN, message);
		(void) CheckForCollision(signalPointer, thePin);
	} /* end if */
	else
		(void) CheckSignalNet(signalPointer);
} /* end CheckSignal */
void CAirMoveType::UpdateFlying(float wantedHeight,float engine)
{
	float3 &pos = owner->pos;
	float3 &rightdir = owner->rightdir;
	float3 &frontdir = owner->frontdir;
	float3 &updir = owner->updir;
	float3 &speed = owner->speed;

	float speedf=speed.Length();
	float goalLength=(goalPos-pos).Length();
	float3 goalDir=(goalPos-pos)/goalLength;
	goalDir.Normalize();

	float aileron=0;
	float rudder=0;
	float elevator=0;

	float gHeight=ground->GetHeight(pos.x,pos.z);

	if(!((gs->frameNum+owner->id)&3))
		CheckForCollision();

	float otherThreat=0;
	float3 otherDir;
	if(lastColWarning){
		float3 otherDif=lastColWarning->pos-pos;
		float otherLength=otherDif.Length();
		otherDir=otherDif/otherLength;
		otherThreat=max(1200.f,goalLength)/otherLength*0.036;
	}

	float goalDot=rightdir.dot(goalDir);
	goalDot/=goalDir.dot(frontdir)*0.5+0.501;
	if(goalDir.dot(frontdir)<-0.1 && goalLength<turnRadius
#ifdef DIRECT_CONTROL_ALLOWED
		&& (!owner->directControl || owner->directControl->mouse2)
#endif
		)
		goalDot=-goalDot;
	if(lastColWarning){
		goalDot-=otherDir.dot(rightdir)*otherThreat;
	}
	//roll
	if(speedf>1.5 && pos.y+speed.y*10>gHeight+wantedHeight*0.6){
		float goalBankDif=goalDot+rightdir.y*0.5;
		if(goalBankDif>maxAileron*speedf*4 && rightdir.y>-maxBank){
			aileron=1;
		} else if(goalBankDif<-maxAileron*speedf*4 && rightdir.y<maxBank){
			aileron=-1;
		} else {
			if(fabs(rightdir.y)<maxBank)
				aileron=goalBankDif/(maxAileron*speedf*4);
			else {
				if(rightdir.y<0 && goalBankDif<0)
					aileron=-1;
				else if(rightdir.y>0 && goalBankDif>0)
					aileron=1;
			}
		}
	} else {
		if(rightdir.y>0.01){
			aileron=1;
		} else if(rightdir.y<-0.01){
			aileron=-1;
		}
	}

	//yaw
	if(pos.y>gHeight+15){
		if(goalDot<-maxRudder*speedf*2){
			rudder=-1;;
		} else if(goalDot>maxRudder*speedf*2){
			rudder=1;
		} else {
			rudder=goalDot/(maxRudder*speedf*2);
		}
	}

	//pitch
	if(speedf>0.8){
		if(lastColWarningType==2 && frontdir.dot(lastColWarning->midPos+lastColWarning->speed*20 - owner->midPos - owner->speed*20)<0){
/*			float pitchMod=updir.y>0?1:-1;
			if(lastColWarning->pos.y>pos.y)
				elevator=-pitchMod;
			else
				elevator=pitchMod;
/*/			elevator=updir.dot(lastColWarning->midPos-owner->midPos)>0?-1:1;/**/
		} else {
			float gHeight2=ground->GetHeight(pos.x+speed.x*40,pos.z+speed.z*40);
			float hdif=max(gHeight,gHeight2)+wantedHeight-pos.y-frontdir.y*speedf*20;
			if(hdif<-(maxElevator*speedf*speedf*20) && frontdir.y>-maxPitch){
				elevator=-1;
			} else if(hdif>(maxElevator*speedf*speedf*20) && frontdir.y<maxPitch){
				elevator=1;
			} else {
				if(fabs(frontdir.y)<maxPitch)
					elevator=hdif/(maxElevator*speedf*speedf*20);
			}
		}
	} else {
		if(frontdir.y<-0.1){
			elevator=1;
		} else if(frontdir.y>0.15){
			elevator=-1;
		}
	}
	UpdateAirPhysics(rudder,aileron,elevator,engine,owner->frontdir);
}
void CTAAirMoveType::UpdateAirPhysics()
{
	float3& pos = owner->pos;
	float3& speed = owner->speed;

	if (!((gs->frameNum + owner->id) & 3)) {
		CheckForCollision();
	}

	float yspeed = speed.y;
	speed.y = 0.0f;

	float3 delta = wantedSpeed - speed;
	float dl = delta.Length();

	if (delta.dot(speed) > 0.0f) {
		// accelerate
		if (dl < accRate) {
			speed = wantedSpeed;
		} else {
			if (dl > 0.0f) {
				speed += delta / dl * accRate;
			}
		}
	} else {
		// break
		if (dl < decRate) {
			speed = wantedSpeed;
		} else {
			if (dl > 0.0f) {
				speed += delta / dl * decRate;
			}
		}
	}

	speed.y = yspeed;
	float h = pos.y - std::max(
		ground->GetHeight(pos.x, pos.z),
		ground->GetHeight(pos.x + speed.x * 40.0f, pos.z + speed.z * 40.0f));

	if (h < 4.0f) {
		speed.x *= 0.95f;
		speed.z *= 0.95f;
	}

	float wh = wantedHeight;

	if (lastColWarningType == 2) {
		const float3 dir = lastColWarning->midPos - owner->midPos;
		const float3 sdir = lastColWarning->speed - speed;

		if (speed.dot(dir + sdir * 20.0f) < 0.0f) {
			if (lastColWarning->midPos.y > owner->pos.y) {
				wh -= 30.0f;
			} else {
				wh += 50.0f;
			}
		}
	}


	float ws = 0.0f;

	if (h < wh) {
		ws = altitudeRate;
		if (speed.y > 0.0f && (wh - h) / speed.y * accRate * 1.5f < speed.y)
			ws = 0.0f;
	} else {
		ws = -altitudeRate;
		if (speed.y < 0.0f && (wh - h) / speed.y * accRate * 0.7f < -speed.y)
			ws = 0.0f;
	}

	if (speed.y > ws) {
		speed.y = std::max(ws, speed.y - accRate * 1.5f);
	} else {
		// let them accelerate upward faster if close to ground
		speed.y = std::min(ws, speed.y + accRate * (h < 20.0f? 2.0f: 0.7f));
	}

	pos += speed;
}
void CAirMoveType::UpdateFighterAttack(void)
{
	float3 &pos = owner->pos;
	float3 &rightdir = owner->rightdir;
	float3 &frontdir = owner->frontdir;
	float3 &updir = owner->updir;
	float3 &speed = owner->speed;

	float speedf=owner->speed.Length();
	if(speedf<0.01){
		UpdateAirPhysics(0,0,0,1,owner->frontdir);
		return;
	}

	if(!((gs->frameNum+owner->id)&3))
		CheckForCollision();

	bool groundTarget=!owner->userTarget || !owner->userTarget->unitDef->canfly;
	if(groundTarget){
		if(frontdir.dot(goalPos-pos)<0 && (pos-goalPos).SqLength()<turnRadius*turnRadius){
			float3 dif=pos-goalPos;
			dif.y=0;
			dif.Normalize();
			goalPos=goalPos+dif*turnRadius*4;
		} else if(frontdir.dot(goalPos-pos)<owner->maxRange*0.7){
			goalPos+=exitVector*(owner->userTarget?owner->userTarget->radius+owner->radius+10:owner->radius+40);
		}
	}
	float3 tgp=goalPos+(goalPos-oldGoalPos)*8;
	oldGoalPos=goalPos;
	goalPos=tgp;

	float goalLength=(goalPos-pos).Length();
	float3 goalDir=(goalPos-pos)/goalLength;
	
	float aileron=0;
	float rudder=0;
	float elevator=0;
	float engine=0;

	float gHeight=ground->GetHeight(pos.x,pos.z);

	float goalDot=rightdir.dot(goalDir);
	goalDot/=goalDir.dot(frontdir)*0.5+0.501;

	if(goalDir.dot(frontdir)<-0.2+inefficientAttackTime*0.002 && frontdir.y>-0.2 && speedf>2.0 && gs->randFloat()>0.996)
		maneuver=1;

	if(goalDir.dot(frontdir)<-0.2+inefficientAttackTime*0.002 && fabs(frontdir.y)<0.2 && gs->randFloat()>0.996 && gHeight+400<pos.y){
		maneuver=2;
		maneuverSubState=0;
	}

	//roll
	if(speedf>0.45 && pos.y+owner->speed.y*60*fabs(frontdir.y)+min(0.f,updir.y)*150>gHeight+60+fabs(rightdir.y)*150){
		float goalBankDif=goalDot+rightdir.y*0.2;
		if(goalBankDif>maxAileron*speedf*4){
			aileron=1;
		} else if(goalBankDif<-maxAileron*speedf*4){
			aileron=-1;
		} else {
			aileron=goalBankDif/(maxAileron*speedf*4);
		}
	} else {
		if(rightdir.y>0){
			if(rightdir.y>maxAileron*speedf || frontdir.y<-0.7)
				aileron=1;
			else
				aileron=rightdir.y/(maxAileron*speedf);
		} else {
			if(rightdir.y<-maxAileron*speedf || frontdir.y<-0.7)
				aileron=-1;
			else 
				aileron=rightdir.y/(maxAileron*speedf);
		}
	}

	//yaw
	if(pos.y>gHeight+30){
		if(goalDot<-maxRudder*speedf){
			rudder=-1;
		} else if(goalDot>maxRudder*speedf){
			rudder=1;
		} else {
			rudder=goalDot/(maxRudder*speedf);
		}
	}

	float upside=1;
	if(updir.y<-0.3)
		upside=-1;

	//pitch
	if(speedf<1.5){
		if(frontdir.y<0.0){
			elevator=upside;
		} else if(frontdir.y>0.0){
			elevator=-upside;
		}
	} else {
		float gHeight2=ground->GetHeight(pos.x+speed.x*40,pos.z+speed.z*40);
		float hdif=max(gHeight,gHeight2)+60-pos.y-frontdir.y*speedf*20;
		float minPitch;//=min(1.0f,hdif/(maxElevator*speedf*speedf*20));

		if(hdif<-(maxElevator*speedf*speedf*20)){
			minPitch=-1;
		} else if(hdif>(maxElevator*speedf*speedf*20)){
			minPitch=1;
		} else {
			minPitch=hdif/(maxElevator*speedf*speedf*20);
		}

/*		if(pos.y+min(0,owner->speed.y)*70*fabs(frontdir.y)+min(0,updir.y)*50<gHeight+50){
		if(frontdir.y<0.5){
			elevator=upside;
		} else if(frontdir.y>0.55){
			elevator=-upside;
		}*/
//	} else {
		if(lastColWarningType==2 && frontdir.dot(lastColWarning->pos+lastColWarning->speed*20-pos-owner->speed*20)<0){
/*			float pitchMod=updir.y>0?1:-1;
			if(lastColWarning->pos.y>pos.y)
				elevator=-pitchMod;
			else
				elevator=pitchMod;
/*/			elevator=updir.dot(lastColWarning->midPos-owner->midPos)>0?-1:1;/**/
		} else {
			float hdif=goalDir.dot(updir);
			if(hdif<-maxElevator*speedf){
				elevator=-1;
			} else if(hdif>maxElevator*speedf){
				elevator=1;
			} else {
				elevator=hdif/(maxElevator*speedf);
			}
		}
		if(elevator*upside<minPitch)
			elevator=minPitch*upside;
	}
#ifdef DEBUG_AIRCRAFT
	if(selectedUnits.selectedUnits.find(this)!=selectedUnits.selectedUnits.end()){
		info->AddLine("FAttack %.1f %.1f %.2f",pos.y-gHeight,goalLength,goalDir.dot(frontdir));
	}
#endif

	if(groundTarget)
		engine=1;
	else
		engine=min(1.f,(float)(goalLength/owner->maxRange+1-goalDir.dot(frontdir)*0.7));

	UpdateAirPhysics(rudder,aileron,elevator,engine,owner->frontdir);
/*
	std::vector<CWeapon*>::iterator wi;
	for(wi=owner->weapons.begin();wi!=owner->weapons.end();++wi){
		(*wi)->targetPos=goalPos;
		if(owner->userTarget){
			(*wi)->AttackUnit(owner->userTarget,true);
		}
	}*/
/*	DrawLine dl;
	dl.color=UpVector;
	dl.pos1=pos;
	dl.pos2=goalPos;
	lines.push_back(dl);
	dl.color=float3(1,0,0);
	dl.pos1=pos;
	dl.pos2=pos+frontdir*maxRange;
	lines.push_back(dl);/**/
}
void CTAAirMoveType::UpdateAirPhysics()
{
	float3& pos=owner->pos;
	float3& speed=owner->speed;

	if(!((gs->frameNum+owner->id)&3))
		CheckForCollision();
/*
	if(lastColWarningType==1){
		int g=geometricObjects->AddLine(owner->pos,lastColWarning->pos,10,1,1);
		geometricObjects->SetColor(g,0.2f,1,0.2f,0.6f);
	} else if(lastColWarningType==2){
		int g=geometricObjects->AddLine(owner->pos,lastColWarning->pos,10,1,1);
		if(speed.dot(lastColWarning->midPos+lastColWarning->speed*20 - owner->midPos - owner->speed*20)<0)
			geometricObjects->SetColor(g,1,0.2f,0.2f,0.6f);
		else
			geometricObjects->SetColor(g,1,1,0.2f,0.6f);
	}
*/
	float yspeed=speed.y;
	speed.y=0;

	float3 delta = wantedSpeed - speed;
	float dl=delta.Length();

	if(delta.dot(speed)>0){	//accelerate
		if(dl<accRate)
			speed=wantedSpeed;
		else
			speed+=delta/dl*accRate;
	} else {											//break
		if(dl<decRate)
			speed=wantedSpeed;
		else
			speed+=delta/dl*decRate;
	}

	speed.y=yspeed;
	float h = pos.y - max(ground->GetHeight(pos.x, pos.z),ground->GetHeight(pos.x+speed.x*40,pos.z+speed.z*40));

	if(h<4){
		speed.x*=0.95f;
		speed.z*=0.95f;
	}

	float wh=wantedHeight;
	if(lastColWarningType==2 && speed.dot(lastColWarning->midPos+lastColWarning->speed*20-owner->midPos-speed*20)<0){
		if(lastColWarning->midPos.y>owner->pos.y)
			wh-=30;
		else
			wh+=50;
	}
	float ws;
	if (h < wh){
		ws= altitudeRate;
		if(speed.y>0 && (wh-h)/speed.y*accRate*1.5f < speed.y)
			ws=0;
	} else {
		ws= -altitudeRate;
		if(speed.y<0 && (wh-h)/speed.y*accRate*0.7f < -speed.y)
			ws=0;
	}
	if(speed.y>ws)
		speed.y=max(ws,speed.y-accRate*1.5f);
	else
		speed.y=min(ws,speed.y+accRate*(h<20?2.0f:0.7f));	//let them accelerate upward faster if close to ground

	pos+=speed;
}
Beispiel #16
0
void CHoverAirMoveType::UpdateAirPhysics()
{
	const float3& pos = owner->pos;
	const float4& spd = owner->speed;

	// copy vertical speed
	const float yspeed = spd.y;

	if (((gs->frameNum + owner->id) & 3) == 0) {
		CheckForCollision();
	}

	// cancel out vertical speed, acc and dec are applied in xz-plane
	owner->SetVelocity(spd * XZVector);

	const float3 deltaSpeed = wantedSpeed - spd;
	const float deltaDotSpeed = deltaSpeed.dot(spd);
	const float deltaSpeedSq = deltaSpeed.SqLength();

	if (deltaDotSpeed >= 0.0f) {
		// accelerate
		if (deltaSpeedSq < Square(accRate)) {
			owner->SetVelocity(wantedSpeed);
		} else {
			if (deltaSpeedSq > 0.0f) {
				owner->SetVelocity(spd + (deltaSpeed / math::sqrt(deltaSpeedSq) * accRate));
			}
		}
	} else {
		// deccelerate
		if (deltaSpeedSq < Square(decRate)) {
			owner->SetVelocity(wantedSpeed);
		} else {
			if (deltaSpeedSq > 0.0f) {
				owner->SetVelocity(spd + (deltaSpeed / math::sqrt(deltaSpeedSq) * decRate));
			}
		}
	}

	// absolute and relative ground height at (pos.x, pos.z)
	// if this aircraft uses the smoothmesh, these values are
	// calculated with respect to that (for changing vertical
	// speed, but not for ground collision)
	float curAbsHeight = owner->unitDef->canSubmerge?
		CGround::GetHeightReal(pos.x, pos.z):
		CGround::GetHeightAboveWater(pos.x, pos.z);

	// always stay above the actual terrain (therefore either the value of
	// <midPos.y - radius> or pos.y must never become smaller than the real
	// ground height)
	// note: unlike StrafeAirMoveType, UpdateTakeoff and UpdateLanding call
	// UpdateAirPhysics() so we ignore terrain while we are in those states
	if (modInfo.allowAircraftToHitGround) {
		const bool groundContact = (curAbsHeight > (owner->midPos.y - owner->radius));
		const bool handleContact = (aircraftState != AIRCRAFT_LANDED && aircraftState != AIRCRAFT_TAKEOFF && padStatus == PAD_STATUS_FLYING);

		if (groundContact && handleContact) {
			owner->Move(UpVector * (curAbsHeight - (owner->midPos.y - owner->radius) + 0.01f), true);
		}
	}

	if (UseSmoothMesh()) {
		curAbsHeight = owner->unitDef->canSubmerge?
			smoothGround->GetHeight(pos.x, pos.z):
			smoothGround->GetHeightAboveWater(pos.x, pos.z);
	}

	// restore original vertical speed, then compute new
	UpdateVerticalSpeed(spd, pos.y - curAbsHeight, yspeed);

	if (modInfo.allowAircraftToLeaveMap || (pos + spd).IsInBounds()) {
		owner->Move(spd, true);
	}
}
Beispiel #17
0
void CHoverAirMoveType::UpdateAirPhysics()
{
	const float3& pos = owner->pos;
	const float4& spd = owner->speed;

	// copy vertical speed
	const float yspeed = spd.y;

	if (((gs->frameNum + owner->id) & 3) == 0) {
		CheckForCollision();
	}

	owner->SetVelocity(spd * XZVector);

	const float3 deltaSpeed = wantedSpeed - spd;
	const float deltaDotSpeed = deltaSpeed.dot(spd);
	const float deltaSpeedSq = deltaSpeed.SqLength();

	if (deltaDotSpeed >= 0.0f) {
		// accelerate
		if (deltaSpeedSq < Square(accRate)) {
			owner->SetVelocity(wantedSpeed);
		} else {
			if (deltaSpeedSq > 0.0f) {
				owner->SetVelocity(spd + (deltaSpeed / math::sqrt(deltaSpeedSq) * accRate));
			}
		}
	} else {
		// deccelerate
		if (deltaSpeedSq < Square(decRate)) {
			owner->SetVelocity(wantedSpeed);
		} else {
			if (deltaSpeedSq > 0.0f) {
				owner->SetVelocity(spd + (deltaSpeed / math::sqrt(deltaSpeedSq) * decRate));
			}
		}
	}

	// absolute and relative ground height at (pos.x, pos.z)
	// if this aircraft uses the smoothmesh, these values are
	// calculated with respect to that (for changing vertical
	// speed, but not for ground collision)
	float curAbsHeight = owner->unitDef->canSubmerge?
		ground->GetHeightReal(pos.x, pos.z):
		ground->GetHeightAboveWater(pos.x, pos.z);
	float curRelHeight = 0.0f;

	float wh = wantedHeight; // wanted RELATIVE height (altitude)
	float ws = 0.0f;         // wanted vertical speed

	// always stay above the actual terrain (therefore either the value of
	// <midPos.y - radius> or pos.y must never become smaller than the real
	// ground height)
	// note: unlike StrafeAirMoveType, UpdateTakeoff and UpdateLanding call
	// UpdateAirPhysics() so we ignore terrain while we are in those states
	if (modInfo.allowAircraftToHitGround) {
		const bool groundContact = (curAbsHeight > (owner->midPos.y - owner->radius));
		const bool handleContact = (aircraftState != AIRCRAFT_LANDED && aircraftState != AIRCRAFT_TAKEOFF && padStatus == PAD_STATUS_FLYING);

		if (groundContact && handleContact) {
			owner->Move(UpVector * (curAbsHeight - (owner->midPos.y - owner->radius) + 0.01f), true);
		}
	}

	if (UseSmoothMesh()) {
		curAbsHeight = owner->unitDef->canSubmerge?
			smoothGround->GetHeight(pos.x, pos.z):
			smoothGround->GetHeightAboveWater(pos.x, pos.z);
	}

	// restore original vertical speed
	owner->SetVelocity((spd * XZVector) + (UpVector * yspeed));

	if (lastColWarningType == 2) {
		const float3 dir = lastColWarning->midPos - owner->midPos;
		const float3 sdir = lastColWarning->speed - spd;

		if (spd.dot(dir + sdir * 20.0f) < 0.0f) {
			if (lastColWarning->midPos.y > owner->pos.y) {
				wh -= 30.0f;
			} else {
				wh += 50.0f;
			}
		}
	}

	curRelHeight = pos.y - curAbsHeight;

	if (curRelHeight < wh) {
		ws = altitudeRate;

		if ((spd.y > 0.0001f) && (((wh - curRelHeight) / spd.y) * accRate * 1.5f) < spd.y) {
			ws = 0.0f;
		}
	} else {
		ws = -altitudeRate;

		if ((spd.y < -0.0001f) && (((wh - curRelHeight) / spd.y) * accRate * 0.7f) < -spd.y) {
			ws = 0.0f;
		}
	}

	if (!owner->beingBuilt) {
		if (math::fabs(wh - curRelHeight) > 2.0f) {
			if (spd.y > ws) {
				owner->SetVelocity((spd * XZVector) + (UpVector * std::max(ws, spd.y - accRate * 1.5f)));
			} else {
				// accelerate upward faster if close to ground
				owner->SetVelocity((spd * XZVector) + (UpVector * std::min(ws, spd.y + accRate * ((curRelHeight < 20.0f)? 2.0f: 0.7f))));
			}
		} else {
			owner->SetVelocity((spd * XZVector) + (UpVector * spd.y * 0.95f));
		}
	}

	owner->SetSpeed(spd);

	if (modInfo.allowAircraftToLeaveMap || (pos + spd).IsInBounds()) {
		owner->Move(spd, true);
	}
}
Beispiel #18
0
/* Function: modEuler
 * Description: Modified Euler Integrator using Implicit and Explicit
 *				vi(t + h) = vi(t) + (ALPHA / h) * (gi(t) - xi(t)) + (h / mi) * Fext(t) 
 *				xi(t + h) = xi(t) + h * vi(t + h)
 * Input: None
 * Output: None
 */
void ModEuler(phyzx *phyzxObj, int mIndex, int deformMode)
{
	point vertex, velocity, extVel, position, velDamp;
	point vDiff, velTotal, newPos, temp;
	matrix R, matTemp;

	memset( (void*)&temp, 0, sizeof(temp));
	memset((void*)&extVel, 0, sizeof(point));
	memset((void*)&velocity, 0, sizeof(point));
	memset((void*)&position, 0, sizeof(point));
	memset((void*)&vDiff, 0, sizeof(point));
	memset((void*)&velTotal, 0, sizeof(point));
	memset((void*)&newPos, 0, sizeof(point));
	memset((void*)&phyzxObj->avgVel, 0, sizeof(point));

	matInit(&R, 0, 0);
	matInit(&matTemp, 0, 0);

	if (deformMode == 3)
		quadDeformRot(&R, phyzxObj);

	for (unsigned int index = STARTFROM; index <= phyzxObj->model->numvertices; index++)
	{
		if (deformMode == 3)
		{
			// Compute Quadratic Deformation Goal Positions
			matMult(R, phyzxObj->q[index], &matTemp);						// R(q)
			temp = matToPoint(matTemp);										// Data type conversion
			pSUM(temp, phyzxObj->cmDeformed, phyzxObj->goal[index]);		// g = R(q) + xcm
		} //end if
		else
		{
			// Compute Goal Positions
			matMult3331(phyzxObj->R, phyzxObj->relStableLoc[index], &temp);				// R(xi0 - xcm0)
			pSUM(temp, phyzxObj->cmDeformed, phyzxObj->goal[index]);					// g = R(xi0 - xcm0) + xcm
		} //end if

		vertex.x = phyzxObj->model->vertices[3*index];
		vertex.y = phyzxObj->model->vertices[3*index + 1];
		vertex.z = phyzxObj->model->vertices[3*index + 2];\

		if (stickyFloor == 1)
			if (vertex.y <= -WALLDIST)
				continue;

		// Add user force
		if (mIndex == iMouseModel && lMouseVal == 2 && objectName != -1)// && index == objectName)
		{
			//point uForce;
			/*GLMnode *node;
			node = NBVStruct[objectName];

			while (node->next != NULL)
			{
				pSUM(phyzxObj->extForce[node->index], userForce, phyzxObj->extForce[node->index]);
				node = node->next;
			} //end while*/
			/*if (index != objectName)
			{
				point extPos = vMake(phyzxObj->model->vertices[3*objectName], phyzxObj->model->vertices[3*objectName+1], phyzxObj->model->vertices[3*objectName+2]);
				double dist = vecLeng(extPos, vertex);
				//if (dist > 0.04)
				//{
					pMULTIPLY(userForce, (1.0/dist), uForce);
					pSUM(phyzxObj->extForce[index], uForce, phyzxObj->extForce[index]);
					//pDisp("user", userForce);
				//} //end if
				//else
				//{
					//pSUM(phyzxObj->extForce[index], userForce, phyzxObj->extForce[index]);
				//} //end else
			} //end if
			else
			{*/
				pSUM(phyzxObj->extForce[index], userForce, phyzxObj->extForce[index]);
			//} //end else
		} //end if

		// Explicit Euler Integrator for veloctiy -> vi(t + h)
		pDIFFERENCE(phyzxObj->goal[index], vertex, vDiff);												// gi(t) - xi(t)
		pMULTIPLY(vDiff, (phyzxObj->alpha / phyzxObj->h), velocity);									// vi(h) = (ALPHA / h) * (gi(t) - xi(t))
		pMULTIPLY(phyzxObj->extForce[index], (phyzxObj->h / phyzxObj->mass[index]), extVel);			// (h / mi) * Fext(t)
//		pMULTIPLY(phyzxObj->extForce[index], phyzxObj->h, extVel);			// (h / mi) * Fext(t)
		pSUM(velocity, extVel, velTotal);																// vi(h) = (ALPHA / h) * (gi(t) - xi(t)) + (h / mi) * Fext(t) 

		pSUM(phyzxObj->velocity[index], velTotal, phyzxObj->velocity[index]);							// vi(t + h) = vi(t) + vi(h)
		
		// Velocity Damping
		pMULTIPLY(phyzxObj->velocity[index], -phyzxObj->delta, velDamp);
		pSUM(phyzxObj->velocity[index], velDamp, phyzxObj->velocity[index]);

		// Implicity Euler Integrator for position
		pMULTIPLY(phyzxObj->velocity[index], phyzxObj->h, position);									// xi(h) = h * vi(t + h)
		pSUM(vertex, position, newPos);																// xi(t + h) = xi(t) + xi(h)

		// Store new position into data structure
		phyzxObj->model->vertices[3*index] = newPos.x;
		phyzxObj->model->vertices[3*index + 1] = newPos.y;
		phyzxObj->model->vertices[3*index + 2] = newPos.z;

		pSUM(phyzxObj->avgVel, phyzxObj->velocity[index], phyzxObj->avgVel);

		//if (objCollide)
			CheckForCollision(index, phyzxObj, mIndex);
	} //end for

	pMULTIPLY(phyzxObj->avgVel, 1.0 / phyzxObj->model->numvertices, phyzxObj->avgVel);

	delete[] R.data;
	delete[] matTemp.data;
} //end ModEuler()
Beispiel #19
0
void CHoverAirMoveType::UpdateAirPhysics()
{
	const float3& pos = owner->pos;
	      float3& speed = owner->speed;

	if (!((gs->frameNum + owner->id) & 3)) {
		CheckForCollision();
	}

	const float yspeed = speed.y; speed.y = 0.0f;

	const float3 deltaSpeed = wantedSpeed - speed;
	const float deltaDotSpeed = (speed != ZeroVector)? deltaSpeed.dot(speed): 1.0f;

	if (deltaDotSpeed == 0.0f) {
		// we have the wanted speed
	} else if (deltaDotSpeed > 0.0f) {
		// accelerate
		const float sqdl = deltaSpeed.SqLength();

		if (sqdl < Square(accRate)) {
			speed = wantedSpeed;
		} else {
			speed += (deltaSpeed / math::sqrt(sqdl) * accRate);
		}
	} else {
		// break
		const float sqdl = deltaSpeed.SqLength();

		if (sqdl < Square(decRate)) {
			speed = wantedSpeed;
		} else {
			speed += (deltaSpeed / math::sqrt(sqdl) * decRate);
		}
	}

	// absolute and relative ground height at (pos.x, pos.z)
	// if this aircraft uses the smoothmes, these values are
	// calculated with respect to that for changing vertical
	// speed, but not for ground collision
	float curAbsHeight = owner->unitDef->canSubmerge?
		ground->GetHeightReal(pos.x, pos.z):
		ground->GetHeightAboveWater(pos.x, pos.z);
	float curRelHeight = 0.0f;

	float wh = wantedHeight; // wanted RELATIVE height (altitude)
	float ws = 0.0f;         // wanted vertical speed

	// always stay above the actual terrain (therefore either the value of
	// <midPos.y - radius> or pos.y must never become smaller than the real
	// ground height)
	// note: unlike StrafeAirMoveType, UpdateTakeoff calls UpdateAirPhysics
	// so we ignore terrain while we are in the takeoff state to avoid jumps
	if (modInfo.allowAircraftToHitGround) {
		const bool groundContact = (curAbsHeight > (owner->midPos.y - owner->radius));
		const bool handleContact = (aircraftState != AIRCRAFT_LANDED && aircraftState != AIRCRAFT_TAKEOFF);

		if (groundContact && handleContact) {
			owner->Move1D(curAbsHeight - (owner->midPos.y - owner->radius) + 0.01f, 1, true);
		}
	}

	if (UseSmoothMesh()) {
		curAbsHeight = owner->unitDef->canSubmerge?
			smoothGround->GetHeight(pos.x, pos.z):
			smoothGround->GetHeightAboveWater(pos.x, pos.z);
	}

	speed.y = yspeed;
	curRelHeight = pos.y - curAbsHeight;

	if (lastColWarningType == 2) {
		const float3 dir = lastColWarning->midPos - owner->midPos;
		const float3 sdir = lastColWarning->speed - speed;

		if (speed.dot(dir + sdir * 20.0f) < 0.0f) {
			if (lastColWarning->midPos.y > owner->pos.y) {
				wh -= 30.0f;
			} else {
				wh += 50.0f;
			}
		}
	}



	if (curRelHeight < wh) {
		ws = altitudeRate;

		if ((speed.y > 0.0001f) && (((wh - curRelHeight) / speed.y) * accRate * 1.5f) < speed.y) {
			ws = 0.0f;
		}
	} else {
		ws = -altitudeRate;

		if ((speed.y < -0.0001f) && (((wh - curRelHeight) / speed.y) * accRate * 0.7f) < -speed.y) {
			ws = 0.0f;
		}
	}

	if (!owner->beingBuilt) {
		if (math::fabs(wh - curRelHeight) > 2.0f) {
			if (speed.y > ws) {
				speed.y = std::max(ws, speed.y - accRate * 1.5f);
			} else {
				// accelerate upward faster if close to ground
				speed.y = std::min(ws, speed.y + accRate * ((curRelHeight < 20.0f)? 2.0f: 0.7f));
			}
		} else {
			speed.y *= 0.95;
		}
	}


	if (modInfo.allowAircraftToLeaveMap || (pos + speed).IsInBounds()) {
		owner->Move3D(speed, true);
	}
}
Beispiel #20
0
void CAirMoveType::UpdateFlying(float wantedHeight, float engine)
{
	float3& pos = owner->pos;
	SyncedFloat3& rightdir = owner->rightdir;
	SyncedFloat3& frontdir = owner->frontdir;
	SyncedFloat3& updir = owner->updir;
	float3& speed = owner->speed;

	float speedf = speed.Length();
	float3 goalDir = (goalPos - pos);
	float goalLength = std::max(0.001f, goalDir.Length2D());
	goalDir /= goalLength;

	float3 adjustedGoalDir = float3(goalPos.x, 0, goalPos.z) - float3(pos.x, 0, pos.z);
	adjustedGoalDir.SafeANormalize();

	float aileron = 0.0f;
	float rudder = 0.0f;
	float elevator = 0.0f;
	// do not check if the plane can be submerged here, since it'll cause
	// ground collisions later on
	float gHeight = ground->GetHeight(pos.x, pos.z);

	if (!((gs->frameNum + owner->id) & 3))
		CheckForCollision();

	float otherThreat = 0.0f;
	float3 otherDir;
	if (lastColWarning) {
		float3 otherDif = lastColWarning->pos - pos;
		float otherLength = otherDif.Length();

		otherDir =
			(otherLength > 0.0f)?
			(otherDif / otherLength):
			ZeroVector;
		otherThreat =
			(otherLength > 0.0f)?
			std::max(1200.0f, goalLength) / otherLength * 0.036f:
			0.0f;
	}

	float goalDotRight = rightdir.dot(adjustedGoalDir);
	float goalDotFront = adjustedGoalDir.dot(frontdir) * 0.5f + 0.501f;

	if (goalDotFront > 0.01f) {
		goalDotRight /= goalDotFront;
	}


	if (adjustedGoalDir.dot(frontdir) < -0.1f && goalLength < turnRadius && (!owner->directControl || owner->directControl->mouse2))
		goalDotRight = -goalDotRight;
	if (lastColWarning) {
		goalDotRight -= otherDir.dot(rightdir) * otherThreat;
	}

	// roll
	if (speedf > 1.5f && pos.y + speed.y * 10 > gHeight + wantedHeight * 0.6f) {
		float goalBankDif = goalDotRight + rightdir.y * 0.5f;
		if (goalBankDif > maxAileron*speedf * 4 && rightdir.y > -maxBank) {
			aileron = 1;
		} else if (goalBankDif < -maxAileron * speedf * 4 && rightdir.y < maxBank) {
			aileron = -1;
		} else {
			if (fabs(rightdir.y) < maxBank) {
				aileron = goalBankDif / (maxAileron * speedf * 4);
			} else {
				if (rightdir.y < 0.0f && goalBankDif < 0.0f) {
					aileron = -1;
				} else if (rightdir.y > 0.0f && goalBankDif > 0.0f) {
					aileron = 1;
				}
			}
		}
	} else {
		if (rightdir.y > 0.01f) {
			aileron = 1;
		} else if (rightdir.y < -0.01f) {
			aileron = -1;
		}
	}

	// yaw
	if (pos.y > gHeight + 15) {
		if (goalDotRight < -maxRudder * speedf * 2) {
			rudder = -1;
		} else if (goalDotRight > maxRudder * speedf * 2) {
			rudder = 1;
		} else {
			if (speedf > 0.0f && maxRudder > 0.0f) {
				rudder = goalDotRight / (maxRudder * speedf * 2);
			} else {
				rudder = 0;
			}
		}
	}

	// pitch
	if (speedf > 0.8f) {
		bool notColliding = true;
		if (lastColWarningType == 2) {
			const float3 dir = lastColWarning->midPos - owner->midPos;
			const float3 sdir = lastColWarning->speed - owner->speed;
			if (frontdir.dot(dir + sdir * 20) < 0) {
				elevator = updir.dot(dir) > 0 ? -1 : 1;
				notColliding = false;
			}
		}
		if (notColliding) {
			float gHeight2 = ground->GetHeight(pos.x + speed.x * 40, pos.z + speed.z * 40);
			float hdif = std::max(gHeight, gHeight2) + wantedHeight - pos.y - frontdir.y * speedf * 20;
			if (hdif < -(maxElevator * speedf * speedf * 20) && frontdir.y > -maxPitch) {
				elevator = -1;
			} else if (hdif > (maxElevator * speedf * speedf * 20) && frontdir.y < maxPitch) {
				elevator = 1;
			} else {
				if (fabs(frontdir.y) < maxPitch)
					elevator = hdif / (maxElevator * speedf * speedf * 20);
			}
		}
	}
	else {
		if (frontdir.y < -0.1f) {
			elevator = 1;
		} else if (frontdir.y > 0.15f) {
			elevator = -1;
		}
	}

	UpdateAirPhysics(rudder, aileron, elevator, engine, owner->frontdir);
}
Beispiel #21
0
void CTAAirMoveType::UpdateAirPhysics()
{
    float3& pos = owner->pos;
    float3& speed = owner->speed;

    if (!((gs->frameNum + owner->id) & 3)) {
        CheckForCollision();
    }

    const float yspeed = speed.y;
    speed.y = 0.0f;

    float3 delta = wantedSpeed - speed;
    const float deltaDotSpeed = (speed != ZeroVector)? delta.dot(speed): 1.0f;

    if (deltaDotSpeed == 0.0f) {
        // we have the wanted speed
    } else if (deltaDotSpeed > 0.0f) {
        // accelerate
        const float sqdl = delta.SqLength();
        if (sqdl < Square(accRate)) {
            speed = wantedSpeed;
        } else {
            speed += delta / math::sqrt(sqdl) * accRate;
        }
    } else {
        // break
        const float sqdl = delta.SqLength();
        if (sqdl < Square(decRate)) {
            speed = wantedSpeed;
        } else {
            speed += delta / math::sqrt(sqdl) * decRate;
        }
    }

    speed.y = yspeed;
    float h;

    if (UseSmoothMesh()) {
        h = pos.y - std::max(
                smoothGround->GetHeightAboveWater(pos.x, pos.z),
                smoothGround->GetHeightAboveWater(pos.x + speed.x * 20.0f, pos.z + speed.z * 20.0f));
    } else {
        h = pos.y - std::max(
                ground->GetHeightAboveWater(pos.x, pos.z),
                ground->GetHeightAboveWater(pos.x + speed.x * 40.0f, pos.z + speed.z * 40.0f));
    }

    if (h < 4.0f) {
        speed.x *= 0.95f;
        speed.z *= 0.95f;
    }

    float wh = wantedHeight;

    if (lastColWarningType == 2) {
        const float3 dir = lastColWarning->midPos - owner->midPos;
        const float3 sdir = lastColWarning->speed - speed;

        if (speed.dot(dir + sdir * 20.0f) < 0.0f) {
            if (lastColWarning->midPos.y > owner->pos.y) {
                wh -= 30.0f;
            } else {
                wh += 50.0f;
            }
        }
    }


    float ws = 0.0f;

    if (h < wh) {
        ws = altitudeRate;
        if (speed.y > 0.0001f && (wh - h) / speed.y * accRate * 1.5f < speed.y) {
            ws = 0.0f;
        }
    } else {
        ws = -altitudeRate;
        if (speed.y < -0.0001f && (wh - h) / speed.y * accRate * 0.7f < -speed.y) {
            ws = 0.0f;
        }
    }

    if (fabs(wh - h) > 2.0f) {
        if (speed.y > ws) {
            speed.y = std::max(ws, speed.y - accRate * 1.5f);
        } else if (!owner->beingBuilt) {
            // let them accelerate upward faster if close to ground
            speed.y = std::min(ws, speed.y + accRate * (h < 20.0f? 2.0f: 0.7f));
        }
    } else {
        speed.y = speed.y * 0.95;
    }

    if (modInfo.allowAirPlanesToLeaveMap || (pos+speed).CheckInBounds()) {
        pos += speed;
    }
}
void CHoverAirMoveType::UpdateAirPhysics()
{
	const float3& pos = owner->pos;
	      float3& speed = owner->speed;

	if (!((gs->frameNum + owner->id) & 3)) {
		CheckForCollision();
	}

	const float yspeed = speed.y; speed.y = 0.0f;

	const float3 deltaSpeed = wantedSpeed - speed;
	const float deltaDotSpeed = (speed != ZeroVector)? deltaSpeed.dot(speed): 1.0f;

	if (deltaDotSpeed == 0.0f) {
		// we have the wanted speed
	} else if (deltaDotSpeed > 0.0f) {
		// accelerate
		const float sqdl = deltaSpeed.SqLength();

		if (sqdl < Square(accRate)) {
			speed = wantedSpeed;
		} else {
			speed += (deltaSpeed / math::sqrt(sqdl) * accRate);
		}
	} else {
		// break
		const float sqdl = deltaSpeed.SqLength();

		if (sqdl < Square(decRate)) {
			speed = wantedSpeed;
		} else {
			speed += (deltaSpeed / math::sqrt(sqdl) * decRate);
		}
	}

	float minHeight = 0.0f;  // absolute ground height at (pos.x, pos.z)
	float curHeight = 0.0f;  // relative ground height at (pos.x, pos.z) == pos.y - minHeight (altitude)

	float wh = wantedHeight; // wanted RELATIVE height (altitude)
	float ws = 0.0f;         // wanted vertical speed

	if (UseSmoothMesh()) {
		minHeight = owner->unitDef->canSubmerge?
			smoothGround->GetHeight(pos.x, pos.z):
			smoothGround->GetHeightAboveWater(pos.x, pos.z);
	} else {
		minHeight = owner->unitDef->canSubmerge?
			ground->GetHeightReal(pos.x, pos.z):
			ground->GetHeightAboveWater(pos.x, pos.z);
	}

	// [?] aircraft should never be able to end up below terrain
	// if (pos.y < minHeight)
	//     owner->Move1D(std::min(minHeight - pos.y, altitudeRate), 1, true);

	speed.y = yspeed;
	curHeight = pos.y - minHeight;

	if (curHeight < 4.0f) {
		speed.x *= 0.95f;
		speed.z *= 0.95f;
	}

	if (lastColWarningType == 2) {
		const float3 dir = lastColWarning->midPos - owner->midPos;
		const float3 sdir = lastColWarning->speed - speed;

		if (speed.dot(dir + sdir * 20.0f) < 0.0f) {
			if (lastColWarning->midPos.y > owner->pos.y) {
				wh -= 30.0f;
			} else {
				wh += 50.0f;
			}
		}
	}



	if (curHeight < wh) {
		ws = altitudeRate;

		if ((speed.y > 0.0001f) && (((wh - curHeight) / speed.y) * accRate * 1.5f) < speed.y) {
			ws = 0.0f;
		}
	} else {
		ws = -altitudeRate;

		if ((speed.y < -0.0001f) && (((wh - curHeight) / speed.y) * accRate * 0.7f) < -speed.y) {
			ws = 0.0f;
		}
	}

	if (!owner->beingBuilt) {
		if (math::fabs(wh - curHeight) > 2.0f) {
			if (speed.y > ws) {
				speed.y = std::max(ws, speed.y - accRate * 1.5f);
			} else {
				// accelerate upward faster if close to ground
				speed.y = std::min(ws, speed.y + accRate * ((curHeight < 20.0f)? 2.0f: 0.7f));
			}
		} else {
			speed.y *= 0.95;
		}
	}


	if (modInfo.allowAircraftToLeaveMap || (pos + speed).IsInBounds()) {
		owner->Move3D(speed, true);
	}
}