void 
Spacetime::stepPhysics_analytic(matrix<double> u)
{
	matrix<double> state_1 = getState();
	matrix<double> C_1 = computeC_analytic();
	matrix<double> G_1 = computeG_analytic();
	matrix<double> MInv_1 = !computeM_analytic();

	matrix<double> damping = G_1;//(MInv_1 * (u - C_1 - G_1));
	damping(0,0) *= abs(state_1(2,0));
	damping(1,0) *= abs(state_1(3,0));

	matrix<double> thetaDotDot_1 =  (MInv_1 * (u/*+damping*/ - C_1 - G_1));
	
	matrix<double> stateDot_1(4,1);
	stateDot_1(0,0) = state_1(2,0);
	stateDot_1(1,0) = state_1(3,0);
	stateDot_1(2,0) = thetaDotDot_1(0,0);
	stateDot_1(3,0) = thetaDotDot_1(1,0);
	
	setState(state_1 + stateDot_1*deltaT/2.0);
	
	matrix<double> state_2 = getState();
	matrix<double> C_2 = computeC_analytic();
	matrix<double> G_2 = computeG_analytic();
	matrix<double> MInv_2 = !computeM_analytic();
	
	damping = G_2;
	damping(0,0) *= abs(state_2(2,0));
	damping(1,0) *= abs(state_2(3,0));

	matrix<double> thetaDotDot_2 = (MInv_2 * (u/*+damping*/ - C_2 - G_2));
	
	matrix<double> stateDot_2(4,1);
	stateDot_2(0,0) = state_2(2,0);
	stateDot_2(1,0) = state_2(3,0);
	stateDot_2(2,0) = thetaDotDot_2(0,0);
	stateDot_2(3,0) = thetaDotDot_2(1,0);
	
	setState(state_1 + stateDot_2*deltaT);
}
Exemplo n.º 2
0
SecondOrder::SecondOrder(int x,int y)
{
	mdl=new RectangleView(x,y);

	sNodeType="SecondOrder";
	mosPath="Modelica.Blocks.Continuous.SecondOrder";
	image_index = IM_SECONDORDER;

	this->SetInputCount(1);
	this->SetOutputCount(1);
	this->SetInputsName(0, "u");
	this->SetOutputsName(0, "y");

	//参数初始化
	para gain("k",1,"","二阶环节的增益");                    //二阶环节的增益
	para frequency("w",1,"","二阶环节的固有频率");				 //二阶环节的固有频率
	para damping("D",1,"","二阶环节的阻尼系数");            	 //二阶环节的阻尼系数
	//加入参数列
	para_List.push_back(gain);
	para_List.push_back(frequency);
	para_List.push_back(damping);
}
Exemplo n.º 3
0
bool CPlayerStateSwim::OnPrePhysicsUpdate( CPlayer& player, const SActorFrameMovementParams& movement, float frameTime )
{
	const CPlayerStateSwim_WaterTestProxy& waterProxy = player.m_playerStateSwim_WaterTestProxy;

	CPlayerStateUtil::PhySetFly( player );

	const SPlayerStats& stats = player.m_stats;

#ifdef STATE_DEBUG
	const bool debug = (g_pGameCVars->cl_debugSwimming != 0);
#endif
	
	const Vec3 entityPos = player.GetEntity()->GetWorldPos();
	const Quat baseQuat = player.GetBaseQuat();
	const Vec3 vRight(baseQuat.GetColumn0());
	
	Vec3 velocity = player.GetActorPhysics().velocity;

	// Underwater timer, sounds update and surface wave speed.
	if (waterProxy.IsHeadUnderWater())
	{
		m_headUnderWaterTimer += frameTime;
		if (m_headUnderWaterTimer <= -0.0f && !m_onSurface )
		{
			player.PlaySound(CPlayer::ESound_DiveIn, true, "speed", velocity.len());
			m_headUnderWaterTimer = 0.0f;
		}

		player.PlaySound(CPlayer::ESound_Underwater, true);
	}
	else
	{
		m_headUnderWaterTimer -= frameTime;			
		if (m_headUnderWaterTimer >= 0.0f && (waterProxy.IsHeadComingOutOfWater() || m_onSurface))
		{
			player.PlaySound(CPlayer::ESound_DiveOut, true, "speed", velocity.len());
			m_headUnderWaterTimer = 0.0f;
		}

		player.PlaySound(CPlayer::ESound_Underwater, false);
	}
	m_headUnderWaterTimer = clamp_tpl( m_headUnderWaterTimer, -0.2f, 0.2f );

	// Apply water flow velocity to the player
	Vec3 gravity;
	pe_params_buoyancy buoyancy[s_maxWaterVolumesToConsider];
	if (int count = gEnv->pPhysicalWorld->CheckAreas(entityPos, gravity, &buoyancy[0], s_maxWaterVolumesToConsider))
	{
		for(int i = 0; i < count && i < s_maxWaterVolumesToConsider; ++i)
		{
			// 0 is water
			if( buoyancy[i].iMedium == 0 )
			{
				velocity += (buoyancy[i].waterFlow * frameTime);
			}
		}
	}

	// Calculate desired acceleration (user input)	
	Vec3 desiredWorldVelocity(ZERO);

	Vec3 acceleration(ZERO);
	{
		Vec3 desiredLocalNormalizedVelocity(ZERO);
		Vec3 desiredLocalVelocity(ZERO);

		const Quat viewQuat = player.GetViewQuat();

		const float backwardMultiplier = (float)__fsel(movement.desiredVelocity.y, 1.0f, g_pGameCVars->pl_swimBackSpeedMul);
		desiredLocalNormalizedVelocity.x = movement.desiredVelocity.x * g_pGameCVars->pl_swimSideSpeedMul;
		desiredLocalNormalizedVelocity.y = movement.desiredVelocity.y * backwardMultiplier;

		float sprintMultiplier = 1.0f;
		if ((player.IsSprinting()) && !player.IsCinematicFlagActive(SPlayerStats::eCinematicFlag_RestrictMovement))
		{
			sprintMultiplier = GetSwimParams().m_swimSprintSpeedMul;

			// Higher speed multiplier when sprinting while looking up
			const float upFraction = clamp_tpl(viewQuat.GetFwdZ(), 0.0f, 1.0f);
			sprintMultiplier *= LERP(1.0f, GetSwimParams().m_swimUpSprintSpeedMul, upFraction);
		}

		const float baseSpeed = player.GetStanceMaxSpeed(STANCE_SWIM);
		desiredLocalVelocity.x = desiredLocalNormalizedVelocity.x * sprintMultiplier * baseSpeed;
		desiredLocalVelocity.y = desiredLocalNormalizedVelocity.y * sprintMultiplier * baseSpeed;
		desiredLocalVelocity.z = desiredLocalNormalizedVelocity.z * g_pGameCVars->pl_swimVertSpeedMul * baseSpeed;

		// The desired movement is applied in view-space, not in entity-space, since entity does not necessarily pitch while swimming.
		desiredWorldVelocity += viewQuat.GetColumn0() * desiredLocalVelocity.x;
		desiredWorldVelocity += viewQuat.GetColumn1() * desiredLocalVelocity.y;

		// though, apply up/down in world space.
		desiredWorldVelocity.z += desiredLocalVelocity.z;

#ifdef STATE_DEBUG
		if (debug)
		{
			gEnv->pRenderer->DrawLabel(entityPos - vRight * 1.5f + Vec3(0,0,0.8f), 1.5f, "BaseSpeed %1.3f", baseSpeed);
			gEnv->pRenderer->DrawLabel(entityPos - vRight * 1.5f + Vec3(0,0,1.0f), 1.5f, "SprintMul %1.2f", sprintMultiplier);
			gEnv->pRenderer->DrawLabel(entityPos - vRight * 1.5f + Vec3(0,0,0.6f), 1.5f, "MoveN[%1.3f, %1.3f, %1.3f]", desiredLocalNormalizedVelocity.x, desiredLocalNormalizedVelocity.y, desiredLocalNormalizedVelocity.z);
			gEnv->pRenderer->DrawLabel(entityPos - vRight * 1.5f + Vec3(0,0,0.5f), 1.5f, "VeloL[%1.3f, %1.3f, %1.3f]", desiredLocalVelocity.x, desiredLocalVelocity.y, desiredLocalVelocity.z);
			gEnv->pRenderer->DrawLabel(entityPos - vRight * 1.5f + Vec3(0,0,0.4f), 1.5f, "VeloW[%1.3f, %1.3f, %1.3f]", desiredWorldVelocity.x, desiredWorldVelocity.y, desiredWorldVelocity.z);
		}
#endif

		//Remove a bit of control when entering the water
		const float userControlFraction = (float)__fsel(0.3f - waterProxy.GetSwimmingTimer(), 0.2f, 1.0f); 
		acceleration += desiredWorldVelocity * userControlFraction;
	}

	// Apply acceleration (frame-rate independent)
	const float accelerateDelayInv = 3.333f;
	velocity += acceleration * (frameTime * accelerateDelayInv);

#ifdef STATE_DEBUG
	if( debug )
	{
		gEnv->pRenderer->DrawLabel(entityPos - vRight * 1.5f - Vec3(0,0,0.2f), 1.5f, " Axx[%1.3f, %1.3f, %1.3f]", acceleration.x, acceleration.y, acceleration.z);
	}
#endif

	//--------------------

	const float relativeWaterLevel = waterProxy.GetRelativeWaterLevel() + 0.1f;
	const float surfaceDistanceFraction = clamp_tpl(fabsf(relativeWaterLevel), 0.0f, 1.0f);
	float surfaceProximityInfluence = 1.0f - surfaceDistanceFraction;
	const float verticalVelocityFraction = clamp_tpl((fabsf(desiredWorldVelocity.z) - 0.3f) * 2.5f, 0.0f, 1.0f);
	surfaceProximityInfluence = surfaceProximityInfluence * (1.0f - verticalVelocityFraction);

	// Apply velocity dampening (frame-rate independent)
	Vec3 damping(ZERO);

	const float zSpeedPreDamping = velocity.z;

	{
		damping.x = fabsf(velocity.x);
		damping.y = fabsf(velocity.y);

		// Vertical damping is special, to allow jumping out of water with higher speed, 
		// and also not sink too deep when falling down ito the water after jump or such.
		float zDamp = 1.0f + (6.0f * clamp_tpl((-velocity.z - 1.0f) * 0.333f, 0.0f, 1.0f));
		zDamp *= 1.0f - surfaceProximityInfluence;

		damping.z = fabsf(velocity.z) * zDamp;

		const float stopDelayInv = 3.333f;
		damping *= (frameTime * stopDelayInv);
		velocity.x = (float)__fsel((fabsf(velocity.x) - damping.x), (velocity.x - fsgnf(velocity.x) * damping.x), 0.0f);
		velocity.y = (float)__fsel((fabsf(velocity.y) - damping.y), (velocity.y - fsgnf(velocity.y) * damping.y), 0.0f);
		velocity.z = (float)__fsel((fabsf(velocity.z) - damping.z), (velocity.z - fsgnf(velocity.z) * damping.z), 0.0f);
		
		//Make sure you can not swim above the surface
		if ((relativeWaterLevel >= 0.0f) && (velocity.z > 0.0f))
		{
			velocity.z = 0.0f;
		}
	}

	// Decide if we're on the surface and therefore need to be kept there..
	if( relativeWaterLevel > -0.2f && relativeWaterLevel < 1.0f && fabs_tpl( zSpeedPreDamping ) < 0.5f )
	{
		if( !waterProxy.IsHeadUnderWater() )
		{
			m_onSurface = true;
		}
	}
	else
	{
		// we only leave the surface if the player moves, otherwise we try and keep the 
		// player on the surface, even if they currently arent
		m_onSurface = false;
	}

	// Calculate and apply surface movement to the player.
	float speedDelta = 0.0f;
	if( m_onSurface )
	{
		const float newWaterLevel = waterProxy.GetWaterLevel();
		const float waterLevelDelta = clamp_tpl(newWaterLevel - m_lastWaterLevel, -1.0f, 1.0f );
		const float newCheckedTime = waterProxy.GetWaterLevelTimeUpdated();
		const float timeDelta = newCheckedTime - m_lastWaterLevelTime;

		if( timeDelta > FLT_EPSILON )
		{
			speedDelta = waterLevelDelta/timeDelta;

			velocity.z += speedDelta;
		}

		m_lastWaterLevel = newWaterLevel;
		m_lastWaterLevelTime = newCheckedTime;
	}

	// Set request type and velocity
	player.GetMoveRequest().type = eCMT_Fly;
	player.GetMoveRequest().velocity = velocity;

#ifdef STATE_DEBUG
	// DEBUG VELOCITY
	if (debug)
	{
		gEnv->pRenderer->DrawLabel(entityPos - vRight * 1.5f - Vec3(0,0,0.0f), 1.5f, "Velo[%1.3f, %1.3f, %1.3f]", velocity.x, velocity.y, velocity.z);
		gEnv->pRenderer->DrawLabel(entityPos - vRight * 1.5f - Vec3(0,0,0.4f), 1.5f, "Damp[%1.3f, %1.3f, %1.3f]", damping.x, damping.y, damping.z);
		gEnv->pRenderer->DrawLabel(entityPos - vRight * 1.5f - Vec3(0,0,0.6f), 1.5f, "FrameTime %1.4f", frameTime);
		gEnv->pRenderer->DrawLabel(entityPos - vRight * 1.5f + Vec3(0,0,0.3f), 1.5f, "DeltaSpeed[%1.3f]", speedDelta );
		//if (bNewSwimJumping)
			//gEnv->pRenderer->DrawLabel(entityPos - vRight * 0.15f + Vec3(0,0,0.6f), 2.0f, "JUMP");
	}
#endif

	return true;
}