예제 #1
0
// This gets an AABB for the renderable, but it doesn't cause a parent's bones to be setup.
// This is used for placement in the leaves, but the more expensive version is used for culling.
void CalcRenderableWorldSpaceAABB_Fast( IClientRenderable *pRenderable, Vector &absMin, Vector &absMax )
{
	C_BaseEntity *pEnt = pRenderable->GetIClientUnknown()->GetBaseEntity();
	if ( pEnt && pEnt->IsFollowingEntity() )
	{
		C_BaseEntity *pParent = pEnt->GetMoveParent();
		Assert( pParent );

		// Get the parent's abs space world bounds.
		CalcRenderableWorldSpaceAABB_Fast( pParent, absMin, absMax );

		// Add the maximum of our local render bounds. This is making the assumption that we can be at any
		// point and at any angle within the parent's world space bounds.
		Vector vAddMins, vAddMaxs;
		pEnt->GetRenderBounds( vAddMins, vAddMaxs );
		// if our origin is actually farther away than that, expand again
		float radius = pEnt->GetLocalOrigin().Length();

		float flBloatSize = max( vAddMins.Length(), vAddMaxs.Length() );
		flBloatSize = max(flBloatSize, radius);
		absMin -= Vector( flBloatSize, flBloatSize, flBloatSize );
		absMax += Vector( flBloatSize, flBloatSize, flBloatSize );
	}
	else
	{
		// Start out with our own render bounds. Since we don't have a parent, this won't incur any nasty 
		CalcRenderableWorldSpaceAABB( pRenderable, absMin, absMax );
	}
}
예제 #2
0
//-----------------------------------------------------------------------------
// Helper functions.
//-----------------------------------------------------------------------------
void DefaultRenderBoundsWorldspace( IClientRenderable *pRenderable, Vector &absMins, Vector &absMaxs )
{
	// Tracker 37433:  This fixes a bug where if the stunstick is being wielded by a combine soldier, the fact that the stick was
	//  attached to the soldier's hand would move it such that it would get frustum culled near the edge of the screen.
	C_BaseEntity *pEnt = pRenderable->GetIClientUnknown()->GetBaseEntity();
	if ( pEnt && pEnt->IsFollowingEntity() )
	{
		C_BaseEntity *pParent = pEnt->GetFollowedEntity();
		if ( pParent )
		{
			// Get the parent's abs space world bounds.
			CalcRenderableWorldSpaceAABB_Fast( pParent, absMins, absMaxs );

			// Add the maximum of our local render bounds. This is making the assumption that we can be at any
			// point and at any angle within the parent's world space bounds.
			Vector vAddMins, vAddMaxs;
			pEnt->GetRenderBounds( vAddMins, vAddMaxs );
			// if our origin is actually farther away than that, expand again
			float radius = pEnt->GetLocalOrigin().Length();

			float flBloatSize = max( vAddMins.Length(), vAddMaxs.Length() );
			flBloatSize = max(flBloatSize, radius);
			absMins -= Vector( flBloatSize, flBloatSize, flBloatSize );
			absMaxs += Vector( flBloatSize, flBloatSize, flBloatSize );
			return;
		}
	}

	Vector mins, maxs;
	pRenderable->GetRenderBounds( mins, maxs );

	// FIXME: Should I just use a sphere here?
	// Another option is to pass the OBB down the tree; makes for a better fit
	// Generate a world-aligned AABB
	const QAngle& angles = pRenderable->GetRenderAngles();
	const Vector& origin = pRenderable->GetRenderOrigin();
	if (angles == vec3_angle)
	{
		VectorAdd( mins, origin, absMins );
		VectorAdd( maxs, origin, absMaxs );
	}
	else
	{
		matrix3x4_t	boxToWorld;
		AngleMatrix( angles, origin, boxToWorld );
		TransformAABB( boxToWorld, mins, maxs, absMins, absMaxs );
	}
	Assert( absMins.IsValid() && absMaxs.IsValid() );
}
예제 #3
0
void C_Camera::CalcTVCamView(Vector& eyeOrigin, QAngle& eyeAngles, float& fov)
{
	if (!GetMatchBall())
		return;

	C_BaseEntity *pTarget;
	bool atMinGoalPos;
	Vector targetPos;
	int tvcamMode = GetTVCamMode();

	if (GetReplayManager() && GetReplayManager()->IsReplaying())
	{
		pTarget = GetReplayBall();

		if (!pTarget)
			return;

		atMinGoalPos = GetReplayManager()->m_bAtMinGoalPos;
		targetPos = pTarget->GetLocalOrigin();
	}
	else
	{
		if (GetMatchBall() && GetMatchBall()->m_eBallState == BALL_STATE_GOAL)
		{
			pTarget = GetMatchBall()->m_pLastActivePlayer;

			if (!pTarget)
				pTarget = GetMatchBall();

			atMinGoalPos = pTarget->GetLocalOrigin().y < SDKGameRules()->m_vKickOff.GetY();
			targetPos = pTarget->GetLocalOrigin();
		}
		else
		{
			pTarget = CBasePlayer::GetLocalPlayer()->GetObserverTarget();
			if (!pTarget)
				pTarget = GetMatchBall();

			atMinGoalPos = pTarget->GetLocalOrigin().y < SDKGameRules()->m_vKickOff.GetY();
			targetPos = pTarget->GetLocalOrigin();

			// Move the camera towards the defending team's goal
			if (GetMatchBall()->m_nLastActiveTeam != TEAM_NONE)
			{
				if (m_nLastPossessingTeam == TEAM_NONE)
				{
					m_nLastPossessingTeam = GetMatchBall()->m_nLastActiveTeam;
					m_flLastPossessionChange = gpGlobals->curtime;
					m_flPossCoeff = 0;
					m_flOldPossCoeff = 0;
				}
				else
				{
					if (GetMatchBall()->m_nLastActiveTeam != m_nLastPossessingTeam)
					{
						m_nLastPossessingTeam = GetMatchBall()->m_nLastActiveTeam;
						m_flLastPossessionChange = gpGlobals->curtime;
						m_flOldPossCoeff = m_flPossCoeff;
					}

					float timeFrac = min(1.0f, (gpGlobals->curtime - m_flLastPossessionChange) / mp_tvcam_offset_forward_time.GetFloat());
					float frac = pow(timeFrac, 2) * (3 - 2 * timeFrac); 
					m_flPossCoeff = Lerp(frac, m_flOldPossCoeff, (float)GetGlobalTeam(GetMatchBall()->m_nLastActiveTeam)->m_nForward);
				}

				if (tvcamMode == TVCAM_MODE_SIDELINE)
				{
					targetPos.y += m_flPossCoeff * mp_tvcam_offset_forward.GetInt();
				}
			}
		}
	}

	if (tvcamMode != TVCAM_MODE_CELEBRATION)
	{
		// Make sure the camera doesn't move too far away from the field borders
		targetPos.x = clamp(targetPos.x, SDKGameRules()->m_vFieldMin.GetX() + mp_tvcam_border_south.GetInt(), SDKGameRules()->m_vFieldMax.GetX() - mp_tvcam_border_north.GetInt());
		targetPos.y = clamp(targetPos.y, SDKGameRules()->m_vFieldMin.GetY() + mp_tvcam_border_west.GetInt(), SDKGameRules()->m_vFieldMax.GetY() - mp_tvcam_border_east.GetInt());
		targetPos.z = SDKGameRules()->m_vKickOff.GetZ();
	}

	if (m_vOldTargetPos == vec3_invalid)
		m_vOldTargetPos = targetPos;
	else
	{
		float speedCoeff = tvcamMode == TVCAM_MODE_CELEBRATION ? mp_tvcam_speed_coeff_fast.GetFloat() : mp_tvcam_speed_coeff.GetFloat();
		float speedExp = tvcamMode == TVCAM_MODE_CELEBRATION ? mp_tvcam_speed_exponent_fast.GetFloat() : mp_tvcam_speed_exponent.GetFloat();
		Vector changeDir = targetPos - m_vOldTargetPos;
		float changeDist = changeDir.Length();
		changeDir.NormalizeInPlace();
		targetPos = m_vOldTargetPos + changeDir * min(changeDist, pow(changeDist * speedCoeff, speedExp) * gpGlobals->frametime);
	}

	switch (GetTVCamMode())
	{
	case TVCAM_MODE_SIDELINE:
		{
			if (SDKGameRules() && SDKGameRules()->IsIntermissionState() && GetReplayManager() && !GetReplayManager()->IsReplaying())
			{
				//float xLength = SDKGameRules()->m_vFieldMax.GetX() - SDKGameRules()->m_vFieldMin.GetX();
				//float yLength = SDKGameRules()->m_vFieldMax.GetY() - SDKGameRules()->m_vFieldMin.GetY();

				float zPos = 450;
				Vector points[4];
				points[0] = Vector(SDKGameRules()->m_vFieldMin.GetX(), SDKGameRules()->m_vFieldMin.GetY(), SDKGameRules()->m_vKickOff.GetZ() + zPos);
				points[1] = Vector(SDKGameRules()->m_vFieldMin.GetX(), SDKGameRules()->m_vFieldMax.GetY(), SDKGameRules()->m_vKickOff.GetZ() + zPos);
				points[2] = Vector(SDKGameRules()->m_vFieldMax.GetX(), SDKGameRules()->m_vFieldMax.GetY(), SDKGameRules()->m_vKickOff.GetZ() + zPos);
				points[3] = Vector(SDKGameRules()->m_vFieldMax.GetX(), SDKGameRules()->m_vFieldMin.GetY(), SDKGameRules()->m_vKickOff.GetZ() + zPos);
				float totalLength = (points[1] - points[0]).Length() + (points[2] - points[1]).Length() + (points[3] - points[2]).Length() + (points[0] - points[3]).Length();

				Vector newPoints[4];

				const float maxDuration = 180.0f;
				float timePassed = fmodf(gpGlobals->curtime, maxDuration);
				
				float lengthSum = 0;
				int offset = 0;
				float length = 0;

				do
				{
					for (int i = 0; i < 4; i++)
						newPoints[i] = points[(i + offset) % 4];

					length = (newPoints[2] - newPoints[1]).Length();
					lengthSum += length;
					offset += 1;
				} while (timePassed > (lengthSum / totalLength * maxDuration));

				float maxStepTime = length / totalLength * maxDuration;

				float frac = 1 - ((lengthSum / totalLength * maxDuration) - timePassed) / maxStepTime;

				Vector output;
				Catmull_Rom_Spline(newPoints[0], newPoints[1], newPoints[2], newPoints[3], frac, output);

/*				float targetDist = (newPoints[2] - newPoints[1]).Length() * frac;
				float epsilon = 10.0f;
				float oldDiff = 0;
				float diff = 0;
				float change = 0.001f;
				bool add = true;

				do
				{
					frac = clamp(frac += (add ? change : -change), 0.0f, 1.0f);

					Catmull_Rom_Spline(newPoints[0], newPoints[1], newPoints[2], newPoints[3], frac, output);
					oldDiff = diff;
					diff = abs((output - newPoints[1]).Length() - targetDist);
					if (diff >= oldDiff)
						add = !add;
				} while (diff > epsilon);*/ 

				eyeOrigin = output;
				VectorAngles(SDKGameRules()->m_vKickOff - output, eyeAngles);
			}
			/*else if (SDKGameRules() && !SDKGameRules()->IsIntermissionState() && gpGlobals->curtime <= SDKGameRules()->m_flStateEnterTime + 4)
			{
				Vector points[4];
				float zPosStart = 450;
				float zPosEnd = 50;
				points[0] = Vector(SDKGameRules()->m_vFieldMin.GetX(), SDKGameRules()->m_vKickOff.GetY() + 10000, SDKGameRules()->m_vKickOff.GetZ() + zPosStart);
				points[1] = Vector(SDKGameRules()->m_vFieldMin.GetX(), SDKGameRules()->m_vKickOff.GetY(), SDKGameRules()->m_vKickOff.GetZ() + zPosStart);
				points[2] = Vector(SDKGameRules()->m_vKickOff.GetX(), SDKGameRules()->m_vKickOff.GetY() - 300, SDKGameRules()->m_vKickOff.GetZ() + zPosEnd);
				points[3] = Vector(SDKGameRules()->m_vKickOff.GetX(), SDKGameRules()->m_vKickOff.GetY() + 10000, SDKGameRules()->m_vKickOff.GetZ() + zPosEnd);
				float frac = min(1.0f, (gpGlobals->curtime - SDKGameRules()->m_flStateEnterTime) / 3.0f);
				Vector output;
				Catmull_Rom_Spline(points[0], points[1], points[2], points[3], frac, output);
				eyeOrigin = output;
				VectorAngles(Vector(SDKGameRules()->m_vKickOff.GetX(), SDKGameRules()->m_vKickOff.GetY(), SDKGameRules()->m_vKickOff.GetZ() + 100) - output, eyeAngles);
			}*/
			else
			{		
				Vector newPos = Vector(targetPos.x - mp_tvcam_sideline_offset_north.GetInt(), targetPos.y, targetPos.z + mp_tvcam_sideline_offset_height.GetInt());
				Vector offsetTargetPos = Vector(targetPos.x - mp_tvcam_offset_north.GetInt(), targetPos.y, targetPos.z);
				Vector newDir = offsetTargetPos - newPos;
				newDir.NormalizeInPlace();
				eyeOrigin = newPos;
				VectorAngles(newDir, eyeAngles);
			}
		}
		break;
	case TVCAM_MODE_FIXED_SIDELINE:
		{
			Vector newPos = Vector(SDKGameRules()->m_vFieldMin.GetX() - 500, SDKGameRules()->m_vKickOff.GetY(), SDKGameRules()->m_vKickOff.GetZ() + 1000);
			Vector offsetTargetPos = Vector(targetPos.x - 500, targetPos.y, targetPos.z);
			Vector newDir = offsetTargetPos - newPos;
			float dist = newDir.Length();
			newDir.NormalizeInPlace();
			newPos = offsetTargetPos - min(750, dist) * newDir;
			eyeOrigin = newPos;
			VectorAngles(newDir, eyeAngles);
		}
		break;
	case TVCAM_MODE_BEHIND_GOAL:
		{
			float yPos = atMinGoalPos ? SDKGameRules()->m_vFieldMin.GetY() : SDKGameRules()->m_vFieldMax.GetY();
			Vector goalCenter = Vector((SDKGameRules()->m_vFieldMin.GetX() + SDKGameRules()->m_vFieldMax.GetX()) / 2.0f, yPos, SDKGameRules()->m_vKickOff.GetZ());
			Vector newPos = goalCenter + Vector(0, 300 * (atMinGoalPos ? -1 : 1), 300);
			Vector newDir = targetPos - newPos;
			newDir.NormalizeInPlace();
			eyeOrigin = newPos;
			VectorAngles(newDir, eyeAngles);
		}
		break;
	case TVCAM_MODE_TOPDOWN:
		{
			eyeOrigin = Vector(targetPos.x, targetPos.y, SDKGameRules()->m_vKickOff.GetZ() + 1000);
			eyeAngles = QAngle(89, 0, 0);
		}
		break;
	case TVCAM_MODE_FLY_FOLLOW:
		{
			Vector newPos = Vector(targetPos.x, targetPos.y + (atMinGoalPos ? 1 : -1) * 500, SDKGameRules()->m_vKickOff.GetZ() + 225);
			Vector newDir = targetPos - newPos;
			newDir.NormalizeInPlace();
			eyeOrigin = newPos;
			VectorAngles(newDir, eyeAngles);
		}
		break;
	case TVCAM_MODE_GOAL_LINE:
		{
			Vector center = Vector(SDKGameRules()->m_vKickOff.GetX(), (atMinGoalPos ? SDKGameRules()->m_vFieldMin.GetY() + 5 : SDKGameRules()->m_vFieldMax.GetY() - 5), SDKGameRules()->m_vKickOff.GetZ());
			Vector newPos = center;
			newPos.x -= 350;
			newPos.z += 200;
			QAngle newAng;
			VectorAngles(center - newPos, newAng);
			eyeOrigin = newPos;
			eyeAngles = newAng;
		}
		break;
	case TVCAM_MODE_CELEBRATION:
		{
			Vector newPos = Vector(
				targetPos.x < SDKGameRules()->m_vKickOff.GetX() ? SDKGameRules()->m_vFieldMin.GetX() - 500 : SDKGameRules()->m_vFieldMax.GetX() + 500,
				targetPos.y < SDKGameRules()->m_vKickOff.GetY() ? SDKGameRules()->m_vFieldMin.GetY() - 500 : SDKGameRules()->m_vFieldMax.GetY() + 500,
				SDKGameRules()->m_vKickOff.GetZ() + 1000);
			Vector newDir = targetPos - newPos;
			float dist = newDir.Length();
			newDir.NormalizeInPlace();
			newPos = targetPos - min(300, dist) * newDir;
			eyeOrigin = newPos;
			VectorAngles(newDir, eyeAngles);
		}
		break;
	}

	m_vOldTargetPos = targetPos;

	fov = C_SDKPlayer::GetLocalSDKPlayer()->GetFOV();
}
예제 #4
0
void CheckAutoTransparentProps(const Vector &pos, const QAngle &ang)
{
	float opacity = clamp(cl_goal_opacity.GetFloat(), 0.0f, 1.0f);

	for (int i = gpGlobals->maxClients; i <= ClientEntityList().GetHighestEntityIndex(); i++)
	{
		C_BaseEntity *pEnt = ClientEntityList().GetBaseEntity(i);
		if(!dynamic_cast<C_AutoTransparentProp *>(pEnt))
			continue;

		// Check if the camera is behind the goal line and close to the goal. Use an additional offset so the goal post doesn't get in the way.
		if (opacity != 1.0f
			&& (pos.y <= SDKGameRules()->m_vFieldMin.GetY() + cl_goal_opacity_fieldoffset.GetFloat() && pEnt->GetLocalOrigin().y < SDKGameRules()->m_vKickOff.GetY()
				|| pos.y >= SDKGameRules()->m_vFieldMax.GetY() - cl_goal_opacity_fieldoffset.GetFloat() && pEnt->GetLocalOrigin().y > SDKGameRules()->m_vKickOff.GetY())
			&& pos.x >= SDKGameRules()->m_vKickOff.GetX() - 500 && pos.x <= SDKGameRules()->m_vKickOff.GetX() + 500)
		{
			pEnt->SetRenderMode(kRenderTransColor);
			pEnt->SetRenderColorA(opacity * 255);
		}
		else
		{
			pEnt->SetRenderMode(kRenderNormal);
		}
	}
}