Example #1
0
CSmokeTrailProjectile::CSmokeTrailProjectile(
	const float3& pos1,
	const float3& pos2,
	const float3& dir1,
	const float3& dir2,
	CUnit* owner,
	bool firstSegment,
	bool lastSegment,
	float size,
	int time,
	float color,
	bool drawTrail,
	CProjectile* drawCallback,
	AtlasedTexture* texture):

	CProjectile((pos1 + pos2) * 0.5f, ZeroVector, owner, false, false, false),
	pos1(pos1),
	pos2(pos2),
	orgSize(size),
	creationTime(gs->frameNum),
	lifeTime(time),
	color(color),
	dir1(dir1),
	dir2(dir2),
	drawTrail(drawTrail),
	drawSegmented(false),
	firstSegment(firstSegment),
	lastSegment(lastSegment),
	drawCallbacker(drawCallback),
	texture(texture)
{
	checkCol = false;
	castShadow = true;

	// if no custom texture is defined, use the default texture
	// Note that this will crash anyway (no idea why) so never have a null texture!
	if (texture == NULL) {
		texture = projectileDrawer->smoketrailtex;
	}

	if (!drawTrail) {
		const float dist = pos1.distance(pos2);
		dirpos1 = pos1 - dir1 * dist * 0.33f;
		dirpos2 = pos2 + dir2 * dist * 0.33f;
	} else if (dir1.dot(dir2) < 0.98f) {
		const float dist = pos1.distance(pos2);
		dirpos1 = pos1 - dir1 * dist * 0.33f;
		dirpos2 = pos2 + dir2 * dist * 0.33f;
//		float3 mp = (pos1 + pos2) / 2;
		midpos = CalcBeizer(0.5f, pos1, dirpos1, dirpos2, pos2);
		middir = (dir1 + dir2).ANormalize();
		drawSegmented = true;
	}
	SetRadiusAndHeight(pos1.distance(pos2), 0.0f);

	if ((pos.y - ground->GetApproximateHeight(pos.x, pos.z)) > 10) {
		useAirLos = true;
	}
}
Example #2
0
CSmokeTrailProjectile::CSmokeTrailProjectile(
	CUnit* owner,
	const float3& pos1,
	const float3& pos2,
	const float3& dir1,
	const float3& dir2,
	bool firstSegment,
	bool lastSegment,
	float size,
	int time,
	float color,
	bool drawTrail,
	CProjectile* drawCallback,
	AtlasedTexture* texture
):
	CProjectile((pos1 + pos2) * 0.5f, ZeroVector, owner, false, false, false),

	pos1(pos1),
	pos2(pos2),
	orgSize(size),
	creationTime(gs->frameNum),
	lifeTime(time),
	color(color),
	dir1(dir1),
	dir2(dir2),
	drawTrail(drawTrail),
	drawSegmented(false),
	firstSegment(firstSegment),
	lastSegment(lastSegment),
	drawCallbacker(drawCallback),
	texture(texture == NULL ? projectileDrawer->smoketrailtex : texture)
{
	checkCol = false;
	castShadow = true;

	if (!drawTrail) {
		const float dist = pos1.distance(pos2);
		dirpos1 = pos1 - dir1 * dist * 0.33f;
		dirpos2 = pos2 + dir2 * dist * 0.33f;
	} else if (dir1.dot(dir2) < 0.98f) {
		const float dist = pos1.distance(pos2);
		dirpos1 = pos1 - dir1 * dist * 0.33f;
		dirpos2 = pos2 + dir2 * dist * 0.33f;
//		float3 mp = (pos1 + pos2) / 2;
		midpos = CalcBeizer(0.5f, pos1, dirpos1, dirpos2, pos2);
		middir = (dir1 + dir2).ANormalize();
		drawSegmented = true;
	}
	SetRadiusAndHeight(pos1.distance(pos2), 0.0f);

	if ((pos.y - CGround::GetApproximateHeight(pos.x, pos.z)) > 10) {
		useAirLos = true;
	}
}
void CSound::PlaySample(size_t id, const float3& p, const float3& velocity, float volume, bool relative)
{
	boost::mutex::scoped_lock lck(soundMutex);

	if (sources.empty() || volume == 0.0f)
		return;

	if (id == 0)
	{
		numEmptyPlayRequests++;
		return;
	}

	if (p.distance(myPos) > sounds[id].MaxDistance())
	{
		if (!relative)
			return;
		else
			LogObject(LOG_SOUND) << "CSound::PlaySample: maxdist ignored for relative payback: " << sounds[id].Name();
	}

	SoundSource* best = GetNextBestSource(false);
	if (!best->IsPlaying() || (best->GetCurrentPriority() <= 0 && best->GetCurrentPriority() < sounds[id].GetPriority()))
		best->Play(&sounds[id], p, velocity, volume, relative);
	CheckError("CSound::PlaySample");
}
Example #4
0
int cCombatManager::GetClosestEnemy(float3 Pos, UnitInfo* U)
{
	U->enemyID=-1;
	// these two function need improvement, for now I'll just use a short cut
	if( !G->UM->ActiveAttackOrders() && U->udrBL->task != TASK_SUICIDE )
		return GetClosestThreat(Pos, U);
	sWeaponEfficiency* weTemp;
	float distance,fTemp;
	float3 fE;
	for( map<int,EnemyInfo>::iterator E=G->Enemies.begin(); E!=G->Enemies.end(); E++ )
	{
		fE=GetEnemyPosition(E->first,&E->second);
		if( (weTemp = CanAttack(U,&E->second,fE)) != 0 )
		{
			fTemp=Pos.distance(fE);
			if( U->enemyID == -1 || fTemp < distance )
			{
				U->enemyID=E->first;
				U->E = &E->second;
				U->enemyEff = weTemp;
				distance=fTemp;
			}
		}
	}
	if( U->enemyID != -1 && U->group != 0 )
		G->UM->GroupAddEnemy(U->enemyID,U->E,U->group);
	return U->enemyID;
}
CLightingProjectile::CLightingProjectile(const float3& pos,const float3& end,CUnit* owner,const float3& color, WeaponDef *weaponDef,int ttl,CWeapon* weap)
:	CWeaponProjectile(pos,ZeroVector, owner, 0, ZeroVector, weaponDef,0), //CProjectile(pos,ZeroVector,owner),
	ttl(ttl),
	color(color),
	endPos(end),
	weapon(weap)
{
	checkCol=false;
	drawRadius=pos.distance(endPos);

	displacements[0]=0;
	for(int a=1;a<10;++a)
		displacements[a]=(gs->randFloat()-0.5f)*drawRadius*0.05f;

	displacements2[0]=0;
	for(int a=1;a<10;++a)
		displacements2[a]=(gs->randFloat()-0.5f)*drawRadius*0.05f;

	if(weapon)
		AddDeathDependence(weapon);

#ifdef TRACE_SYNC
	tracefile << "New lighting: ";
	tracefile << pos.x << " " << pos.y << " " << pos.z << " " << end.x << " " << end.y << " " << end.z << "\n";
#endif
}
bool CTransportCAI::FindEmptyDropSpots(float3 startpos, float3 endpos, std::list<float3>& dropSpots) {
	//should only be used by air

	CTransportUnit* transport=(CTransportUnit*)owner;
	//dropSpots.clear();
	float gap = 25.5; //TODO - set tag for this?
	float3 dir = endpos - startpos;
	dir.Normalize();

	float3 nextPos = startpos;
	float3 pos;

	list<CTransportUnit::TransportedUnit>::iterator ti = transport->transported.begin();
	dropSpots.push_front(nextPos);

	//first spot
	if (ti!=transport->transported.end()) {
		//float3 p = nextPos; //test to make intended land spots visible
		//inMapDrawer->CreatePoint(p,ti->unit->unitDef->name);
		//p.z +=transport->transportCapacityUsed*5;
		nextPos += dir*(gap + ti->unit->radius);
		ti++;
	}

	//remaining spots
	if (dynamic_cast<CTAAirMoveType*>(owner->moveType)) {
		while (ti != transport->transported.end() && startpos.distance(nextPos) < startpos.distance(endpos)) {
			nextPos += dir*(ti->unit->radius);
			nextPos.y = ground->GetHeight(nextPos.x, nextPos.z);

			//check landing spot is ok for landing on
			if (!SpotIsClear(nextPos,ti->unit))
				continue;

			dropSpots.push_front(nextPos);
			//float3 p = nextPos; //test to make intended land spots visible
			//inMapDrawer->CreatePoint(p,ti->unit->unitDef->name);
			//p.z +=transport->transportCapacityUsed*5;
			nextPos += dir*(gap + ti->unit->radius);
			ti++;
		}
		return true;
	}
	return false;
}
CMissileProjectile::CMissileProjectile(const float3& pos,const float3& speed,CUnit* owner,const DamageArray& damages,float areaOfEffect,float maxSpeed, int ttl,CUnit* target, WeaponDef *weaponDef,float3 targetPos)
: CWeaponProjectile(pos,speed,owner,target,ZeroVector,weaponDef,0),
	damages(damages),
	ttl(ttl),
	maxSpeed(maxSpeed),
	target(target),
	dir(speed),
	oldSmoke(pos),
	age(0),
	drawTrail(true),
	numParts(0),
	areaOfEffect(areaOfEffect),
	decoyTarget(0),
	targPos(targetPos),
	wobbleTime(1),
	wobbleDir(0,0,0),
	wobbleDif(0,0,0),
	isWobbling(weaponDef->wobble>0),
	extraHeightTime(0)
{
	curSpeed=speed.Length();
	dir.Normalize();
	oldDir=dir;
	if(target)
		AddDeathDependence(target);

	SetRadius(0.0);
	if(!weaponDef->visuals.modelName.empty()){
		S3DOModel* model = modelParser->Load3DO(string("objects3d/")+weaponDef->visuals.modelName,1,0);
		if(model){
			SetRadius(model->radius);
		}
	}

	drawRadius=radius+maxSpeed*8;
	ENTER_MIXED;
	float3 camDir=(pos-camera->pos).Normalize();
	if(camera->pos.distance(pos)*0.2+(1-fabs(camDir.dot(dir)))*3000 < 200)
		drawTrail=false;
	ENTER_SYNCED;
	castShadow=true;
#ifdef TRACE_SYNC
	tracefile << "New missile: ";
	tracefile << pos.x << " " << pos.y << " " << pos.z << " " << speed.x << " " << speed.y << " " << speed.z << "\n";
#endif
	if(target)
		target->IncomingMissile(this);

	if(weaponDef->trajectoryHeight>0){
		float dist=pos.distance(targPos);
		extraHeight=dist*weaponDef->trajectoryHeight;
		if(dist<maxSpeed)
			dist=maxSpeed;
		extraHeightTime=(int)(dist/*+pos.distance(targPos+UpVector*dist))*0.5*//maxSpeed);
		extraHeightDecay=extraHeight/extraHeightTime;
	}
}
CSmokeTrailProjectile::CSmokeTrailProjectile(const float3& pos1,const float3& pos2,const float3& dir1,const float3& dir2, CUnit* owner,bool firstSegment,bool lastSegment,float size,float time,float color,bool drawTrail,CProjectile* drawCallback)
: CProjectile((pos1+pos2)*0.5f,ZeroVector,owner, false),
	pos1(pos1),
	pos2(pos2),
	creationTime(gs->frameNum),
	lifeTime((int)time),
	orgSize(size),
	color(color),
	dir1(dir1),
	dir2(dir2),
	drawTrail(drawTrail),
	drawSegmented(false),
	drawCallbacker(drawCallback),
	firstSegment(firstSegment),
	lastSegment(lastSegment)
{
	checkCol=false;
	castShadow=true;

	if(!drawTrail){
		float dist=pos1.distance(pos2);
		dirpos1=pos1-dir1*dist*0.33f;
		dirpos2=pos2+dir2*dist*0.33f;
	} else if(dir1.dot(dir2)<0.98f){
		float dist=pos1.distance(pos2);
		dirpos1=pos1-dir1*dist*0.33f;
		dirpos2=pos2+dir2*dist*0.33f;
		float3 mp=(pos1+pos2)/2;
		midpos=CalcBeizer(0.5f,pos1,dirpos1,dirpos2,pos2);
		middir=(dir1+dir2).Normalize();
		drawSegmented=true;
	}
	SetRadius(pos1.distance(pos2));

	if(pos.y-ground->GetApproximateHeight(pos.x,pos.z)>10)
		useAirLos=true;
}
Example #9
0
void CSound::PlaySample(size_t id, const float3& p, const float3& velocity, float volume, bool relative)
{
	GML_RECMUTEX_LOCK(sound); // PlaySample

	if (sources.empty() || volume == 0.0f)
		return;

	if (id == 0)
	{
		numEmptyPlayRequests++;
		return;
	}

	if (p.distance(myPos) > sounds[id].MaxDistance())
	{
		if (!relative)
			return;
		else
			LogObject(LOG_SOUND) << "CSound::PlaySample: maxdist ignored for relative payback: " << sounds[id].Name();
	}

	bool found1Free = false;
	int minPriority = 1;
	size_t minPos = 0;

	for (size_t pos = 0; pos != sources.size(); ++pos)
	{
		if (!sources[pos].IsPlaying())
		{
			minPos = pos;
			found1Free = true;
			break;
		}
		else
		{
			if (sources[pos].GetCurrentPriority() < minPriority && sources[pos].GetCurrentPriority() <=  sounds[id].GetPriority())
			{
				found1Free = true;
				minPriority = sources[pos].GetCurrentPriority();
				minPos = pos;
			}
		}
	}

	if (found1Free)
		sources[minPos].Play(&sounds[id], p, velocity, volume, relative);
	CheckError("CSound::PlaySample");
}
CGeoSquareProjectile::CGeoSquareProjectile(const float3& p1,const float3& p2,const float3& v1,const float3& v2,float w1,float w2)
: CProjectile((p1+p2)*0.5f,ZeroVector,0, false),
	p1(p1),
	p2(p2),
	v1(v1),
	v2(v2),
	w1(w1),
	w2(w2),
	r(0.5f),
	g(1.0f),
	b(0.5f),
	a(0.5f)
{
	checkCol=false;
	alwaysVisible=true;
	SetRadius(p1.distance(p2)*0.55f);
}
Example #11
0
void AudioChannel::FindSourceAndPlay(size_t id, const float3& pos, const float3& velocity, float volume, bool relative)
{
	if (!enabled)
		return;

	if (volume <= 0.0f)
		return;

	boost::recursive_mutex::scoped_lock slck(soundMutex);

	SoundItem* sndItem = sound->GetSoundItem(id);
	if (!sndItem)
	{
		sound->numEmptyPlayRequests++;
		return;
	}

	if (pos.distance(sound->GetListenerPos()) > sndItem->MaxDistance())
	{
		if (!relative)
			return;
		else
			LogObject(LOG_SOUND) << "CSound::PlaySample: maxdist ignored for relative payback: " << sndItem->Name();
	}

	if (emmitsThisFrame >= emmitsPerFrame)
		return;
	emmitsThisFrame++;
	
	CSoundSource* sndSource = sound->GetNextBestSource();
	if (!sndSource)
		return;

	if (sndSource->GetCurrentPriority() < sndItem->GetPriority())
	{
		if (sndSource->IsPlaying())
			sound->numAbortedPlays++;

		sndSource->Play(this, sndItem, pos, velocity, volume, relative);
		CheckError("CSound::FindSourceAndPlay");

		boost::recursive_mutex::scoped_lock lck(chanMutex);

		cur_sources[sndSource] = true;
	}
}
Example #12
0
int cCombatManager::GetClosestThreat(float3 Pos, UnitInfo* U)
{
    sWeaponEfficiency* weTemp;
    float distance,fTemp;
    distance=0.0f;
    float3 fE;
    set<int> deletion;
    for( map<int,EnemyInfo*>::iterator E=G->EThreat.begin(); E!=G->EThreat.end(); ++E )
    {
        fE=GetEnemyPosition(E->first,E->second);
        if( E->second->baseThreatFrame > cb->GetCurrentFrame()+3600 ||
                (E->second->baseThreatFrame > cb->GetCurrentFrame()+1200 && G->UImmobile.find(E->second->baseThreatID) == G->UImmobile.end() ) ||
                (E->second->ud != 0 && G->UImmobile.find(E->second->baseThreatID) != G->UImmobile.end() && 1.3*E->second->ud->maxWeaponRange < fE.distance(cb->GetUnitPos(E->second->baseThreatID)) ) )
        {
            E->second->baseThreatID = -1;
            E->second->baseThreatFrame = -1;
            deletion.insert(E->first);
        }
        else if( (weTemp = CanAttack(U,E->second,fE)) != 0 )
        {
            fTemp=Pos.distance(fE);
            if( U->enemyID == -1 || fTemp < distance )
            {
                U->enemyID=E->first;
                U->E = E->second;
                U->enemyEff = weTemp;
                distance=fTemp;
            }
        }
    }
    while( int(deletion.size()) > 0 )
    {
        if( !G->UM->ActiveAttackOrders() )
        {
            EnemyInfo* E = G->EThreat.find(*deletion.begin())->second;
            while( int(E->attackGroups.size()) > 0 )
                G->UM->GroupRemoveEnemy(*deletion.begin(),E,*E->attackGroups.begin());
        }
        G->EThreat.erase(*deletion.begin());
        deletion.erase(*deletion.begin());
    }
    if( U->enemyID != -1 && U->group != 0 )
        G->UM->GroupAddEnemy(U->enemyID,U->E,U->group);
    return U->enemyID;
}
CLightningProjectile::CLightningProjectile(
	const float3& pos, const float3& end,
	CUnit* owner,
	const float3& color,
	const WeaponDef* weaponDef,
	int ttl, CWeapon* weap):

	CWeaponProjectile(pos, ZeroVector, owner, 0, ZeroVector, weaponDef, 0, ttl),
	color(color),
	endPos(end),
	weapon(weap)
{
	projectileType = WEAPON_LIGHTNING_PROJECTILE;
	checkCol = false;
	drawRadius = pos.distance(endPos);

	displacements[0]=0;
	for(int a=1;a<10;++a)
		displacements[a]=(gs->randFloat()-0.5f)*drawRadius*0.05f;

	displacements2[0]=0;
	for(int a=1;a<10;++a)
		displacements2[a]=(gs->randFloat()-0.5f)*drawRadius*0.05f;

	if(weapon)
		AddDeathDependence(weapon);

#ifdef TRACE_SYNC
	tracefile << "New lightning: ";
	tracefile << pos.x << " " << pos.y << " " << pos.z << " " << end.x << " " << end.y << " " << end.z << "\n";
#endif

	if (!cegTag.empty()) {
		ceg.Load(explGenHandler, cegTag);
	}
}
CLightningProjectile::CLightningProjectile(
		const float3& pos, const float3& end,
		CUnit* owner,
		const float3& color,
		const WeaponDef* weaponDef,
		int ttl, CWeapon* weap)
	: CWeaponProjectile(pos, ZeroVector, owner, NULL, ZeroVector, weaponDef, NULL, ttl)
	, color(color)
	, endPos(end)
	, weapon(weap)
{
	projectileType = WEAPON_LIGHTNING_PROJECTILE;
	checkCol = false;
	drawRadius = pos.distance(endPos);

	displacements[0] = 0.0f;
	for (size_t d = 1; d < displacements_size; ++d) {
		displacements[d]  = (gs->randFloat() - 0.5f) * drawRadius * 0.05f;
	}

	displacements2[0] = 0.0f;
	for (size_t d = 1; d < displacements_size; ++d) {
		displacements2[d] = (gs->randFloat() - 0.5f) * drawRadius * 0.05f;
	}

	if (weapon) {
		AddDeathDependence(weapon);
	}

#ifdef TRACE_SYNC
	tracefile << "New lightning: ";
	tracefile << pos.x << " " << pos.y << " " << pos.z << " " << end.x << " " << end.y << " " << end.z << "\n";
#endif

	cegID = gCEG->Load(explGenHandler, cegTag);
}
Example #15
0
void AudioChannel::FindSourceAndPlay(size_t id, const float3& pos, const float3& velocity, float volume, bool relative)
{
	std::lock_guard<spring::recursive_mutex> lck(soundMutex);

	if (!enabled)
		return;

	if (volume <= 0.0f)
		return;

	// generate the sound item
	SoundItem* sndItem = sound->GetSoundItem(id);

	if (sndItem == nullptr) {
		sound->numEmptyPlayRequests++;
		return;
	}

	// check distance to listener
	if (pos.distance(sound->GetListenerPos()) > sndItem->MaxDistance()) {
		if (!relative)
			return;

		LOG("CSound::PlaySample: maxdist ignored for relative playback: %s", sndItem->Name().c_str());
	}

	// don't spam to many sounds per frame
	if (emitsThisFrame >= emitsPerFrame)
		return;
	emitsThisFrame++;

	// check if the sound item is already played
	if (curSources.size() >= maxConcurrentSources) {
		CSoundSource* src = nullptr;

		int prio = INT_MAX;

		for (auto it = curSources.begin(); it != curSources.end(); ++it) {
			if ((*it)->GetCurrentPriority() < prio) {
				src  = *it;
				prio = src->GetCurrentPriority();
			}
		}

		if (src == nullptr || prio > sndItem->GetPriority()) {
			LOG_L(L_DEBUG, "CSound::PlaySample: Max concurrent sounds in channel reached! Dropping playback!");
			return;
		}

		src->Stop();
	}

	// find a sound source to play the item in
	CSoundSource* sndSource = sound->GetNextBestSource();

	if (sndSource == nullptr || (sndSource->GetCurrentPriority() >= sndItem->GetPriority())) {
		LOG_L(L_DEBUG, "CSound::PlaySample: Max sounds reached! Dropping playback!");
		return;
	}
	if (sndSource->IsPlaying())
		sound->numAbortedPlays++;

	// play the sound item
	sndSource->PlayAsync(this, sndItem, pos, velocity, volume, relative);
	curSources.insert(sndSource);
}
// problems: giving reclaim order on moving target causes commander
// to walk (messing up subsequent dgun order if target still moving)
// and does not take commander torso rotation time into account
//
void CDGunController::TrackAttackTarget(unsigned int currentFrame) {
	if (currentFrame - state.targetSelectionFrame == 5) {
		// five sim-frames have passed since selecting target, attack
		const UnitDef* udef = ai->cb->GetUnitDef(state.targetID);

		const float3 curTargetPos = ai->cb->GetUnitPos(state.targetID);              // current target position
		const float3 commanderPos = ai->cb->GetUnitPos(commanderID);                 // current commander position

		const float3 targetDif    = (commanderPos - curTargetPos);
		const float  targetDist   = targetDif.Length();                              // distance to target
		const float3 targetVel    = (curTargetPos - state.oldTargetPos);

		float3 targetMoveDir   = targetVel;
		float  targetMoveSpeed = 0.0f;

		if (targetVel != ZeroVector) {
			targetMoveSpeed = targetVel.Length() / 5.0f;                             // target speed per sim-frame during tracking interval
			targetMoveDir   = targetVel / (targetMoveSpeed * 5.0f);                  // target direction of movement
		}

		const float  dgunDelay    = targetDist / commanderWD->projectilespeed;       // sim-frames needed for dgun to reach target position
		const float3 leadPos      = targetMoveDir * (targetMoveSpeed * dgunDelay);
		const float3 dgunPos      = curTargetPos + leadPos;                          // position where target will be in <dgunDelay> frames
		const float  maxRange     = ai->cb->GetUnitMaxRange(commanderID);

		bool haveClearShot = true;
		int orderType = -1;

		AIHCTraceRay rayData = {
			commanderPos,
			targetDif / targetDist, // direction
			maxRange,
			commanderID,
			-1,
			0
		};

		ai->cb->HandleCommand(AIHCTraceRayId, &rayData);

		if (rayData.hitUID != -1) {
			// note: still fails when allied structure is between us and enemy
			// can also fail if enemy is in front of allied structure and both
			// are within the d-gun's range
			haveClearShot = (ai->cb->GetUnitAllyTeam(rayData.hitUID) != ai->cb->GetMyAllyTeam());

			// TODO: get DGun weapon properties & check if it can pass through
			// a unit, if yes then allow executing the code below
			if(haveClearShot) {
				// check if there is a unit next to hit unit on DGun path...
				const float3 enemyPos = ai->cb->GetUnitPos(rayData.hitUID);
				const float segmentLeft = maxRange - commanderPos.distance(enemyPos);

				if(segmentLeft > 0.0) {
					AIHCTraceRay rayData2 = {
						enemyPos,
						targetDif / targetDist,
						segmentLeft,
						rayData.hitUID,
						-1,
						0
					};

					ai->cb->HandleCommand(AIHCTraceRayId, &rayData2);

					if(rayData2.hitUID != -1) {
						haveClearShot = (ai->cb->GetUnitAllyTeam(rayData2.hitUID) != ai->cb->GetMyAllyTeam());
					}
				}
			}
		}

		// multiply by 0.9 to ensure commander does not have to walk
		if ((commanderPos - dgunPos).Length() < maxRange * 0.9f) {
			bool canDGun =
				(ai->cb->GetEnergy() >= DGUN_MIN_ENERGY_LEVEL)
				&& haveClearShot
				&& (udef != NULL && !udef->weapons.empty());

			if(canDGun) {
				IssueOrder(dgunPos, orderType = CMD_DGUN, 0);
			} else {
				bool bDanger = ai->tm->ThreatAtThisPoint(commanderPos/*curTargetPos*/) > ai->tm->GetAverageThreat();
				if(bDanger) {
					state.Reset(currentFrame, true);
				} else {
					if (ai->cb->GetUnitHealth(state.targetID) < ai->cb->GetUnitMaxHealth(state.targetID) * 0.5f) {
						IssueOrder(state.targetID, orderType = CMD_RECLAIM, 0);
					} else {
						IssueOrder(state.targetID, orderType = CMD_CAPTURE, 0);
					}
				}
			}

			if (orderType == CMD_DGUN   ) { state.dgunOrderFrame    = ai->cb->GetCurrentFrame(); }
			if (orderType == CMD_RECLAIM) { state.reclaimOrderFrame = ai->cb->GetCurrentFrame(); }
			if (orderType == CMD_CAPTURE) { state.captureOrderFrame = ai->cb->GetCurrentFrame(); }
		} else {
			state.Reset(currentFrame, true);
		}
	}

	state.Reset(currentFrame, false);
}
Example #17
0
void CAdvTreeDrawer::DrawShadowPass(void)
{
	const float treeDistance = oldTreeDistance;
	const int activeFarTex = (camera->forward.z < 0.0f)? treeGen->farTex[0] : treeGen->farTex[1];
	const bool drawDetailed = (treeDistance >= 4.0f);

	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, activeFarTex);
	glEnable(GL_TEXTURE_2D);
	glEnable(GL_ALPHA_TEST);
	glDisable(GL_CULL_FACE);

	glPolygonOffset(1, 1);
	glEnable(GL_POLYGON_OFFSET_FILL);

	CAdvTreeSquareDrawer_SP drawer;
	const int cx = drawer.cx = (int)(camera->pos.x / (SQUARE_SIZE * TREE_SQUARE_SIZE));
	const int cy = drawer.cy = (int)(camera->pos.z / (SQUARE_SIZE * TREE_SQUARE_SIZE));

	drawer.drawDetailed = drawDetailed;
	drawer.td = this;
	drawer.treeDistance = treeDistance * SQUARE_SIZE * TREE_SQUARE_SIZE;

	Shader::IProgramObject* po = NULL;

	GML_STDMUTEX_LOCK(tree); // DrawShadowPass

	// draw with extraSize=1
	readmap->GridVisibility(camera, TREE_SQUARE_SIZE, drawer.treeDistance * 2.0f, &drawer, 1);

	if (drawDetailed) {
		const int xstart = std::max(                              0, cx - 2);
		const int xend   = std::min(gs->mapx / TREE_SQUARE_SIZE - 1, cx + 2);
		const int ystart = std::max(                              0, cy - 2);
		const int yend   = std::min(gs->mapy / TREE_SQUARE_SIZE - 1, cy + 2);

		glBindTexture(GL_TEXTURE_2D, treeGen->barkTex);
		glEnable(GL_TEXTURE_2D);

		po = shadowHandler->GetShadowGenProg(CShadowHandler::SHADOWGEN_PROGRAM_TREE_NEAR);
		po->Enable();

		if (globalRendering->haveGLSL) {
			po->SetUniform3fv(1, &camera->right[0]);
			po->SetUniform3fv(2, &camera->up[0]);
		} else {
			po->SetUniformTarget(GL_VERTEX_PROGRAM_ARB);
			po->SetUniform4f(13, camera->right.x, camera->right.y, camera->right.z, 0.0f);
			po->SetUniform4f(9,  camera->up.x,    camera->up.y,    camera->up.z,    0.0f);
			po->SetUniform4f(11, 1.0f, 1.0f, 1.0f, 0.85f                           );
			po->SetUniform4f(12, 0.0f, 0.0f, 0.0f, 0.20f * (1.0f / MAX_TREE_HEIGHT));   // w = alpha/height modifier
		}

		glAlphaFunc(GL_GREATER, 0.5f);
		glEnable(GL_ALPHA_TEST);
		glColor4f(1.0f, 1.0f, 1.0f, 1.0f);

		varr = GetVertexArray();
		varr->Initialize();

		static FadeTree fadeTrees[3000];
		FadeTree* pFT = fadeTrees;

		for (TreeSquareStruct* pTSS = trees + ystart * treesX; pTSS <= trees + yend * treesX; pTSS += treesX) {
			for (TreeSquareStruct* tss = pTSS + xstart; tss <= pTSS + xend; ++tss) {
				tss->lastSeen = gs->frameNum;
				varr->EnlargeArrays(12 * tss->trees.size(), 0, VA_SIZE_T); //!alloc room for all tree vertexes

				for (std::map<int, TreeStruct>::iterator ti = tss->trees.begin(); ti != tss->trees.end(); ++ti) {
					const TreeStruct* ts = &ti->second;
					const float3 pos(ts->pos);

					if (!camera->InView(pos + float3(0, MAX_TREE_HEIGHT / 2, 0), MAX_TREE_HEIGHT / 2 + 150)) {
						continue;
					}

					const float camDist = (pos - camera->pos).SqLength();
					int type = ts->type;
					float dy = 0.0f;
					unsigned int displist;

					if (type < 8) {
						dy = 0.5f;
						displist = treeGen->pineDL + type;
					} else {
						type -= 8;
						dy = 0;
						displist = treeGen->leafDL + type;
					}

					if (camDist < SQUARE_SIZE * SQUARE_SIZE * 110 * 110) {
						po->SetUniform3f((globalRendering->haveGLSL? 3: 10), pos.x, pos.y, pos.z);
						glCallList(displist);
					} else if (camDist < SQUARE_SIZE * SQUARE_SIZE * 125 * 125) {
						const float relDist = (pos.distance(camera->pos) - SQUARE_SIZE * 110) / (SQUARE_SIZE * 15);

						glAlphaFunc(GL_GREATER, 0.8f + relDist * 0.2f);
						po->SetUniform3f((globalRendering->haveGLSL? 3: 10), pos.x, pos.y, pos.z);
						glCallList(displist);
						glAlphaFunc(GL_GREATER, 0.5f);

						pFT->pos = pos;
						pFT->deltaY = dy;
						pFT->type = type;
						pFT->relDist = relDist;
						++pFT;
					} else {
						DrawTreeVertex(varr, pos, type * 0.125f, dy, false);
					}
				}
			}
		}


		po->SetUniform3f((globalRendering->haveGLSL? 3: 10), 0.0f, 0.0f, 0.0f);

		for (std::list<FallingTree>::iterator fti = fallingTrees.begin(); fti != fallingTrees.end(); ++fti) {
			const float3 pos = fti->pos - UpVector * (fti->fallPos * 20);

			if (camera->InView(pos + float3(0, MAX_TREE_HEIGHT / 2, 0), MAX_TREE_HEIGHT / 2)) {
				const float ang = fti->fallPos * PI;

				const float3 yvec(fti->dir.x * sin(ang), cos(ang), fti->dir.z * sin(ang));
				const float3 zvec((yvec.cross(float3(1.0f, 0.0f, 0.0f))).ANormalize());
				const float3 xvec(zvec.cross(yvec));

				CMatrix44f transMatrix(pos, xvec, yvec, zvec);

				glPushMatrix();
				glMultMatrixf(&transMatrix[0]);

				int type = fti->type;
				int displist;

				if (type < 8) {
					displist = treeGen->pineDL + type;
				} else {
					type -= 8;
					displist = treeGen->leafDL + type;
				}

				glCallList(displist);
				glPopMatrix();
			}
		}

		po->Disable();
		po = shadowHandler->GetShadowGenProg(CShadowHandler::SHADOWGEN_PROGRAM_TREE_FAR);
		po->Enable();

		glBindTexture(GL_TEXTURE_2D, activeFarTex);
		varr->DrawArrayT(GL_QUADS);

		for (FadeTree* pFTree = fadeTrees; pFTree < pFT; ++pFTree) {
			// faded close trees
			varr = GetVertexArray();
			varr->Initialize();
			varr->CheckInitSize(12 * VA_SIZE_T);

			DrawTreeVertex(varr, pFTree->pos, pFTree->type * 0.125f, pFTree->deltaY, false);

			glAlphaFunc(GL_GREATER, 1.0f - (pFTree->relDist * 0.5f));
			varr->DrawArrayT(GL_QUADS);
		}

		po->Disable();
	}

	glEnable(GL_CULL_FACE);
	glDisable(GL_POLYGON_OFFSET_FILL);
	glDisable(GL_TEXTURE_2D);
	glDisable(GL_ALPHA_TEST);
}
Example #18
0
CMissileProjectile::CMissileProjectile(
		const float3& pos, const float3& speed,
		CUnit* owner,
		float areaOfEffect, float maxSpeed, int ttl,
		CUnit* target, const WeaponDef* weaponDef,
		float3 targetPos)
	: CWeaponProjectile(pos, speed, owner, target, targetPos, weaponDef, NULL, ttl)
	, maxSpeed(maxSpeed)
	, areaOfEffect(areaOfEffect)
	, age(0)
	, oldSmoke(pos)
	, target(target)
	, decoyTarget(NULL)
	, drawTrail(true)
	, numParts(0)
	, targPos(targetPos)
	, isWobbling(weaponDef? (weaponDef->wobble > 0): false)
	, wobbleDir(ZeroVector)
	, wobbleTime(1)
	, wobbleDif(ZeroVector)
	, isDancing(weaponDef? (weaponDef->dance > 0): false)
	, danceTime(1)
	, danceMove(ZeroVector)
	, danceCenter(ZeroVector)
	, extraHeightTime(0)
{
	projectileType = WEAPON_MISSILE_PROJECTILE;
	curSpeed = speed.Length();
	dir = speed / curSpeed;
	oldDir = dir;

	if (target) {
		AddDeathDependence(target);
	}

	SetRadius(0.0f);

	if (weaponDef) {
		model = LoadModel(weaponDef);
		if (model) {
			SetRadius(model->radius);
		}
	}

	drawRadius = radius + maxSpeed * 8;

	float3 camDir = (pos - camera->pos).Normalize();
	if ((camera->pos.distance(pos) * 0.2f + (1 - fabs(camDir.dot(dir))) * 3000) < 200) {
		drawTrail = false;
	}

	castShadow = true;

#ifdef TRACE_SYNC
	tracefile << "New missile: ";
	tracefile << pos.x << " " << pos.y << " " << pos.z << " " << speed.x << " " << speed.y << " " << speed.z << "\n";
#endif

	if (target) {
		target->IncomingMissile(this);
	}

	if ((weaponDef) && (weaponDef->trajectoryHeight > 0)) {
		float dist = pos.distance(targPos);
		extraHeight = (dist * weaponDef->trajectoryHeight);

		if (dist < maxSpeed) {
			dist = maxSpeed;
		}

		extraHeightTime = (int)(dist / maxSpeed);
		extraHeightDecay = extraHeight / extraHeightTime;
	}


	cegID = gCEG->Load(explGenHandler, cegTag);
}
Example #19
0
void CAdvTreeDrawer::Draw(float treeDistance, bool drawReflection)
{
	const int activeFarTex = (camera->forward.z < 0.0f)? treeGen->farTex[0]: treeGen->farTex[1];
	const bool drawDetailed = ((treeDistance >= 4.0f) || drawReflection);

	CBaseGroundDrawer* gd = readmap->GetGroundDrawer();
	Shader::IProgramObject* treeShader = NULL;

	#define L mapInfo->light

	glEnable(GL_ALPHA_TEST);
	glEnable(GL_TEXTURE_2D);

	if (globalRendering->drawFog) {
		glFogfv(GL_FOG_COLOR, mapInfo->atmosphere.fogColor);
		glEnable(GL_FOG);
	}


	if (shadowHandler->shadowsLoaded && !gd->DrawExtraTex()) {
		glActiveTexture(GL_TEXTURE1);
		glBindTexture(GL_TEXTURE_2D, activeFarTex);
		glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_2D, shadowHandler->shadowTexture);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
		glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_ALPHA);

		treeShader = treeShaders[TREE_PROGRAM_DIST_SHADOW];
		treeShader->Enable();

		if (globalRendering->haveGLSL) {
			treeShader->SetUniformMatrix4fv(7, false, &shadowHandler->shadowMatrix.m[0]);
			treeShader->SetUniform4fv(8, &(shadowHandler->GetShadowParams().x));
		} else {
			treeShader->SetUniformTarget(GL_FRAGMENT_PROGRAM_ARB);
			treeShader->SetUniform4f(10, L.groundAmbientColor.x, L.groundAmbientColor.y, L.groundAmbientColor.z, 1.0f);
			treeShader->SetUniform4f(11, 0.0f, 0.0f, 0.0f, 1.0f - (sky->GetLight()->GetGroundShadowDensity() * 0.5f));
			treeShader->SetUniformTarget(GL_VERTEX_PROGRAM_ARB);

			glMatrixMode(GL_MATRIX0_ARB);
			glLoadMatrixf(shadowHandler->shadowMatrix.m);
			glMatrixMode(GL_MODELVIEW);
		}
	} else {
		glBindTexture(GL_TEXTURE_2D, activeFarTex);
	}


	const int cx = int(camera->pos.x / (SQUARE_SIZE * TREE_SQUARE_SIZE));
	const int cy = int(camera->pos.z / (SQUARE_SIZE * TREE_SQUARE_SIZE));

	CAdvTreeSquareDrawer drawer(this, cx, cy, treeDistance * SQUARE_SIZE * TREE_SQUARE_SIZE, drawDetailed);

	GML_STDMUTEX_LOCK(tree); // Draw

	oldTreeDistance = treeDistance;

	// draw far-trees using map-dependent grid-visibility
	readmap->GridVisibility(camera, TREE_SQUARE_SIZE, drawer.treeDistance * 2.0f, &drawer);


	if (drawDetailed) {
		// draw near-trees
		const int xstart = std::max(                              0, cx - 2);
		const int xend   = std::min(gs->mapx / TREE_SQUARE_SIZE - 1, cx + 2);
		const int ystart = std::max(                              0, cy - 2);
		const int yend   = std::min(gs->mapy / TREE_SQUARE_SIZE - 1, cy + 2);

		if (shadowHandler->shadowsLoaded && !gd->DrawExtraTex()) {
			treeShader->Disable();
			treeShader = treeShaders[TREE_PROGRAM_NEAR_SHADOW];
			treeShader->Enable();

			if (globalRendering->haveGLSL) {
				treeShader->SetUniformMatrix4fv(7, false, &shadowHandler->shadowMatrix.m[0]);
				treeShader->SetUniform4fv(8, &(shadowHandler->GetShadowParams().x));
			}

			glActiveTexture(GL_TEXTURE1);
			glEnable(GL_TEXTURE_2D);
			glBindTexture(GL_TEXTURE_2D, treeGen->barkTex);
			glActiveTexture(GL_TEXTURE0);
		} else {
			glBindTexture(GL_TEXTURE_2D, treeGen->barkTex);

			treeShader = treeShaders[TREE_PROGRAM_NEAR_BASIC];
			treeShader->Enable();

			if (!globalRendering->haveGLSL) {
				#define MX (gs->pwr2mapx * SQUARE_SIZE)
				#define MY (gs->pwr2mapy * SQUARE_SIZE)
				treeShader->SetUniformTarget(GL_VERTEX_PROGRAM_ARB);
				treeShader->SetUniform4f(15, 1.0f / MX, 1.0f / MY, 1.0f / MX, 1.0f);
				#undef MX
				#undef MY
			}
		}


		if (globalRendering->haveGLSL) {
			treeShader->SetUniform3fv(0, &camera->right[0]);
			treeShader->SetUniform3fv(1, &camera->up[0]);
			treeShader->SetUniform2f(5, 0.20f * (1.0f / MAX_TREE_HEIGHT), 0.85f);
		} else {
			treeShader->SetUniformTarget(GL_VERTEX_PROGRAM_ARB);
			treeShader->SetUniform3f(13, camera->right.x, camera->right.y, camera->right.z);
			treeShader->SetUniform3f( 9, camera->up.x,    camera->up.y,    camera->up.z   );
			treeShader->SetUniform4f(11, L.groundSunColor.x,     L.groundSunColor.y,     L.groundSunColor.z,     0.85f);
			treeShader->SetUniform4f(14, L.groundAmbientColor.x, L.groundAmbientColor.y, L.groundAmbientColor.z, 0.85f);
			treeShader->SetUniform4f(12, 0.0f, 0.0f, 0.0f, 0.20f * (1.0f / MAX_TREE_HEIGHT)); // w = alpha/height modifier
		}


		glAlphaFunc(GL_GREATER, 0.5f);
		glDisable(GL_BLEND);
		glColor4f(1.0f, 1.0f, 1.0f, 1.0f);

		varr = GetVertexArray();
		varr->Initialize();

		static FadeTree fadeTrees[3000];
		FadeTree* pFT = fadeTrees;


		for (TreeSquareStruct* pTSS = trees + ystart * treesX; pTSS <= trees + yend * treesX; pTSS += treesX) {
			for (TreeSquareStruct* tss = pTSS + xstart; tss <= pTSS + xend; ++tss) {
				tss->lastSeen = gs->frameNum;
				varr->EnlargeArrays(12 * tss->trees.size(), 0, VA_SIZE_T); //!alloc room for all tree vertexes

				for (std::map<int, TreeStruct>::iterator ti = tss->trees.begin(); ti != tss->trees.end(); ++ti) {
					const TreeStruct* ts = &ti->second;
					const float3 pos(ts->pos);

					if (!camera->InView(pos + float3(0.0f, MAX_TREE_HEIGHT / 2.0f, 0.0f), MAX_TREE_HEIGHT / 2.0f)) {
						continue;
					}

					const float camDist = (pos - camera->pos).SqLength();
					int type = ts->type;
					float dy = 0.0f;
					unsigned int displist;

					if (type < 8) {
						dy = 0.5f;
						displist = treeGen->pineDL + type;
					} else {
						type -= 8;
						dy = 0.0f;
						displist = treeGen->leafDL + type;
					}

					if (camDist < (SQUARE_SIZE * SQUARE_SIZE * 110 * 110)) {
						// draw detailed near-distance tree (same as mid-distance trees without alpha)
						treeShader->SetUniform3f(((globalRendering->haveGLSL)? 2: 10), pos.x, pos.y, pos.z);
						glCallList(displist);
					} else if (camDist < (SQUARE_SIZE * SQUARE_SIZE * 125 * 125)) {
						// draw mid-distance tree
						const float relDist = (pos.distance(camera->pos) - SQUARE_SIZE * 110) / (SQUARE_SIZE * 15);

						treeShader->SetUniform3f(((globalRendering->haveGLSL)? 2: 10), pos.x, pos.y, pos.z);

						glAlphaFunc(GL_GREATER, 0.8f + relDist * 0.2f);
						glCallList(displist);
						glAlphaFunc(GL_GREATER, 0.5f);

						// save for second pass
						pFT->pos = pos;
						pFT->deltaY = dy;
						pFT->type = type;
						pFT->relDist = relDist;
						++pFT;
					} else {
						// draw far-distance tree
						DrawTreeVertex(varr, pos, type * 0.125f, dy, false);
					}
				}
			}
		}


		// reset the world-offset
		treeShader->SetUniform3f(((globalRendering->haveGLSL)? 2: 10), 0.0f, 0.0f, 0.0f);

		// draw trees that have been marked as falling
		for (std::list<FallingTree>::iterator fti = fallingTrees.begin(); fti != fallingTrees.end(); ++fti) {
			const float3 pos = fti->pos - UpVector * (fti->fallPos * 20);

			if (camera->InView(pos + float3(0.0f, MAX_TREE_HEIGHT / 2, 0.0f), MAX_TREE_HEIGHT / 2.0f)) {
				const float ang = fti->fallPos * PI;

				const float3 yvec(fti->dir.x * sin(ang), cos(ang), fti->dir.z * sin(ang));
				const float3 zvec((yvec.cross(float3(-1.0f, 0.0f, 0.0f))).ANormalize());
				const float3 xvec(yvec.cross(zvec));

				CMatrix44f transMatrix(pos, xvec, yvec, zvec);

				glPushMatrix();
				glMultMatrixf(&transMatrix[0]);

				int type = fti->type;
				int displist = 0;

				if (type < 8) {
					displist = treeGen->pineDL + type;
				} else {
					type -= 8;
					displist = treeGen->leafDL + type;
				}

				glCallList(displist);
				glPopMatrix();
			}
		}


		if (shadowHandler->shadowsLoaded && !gd->DrawExtraTex()) {
			treeShader->Disable();
			treeShader = treeShaders[TREE_PROGRAM_DIST_SHADOW];
			treeShader->Enable();

			glActiveTexture(GL_TEXTURE1);
			glBindTexture(GL_TEXTURE_2D, activeFarTex);
			glActiveTexture(GL_TEXTURE0);
		} else {
			treeShader->Disable();
			glBindTexture(GL_TEXTURE_2D, activeFarTex);
		}


		// draw far-distance trees
		varr->DrawArrayT(GL_QUADS);

		// draw faded mid-distance trees
		for (FadeTree* pFTree = fadeTrees; pFTree < pFT; ++pFTree) {
			varr = GetVertexArray();
			varr->Initialize();
			varr->CheckInitSize(12 * VA_SIZE_T);

			DrawTreeVertex(varr, pFTree->pos, pFTree->type * 0.125f, pFTree->deltaY, false);

			glAlphaFunc(GL_GREATER, 1.0f - (pFTree->relDist * 0.5f));
			varr->DrawArrayT(GL_QUADS);
		}
	}

	if (shadowHandler->shadowsLoaded && !gd->DrawExtraTex()) {
		treeShader->Disable();

		glActiveTexture(GL_TEXTURE1);
		glBindTexture(GL_TEXTURE_2D, 0);
		glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_2D, 0);
		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
		glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
	} else {
		glBindTexture(GL_TEXTURE_2D, 0);
	}

	glDisable(GL_TEXTURE_2D);
	glDisable(GL_FOG);
	glDisable(GL_ALPHA_TEST);



	// clean out squares from memory that are no longer visible
	const int startClean = lastListClean * 20 % (nTrees);
	const int endClean = gs->frameNum * 20 % (nTrees);

	lastListClean = gs->frameNum;

	if (startClean > endClean) {
		for (TreeSquareStruct* pTSS = trees + startClean; pTSS < trees + nTrees; ++pTSS) {
			if ((pTSS->lastSeen < gs->frameNum - 50) && pTSS->displist) {
				glDeleteLists(pTSS->displist, 1);
				pTSS->displist = 0;
			}
			if ((pTSS->lastSeenFar < gs->frameNum - 50) && pTSS->farDisplist) {
				glDeleteLists(pTSS->farDisplist, 1);
				pTSS->farDisplist = 0;
			}
		}
		for (TreeSquareStruct* pTSS = trees; pTSS < trees + endClean; ++pTSS) {
			if ((pTSS->lastSeen < gs->frameNum - 50) && pTSS->displist) {
				glDeleteLists(pTSS->displist, 1);
				pTSS->displist = 0;
			}
			if ((pTSS->lastSeenFar < gs->frameNum - 50) && pTSS->farDisplist) {
				glDeleteLists(pTSS->farDisplist, 1);
				pTSS->farDisplist = 0;
			}
		}
	} else {
		for (TreeSquareStruct* pTSS = trees + startClean; pTSS < trees + endClean; ++pTSS) {
			if ((pTSS->lastSeen < gs->frameNum - 50) && pTSS->displist) {
				glDeleteLists(pTSS->displist, 1);
				pTSS->displist = 0;
			}
			if ((pTSS->lastSeenFar < gs->frameNum - 50) && pTSS->farDisplist) {
				glDeleteLists(pTSS->farDisplist, 1);
				pTSS->farDisplist = 0;
			}
		}
	}

	#undef L
}
Example #20
0
static inline float LineGroundSquareCol(
	const float* heightmap,
	const float3* normalmap,
	const float3& from,
	const float3& to,
	const int xs,
	const int ys)
{
	const bool inMap = (xs >= 0) && (ys >= 0) && (xs <= mapDims.mapxm1) && (ys <= mapDims.mapym1);
//	assert(inMap);
	if (!inMap)
		return -1.0f;

	// The terrain grid is "composed" of two right-isosceles triangles
	// per square, so we have to check both faces (triangles) whether an
	// intersection exists
	// for each triangle, we pick one representative vertex

	// top-left corner vertex
	{
		float3 cornerVertex;
		cornerVertex.x = xs * SQUARE_SIZE;
		cornerVertex.z = ys * SQUARE_SIZE;
		cornerVertex.y = heightmap[ys * mapDims.mapxp1 + xs];

		// project \<to - cornerVertex\> vector onto the TL-normal
		// if \<to\> lies below the terrain, this will be negative
		const float3 faceNormalTL = normalmap[(ys * mapDims.mapx + xs) * 2    ];
		float toFacePlaneDist = (to - cornerVertex).dot(faceNormalTL);

		if (toFacePlaneDist <= 0.0f) {
			// project \<from - cornerVertex\> onto the TL-normal
			float fromFacePlaneDist = (from - cornerVertex).dot(faceNormalTL);

			if (fromFacePlaneDist != toFacePlaneDist) {
				const float alpha = fromFacePlaneDist / (fromFacePlaneDist - toFacePlaneDist);
				const float3 col = mix(from, to, alpha);

				if ((col.x >= cornerVertex.x) && (col.z >= cornerVertex.z) && (col.x + col.z <= cornerVertex.x + cornerVertex.z + SQUARE_SIZE)) {
					// point of intersection is inside the TL triangle
					return col.distance(from);
				}
			}
		}
	}

	// bottom-right corner vertex
	{
		float3 cornerVertex;
		cornerVertex.x = (xs + 1) * SQUARE_SIZE;
		cornerVertex.z = (ys + 1) * SQUARE_SIZE;
		cornerVertex.y = heightmap[(ys + 1) * mapDims.mapxp1 + (xs + 1)];

		// project \<to - cornerVertex\> vector onto the TL-normal
		// if \<to\> lies below the terrain, this will be negative
		const float3 faceNormalBR = normalmap[(ys * mapDims.mapx + xs) * 2 + 1];
		float toFacePlaneDist = (to - cornerVertex).dot(faceNormalBR);

		if (toFacePlaneDist <= 0.0f) {
			// project \<from - cornerVertex\> onto the BR-normal
			float fromFacePlaneDist = (from - cornerVertex).dot(faceNormalBR);

			if (fromFacePlaneDist != toFacePlaneDist) {
				const float alpha = fromFacePlaneDist / (fromFacePlaneDist - toFacePlaneDist);
				const float3 col = mix(from, to, alpha);

				if ((col.x <= cornerVertex.x) && (col.z <= cornerVertex.z) && (col.x + col.z >= cornerVertex.x + cornerVertex.z - SQUARE_SIZE)) {
					// point of intersection is inside the BR triangle
					return col.distance(from);
				}
			}
		}
	}

	return -2.0f;
}
Example #21
0
float CGround::LineGroundCol(float3 from, float3 to, bool synced)
{
	const float* hm  = readMap->GetSharedCornerHeightMap(synced);
	const float3* nm = readMap->GetSharedFaceNormals(synced);

	const float3 pfrom = from;

	// only for performance -> skip part that can impossibly collide
	// with the terrain, cause it is above map's current max height
	ClampInMapHeight(from, to);

	// handle special cases where the ray origin is out of bounds:
	// need to move <from> to the closest map-edge along the ray
	// (if both <from> and <to> are out of bounds, the ray might
	// still hit)
	// clamping <from> naively would change the direction of the
	// ray, hence we save the distance along it that got skipped
	ClampLineInMap(from, to);

	if (from == to) {
		// ClampLineInMap & ClampInMapHeight set `from == to == vec(-1,-1,-1)`
		// in case the line is outside of the map
		return -1.0f;
	}

	const float skippedDist = pfrom.distance(from);

	if (synced) { //TODO do this in unsynced too once the map border rendering is finished?
		// check if our start position is underground (assume ground is unpassable for cannons etc.)
		const int sx = from.x / SQUARE_SIZE;
		const int sz = from.z / SQUARE_SIZE;

		if (from.y <= hm[sz * mapDims.mapxp1 + sx]) {
			return 0.0f + skippedDist;
		}
	}

	const float dx = to.x - from.x;
	const float dz = to.z - from.z;
	const int dirx = (dx > 0.0f) ? 1 : -1;
	const int dirz = (dz > 0.0f) ? 1 : -1;

	// Clamping is done cause LineGroundSquareCol() operates on the 2 triangles faces each heightmap
	// square is formed of.
	const float ffsx = Clamp(from.x / SQUARE_SIZE, 0.0f, (float)mapDims.mapx);
	const float ffsz = Clamp(from.z / SQUARE_SIZE, 0.0f, (float)mapDims.mapy);
	const float ttsx = Clamp(to.x / SQUARE_SIZE, 0.0f, (float)mapDims.mapx);
	const float ttsz = Clamp(to.z / SQUARE_SIZE, 0.0f, (float)mapDims.mapy);
	const int fsx = ffsx;
	const int fsz = ffsz;
	const int tsx = ttsx;
	const int tsz = ttsz;

	bool keepgoing = true;

	if ((fsx == tsx) && (fsz == tsz)) {
		// <from> and <to> are the same
		const float ret = LineGroundSquareCol(hm, nm,  from, to,  fsx, fsz);

		if (ret >= 0.0f) {
			return (ret + skippedDist);
		}
	} else if (fsx == tsx) {
		// ray is parallel to z-axis
		int zp = fsz;

		while (keepgoing) {
			const float ret = LineGroundSquareCol(hm, nm,  from, to,  fsx, zp);

			if (ret >= 0.0f) {
				return (ret + skippedDist);
			}

			keepgoing = (zp != tsz);
			zp += dirz;
		}
	} else if (fsz == tsz) {
		// ray is parallel to x-axis
		int xp = fsx;

		while (keepgoing) {
			const float ret = LineGroundSquareCol(hm, nm,  from, to,  xp, fsz);

			if (ret >= 0.0f) {
				return (ret + skippedDist);
			}

			keepgoing = (xp != tsx);
			xp += dirx;
		}
	} else {
		// general case
		const float rdsx = SQUARE_SIZE / dx; // := 1 / (dx / SQUARE_SIZE)
		const float rdsz = SQUARE_SIZE / dz;

		// we need to shift the `test`-point in case of negative directions
		// case: dir<0
		//  ___________
		// |   |   |   |
		// |___|___|___|
		//     ^cur
		// ^cur + dir
		// >   < range of int(cur + dir)
		//     ^wanted test point := cur - epsilon
		// you can set epsilon=0 and then handle the `beyond end`-case (xn >= 1.0f && zn >= 1.0f) separate
		// (we already need to do so cause of floating point precision limits, so skipping epsilon doesn't add
		// any additional performance cost nor precision issue)
		//
		// case : dir>0
		// in case of `dir>0` the wanted test point is idential with `cur + dir`
		const float testposx = (dx > 0.0f) ? 0.0f : 1.0f;
		const float testposz = (dz > 0.0f) ? 0.0f : 1.0f;

		int curx = fsx;
		int curz = fsz;

		while (keepgoing) {
			// do the collision test with the squares triangles
			const float ret = LineGroundSquareCol(hm, nm,  from, to,  curx, curz);

			if (ret >= 0.0f) {
				return (ret + skippedDist);
			}

			// check if we reached the end already and need to stop the loop
			const bool endReached = (curx == tsx && curz == tsz);
			const bool beyondEnd = ((curx - tsx) * dirx > 0) || ((curz - tsz) * dirz > 0);

			assert(!beyondEnd);
			keepgoing = !endReached && !beyondEnd;

			if (!keepgoing)
				 break;

			// calculate the `normalized position` of the next edge in x & z direction
			//  `normalized position`:=n :   x = from.x + n * (to.x - from.x)   (with 0<= n <=1)
			int nextx = curx + dirx;
			int nextz = curz + dirz;
			float xn = (nextx + testposx - ffsx) * rdsx;
			float zn = (nextz + testposz - ffsz) * rdsz;

			// handles the following 2 case:
			// case1: (floor(to.x) == to.x) && (to.x < from.x)
			//   In this case we calculate xn at to.x but set curx = to.x - 1,
			//   and so we would be beyond the end of the ray.
			// case2: floating point precision issues
			if ((nextx - tsx) * dirx > 0) { xn=1337.0f; nextx=tsx; }
			if ((nextz - tsz) * dirz > 0) { zn=1337.0f; nextz=tsz; }

			// advance to the next nearest edge in either x or z dir, or in the case we reached the end make sure
			// we set it to the exact square positions (floating point precision sometimes hinders us to hit it)
			if (xn >= 1.0f && zn >= 1.0f) {
				assert(curx != nextx || curz != nextz);
				curx = nextx;
				curz = nextz;
			} else if (xn < zn) {
				assert(curx != nextx);
				curx = nextx;
			} else {
				assert(curz != nextz);
				curz = nextz;
			}
		}
	}

	return -1.0f;
}
Example #22
0
void AudioChannel::FindSourceAndPlay(size_t id, const float3& pos, const float3& velocity, float volume, bool relative)
{
	boost::recursive_mutex::scoped_lock lck(soundMutex);

	if (!enabled)
		return;

	if (volume <= 0.0f)
		return;

	SoundItem* sndItem = sound->GetSoundItem(id);
	if (!sndItem) {
		sound->numEmptyPlayRequests++;
		return;
	}

	if (pos.distance(sound->GetListenerPos()) > sndItem->MaxDistance()) {
		if (!relative) {
			return;
		} else {
			LOG("CSound::PlaySample: maxdist ignored for relative playback: %s",
					sndItem->Name().c_str());
		}
	}

	if (emmitsThisFrame >= emmitsPerFrame)
		return;
	emmitsThisFrame++;

	if (cur_sources.size() >= maxConcurrentSources) {
		CSoundSource* src = NULL;
		int prio = INT_MAX;
		for (std::map<CSoundSource*, bool>::iterator it = cur_sources.begin(); it != cur_sources.end(); ++it) {
			if (it->first->GetCurrentPriority() < prio) {
				src  = it->first;
				prio = it->first->GetCurrentPriority();
			}
		}

		if (src && prio <= sndItem->GetPriority()) {
			src->Stop();
		} else {
			LOG_L(L_DEBUG, "CSound::PlaySample: Max concurrent sounds in channel reached! Dropping playback!");
			return;
		}
	}

	CSoundSource* sndSource = sound->GetNextBestSource();
	if (!sndSource) {
		LOG_L(L_DEBUG, "CSound::PlaySample: Max sounds reached! Dropping playback!");
		return;
	}

	if (sndSource->GetCurrentPriority() < sndItem->GetPriority()) {
		if (sndSource->IsPlaying())
			sound->numAbortedPlays++;

		sndSource->Play(this, sndItem, pos, velocity, volume, relative);
		CheckError("CSound::FindSourceAndPlay");

		cur_sources[sndSource] = true;
	}
}
Example #23
0
float CAICallback::GetPathLength(float3 start, float3 end, int pathType, float goalRadius)
{
	const int pathID  = InitPath(start, end, pathType, goalRadius);
	float     pathLen = -1.0f;

	if (pathID == 0) {
		return pathLen;
	}

	std::vector<float3> points;
	std::vector<int>    lengths;

	pathManager->GetPathWayPoints(pathID, points, lengths);

	if (points.empty()) {
		return 0.0f;
	}

	// distance to first intermediate node
	pathLen = start.distance(points[0]);

	// we don't care which path segment has
	// what resolution, just lump all points
	// together
	for (size_t i = 1; i < points.size(); i++) {
		pathLen += points[i].distance(points[i - 1]);
	}

	/*
	// this method does not work without a path-owner
	// TODO: add an alternate GPL() callback for this?
	bool      haveNextWP = true;
	float3    currWP     = start;
	float3    nextWP     = start;

	while (haveNextWP) {
		nextWP = GetNextWaypoint(pathID);

		if (nextWP.y == -2) {
			// next path node not yet known
			continue;
		}

		if (nextWP.y == -1) {
			if (nextWP.x >= 0.0f && nextWP.z >= 0.0f) {
				// end of path (nextWP == end)
				pathLen += (nextWP - currWP).Length2D();
			} else {
				// invalid path
				pathLen = -1.0f;
			}

			haveNextWP = false;
		} else {
			pathLen += (nextWP - currWP).Length2D();
			currWP   = nextWP;
		}
	}
	*/

	FreePath(pathID);
	return pathLen;
}