Example #1
0
bool AAirMoveType::CanLandOnPad(const float3& padPos) const {
	// once distance to pad becomes smaller than current braking distance, switch states
	// (but do not allow state-switch until the aircraft is heading ~directly toward pad)
	// braking distance is 0.5*a*t*t where t is v/a --> 0.5*a*((v*v)/(a*a)) --> 0.5*v*v*(1/a)
	// FIXME:
	//   apply N-frame lookahead when deciding to switch state for strafing aircraft
	//   (see comments in StrafeAirMoveType::UpdateLanding, overshooting prevention)
	//   the lookahead is roughly based on the time to descend to pad-target altitude
	const float3 flatFrontDir = (float3(owner->frontdir)).Normalize2D();

	const float brakingDistSq = Square(0.5f * owner->speed.SqLength2D() / decRate);
	const float descendDistSq = Square(maxSpeed * ((owner->pos.y - padPos.y) / altitudeRate)) * owner->unitDef->IsStrafingAirUnit();

	if (padPos.SqDistance2D(owner->pos) > std::max(brakingDistSq, descendDistSq))
		return false;

	if (owner->unitDef->IsStrafingAirUnit()) {
		// horizontal guide
		if (flatFrontDir.dot((padPos - owner->pos).SafeNormalize2D()) < 0.985f)
			return false;
		// vertical guide
		if (flatFrontDir.dot((padPos - owner->pos).SafeNormalize()) < 0.707f)
			return false;
	}

	return true;
}
Example #2
0
int CLaserProjectile::ShieldRepulse(CPlasmaRepulser* shield, float3 shieldPos, float shieldForce, float shieldMaxSpeed)
{
    if (!luaMoveCtrl) {
        const float3 rdir = (pos - shieldPos).Normalize();

        if (rdir.dot(speed) < 0.0f) {
            speed -= (rdir * rdir.dot(speed) * 2.0f);
            dir = speed;
            dir.Normalize();
            return 1;
        }
    }

    return 0;
}
Example #3
0
void CubeMapHandler::CreateSpecularFace(
	unsigned int texType,
	int size,
	const float3& cdir,
	const float3& xdif,
	const float3& ydif,
	float specExponent)
{
	unsigned char* buf = new unsigned char[size * size * 4];

	for (int y = 0; y < size; ++y) {
		for (int x = 0; x < size; ++x) {
			const float3 dir = (cdir + (xdif * (x + 0.5f)) / size + (ydif * (y + 0.5f)) / size).Normalize();
			const float dot = std::max(0.0f, dir.dot(mapInfo->light.sunDir));
			const float spec = std::min(1.0f, pow(dot, specExponent) + pow(dot, 3.0f) * 0.25f);

			buf[(y * size + x) * 4 + 0] = (unsigned char) (mapInfo->light.unitSpecularColor.x * spec * 255);
			buf[(y * size + x) * 4 + 1] = (unsigned char) (mapInfo->light.unitSpecularColor.y * spec * 255);
			buf[(y * size + x) * 4 + 2] = (unsigned char) (mapInfo->light.unitSpecularColor.z * spec * 255);
			buf[(y * size + x) * 4 + 3] = 255;
		}
	}

	//! note: no mipmaps, cubemap linear filtering is broken
	glTexImage2D(texType, 0, GL_RGBA8, size, size, 0, GL_RGBA,GL_UNSIGNED_BYTE, buf);
	delete[] buf;
}
Example #4
0
void CPlasmaRepulser::NewProjectile(CWeaponProjectile* p)
{
	if (weaponDef->smartShield && teamHandler->AlliedTeams(p->owner()->team, owner->team)) {
		return;
	}

	float3 dir = p->speed;
	if (p->targetPos != ZeroVector) {
		dir = p->targetPos - p->pos; // assume that it will travel roughly in the direction of the targetpos if it have one
	}

	dir.y = 0.0f;
	dir.SafeNormalize();

	const float3 dif = owner->pos - p->pos;

	if (weaponDef->exteriorShield && (dif.SqLength() < sqRadius)) {
		return;
	}

	const float closeLength = std::max(0.0f, dif.dot(dir));
	const float3 closeVect = dif - dir * closeLength;
	const float closeDist = closeVect.SqLength2D();

	// TODO: this isn't good enough in case shield is mounted on a mobile unit,
	//       and this unit moves relatively fast compared to the projectile.
	// it should probably be: radius + closeLength / |projectile->speed| * |owner->speed|,
	// but this still doesn't solve anything for e.g. teleporting shields.
	if (closeDist < Square(radius * 1.5f)) {
		incomingProjectiles[p->id] = p;
		AddDeathDependence(p, DEPENDENCE_REPULSED);
	}
}
Example #5
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 #6
0
float CShadowHandler::GetOrthoProjectedMapRadius(const float3& sunDir, float3& projectionMidPos) const {
	// to fit the map inside the frustum, we need to know
	// the distance from one corner to its opposing corner
	//
	// this distance is maximal when the sun direction is
	// orthogonal to the diagonal, but in other cases we
	// can gain some precision by projecting the diagonal
	// onto a vector orthogonal to the sun direction and
	// using the length of that projected vector instead
	//
	// note: "radius" is actually the diameter
	static const float maxMapDiameter = math::sqrtf(Square(gs->mapx * SQUARE_SIZE) + Square(gs->mapy * SQUARE_SIZE));
	static       float curMapDiameter = 0.0f;

	static float3 sunDir3D = ZeroVector;

	if ((sunDir3D != sunDir)) {
		float3 sunDir2D;
		float3 mapVerts[2];

		sunDir3D   = sunDir;
		sunDir2D.x = sunDir3D.x;
		sunDir2D.z = sunDir3D.z;
		sunDir2D.ANormalize();

		if (sunDir2D.x >= 0.0f) {
			if (sunDir2D.z >= 0.0f) {
				// use diagonal vector from top-right to bottom-left
				mapVerts[0] = float3(gs->mapx * SQUARE_SIZE, 0.0f,                   0.0f);
				mapVerts[1] = float3(                  0.0f, 0.0f, gs->mapy * SQUARE_SIZE);
			} else {
				// use diagonal vector from top-left to bottom-right
				mapVerts[0] = float3(                  0.0f, 0.0f,                   0.0f);
				mapVerts[1] = float3(gs->mapx * SQUARE_SIZE, 0.0f, gs->mapy * SQUARE_SIZE);
			}
		} else {
			if (sunDir2D.z >= 0.0f) {
				// use diagonal vector from bottom-right to top-left
				mapVerts[0] = float3(gs->mapx * SQUARE_SIZE, 0.0f, gs->mapy * SQUARE_SIZE);
				mapVerts[1] = float3(                  0.0f, 0.0f,                   0.0f);
			} else {
				// use diagonal vector from bottom-left to top-right
				mapVerts[0] = float3(                  0.0f, 0.0f, gs->mapy * SQUARE_SIZE);
				mapVerts[1] = float3(gs->mapx * SQUARE_SIZE, 0.0f,                   0.0f);
			}
		}

		const float3 v1 = (mapVerts[1] - mapVerts[0]).ANormalize();
		const float3 v2 = float3(-sunDir2D.z, 0.0f, sunDir2D.x);

		curMapDiameter = maxMapDiameter * v2.dot(v1);

		projectionMidPos.x = (gs->mapx * SQUARE_SIZE) * 0.5f;
		projectionMidPos.z = (gs->mapy * SQUARE_SIZE) * 0.5f;
		projectionMidPos.y = ground->GetHeightReal(projectionMidPos.x, projectionMidPos.z, false);
	}

	return curMapDiameter;
}
Example #7
0
	float3 refract(float3 inDir, float3 normal) {
		float ri = refractiveIndex;
		float cosa = -normal.dot(inDir);
		if(cosa < 0) { cosa = -cosa; normal = -normal; ri = 1 / ri; }
		float disc = 1 - (1 - cosa * cosa) / ri / ri;
		if(disc < 0) return reflect(inDir, normal);
		return inDir * (1.0 / ri) + normal * (cosa / ri - sqrt(disc));
	}
Example #8
0
float CPlasmaRepulser::NewBeam(CWeapon* emitter, float3 start, float3 dir, float length, float3& newDir)
{
	if (!isEnabled) {
		return -1.0f;
	}

	// ::Update handles projectile <-> shield interactions for normal weapons, but
	// does not get called when the owner is stunned (CUnit::Update returns early)
	// BeamLasers and LightningCannons are hitscan (their projectiles do not move),
	// they call InterceptHandler to figure out if a shield is in the way so check
	// the stunned-state here keep things consistent
	if (owner->stunned) {
		return -1.0f;
	}

	if (emitter->weaponDef->damages[0] > curPower) {
		return -1.0f;
	}
	if (weaponDef->smartShield && teamHandler->AlliedTeams(emitter->owner->team, owner->team)) {
		return -1.0f;
	}

	const float3 dif = weaponPos - start;

	if (weaponDef->exteriorShield && dif.SqLength() < sqRadius) {
		return -1.0f;
	}

	const float closeLength = dif.dot(dir);

	if (closeLength < 0.0f) {
		return -1.0f;
	}

	const float3 closeVect = dif - dir * closeLength;

	const float tmp = sqRadius - closeVect.SqLength();
	if ((tmp > 0.0f) && (length > (closeLength - math::sqrt(tmp)))) {
		const float colLength = closeLength - math::sqrt(tmp);
		const float3 colPoint = start + dir * colLength;
		const float3 normal = (colPoint - weaponPos).Normalize();
		newDir = dir - normal * normal.dot(dir) * 2;
		return colLength;
	}
	return -1.0f;
}
Example #9
0
static inline bool AABBInOriginPlane(const float3& plane, const float3& camPos,
                                     const float3& mins, const float3& maxs)
{
    float3 fp; // far point
    fp.x = (plane.x > 0.0f) ? mins.x : maxs.x;
    fp.y = (plane.y > 0.0f) ? mins.y : maxs.y;
    fp.z = (plane.z > 0.0f) ? mins.z : maxs.z;
    return (plane.dot(fp - camPos) < 0.0f);
}
Example #10
0
bool CCamera::InView(const float3& p, float radius) const
{
	const float3 t(p - pos);

	if ((t.dot(rgtFrustumSideDir) > radius) ||
	    (t.dot(lftFrustumSideDir) > radius) ||
	    (t.dot(botFrustumSideDir) > radius) ||
	    (t.dot(topFrustumSideDir) > radius)) {
		return false;
	}

	const float lsq = t.SqLength();
	if (lsq > Square(globalRendering->viewRange)) {
		return false;
	}

	return true;
}
Example #11
0
    virtual float3 shade(float3 normal,
                         float3 viewDir,
                         float3 lightDir,
                         float3 lightPowerDensity)
    {
        float cosTheta = normal.dot(lightDir);
        if(cosTheta < 0) {
            return float3(0,0,0);
        }
        float3 diffuse = lightPowerDensity * kd * cosTheta;

        float3 halfway = (viewDir + lightDir).normalize();
        float cosDelta = normal.dot(halfway);
        if(cosDelta < 0) {
            return diffuse;
        }
        return lightPowerDensity * ks * pow(cosDelta, shininess) + diffuse;
    }
Example #12
0
CStarburstProjectile::CStarburstProjectile(const ProjectileParams& params,
        float areaOfEffect, float maxSpeed, float tracking, int uptime, float maxRange, float3 aimError)
    : CWeaponProjectile(params)
    , tracking(tracking)
    , maxSpeed(maxSpeed)
    , acceleration(0.f)
    , areaOfEffect(areaOfEffect)
    , age(0)
    , oldSmoke(pos)
    , aimError(aimError)
    , drawTrail(true)
    , numParts(0)
    , doturn(true)
    , curCallback(NULL)
    , missileAge(0)
    , distanceToTravel(maxRange)
    , curTracerPart(0)
{
    projectileType = WEAPON_STARBURST_PROJECTILE;
    this->uptime = uptime;

    if (weaponDef) {
        if (weaponDef->flighttime == 0) {
            ttl = (int) std::min(3000.0f, uptime + weaponDef->range / maxSpeed + 100);
        } else {
            ttl = weaponDef->flighttime;
        }
    }

    maxGoodDif = math::cos(tracking * 0.6f);
    curSpeed = speed.Length();
    dir = speed / curSpeed;
    oldSmokeDir = dir;

    const float3 camDir = (pos - camera->pos).ANormalize();
    const float camDist = (camera->pos.distance(pos) * 0.2f) + ((1.0f - math::fabs(camDir.dot(dir))) * 3000);

    drawTrail = (camDist >= 200.0f);
    drawRadius = maxSpeed * 8.0f;

    for (int a = 0; a < NUM_TRACER_PARTS; ++a) {
        tracerParts[a].dir = dir;
        tracerParts[a].pos = pos;
        tracerParts[a].speedf = curSpeed;

        tracerParts[a].ageMods.resize(std::floor((curSpeed + 0.6f) / TRACER_PARTS_STEP), 1.0f);
    }
    castShadow = true;

#ifdef TRACE_SYNC
    tracefile << "[" << __FUNCTION__ << "] ";
    tracefile << pos.x << " " << pos.y << " " << pos.z << " " << speed.x << " " << speed.y << " " << speed.z << "\n";
#endif

    cegID = gCEG->Load(explGenHandler, (weaponDef != NULL)? weaponDef->cegTag: "");
}
Example #13
0
bool CWeapon::TryTarget(const float3& tgtPos, bool /*userTarget*/, CUnit* targetUnit)
{
	if (targetUnit && !(onlyTargetCategory & targetUnit->category)) {
		return false;
	}

	if (targetUnit && ((targetUnit->isDead   && (modInfo.fireAtKilled   == 0)) ||
	                   (targetUnit->crashing && (modInfo.fireAtCrashing == 0)))) {
		return false;
	}
	if (weaponDef->stockpile && !numStockpiled) {
		return false;
	}

	float3 targetPos = tgtPos;
	float3 targetVec = targetPos - weaponMuzzlePos;
	float3 targetDir = targetVec;

	float heightDiff = 0.0f; // negative when target below owner
	float weaponRange = 0.0f; // range modified by heightDiff and cylinderTargetting
	bool targetDirNormalized = false;

	if (targetBorder != 0.0f && targetUnit != NULL) {
		// adjust the length of <targetVec> based on the targetBorder factor
		targetDirNormalized = AdjustTargetVectorLength(targetUnit, targetPos, targetVec, targetDir);
		targetPos.y = weaponPos.y + targetVec.y;
	}

	heightDiff = targetPos.y - owner->pos.y;

	if (targetUnit == NULL || cylinderTargetting < 0.01f) {
		// check range in a sphere (with extra radius <heightDiff * heightMod>)
		weaponRange = GetRange2D(heightDiff * heightMod);
	} else {
		// check range in a cylinder (with height <cylinderTargetting * range>)
		if ((cylinderTargetting * range) > (math::fabsf(heightDiff) * heightMod)) {
			weaponRange = GetRange2D(0.0f);
		}
	}

	if (targetVec.SqLength2D() >= (weaponRange * weaponRange))
		return false;

	if (maxMainDirAngleDif > -0.999f) {
		const float3 targetNormDir = targetDirNormalized? targetDir: targetDir.SafeNormalize();
		const float3 modMainDir =
			owner->frontdir * mainDir.z +
			owner->rightdir * mainDir.x +
			owner->updir    * mainDir.y;

		if (modMainDir.dot(targetNormDir) < maxMainDirAngleDif)
			return false;
	}

	return true;
}
float CShadowHandler::GetOrthoProjectedMapRadius(const float3& sunDir, float3& projPos) {
	// to fit the map inside the frustum, we need to know
	// the distance from one corner to its opposing corner
	//
	// this distance is maximal when the sun direction is
	// orthogonal to the diagonal, but in other cases we
	// can gain some precision by projecting the diagonal
	// onto a vector orthogonal to the sun direction and
	// using the length of that projected vector instead
	//
	const float maxMapDiameter = readMap->GetBoundingRadius() * 2.0f;
	static float curMapDiameter = 0.0f;

	// recalculate pos only if the sun-direction has changed
	if (sunProjDir != sunDir) {
		sunProjDir = sunDir;

		float3 sunDirXZ = (sunDir * XZVector).ANormalize();
		float3 mapVerts[2];

		if (sunDirXZ.x >= 0.0f) {
			if (sunDirXZ.z >= 0.0f) {
				// use diagonal vector from top-right to bottom-left
				mapVerts[0] = float3(mapDims.mapx * SQUARE_SIZE, 0.0f,                       0.0f);
				mapVerts[1] = float3(                      0.0f, 0.0f, mapDims.mapy * SQUARE_SIZE);
			} else {
				// use diagonal vector from top-left to bottom-right
				mapVerts[0] = float3(                      0.0f, 0.0f,                       0.0f);
				mapVerts[1] = float3(mapDims.mapx * SQUARE_SIZE, 0.0f, mapDims.mapy * SQUARE_SIZE);
			}
		} else {
			if (sunDirXZ.z >= 0.0f) {
				// use diagonal vector from bottom-right to top-left
				mapVerts[0] = float3(mapDims.mapx * SQUARE_SIZE, 0.0f, mapDims.mapy * SQUARE_SIZE);
				mapVerts[1] = float3(                      0.0f, 0.0f,                       0.0f);
			} else {
				// use diagonal vector from bottom-left to top-right
				mapVerts[0] = float3(                      0.0f, 0.0f, mapDims.mapy * SQUARE_SIZE);
				mapVerts[1] = float3(mapDims.mapx * SQUARE_SIZE, 0.0f,                       0.0f);
			}
		}

		const float3 v1 = (mapVerts[1] - mapVerts[0]).ANormalize();
		const float3 v2 = float3(-sunDirXZ.z, 0.0f, sunDirXZ.x);

		curMapDiameter = maxMapDiameter * v2.dot(v1);

		projPos.x = (mapDims.mapx * SQUARE_SIZE) * 0.5f;
		projPos.z = (mapDims.mapy * SQUARE_SIZE) * 0.5f;
		projPos.y = CGround::GetHeightReal(projPos.x, projPos.z, false);
	}

	return curMapDiameter;
}
Example #15
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;
	}
}
Example #16
0
/**
 * helper for TestCone
 * @return true if object <o> is in the firing cone, false otherwise
 */
inline static bool TestConeHelper(
	const float3& pos3D,
	const float3& dir3D,
	const float length,
	const float spread,
	const CSolidObject* obj)
{
	const CollisionVolume* cv = obj->collisionVolume;

	const float3 objVec3D = cv->GetWorldSpacePos(obj, ZeroVector) - pos3D;
	const float  objDst1D = Clamp(objVec3D.dot(dir3D), 0.0f, length);
	const float  coneSize = math::fabs(objDst1D) * spread + 1.0f;

	// theoretical impact position assuming no spread
	const float3 expVec3D = dir3D * objDst1D;
	const float3 expPos3D = pos3D + expVec3D;

	bool ret = false;

	if (obj->GetBlockingMapID() < unitHandler->MaxUnits()) {
		if (!ret) { ret = ((cv->GetPointSurfaceDistance(static_cast<const CUnit*>(obj), NULL,    pos3D) - coneSize) <= 0.0f); }
		if (!ret) { ret = ((cv->GetPointSurfaceDistance(static_cast<const CUnit*>(obj), NULL, expPos3D) - coneSize) <= 0.0f); }
	} else {
		if (!ret) { ret = ((cv->GetPointSurfaceDistance(static_cast<const CFeature*>(obj), NULL,    pos3D) - coneSize) <= 0.0f); }
		if (!ret) { ret = ((cv->GetPointSurfaceDistance(static_cast<const CFeature*>(obj), NULL, expPos3D) - coneSize) <= 0.0f); }
	}

	if (globalRendering->drawdebugtraceray && (!GML::SimEnabled() || Threading::IsSimThread())) {
		#define go geometricObjects

		if (ret) {
			go->SetColor(go->AddLine(expPos3D - (UpVector * expPos3D.dot(UpVector)), expPos3D, 3, 1, GAME_SPEED), 1.0f, 0.0f, 0.0f, 1.0f);
		} else {
			go->SetColor(go->AddLine(expPos3D - (UpVector * expPos3D.dot(UpVector)), expPos3D, 3, 1, GAME_SPEED), 0.0f, 1.0f, 0.0f, 1.0f);
		}

		#undef go
	}

	return ret;
}
Example #17
0
bool CCamera::InView(const float3 &p, float radius)
{
	const float3 t = (p - pos);
	const float  l = t.Length();

	if (l < 50.0f) {
		return true;
	}
	else if (l > gu->viewRange) {
		return false;
	}
	
	if ((t.dot(rightside) > radius) ||
	    (t.dot(leftside)  > radius) ||
	    (t.dot(bottom)    > radius) ||
	    (t.dot(top)       > radius)) {
		return false;
	}

	return true;
}
Example #18
0
bool CCamera::InView(const float3& p, float radius)
{
    const float3 t   = (p - pos);
    const float  lsq = t.SqLength();

    if (lsq < 2500.0f) {
        return true;
    }
    else if (lsq > Square(globalRendering->viewRange)) {
        return false;
    }

    if ((t.dot(rightside) > radius) ||
            (t.dot(leftside)  > radius) ||
            (t.dot(bottom)    > radius) ||
            (t.dot(top)       > radius)) {
        return false;
    }

    return true;
}
Example #19
0
/**
 * GetSelectionBoxCoeff
 *  returns the topright & bottomleft corner positions of the SelectionBox in (cam->right, cam->up)-space
 */
void CMouseHandler::GetSelectionBoxCoeff(const float3& pos1, const float3& dir1, const float3& pos2, const float3& dir2, float2& topright, float2& btmleft)
{
	float dist = ground->LineGroundCol(pos1, pos1 + dir1 * globalRendering->viewRange * 1.4f, false);
	if(dist < 0) dist = globalRendering->viewRange * 1.4f;
	float3 gpos1 = pos1 + dir1 * dist;

	dist = ground->LineGroundCol(pos2, pos2 + dir2 * globalRendering->viewRange * 1.4f, false);
	if(dist < 0) dist = globalRendering->viewRange * 1.4f;
	float3 gpos2 = pos2 + dir2 * dist;

	const float3 cdir1 = (gpos1 - camera->pos).ANormalize();
	const float3 cdir2 = (gpos2 - camera->pos).ANormalize();

	// prevent DivByZero
	float cdir1_fw = cdir1.dot(camera->forward); if (cdir1_fw == 0.0f) cdir1_fw = 0.0001f;
	float cdir2_fw = cdir2.dot(camera->forward); if (cdir2_fw == 0.0f) cdir2_fw = 0.0001f;

	// one corner of the rectangle
	topright.x = cdir1.dot(camera->right) / cdir1_fw;
	topright.y = cdir1.dot(camera->up)    / cdir1_fw;

	// opposite corner
	btmleft.x = cdir2.dot(camera->right) / cdir2_fw;
	btmleft.y = cdir2.dot(camera->up)    / cdir2_fw;

	// sort coeff so topright really is the topright corner
	if (topright.x < btmleft.x) std::swap(topright.x, btmleft.x);
	if (topright.y < btmleft.y) std::swap(topright.y, btmleft.y);
}
Example #20
0
int CFlameProjectile::ShieldRepulse(CPlasmaRepulser* shield, float3 shieldPos, float shieldForce, float shieldMaxSpeed)
{
	if (!luaMoveCtrl) {
		const float3 rdir = (pos - shieldPos).Normalize();

		if (rdir.dot(speed) < shieldMaxSpeed) {
			speed += (rdir * shieldForce);
			return 2;
		}
	}

	return 0;
}
int CExplosiveProjectile::ShieldRepulse(const float3& shieldPos, float shieldForce, float shieldMaxSpeed)
{
	if (luaMoveCtrl)
		return 0;

	const float3 rdir = (pos - shieldPos).Normalize();

	if (rdir.dot(speed) < shieldMaxSpeed) {
		SetVelocityAndSpeed(speed + (rdir * shieldForce));
		return 2;
	}

	return 0;
}
Example #22
0
/**
 * helper for TestTrajectoryCone
 * @return true if object <o> is in the firing trajectory, false otherwise
 */
inline bool TestTrajectoryConeHelper(
	const float3& from,
	const float3& flatdir,
	float length,
	float linear,
	float quadratic,
	float spread,
	float baseSize,
	const CSolidObject* o)
{
	const CollisionVolume* cv = o->collisionVolume;
	float3 dif = (o->midPos + cv->GetOffsets()) - from;
	const float3 flatdif(dif.x, 0, dif.z);
	float closeFlatLength = flatdif.dot(flatdir);

	if (closeFlatLength <= 0)
		return false;
	if (closeFlatLength > length)
		closeFlatLength = length;

	if (fabs(linear - quadratic * closeFlatLength) < 0.15f) {
		// relatively flat region -> use approximation
		dif.y -= (linear + quadratic * closeFlatLength) * closeFlatLength;

		// NOTE: overly conservative for non-spherical volumes
		const float3 closeVect = dif - flatdir * closeFlatLength;
		const float r = cv->GetBoundingRadius() + spread * closeFlatLength + baseSize;
		if (closeVect.SqLength() < r * r) {
			return true;
		}
	} else {
		float3 newfrom = from + flatdir * closeFlatLength;
		newfrom.y += (linear + quadratic * closeFlatLength) * closeFlatLength;
		float3 dir = flatdir;
		dir.y = linear + quadratic * closeFlatLength;
		dir.Normalize();

		dif = (o->midPos + cv->GetOffsets()) - newfrom;
		const float closeLength = dif.dot(dir);

		// NOTE: overly conservative for non-spherical volumes
		const float3 closeVect = dif - dir * closeLength;
		const float r = cv->GetBoundingRadius() + spread * closeFlatLength + baseSize;
		if (closeVect.SqLength() < r * r) {
			return true;
		}
	}
	return false;
}
Example #23
0
float CPlasmaRepulser::NewBeam(CWeapon* emitter, float3 start, float3 dir, float length, float3& newDir)
{
	if (!isEnabled) {
		return -1;
	}
	if (emitter->weaponDef->damages[0] > curPower) {
		return -1;
	}
	if (weaponDef->smartShield && teamHandler->AlliedTeams(emitter->owner->team, owner->team)) {
		return -1;
	}

	const float3 dif = weaponPos - start;

	if (weaponDef->exteriorShield && dif.SqLength() < sqRadius) {
		return -1;
	}

	const float closeLength = dif.dot(dir);

	if (closeLength < 0) {
		return -1;
	}

	const float3 closeVect = dif - dir * closeLength;

	const float tmp = sqRadius - closeVect.SqLength();
	if ((tmp > 0) && (length > (closeLength - sqrt(tmp)))) {
		const float colLength = closeLength - sqrt(tmp);
		const float3 colPoint = start + dir * colLength;
		const float3 normal = (colPoint - weaponPos).Normalize();
		newDir = dir - normal * normal.dot(dir) * 2;
		return colLength;
	}
	return -1;
}
Example #24
0
float CGameHelper::GuiTraceRayFeature(const float3& start, const float3& dir, float length, CFeature*& feature)
{
    float nearHit = length;

    GML_RECMUTEX_LOCK(quad); // GuiTraceRayFeature

    std::vector<int> quads = qf->GetQuadsOnRay(start, dir, length);
    std::vector<int>::iterator qi;

    for (qi = quads.begin(); qi != quads.end(); ++qi) {
        const CQuadField::Quad& quad = qf->GetQuad(*qi);
        std::list<CFeature*>::const_iterator ui;

        // NOTE: switch this to custom volumes fully?
        // (not used for any LOF checks, maybe wasteful)
        for (ui = quad.features.begin(); ui != quad.features.end(); ++ui) {
            CFeature* f = *ui;

            if (!gu->spectatingFullView && !f->IsInLosForAllyTeam(gu->myAllyTeam)) {
                continue;
            }
            if (f->noSelect) {
                continue;
            }

            CollisionVolume* cv = f->collisionVolume;
            const float3& midPosOffset = cv? cv->GetOffsets(): ZeroVector;
            const float3 dif = (f->midPos + midPosOffset) - start;
            float closeLength = dif.dot(dir);

            if (closeLength < 0)
                continue;
            if (closeLength > nearHit)
                continue;

            float3 closeVect = dif - dir * closeLength;
            if (closeVect.SqLength() < f->sqRadius) {
                nearHit = closeLength;
                feature = f;
            }
        }
    }

    return nearHit;
}
Example #25
0
void CubeMapHandler::CreateSpecularFacePart(
	unsigned int texType,
	unsigned int size,
	const float3& cdir,
	const float3& xdif,
	const float3& ydif,
	unsigned int y,
	unsigned char* buf)
{
	for (int x = 0; x < size; ++x) {
		const float3 dir = (cdir + (xdif * (x + 0.5f)) / size + (ydif * (y + 0.5f)) / size).Normalize();
		const float dot = std::max(0.0f, dir.dot(globalRendering->sunDir));
		const float spec = std::min(1.0f, pow(dot, specExp) + pow(dot, 3.0f) * 0.25f);

		buf[x * 4 + 0] = (mapInfo->light.unitSpecularColor.x * spec * 255);
		buf[x * 4 + 1] = (mapInfo->light.unitSpecularColor.y * spec * 255);
		buf[x * 4 + 2] = (mapInfo->light.unitSpecularColor.z * spec * 255);
		buf[x * 4 + 3] = 255;
	}
}
Example #26
0
bool CBuilder::ScriptStartBuilding(float3 pos, bool silent)
{
	if (script->HasStartBuilding()) {
		const float3 wantedDir = (pos - midPos).Normalize();
		const float h = GetHeadingFromVectorF(wantedDir.x, wantedDir.z);
		const float p = math::asin(wantedDir.dot(updir));
		const float pitch = math::asin(frontdir.dot(updir));

		// clamping p - pitch not needed, range of asin is -PI/2..PI/2,
		// so max difference between two asin calls is PI.
		// FIXME: convert CSolidObject::heading to radians too.
		script->StartBuilding(ClampRad(h - heading * TAANG2RAD), p - pitch);
	}

	if ((!silent || inBuildStance) && losStatus[gu->myAllyTeam] & LOS_INLOS) {
		Channels::General->PlayRandomSample(unitDef->sounds.build, pos);
	}

	return inBuildStance;
}
Example #27
0
/*
Extract height and slope data from given square and make
a sub-functional call for calculations upon whose data.
*/
float CMoveMath::SpeedMod(const MoveData& moveData, int xSquare, int zSquare,const float3& moveDir) {
    //Error-check
    if(xSquare < 0 || zSquare < 0
            || xSquare >= gs->mapx || zSquare >= gs->mapy)
        return 0.0f;

    //Extract data.
    int square = xSquare/2 + zSquare/2 * gs->hmapx;
    float height = readmap->halfHeightmap[square];
    float slope = readmap->slopemap[square];

    float3 flatNorm=readmap->facenormals[(xSquare + zSquare * gs->mapx)*2];
    flatNorm.y=0;
    flatNorm.Normalize();
    float moveSlope=-moveDir.dot(flatNorm);
    float typemod=moveinfo->terrainType2MoveFamilySpeed[readmap->typemap[square]][moveData.moveFamily];

    //Call calculations.
    return SpeedMod(moveData, height, slope,moveSlope)*typemod;
}
Example #28
0
void CBuilder::SetBuildStanceToward(float3 pos)
{
	if (script->HasStartBuilding()) {
		const float3 wantedDir = (pos - midPos).Normalize();
		const float h = GetHeadingFromVectorF(wantedDir.x, wantedDir.z);
		const float p = asin(wantedDir.dot(updir));
		const float pitch = asin(frontdir.dot(updir));

		// clamping p - pitch not needed, range of asin is -PI/2..PI/2,
		// so max difference between two asin calls is PI.
		// FIXME: convert CSolidObject::heading to radians too.
		script->StartBuilding(ClampRad(h - heading * TAANG2RAD), p - pitch);
	}

	#if (PLAY_SOUNDS == 1)
	if (losStatus[gu->myAllyTeam] & LOS_INLOS) {
		Channels::General.PlayRandomSample(unitDef->sounds.build, pos);
	}
	#endif
}
Example #29
0
void CubeMapHandler::CreateSpecularFacePart(
	unsigned int texType,
	unsigned int size,
	const float3& cdir,
	const float3& xdif,
	const float3& ydif,
	unsigned int y,
	unsigned char* buf)
{
	// TODO move to a shader
	for (int x = 0; x < size; ++x) {
		const float3 dir = (cdir + (xdif * (x + 0.5f)) / size + (ydif * (y + 0.5f)) / size).Normalize();
		const float dot  = std::max(0.0f, dir.dot(sky->GetLight()->GetLightDir()));
		const float spec = std::min(1.0f, pow(dot, mapInfo->light.specularExponent) + pow(dot, 3.0f) * 0.25f);

		buf[x * 4 + 0] = (mapInfo->light.unitSpecularColor.x * spec * 255);
		buf[x * 4 + 1] = (mapInfo->light.unitSpecularColor.y * spec * 255);
		buf[x * 4 + 2] = (mapInfo->light.unitSpecularColor.z * spec * 255);
		buf[x * 4 + 3] = 255;
	}
}
Example #30
0
void CPlasmaRepulser::NewProjectile(CWeaponProjectile* p)
{
	// PlasmaRepulser instances are created if type == "Shield",
	// but projectiles are removed from incomingProjectiles only
	// if def->interceptor || def->isShield --> dangling pointers
	// due to isShield being a separate tag (in 91.0)
	assert(weaponDef->isShield);

	if (weaponDef->smartShield && p->owner() && teamHandler->AlliedTeams(p->owner()->team, owner->team)) {
		return;
	}

	float3 dir = p->speed;
	if (p->GetTargetPos() != ZeroVector) {
		// assume projectile will travel roughly in the direction of its targetpos
		dir = p->GetTargetPos() - p->pos;
	}

	dir.y = 0.0f;
	dir.SafeNormalize();

	const float3 dif = owner->pos - p->pos;

	if (weaponDef->exteriorShield && (dif.SqLength() < sqRadius)) {
		return;
	}

	const float closeLength = std::max(0.0f, dif.dot(dir));
	const float3 closeVect = dif - dir * closeLength;
	const float closeDist = closeVect.SqLength2D();

	// TODO: this isn't good enough in case shield is mounted on a mobile unit,
	//       and this unit moves relatively fast compared to the projectile.
	// it should probably be: radius + closeLength / |projectile->speed| * |owner->speed|,
	// but this still doesn't solve anything for e.g. teleporting shields.
	if (closeDist < Square(radius * 1.5f)) {
		incomingProjectiles[p->id] = p;
		AddDeathDependence(p, DEPENDENCE_REPULSED);
	}
}