//-----------------------------------------------------------------------------
// Purpose: Aim the offset barrel at a position in parent space
// Input  : parentTarget - the position of the target in parent space
// Output : Vector - angles in local space
//-----------------------------------------------------------------------------
QAngle CFuncTank::AimBarrelAt( const Vector &parentTarget )
{
	Vector target = parentTarget - GetLocalOrigin();
	float quadTarget = target.LengthSqr();
	float quadTargetXY = target.x*target.x + target.y*target.y;

	// Target is too close!  Can't aim at it
	if ( quadTarget <= m_barrelPos.LengthSqr() )
	{
		return GetLocalAngles();
	}
	else
	{
		// We're trying to aim the offset barrel at an arbitrary point.
		// To calculate this, I think of the target as being on a sphere with 
		// it's center at the origin of the gun.
		// The rotation we need is the opposite of the rotation that moves the target 
		// along the surface of that sphere to intersect with the gun's shooting direction
		// To calculate that rotation, we simply calculate the intersection of the ray 
		// coming out of the barrel with the target sphere (that's the new target position)
		// and use atan2() to get angles

		// angles from target pos to center
		float targetToCenterYaw = atan2( target.y, target.x );
		float centerToGunYaw = atan2( m_barrelPos.y, sqrt( quadTarget - (m_barrelPos.y*m_barrelPos.y) ) );

		float targetToCenterPitch = atan2( target.z, sqrt( quadTargetXY ) );
		float centerToGunPitch = atan2( -m_barrelPos.z, sqrt( quadTarget - (m_barrelPos.z*m_barrelPos.z) ) );
		return QAngle( -RAD2DEG(targetToCenterPitch+centerToGunPitch), RAD2DEG( targetToCenterYaw - centerToGunYaw ), 0 );		
	}
}
void Matrix4x4::SetRotation(float flAngle, const Vector& v)
{
	// Normalize beforehand
	TAssert(fabs(v.LengthSqr() - 1) < 0.000001f);

	// c = cos(angle), s = sin(angle), t = (1-c)
	// [ xxt+c   xyt-zs  xzt+ys ]
	// [ yxt+zs  yyt+c   yzt-xs ]
	// [ zxt-ys  zyt+xs  zzt+c  ]

	float x = v.x;
	float y = v.y;
	float z = v.z;

	float c = cos(flAngle*(float)M_PI/180);
	float s = sin(flAngle*(float)M_PI/180);
	float t = 1-c;

	m[0][0] = x*x*t + c;
	m[1][0] = x*y*t - z*s;
	m[2][0] = x*z*t + y*s;

	m[0][1] = y*x*t + z*s;
	m[1][1] = y*y*t + c;
	m[2][1] = y*z*t - x*s;

	m[0][2] = z*x*t - y*s;
	m[1][2] = z*y*t + x*s;
	m[2][2] = z*z*t + c;
}
void CPlayerController::Update(const Vector &position, const Vector &velocity, float secondsToArrival, bool onground, IPhysicsObject *ground) {
	btVector3 bullTargetPosition, bullMaxVelocity;

	ConvertPosToBull(position, bullTargetPosition);
	ConvertPosToBull(velocity, bullMaxVelocity);

	// If the targets haven't changed, abort.
	if (bullMaxVelocity.distance2(m_maxVelocity) < FLT_EPSILON && bullTargetPosition.distance2(m_targetPosition) < FLT_EPSILON) {
		return;
	}

	m_targetPosition = bullTargetPosition;
	m_maxVelocity = bullMaxVelocity;

	m_enable = true;

	// FYI: The onground stuff includes any props we may be standing on as well as the world.
	// The ground is valid only if it's significantly heavier than our object ("Rideable physics" > our mass * 2)
	m_onground = onground;

	if (velocity.LengthSqr() <= 0.001f) {
		m_enable = false;
		ground = NULL;
	} else {
		MaxSpeed(velocity);
	}

	m_secondsToArrival = secondsToArrival;

	m_pGround = (CPhysicsObject *)ground;

	m_ticksSinceUpdate = 0;
}
// Actual work code
IterationRetval_t CASW_Scanner_Objects_Enumerator::EnumElement( IHandleEntity *pHandleEntity )
{
#ifndef CLIENT_DLL
		CBaseEntity *pEnt = gEntList.GetBaseEntity( pHandleEntity->GetRefEHandle() );
#else
		C_BaseEntity *pEnt = ClientEntityList().GetBaseEntityFromHandle( pHandleEntity->GetRefEHandle() );
#endif
	
	if ( pEnt == NULL )
		return ITERATION_CONTINUE;

	if (!ValidScannerObject(pEnt))
		return ITERATION_CONTINUE;	

	Vector deltaPos = pEnt->GetAbsOrigin() - m_vecScannerCenter;
	if ( deltaPos.LengthSqr() > m_flRadiusSquared )
		return ITERATION_CONTINUE;

	if ( m_vecScannerCenter.z - pEnt->GetAbsOrigin().z > m_flRadius / 3 )
		return ITERATION_CONTINUE;
	
	CHandle< CBaseEntity > h;
	h = pEnt;
	m_Objects.AddToTail( h );

	return ITERATION_CONTINUE;
}
Example #5
0
void CTriggerMomentumPush::OnSuccessfulTouch(CBaseEntity *pOther)
{
    if (pOther)
    {
        Vector finalVel;
        if (HasSpawnFlags(SF_PUSH_DIRECTION_AS_FINAL_FORCE))
            finalVel = m_vPushDir;
        else
            finalVel = m_vPushDir.Normalized() * m_fPushForce;
        switch (m_iIncrease)
        {
        case 0:
            break;
        case 1:
            finalVel += pOther->GetAbsVelocity();
            break;
        case 2:
            if (finalVel.LengthSqr() < pOther->GetAbsVelocity().LengthSqr())
                finalVel = pOther->GetAbsVelocity();
            break;
        case 3:
            pOther->SetBaseVelocity(finalVel);
            break;
        default:
            DevWarning("CTriggerMomentumPush:: %i not recognised as valid for m_iIncrease", m_iIncrease);
            break;
        }

        pOther->SetAbsVelocity(finalVel);
    }
}
bool C_EnvProjectedTexture::IsWithinFarZ(float flLightFOV)
{
	//No need to check camera space lights for visibility, as they should always be close enough to the player.
	if (m_bCameraSpace)
		return true;

	//Trace forward to the nearest opaque brush face
	Vector vForward;
	GetVectors(&vForward, NULL, NULL);

	Vector vTraceStart = GetAbsOrigin();
	Vector vTraceEnd = GetAbsOrigin() + vForward;

	trace_t tr;
	CTraceFilterWorldOnly filter;

	UTIL_TraceLine(vTraceStart, vTraceEnd, CONTENTS_SOLID && CONTENTS_OPAQUE, &filter, &tr);

	//Test to see if the player is close enough to the light to actually see the light's projection. This is based entirely on it's FarZ.
	C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
	if (pPlayer)
	{
		Vector vDistance;
		VectorSubtract(tr.endpos, pPlayer->EyePosition(), vDistance);

		float fDistance = vDistance.LengthSqr();
		//If distance is greater than the light's FarZ, cease to render.
		//FarZ determines how far away a light can be seen by the player, AND how far the light travels from it's source in stock Valve code.
		if (fDistance > Square(m_flFarZ + flLightFOV * 10))
			return false;
	}

	return true;
}
Example #7
0
void C_Hairball::CHairballDelegate::ApplyConstraints( CSimplePhysics::CNode *pNodes, int nNodes )
{
	int nSegments = m_pParent->m_nNodesPerHair - 1;
	float flSpringDistSqr = m_pParent->m_flSpringDist * m_pParent->m_flSpringDist;

	static int nIterations = 1;
	for( int iIteration=0; iIteration < nIterations; iIteration++ )
	{
		for ( int iHair=0; iHair < m_pParent->m_nHairs; iHair++ )
		{
			CSimplePhysics::CNode *pBase = &pNodes[iHair * m_pParent->m_nNodesPerHair];

			for( int i=0; i < nSegments; i++ )
			{
				Vector &vNode1 = pBase[i].m_vPos;
				Vector &vNode2 = pBase[i+1].m_vPos;
				Vector vTo = vNode1 - vNode2;

				float flDistSqr = vTo.LengthSqr();
				if( flDistSqr > flSpringDistSqr )
				{
					float flDist = (float)sqrt( flDistSqr );
					vTo *= 1 - (m_pParent->m_flSpringDist / flDist);

					vNode1 -= vTo * 0.5f;
					vNode2 += vTo * 0.5f;
				}
			}

			// Lock the base of each hair to the right spot.
			pBase->m_vPos = m_pParent->m_TransformedHairPositions[iHair];
		}
	}
}
void CAI_ASW_HealOtherBehavior::RunTask( const Task_t *pTask )
{	
	switch( pTask->iTask )
	{
		case TASK_HEAL_OTHER_MOVE_TO_TARGET:
			{
				if ( GetNavigator()->GetGoalType() == GOALTYPE_NONE )
				{
					TaskComplete();
				}

				if ( m_hHealTargetEnt.Get() )
				{
					Vector	vDiff = m_hHealTargetEnt->GetAbsOrigin() - GetAbsOrigin();
					if ( vDiff.LengthSqr() <=  ( m_flApproachDistance * m_flApproachDistance ) )
					{
						GetNavigator()->StopMoving( true );
						GetNavigator()->ClearGoal();
						TaskComplete();
					}
				}
				break;
			}

		default:
			BaseClass::RunTask( pTask );
			break;
	}
}
Example #9
0
void CFlex::DoBodyLean( void )
{
	CAI_NPC *myNpc = MyNPCPointer( );

	if (myNpc)
	{
		Vector vecDelta;
		Vector vecPos;
		Vector vecOrigin = GetAbsOrigin();

		if (m_vecPrevOrigin == vec3_origin)
		{
			m_vecPrevOrigin = vecOrigin;
		}

		vecDelta = vecOrigin - m_vecPrevOrigin;
		vecDelta.x = clamp( vecDelta.x, -50, 50 );
		vecDelta.y = clamp( vecDelta.y, -50, 50 );
		vecDelta.z = clamp( vecDelta.z, -50, 50 );

		float dt = gpGlobals->curtime - GetLastThink();
		bool bSkip = ((GetFlags() & (FL_FLY | FL_SWIM)) != 0) || (GetMoveParent() != NULL) || (GetGroundEntity() == NULL) || (GetGroundEntity()->IsMoving());
		bSkip |= myNpc->TaskRanAutomovement() || (myNpc->GetVehicleEntity() != NULL);

		if (!bSkip)
		{
			if (vecDelta.LengthSqr() > m_vecPrevVelocity.LengthSqr())
			{
				float decay =  ExponentialDecay( 0.6, 0.1, dt );
				m_vecPrevVelocity = m_vecPrevVelocity * (decay) + vecDelta * (1.f - decay);
			}
			else
			{
				float decay =  ExponentialDecay( 0.4, 0.1, dt );
				m_vecPrevVelocity = m_vecPrevVelocity * (decay) + vecDelta * (1.f - decay);
			}

			vecPos = m_vecPrevOrigin + m_vecPrevVelocity;

			float decay =  ExponentialDecay( 0.5, 0.1, dt );
			m_vecShift = m_vecShift * (decay) + (vecOrigin - vecPos) * (1.f - decay); // FIXME: Scale this
			m_vecLean = (vecOrigin - vecPos) * 1.0; // FIXME: Scale this
		}
		else
		{
			m_vecPrevVelocity = vecDelta;
			float decay =  ExponentialDecay( 0.5, 0.1, dt );
			m_vecShift = m_vecLean * decay;
			m_vecLean = m_vecShift * decay;
 		}

		m_vecPrevOrigin = vecOrigin;

		/*
		DevMsg( "%.2f %.2f %.2f  (%.2f %.2f %.2f)\n", 
			m_vecLean.Get().x, m_vecLean.Get().y, m_vecLean.Get().z,
			vecDelta.x, vecDelta.y, vecDelta.z );
		*/
	}
}
Example #10
0
int CFuncShootBoost::OnTakeDamage(const CTakeDamageInfo &info)
{
    CBaseEntity *pInflictor = info.GetAttacker();
    if (pInflictor)
    {
        Vector finalVel = m_vPushDir.Normalized() * m_fPushForce;
        switch (m_iIncrease)
        {
        case 0:
            break;
        case 1:
            finalVel += pInflictor->GetAbsVelocity();
            break;
        case 2:
            if (finalVel.LengthSqr() < pInflictor->GetAbsVelocity().LengthSqr())
                finalVel = pInflictor->GetAbsVelocity();
            break;
        case 3: // The description of this method says the player velocity is increaed by final velocity,
            // but we're just adding one vec to the other, which is not quite the same
            if (finalVel.LengthSqr() < pInflictor->GetAbsVelocity().LengthSqr())
                finalVel += pInflictor->GetAbsVelocity();
            break;
        case 4:
            pInflictor->SetBaseVelocity(finalVel);
            break;
        default:
            DevWarning("CFuncShootBoost:: %i not recognised as valid for m_iIncrease", m_iIncrease);
            break;
        }
        if (m_Destination)
        {
            if (((CBaseTrigger *) m_Destination)->IsTouching(pInflictor))
            {
                pInflictor->SetAbsVelocity(finalVel);
            }
        }
        else
        {
            pInflictor->SetAbsVelocity(finalVel);
        }
    }
    // As we don't want to break it, we don't call BaseClass::OnTakeDamage(info);
    // OnTakeDamage returns the damage dealt
    return info.GetDamage();
}
Example #11
0
	float DistToSqr(const Vector &vOther) const {
		Vector delta;

		delta.x = x - vOther.x;
		delta.y = y - vOther.y;
		delta.z = z - vOther.z;

		return delta.LengthSqr();
	}
//-----------------------------------------------------------------------------
// Purpose: If we are shot after being stuck to the world, move a bit
//-----------------------------------------------------------------------------
int CTFGrenadePipebombProjectile::OnTakeDamage( const CTakeDamageInfo &info )
{
	if ( !info.GetAttacker() )
	{
		Assert( !info.GetAttacker() );
		return 0;
	}

	bool bSameTeam = ( info.GetAttacker()->GetTeamNumber() == GetTeamNumber() );


	if ( m_bTouched && ( info.GetDamageType() & (DMG_BULLET|DMG_BUCKSHOT|DMG_BLAST) ) && bSameTeam == false )
	{
		Vector vecForce = info.GetDamageForce();
		if ( info.GetDamageType() & DMG_BULLET )
		{
			vecForce *= tf_grenade_forcefrom_bullet.GetFloat();
		}
		else if ( info.GetDamageType() & DMG_BUCKSHOT )
		{
			vecForce *= tf_grenade_forcefrom_buckshot.GetFloat();
		}
		else if ( info.GetDamageType() & DMG_BLAST )
		{
			vecForce *= tf_grenade_forcefrom_blast.GetFloat();
		}

		// If the force is sufficient, detach & move the pipebomb
		float flForce = tf_pipebomb_force_to_move.GetFloat();
		if ( vecForce.LengthSqr() > (flForce*flForce) )
		{
			if ( VPhysicsGetObject() )
			{
				VPhysicsGetObject()->EnableMotion( true );
			}

			CTakeDamageInfo newInfo = info;
			newInfo.SetDamageForce( vecForce );

			VPhysicsTakeDamage( newInfo );

			// The pipebomb will re-stick to the ground after this time expires
			m_flMinSleepTime = gpGlobals->curtime + tf_grenade_force_sleeptime.GetFloat();
			m_bTouched = false;

			// It has moved the data is no longer valid.
			m_bUseImpactNormal = false;
			m_vecImpactNormal.Init();

			return 1;
		}
	}

	return 0;
}
//-----------------------------------------------------------------------------
// System to update prop opacity
//-----------------------------------------------------------------------------
void CStaticPropMgr::ComputePropOpacity( const Vector &viewOrigin )
{
	// We need to recompute translucency information for all static props
	int i;
#ifndef SWDS
	for (i = m_StaticPropDict.Size(); --i >= 0; )
	{
		if (modelinfoclient->ModelHasMaterialProxy( m_StaticPropDict[i].m_pModel ))
		{
			modelinfoclient->RecomputeTranslucency( m_StaticPropDict[i].m_pModel );
		}
	}
#endif

	// Distance-based fading.
	// Step over the list of all things that want to be faded out and recompute alpha

	// Not sure if this is a fast enough way of doing it
	// but it's easy for now; we'll have to test later how large this list gets.
	// If it's <100 or so, we should be fine
	Vector v;
	for ( i = m_StaticPropFade.Count(); --i >= 0; )
	{
		StaticPropFade_t& fade = m_StaticPropFade[i];
 		CStaticProp& prop = m_StaticProps[fade.m_Model];

		// Calculate distance (badly)
		VectorSubtract( prop.GetRenderOrigin(), viewOrigin, v );

#ifndef SWDS
		ClientRenderHandle_t renderHandle = prop.GetRenderHandle();
		float sqDist = v.LengthSqr();
		if ( sqDist < fade.m_MaxDistSq )
		{
			if ((fade.m_MinDistSq >= 0) && (sqDist > fade.m_MinDistSq))
			{
				clientleafsystem->ChangeRenderableRenderGroup( renderHandle, RENDER_GROUP_TRANSLUCENT_ENTITY );
				prop.SetAlpha( fade.m_FalloffFactor * (fade.m_MaxDistSq - sqDist) );
			}
			else
			{
				// We can stick the prop into the opaque list
				clientleafsystem->ChangeRenderableRenderGroup( renderHandle, RENDER_GROUP_OPAQUE_ENTITY );
				prop.SetAlpha( 255 );
			}
		}
		else
		{
			// We can stick the prop into the opaque list now; we're not drawing it!
			clientleafsystem->ChangeRenderableRenderGroup( renderHandle, RENDER_GROUP_OPAQUE_ENTITY );
			prop.SetAlpha( 0 );
		}
#endif
	}
}
void Matrix4x4::SetReflection(const Vector& vecPlane)
{
	// Normalize beforehand or use ::SetReflection()
	TAssert(fabs(vecPlane.LengthSqr() - 1) < 0.000001f);

	m[0][0] = 1 - 2 * vecPlane.x * vecPlane.x;
	m[1][1] = 1 - 2 * vecPlane.y * vecPlane.y;
	m[2][2] = 1 - 2 * vecPlane.z * vecPlane.z;
	m[1][0] = m[0][1] = -2 * vecPlane.x * vecPlane.y;
	m[2][0] = m[0][2] = -2 * vecPlane.x * vecPlane.z;
	m[1][2] = m[2][1] = -2 * vecPlane.y * vecPlane.z;
}
// In order to do rendering we have to transform our global coordinates to be
// in the local space of the camera, with the specific requirement that the
// camera looks down the -Z axis. In this function we construct a matrix for
// this transformation. http://youtu.be/3ZmqJb7J5wE
Matrix4x4 Matrix4x4::ConstructCameraView(const Vector& vecPosition, const Vector& vecDirection, const Vector& vecUp)
{
	TAssert(fabs(vecDirection.LengthSqr()-1) < 0.0001f);

	Vector vecCamRight = CrossProduct(vecDirection, vecUp).Normalized();
	Vector vecCamUp = CrossProduct(vecCamRight, vecDirection);

	// OpenGL wants to be looking down the -Z axis. So, pass -vecDirection into the Z position.
	// Then invert the matrix because we're going from global space into local camera space.
	// Easy!
	return Matrix4x4(vecCamRight, vecCamUp, -vecDirection, vecPosition).InvertedTR();
}
Example #16
0
void CNPC_Stalker::AddZigZagToPath(void) 
{
	// If already on a detour don't add a zigzag
	if (GetNavigator()->GetCurWaypointFlags() & bits_WP_TO_DETOUR)
	{
		return;
	}

	// If enemy isn't facing me or occluded, don't add a zigzag
	if (HasCondition(COND_ENEMY_OCCLUDED) || !HasCondition ( COND_ENEMY_FACING_ME ))
	{
		return;
	}

	Vector waypointPos = GetNavigator()->GetCurWaypointPos();
	Vector waypointDir = (waypointPos - GetAbsOrigin());

	// If the distance to the next node is greater than ZIG_ZAG_SIZE
	// then add a random zig/zag to the path
	if (waypointDir.LengthSqr() > ZIG_ZAG_SIZE)
	{
		// Pick a random distance for the zigzag (less that sqrt(ZIG_ZAG_SIZE)
		float distance = random->RandomFloat( 30, 60 );

		// Get me a vector orthogonal to the direction of motion
		VectorNormalize( waypointDir );
		Vector vDirUp(0,0,1);
		Vector vDir;
		CrossProduct( waypointDir, vDirUp, vDir);

		// Pick a random direction (left/right) for the zigzag
		if (random->RandomInt(0,1))
		{
			vDir = -1 * vDir;
		}

		// Get zigzag position in direction of target waypoint
		Vector zigZagPos = GetAbsOrigin() + waypointDir * 60;

		// Now offset 
		zigZagPos = zigZagPos + (vDir * distance);

		// Now make sure that we can still get to the zigzag position and the waypoint
		AIMoveTrace_t moveTrace1, moveTrace2;
		GetMoveProbe()->MoveLimit( NAV_GROUND, GetAbsOrigin(), zigZagPos, GetAITraceMask(), NULL, &moveTrace1);
		GetMoveProbe()->MoveLimit( NAV_GROUND, zigZagPos, waypointPos, GetAITraceMask(), NULL, &moveTrace2);
		if ( !IsMoveBlocked( moveTrace1 ) && !IsMoveBlocked( moveTrace2 ) )
		{
			GetNavigator()->PrependWaypoint( zigZagPos, NAV_GROUND, bits_WP_TO_DETOUR );
		}
	}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CMapData_Server::GetMapBounds( Vector &vecMins, Vector &vecMaxs )
{
	CWorld *pWorld = static_cast<CWorld*>( GetWorldEntity() );
	if ( pWorld )
	{
		// Get the world bounds.
		pWorld->GetWorldBounds( vecMins, vecMaxs );

		// Backward compatability...
		if ( ( vecMins.LengthSqr() == 0.0f ) && ( vecMaxs.LengthSqr() == 0.0f ) )
		{
			vecMins.Init( -6500.0f, -6500.0f, -6500.0f );
			vecMaxs.Init( 6500.0f, 6500.0f, 6500.0f );
		}
	}
	else
	{
		Assert( 0 );
		vecMins.Init( 0.0f, 0.0f, 0.0f );
		vecMaxs.Init( 1.0f, 1.0f, 1.0f );
	}
}
//------------------------------------------------------------------------------
// Purpose:
//------------------------------------------------------------------------------
bool CAI_ASW_RangedAttackBehavior::FindFiringLocation( )
{
    CBaseEntity *pBestEnt = NULL;
    float flBestDistSq = FLT_MAX;
    AIEnemiesIter_t iter;
    CBaseEntity *pEnemy;

    pEnemy = GetEnemy();

    if ( pEnemy && pEnemy->IsAlive() && GetOuter()->FVisible( pEnemy ) )
    {
        m_hTarget = pEnemy;
        UpdateTargetLocation();
        return true;
    }

    for( AI_EnemyInfo_t *pEMemory = GetEnemies()->GetFirst( &iter ); pEMemory != NULL; pEMemory = GetEnemies()->GetNext( &iter ) )
    {
        pEnemy = pEMemory->hEnemy;
        if ( !pEnemy || !pEnemy->IsAlive() || !GetOuter()->FVisible( pEnemy ) )
        {
            continue;
        }

        Vector vDelta = GetAbsOrigin() - pEnemy->GetAbsOrigin();

        float flLenSq = vDelta.LengthSqr();
        if ( flLenSq <= flBestDistSq )
        {
            pBestEnt = pEnemy;
            flBestDistSq = flLenSq;
        }
    }

    if ( !pBestEnt )
    {
        // just try shooting at our enemy for now
        if ( pEnemy && pEnemy->IsAlive() )
        {
            UpdateTargetLocation();
            return true;
        }
        return false;
    }

    m_hTarget = pBestEnt;
    GetOuter()->SetEnemy( pBestEnt );
    UpdateTargetLocation();
    return true;
}
Example #19
0
//-----------------------------------------------------------------------------
// Builds a rotation matrix that rotates one direction vector into another
//-----------------------------------------------------------------------------
void MatrixBuildRotation( VMatrix &dst, const Vector& initialDirection, const Vector& finalDirection )
{
	float angle = DotProduct( initialDirection, finalDirection );
	assert( IsFinite(angle) );
	
	Vector axis;

	// No rotation required
	if (angle - 1.0 > -1e-3)
	{
		// parallel case
		MatrixSetIdentity(dst);
		return;
	}
	else if (angle + 1.0 < 1e-3)
	{
		// antiparallel case, pick any axis in the plane
		// perpendicular to the final direction. Choose the direction (x,y,z)
		// which has the minimum component of the final direction, use that
		// as an initial guess, then subtract out the component which is 
		// parallel to the final direction
		int idx = 0;
		if (FloatMakePositive(finalDirection[1]) < FloatMakePositive(finalDirection[idx]))
			idx = 1;
		if (FloatMakePositive(finalDirection[2]) < FloatMakePositive(finalDirection[idx]))
			idx = 2;

		axis.Init( 0, 0, 0 );
		axis[idx] = 1.0f;
		VectorMA( axis, -DotProduct( axis, finalDirection ), finalDirection, axis );
		VectorNormalize(axis);
		angle = 180.0f;
	}
	else
	{
		CrossProduct( initialDirection, finalDirection, axis );
		VectorNormalize( axis );
		angle = acos(angle) * 180 / M_PI;
	}

	MatrixBuildRotationAboutAxis( dst, axis, angle );

#ifdef _DEBUG
	Vector test;
	Vector3DMultiply( dst, initialDirection, test );
	test -= finalDirection;
	assert( test.LengthSqr() < 1e-3 );
#endif
}
//-----------------------------------------------------------------------------
// Purpose: The turret doesn't run base AI properly, which is a bad decision.
//			As a result, it has to manually find enemies.
//-----------------------------------------------------------------------------
void CNPC_Portal_FloorTurret::HackFindEnemy( void )
{
	// We have to refresh our memories before finding enemies, so
	// dead enemies are cleared out before new ones are added.
	GetEnemies()->RefreshMemories();

	GetSenses()->Look( PORTAL_FLOOR_TURRET_RANGE );
	SetEnemy( BestEnemy() );

	if ( GetEnemy() == NULL )
	{
		// Look through the list of sensed objects for possible targets
		AISightIter_t iter;
		CBaseEntity *pObject;
		CBaseEntity	*pNearest = NULL;
		float flClosestDistSqr = PORTAL_FLOOR_TURRET_RANGE * PORTAL_FLOOR_TURRET_RANGE;

		for ( pObject = GetSenses()->GetFirstSeenEntity( &iter, SEEN_MISC ); pObject; pObject = GetSenses()->GetNextSeenEntity( &iter ) )
		{
			Vector vVelocity;
			pObject->GetVelocity( &vVelocity );

			// Ignore objects going too slowly
			if ( vVelocity.LengthSqr() < m_fMovingTargetThreashold )
				continue;

			float flDistSqr = pObject->WorldSpaceCenter().DistToSqr( GetAbsOrigin() );
			if ( flDistSqr < flClosestDistSqr )
			{
				flClosestDistSqr = flDistSqr;
				pNearest = pObject;
			}
		}

		if ( pNearest )
		{
			SetEnemy( pNearest );
			m_fMovingTargetThreashold += gpGlobals->curtime * 15.0f;
			if ( m_fMovingTargetThreashold > 800.0f )
			{
				m_fMovingTargetThreashold = 800.0f;
			}
		}
	}
	else
	{
		m_fMovingTargetThreashold = 20.0f;
	}
}
// Actual work code
IterationRetval_t CPlayerAndObjectEnumerator::EnumElement( IHandleEntity *pHandleEntity )
{
	if ( !m_pLocal )
		return ITERATION_STOP;

	C_BaseEntity *pEnt = ClientEntityList().GetBaseEntityFromHandle( pHandleEntity->GetRefEHandle() );
	if ( pEnt == NULL )
		return ITERATION_CONTINUE;

	if ( pEnt == m_pLocal )
		return ITERATION_CONTINUE;

	if ( !pEnt->IsPlayer() &&
		 !pEnt->IsNPC() )
	{
		return ITERATION_CONTINUE;
	}

	if ( pEnt->IsNPC() )
	{
		C_AI_BaseNPC *pNPC = (C_AI_BaseNPC *)pEnt;

		if ( !pNPC->ShouldAvoidObstacle() )
			 return ITERATION_CONTINUE;
	}

	// Ignore vehicles, since they have vcollide collisions that's push me away
	if ( pEnt->GetCollisionGroup() == COLLISION_GROUP_VEHICLE )
		return ITERATION_CONTINUE;

#ifdef INVASION_CLIENT_DLL
	// If it's solid to player movement, don't steer around it since we'll just bump into it
	if ( pEnt->GetCollisionGroup() == TFCOLLISION_GROUP_OBJECT_SOLIDTOPLAYERMOVEMENT )
		return ITERATION_CONTINUE;
#endif

	Vector	deltaPos = pEnt->GetAbsOrigin() - m_pLocal->GetAbsOrigin();
	if ( deltaPos.LengthSqr() > m_flRadiusSquared )
		return ITERATION_CONTINUE;

	CHandle< C_BaseEntity > h;
	h = pEnt;
	m_Objects.AddToTail( h );

	return ITERATION_CONTINUE;
}
Example #22
0
//-----------------------------------------------------------------------------
// Primary gun 
//-----------------------------------------------------------------------------
void CPropAPC::AimPrimaryWeapon( const Vector &vecWorldTarget ) 
{
	EntityMatrix parentMatrix;
	parentMatrix.InitFromEntity( this, m_nMachineGunBaseAttachment );
	Vector target = parentMatrix.WorldToLocal( vecWorldTarget ); 

	float quadTarget = target.LengthSqr();
	float quadTargetXY = target.x*target.x + target.y*target.y;

	// Target is too close!  Can't aim at it
	if ( quadTarget > m_vecBarrelPos.LengthSqr() )
	{
		// We're trying to aim the offset barrel at an arbitrary point.
		// To calculate this, I think of the target as being on a sphere with 
		// it's center at the origin of the gun.
		// The rotation we need is the opposite of the rotation that moves the target 
		// along the surface of that sphere to intersect with the gun's shooting direction
		// To calculate that rotation, we simply calculate the intersection of the ray 
		// coming out of the barrel with the target sphere (that's the new target position)
		// and use atan2() to get angles

		// angles from target pos to center
		float targetToCenterYaw = atan2( target.y, target.x );
		float centerToGunYaw = atan2( m_vecBarrelPos.y, sqrt( quadTarget - (m_vecBarrelPos.y*m_vecBarrelPos.y) ) );

		float targetToCenterPitch = atan2( target.z, sqrt( quadTargetXY ) );
		float centerToGunPitch = atan2( -m_vecBarrelPos.z, sqrt( quadTarget - (m_vecBarrelPos.z*m_vecBarrelPos.z) ) );

		QAngle angles;
		angles.Init( -RAD2DEG(targetToCenterPitch+centerToGunPitch), RAD2DEG( targetToCenterYaw + centerToGunYaw ), 0 );

		SetPoseParameter( "vehicle_weapon_yaw", angles.y );
		SetPoseParameter( "vehicle_weapon_pitch", angles.x );
		StudioFrameAdvance();

		float curPitch = GetPoseParameter( "vehicle_weapon_pitch" );
		float curYaw = GetPoseParameter( "vehicle_weapon_yaw" );
		m_bInFiringCone = (fabs(curPitch - angles.x) < 1e-3) && (fabs(curYaw - angles.y) < 1e-3);
	}
	else
	{
		m_bInFiringCone = false;
	}
}
Example #23
0
Matrix4x4 Matrix4x4::ConstructCameraView(const Vector& vecPosition, const Vector& vecDirection, const Vector& vecUp)
{
	Matrix4x4 m;
	
	m.Identity();

	TAssertNoMsg(fabs(vecDirection.LengthSqr()-1) < 0.0001f);

	Vector vecCamSide = vecDirection.Cross(vecUp).Normalized();
	Vector vecCamUp = vecCamSide.Cross(vecDirection);

	m.SetForwardVector(Vector(vecCamSide.x, vecCamUp.x, -vecDirection.x));
	m.SetLeftVector(Vector(vecCamSide.y, vecCamUp.y, -vecDirection.y));
	m.SetUpVector(Vector(vecCamSide.z, vecCamUp.z, -vecDirection.z));

	m.AddTranslation(-vecPosition);

	return m;
}
// Actual work code
IterationRetval_t CPlayerAndObjectEnumerator::EnumElement( IHandleEntity *pHandleEntity )
{
	if ( !m_pLocal )
		return ITERATION_STOP;

	C_BaseEntity *pEnt = ClientEntityList().GetBaseEntityFromHandle( pHandleEntity->GetRefEHandle() );
	if ( pEnt == NULL )
		return ITERATION_CONTINUE;

	if ( pEnt == m_pLocal )
		return ITERATION_CONTINUE;

	if ( !pEnt->IsPlayer() &&
		 !pEnt->IsNPC() )
	{
		return ITERATION_CONTINUE;
	}

	if ( pEnt->IsNPC() )
	{
		C_AI_BaseNPC *pNPC = (C_AI_BaseNPC *)pEnt;

		if ( !pNPC->ShouldAvoidObstacle() )
			 return ITERATION_CONTINUE;
	}

	// Ignore vehicles, since they have vcollide collisions that's push me away
	if ( pEnt->GetCollisionGroup() == COLLISION_GROUP_VEHICLE )
		return ITERATION_CONTINUE;



	Vector	deltaPos = pEnt->GetAbsOrigin() - m_pLocal->GetAbsOrigin();
	if ( deltaPos.LengthSqr() > m_flRadiusSquared )
		return ITERATION_CONTINUE;

	CHandle< C_BaseEntity > h;
	h = pEnt;
	m_Objects.AddToTail( h );

	return ITERATION_CONTINUE;
}
void CPlayerController::Update( const Vector& position, const Vector& velocity, bool onground, IPhysicsObject *ground )
{
	IVP_U_Point	targetPositionIVP;
	IVP_U_Float_Point targetSpeedIVP;

	ConvertPositionToIVP( position, targetPositionIVP );
	ConvertPositionToIVP( velocity, targetSpeedIVP );
	
	// if the object hasn't moved, abort
	if ( targetSpeedIVP.quad_distance_to( &m_currentSpeed ) < 1e-6 )
	{
		if ( targetPositionIVP.quad_distance_to( &m_targetPosition ) < 1e-6 )
		{
			return;
		}
	}

	m_targetPosition = targetPositionIVP;
	m_currentSpeed = targetSpeedIVP;

	IVP_Real_Object *pivp = m_pObject->GetObject();
	IVP_Core *pCore = pivp->get_core();
	IVP_Environment *pEnv = pivp->get_environment();
	pEnv->get_controller_manager()->ensure_core_in_simulation(pCore);

	m_enable = true;
	// m_onground makes this object anti-grav
	// UNDONE: Re-evaluate this
	m_onground = false;//onground;

	if ( velocity.LengthSqr() <= 0.1f )
	{
		// no input velocity, just go where physics takes you.
		m_enable = false;
		ground = NULL;
	}
	else
	{
		MaxSpeed( velocity );
	}
}
void CLightingManager::CullLights()
{
	Assert( m_hRenderLights.Count() == 0 );

	FOR_EACH_VEC_FAST( def_light_t*, m_hDeferredLights, l )
	{
		if ( !m_bDrawWorldLights && l->bWorldLight )
			continue;

		if ( !render->AreAnyLeavesVisible( l->iLeaveIDs, l->iNumLeaves ) )
			continue;

		// if the optimized bounds cause popping for you, use the naive ones or
		// ...improve the optimization code
		//if( !engine->IsBoxInViewCluster( l->bounds_min_naive, l->bounds_max_naive ) )
		//	continue;

		if ( engine->CullBox( l->bounds_min_naive, l->bounds_max_naive ) )
		//if ( engine->CullBox( l->bounds_min, l->bounds_max ) )
			continue;

		if ( l->IsSpot() && l->HasShadow() )
		{
			if ( IntersectFrustumWithFrustum( m_matScreenToWorld, l->spotMVPInv ) )
				continue;
		}

		Vector veclightDelta = l->boundsCenter - m_vecViewOrigin;

		if ( veclightDelta.LengthSqr() > l->flMaxDistSqr )
			continue;

		l->flDistance_ViewOrigin = veclightDelta.Length();
		l->flShadowFade = l->HasShadow() ?
			( SATURATE( ( l->flDistance_ViewOrigin - l->iShadow_Dist ) / l->iShadow_Range ) )
			: 1.0f;

		m_hRenderLights.AddToTail( l );
	}
	FOR_EACH_VEC_FAST_END
}
void C_SkeletonPlayer::UpdateClientSideAnimation()
{
	int curSeq = GetSequence();
	
	Vector vel = GetLocalVelocity();
	//EstimateAbsVelocity( vel );

	int goalSeq = curSeq;

	if ( vel.LengthSqr() > 4 )
	{
		QAngle velAng;
		VectorAngles( vel, velAng );

		goalSeq = SelectWeightedSequence( ACT_RUN );

		float speed = vel.Length2D();
		float yaw = AngleNormalize( -(GetRenderAngles().y - velAng.y) );
		float seqspeed = 150.0f;
		float rate = speed / seqspeed;

		SetPoseParameter( LookupPoseParameter( "move_x" ), cos( DEG2RAD( yaw ) ) * rate );
		SetPoseParameter( LookupPoseParameter( "move_y" ), -sin( DEG2RAD( yaw ) ) * rate );

		SetPlaybackRate( clamp( rate * 0.6f, 1, 1.5f ) );
	}
	else
		goalSeq = SelectWeightedSequence( ACT_IDLE );

	if ( curSeq != goalSeq )
	{
		ResetSequence( goalSeq );
	}

	//m_flAnimTime = gpGlobals->curtime;
	//StudioFrameAdvance();

	if ( GetCycle() >= 1.0f )
		SetCycle( GetCycle() - 1.0f );
}
void CBaseRopePhysics::ApplyConstraints( CSimplePhysics::CNode *pNodes, int nNodes )
{
	// Handle springs..
	//
	// Iterate multiple times here. If we don't, then gravity tends to
	// win over the constraint solver and it's impossible to get straight ropes.
	static int nIterations = 3;
	for( int iIteration=0; iIteration < nIterations; iIteration++ )
	{
		for( int i=0; i < NumSprings(); i++ )
		{
			CRopeSpring *s = &m_pSprings[i];

			Vector vTo = *s->m_pNode1 - *s->m_pNode2;

			float flDistSqr = vTo.LengthSqr();

			// If we don't have an overall spring distance, see if we have a per-node one
			float flSpringDist = m_flSpringDistSqr;
			if ( !flSpringDist )
			{
				// TODO: This still isn't enough. Ropes with different spring lengths
				// per-node will oscillate forever.
				flSpringDist = m_flNodeSpringDistsSqr[i];
			}

			if( flDistSqr > flSpringDist )
			{
				float flDist = (float)sqrt( flDistSqr );
				vTo *= 1 - (m_flSpringDist / flDist);

				*s->m_pNode1 -= vTo * 0.5f;
				*s->m_pNode2 += vTo * 0.5f;
			}
		}

		if( m_pDelegate )
			m_pDelegate->ApplyConstraints( pNodes, nNodes );
	}
}
Example #29
0
bool CColorPicker::Update(int x, int y)
{
	if (x > BarX() && y > BarY() && x < BarX() + BarW() && y < BarY() + BarH())
	{
		m_flLightness = RemapVal((float)y, BarY(), BarY() + BarH(), 1, 0);
		m_clrRGB.SetHSL(m_flHue, m_flSaturation, m_flLightness);

		m_hValue->SetText(sprintf("%i %i %i", m_clrRGB.r(), m_clrRGB.g(), m_clrRGB.b()));

		if (m_pfnChangedCallback)
			m_pfnChangedCallback(m_pChangedListener, sprintf("%f %f %f", GetColorVector().x, GetColorVector().y, GetColorVector().z));

		return true;
	}

	float flRadius = CircleW()/2;
	float flRadiusSqr = flRadius*flRadius;

	Vector vecCenter(CircleX() + flRadius, CircleY() + flRadius, 0);

	Vector vecFromCenter = Vector((float)x, (float)y, 0) - vecCenter;
	float flDistanceSqr = vecFromCenter.LengthSqr();
	if (flDistanceSqr > flRadiusSqr)
		return false;

	float flTan = atan2(vecFromCenter.y, -vecFromCenter.x);

	m_flHue = RemapVal(flTan, (float)-M_PI, (float)M_PI, 0.0f, 360.0f);
	m_flSaturation = sqrt(flDistanceSqr)/flRadius;

	m_clrRGB.SetHSL(m_flHue, m_flSaturation, m_flLightness);

	m_hValue->SetText(sprintf("%i %i %i", m_clrRGB.r(), m_clrRGB.g(), m_clrRGB.b()));

	if (m_pfnChangedCallback)
		m_pfnChangedCallback(m_pChangedListener, sprintf("%f %f %f", GetColorVector().x, GetColorVector().y, GetColorVector().z));

	return true;
}
Example #30
0
void CCharacterController::PlayerWalk(btCollisionWorld* pCollisionWorld, btScalar dt)
{
	Vector vecCurrentVelocity = m_hEntity->GetLocalVelocity();
	vecCurrentVelocity.z = 0;

	// Calculate friction first, so that the player's movement commands can overwhelm it.
	if (vecCurrentVelocity.Length2DSqr() > 0.00001f)
	{
		if (m_hEntity->GetGroundEntity())
		{
			float flSpeed2D = vecCurrentVelocity.Length2D();

			float flFriction = sv_friction.GetFloat() * flSpeed2D * dt;

			float flNewSpeed = flSpeed2D - flFriction;

			if (flNewSpeed < 0)
				flNewSpeed = 0;

			float flScale = flNewSpeed / flSpeed2D;

			vecCurrentVelocity *= flScale;

			m_hEntity->SetLocalVelocity(vecCurrentVelocity);
		}
	}

	// Calculate a new velocity using the player's desired direction of travel.
	btVector3 vecWishDirection = m_vecMoveVelocity;
	vecWishDirection.setZ(0);
	float flWishVelocity = m_vecMoveVelocity.length();
	if (flWishVelocity)
		vecWishDirection = vecWishDirection / flWishVelocity;
	else
		vecWishDirection = btVector3(0, 0, 0);

	if (flWishVelocity > m_hEntity->CharacterSpeed())
		flWishVelocity = m_hEntity->CharacterSpeed();

	float flVelocityInWishDirection = GetVelocity().dot(vecWishDirection);

	float flDirectionChange = flWishVelocity - flVelocityInWishDirection;

	if (flDirectionChange > 0)
	{
		float flAccelerationAmount = flWishVelocity * m_hEntity->CharacterAcceleration() * dt;
		if (flAccelerationAmount > flDirectionChange)
			flAccelerationAmount = flDirectionChange;
		vecCurrentVelocity = vecCurrentVelocity + ToTVector(vecWishDirection) * flAccelerationAmount;

		TAssert(vecCurrentVelocity.z == 0);
	}

	float flCurrentVelocity = vecCurrentVelocity.Length();

	if (flCurrentVelocity > m_hEntity->CharacterSpeed())
		vecCurrentVelocity *= m_hEntity->CharacterSpeed()/flCurrentVelocity;

	if (vecCurrentVelocity.LengthSqr() < 0.001f)
	{
		m_hEntity->SetLocalVelocity(Vector());
		return;
	}

	btTransform mWorld = m_pGhostObject->getWorldTransform();

	// Try moving the player directly, if it's possible.
	{
		btVector3 vecTargetPosition = mWorld.getOrigin() + ToBTVector(vecCurrentVelocity) * dt;

		CTraceResult tr;
		PlayerTrace(pCollisionWorld, mWorld.getOrigin(), vecTargetPosition, tr);

		if (tr.m_flFraction == 1)
		{
			mWorld.setOrigin(vecTargetPosition);
			m_pGhostObject->setWorldTransform(mWorld);
			m_hEntity->SetLocalVelocity(vecCurrentVelocity);
			return;
		}
	}

	// There was something blocking the way. Try walking up a step or along walls.

	btVector3 vecSavedStepUp(0, 0, 0);

	{
		// Move up a bit to try to clear a step.
		btVector3 vecStartPosition = m_pGhostObject->getWorldTransform().getOrigin();
		btVector3 vecTargetPosition = m_pGhostObject->getWorldTransform().getOrigin() + GetUpVector() * m_flStepHeight;

		CTraceResult tr;
		PlayerTrace(pCollisionWorld, vecStartPosition, vecTargetPosition, tr);

		if (tr.m_flFraction < 1)
		{
			// we moved up only a fraction of the step height
			btVector3 vecInterpolated;
			vecInterpolated.setInterpolate3(m_pGhostObject->getWorldTransform().getOrigin(), vecTargetPosition, tr.m_flFraction);
			m_pGhostObject->getWorldTransform().setOrigin(vecInterpolated);

			vecSavedStepUp = vecInterpolated - vecStartPosition;
		}
		else
		{
			vecSavedStepUp = vecTargetPosition - vecStartPosition;
			m_pGhostObject->getWorldTransform().setOrigin(vecTargetPosition);
		}
	}

	StepForwardAndStrafe(pCollisionWorld, ToBTVector(vecCurrentVelocity) * dt);

	if (vecSavedStepUp.length2() > 0)
	{
		// Move back down as much as we moved up.
		btVector3 vecStartPosition = m_pGhostObject->getWorldTransform().getOrigin();
		btVector3 vecTargetPosition = m_pGhostObject->getWorldTransform().getOrigin() - vecSavedStepUp;

		CTraceResult tr;
		PlayerTrace(pCollisionWorld, vecStartPosition, vecTargetPosition, tr);

		if (tr.m_flFraction < 1)
		{
			btVector3 vecInterpolated;
			vecInterpolated.setInterpolate3(m_pGhostObject->getWorldTransform().getOrigin(), vecTargetPosition, tr.m_flFraction);
			m_pGhostObject->getWorldTransform().setOrigin(vecInterpolated);
		}
		else
			m_pGhostObject->getWorldTransform().setOrigin(vecTargetPosition);
	}
}