void OGLReverseSphericalCamera::animate()
{
   // See http://en.wikipedia.org/wiki/Spherical_coordinate_system#Cartesian_coordinates
   // Spherical to Cartesian
   // x = r * sin(theta) * cos(phi)
   // y = r * cos(theta)
   // z = r * sin(theta) * sin(phi)
    
   float phi = OGLUtil::degToRad(cameraPosSpherical.phi);
   float theta = OGLUtil::degToRad(cameraPosSpherical.theta + 90.0f); // Remember -90 to 90
    
   float fSinTheta = sinf(theta);
   float fCosTheta = cosf(theta);
   float fCosPhi = cosf(phi);
   float fSinPhi = sinf(phi);
    
   glm::vec3 dirToTarget(fSinTheta * fCosPhi, -fCosTheta, fSinTheta * fSinPhi);
   cameraTarget = (dirToTarget * cameraPosSpherical.rho) + position;

   lookDir = glm::normalize(position - cameraTarget);
}
//------------------------------------------------------------------------
void CMelee::Update(float frameTime, uint32 frameId)
{
	FUNCTION_PROFILER( GetISystem(), PROFILE_GAME );

	bool remote = false;
	bool doMelee = false;
	bool requireUpdate = false;

	Vec3 dirToTarget(ZERO);
	if(m_pMeleeAction && s_meleeSnapTargetId && g_pGameCVars->pl_melee.mp_melee_system_camera_lock_and_turn)
	{
		m_attackTime += frameTime;

		CActor* pOwner = m_pWeapon->GetOwnerActor();
		IEntity* pTarget = gEnv->pEntitySystem->GetEntity(s_meleeSnapTargetId);
		if(pOwner && pTarget)
		{
			Vec3 targetPos = pTarget->GetWorldPos();

			if(s_bMeleeSnapTargetCrouched)
			{
				targetPos.z -= g_pGameCVars->pl_melee.mp_melee_system_camera_lock_crouch_height_offset;
			}

			dirToTarget = targetPos - pOwner->GetEntity()->GetWorldPos();
			dirToTarget.Normalize();

			static const float smooth_time = 0.1f;
			SmoothCD(m_attackTurnAmount, m_attackTurnAmountSmoothRate, frameTime, 1.f, smooth_time);
			Quat newViewRotation;
			newViewRotation.SetSlerp(pOwner->GetViewRotation(), Quat::CreateRotationVDir(dirToTarget), m_attackTurnAmount);
			Ang3 newAngles(newViewRotation);
			newAngles.y = 0.f; //No head tilting
			newViewRotation = Quat(newAngles);
			pOwner->SetViewRotation( newViewRotation );
		}

		if(m_attackTime >= g_pGameCVars->pl_melee.mp_melee_system_camera_lock_time && pOwner && pOwner->IsClient())
		{
			pOwner->GetActorParams().viewLimits.ClearViewLimit(SViewLimitParams::eVLS_Item);
		}
	}

	if (m_attacking)
	{
		MeleeDebugLog ("CMelee<%p> Update while attacking: m_attacked=%d, delay=%f", this, m_attacked, m_delayTimer);

		requireUpdate = true;
		if (m_delayTimer>0.0f)
		{
			RequestAlignmentToNearestTarget();
			m_delayTimer-=frameTime;
			if (m_delayTimer<=0.0f)
			{
				m_delayTimer=0.0f;
			}
		}
		else if (m_netAttacking)
		{
			remote = true;
			doMelee = true;
			m_attacking = false;
			m_slideKick = false;
			m_netAttacking = false;

			m_pWeapon->SetBusy(false);
		}	
		else if (!m_attacked)
		{
			doMelee = true;
			m_attacked = true;
		}

		if ( !m_collisionHelper.IsBlocked() && doMelee)
		{
			if (CActor *pActor = m_pWeapon->GetOwnerActor())
			{
				if (IMovementController * pMC = pActor->GetMovementController())
				{
					SMovementState info;
					pMC->GetMovementState(info);

					if(!dirToTarget.IsZeroFast())
					{
						PerformMelee(info.weaponPosition, dirToTarget, remote); //We know where we will be facing at the point of impact - using our current fire direction is not accurate enough
					}
					else
					{
						PerformMelee(info.weaponPosition, info.fireDirection, remote);
					}
				}
			}
		}

		if( (m_useMeleeWeaponDelay <= 0.0f && m_useMeleeWeaponDelay > -1.0f) )
		{
			m_useMeleeWeaponDelay = -1.0f;

			// Switch to the MELEE WEAPON.
			SwitchToMeleeWeaponAndAttack();

			m_attacking = false;
		}
		m_useMeleeWeaponDelay -= frameTime;
	}

	if (requireUpdate)
		m_pWeapon->RequireUpdate(eIUS_FireMode);
}