// Handles logic of contact points stored in array and passes parameters to ApplyFriction() where actual physics calculations are done
void UMMTFrictionComponent::PhysicsUpdate(const float& NumberOfContactPoints, const float& DeltaTime, FVector& NormalizedReactionForce, FVector& RollingFrictionForce)
{
    //Gather stats
    SCOPE_CYCLE_COUNTER(STAT_MMTFrictionPhysicsUpdate);

    FVector NormalizedReactionForceOut = FVector::ZeroVector;
    FVector RollingFrictionForceOut = FVector::ZeroVector;

    if (ContactPointsData.Num() > 0)
    {
        if (ContactPointsData[0].IsPointActive)
        {
            // Get physics sub-stepping valid transform of the friction component
            ReferenceFrameTransform = UMMTBPFunctionLibrary::MMTGetTransformComponent( this, NAME_None);

            // Collisions are often to happen on the edge of the collision mesh, we "project" points on the X axis of the friction component as if collision happened
            // on the center-line of the track
            FVector PointLocationCentered = ReferenceFrameTransform.InverseTransformPosition(ContactPointsData[0].ContactPointLocation);
            PointLocationCentered = ReferenceFrameTransform.TransformPosition(FVector(PointLocationCentered.X, 0.0f, PointLocationCentered.Z));

            FVector PointNormalCentered = ReferenceFrameTransform.InverseTransformVector(ContactPointsData[0].ContactPointNormal);
            PointNormalCentered = ReferenceFrameTransform.TransformVector(FVector(PointNormalCentered.X, 0.0f, PointNormalCentered.Z));

            FVector PreNormalForceCentered = ReferenceFrameTransform.InverseTransformVector(ContactPointsData[0].NormalImpulseAtPoint / DeltaTime);
            PreNormalForceCentered = ReferenceFrameTransform.TransformVector(FVector(PreNormalForceCentered.X, 0.0f, PreNormalForceCentered.Z));

            //Apply Friction calculations
            ApplyFriction(PointLocationCentered, PointNormalCentered, ContactPointsData[0].InducedVelocity, PreNormalForceCentered, ContactPointsData[0].PhysicalSurface,
                          NumberOfContactPoints, DeltaTime, NormalizedReactionForce, RollingFrictionForce);
        }
        else
        {
            //Return zero vector if point is inactive
            NormalizedReactionForce = FVector::ZeroVector;
            RollingFrictionForce = FVector::ZeroVector;
        }

        // Remove first element as it was processed or wasn't active
        ContactPointsData.RemoveAt(0, 1, true);
    }
    else
    {
        //Return zero vector if no points are stored in array
        NormalizedReactionForce = FVector::ZeroVector;
        RollingFrictionForce = FVector::ZeroVector;
    }
}
Example #2
0
/*
 * DrawAllUnits
 *
 * Draw all the units
 */
void DrawAllUnits (GdkPixmap *pixmap, 
               GtkWidget *drawing_area)
{
    /*
     * Move and display the hero
     */
    ApplyFriction ();
    Move (hero);

    /* --- Keep him in-bounds. --- */
    AdjustSpriteHeight (hero);

    DisplaySprite (drawing_area, sprite_ship, 
                   nShipAdjustment - (sprite_ship->width / 2), 
                   (int) hero->y - (sprite_ship->height / 2));
    /*
     * Move and display everyone else
     */
    DisplayOtherUnits (pixmap, drawing_area);
}
Example #3
0
/*************************************************************************************************************
UPDATES KINETMATICS/POSITION: Velocity, Acceleration, Force, Position
*************************************************************************************************************/
void PhysicsComponent::Update(float dt)
{
	if (!isActive)
		return;

	//Calculate New Acceleration/Velocity
	this->v_Acceleration = this->v_Force / mass;
	this->v_Velocity = v_Velocity + v_Acceleration;

	//Limit
	if ((fabs)(v_Velocity.x) >= MAX_VELOCITY)
		v_Velocity.x = ((fabs)(v_Velocity.x) / v_Velocity.x) * MAX_VELOCITY;
	if ((fabs)(v_Velocity.y) >= MAX_VELOCITY)
		v_Velocity.y = ((fabs)(v_Velocity.y) / v_Velocity.y) * MAX_VELOCITY;

	if ((fabs)(v_Acceleration.x) >= MAX_ACCELERATION)
		v_Acceleration.x = ((fabs)(v_Acceleration.x) / v_Acceleration.x) * MAX_ACCELERATION;
	if ((fabs)(v_Acceleration.y) >= MAX_ACCELERATION)
		v_Acceleration.y = ((fabs)(v_Acceleration.y) / v_Acceleration.y) * MAX_ACCELERATION;

	/***************************************************************************************************************************
	Horizontal Force
	****************************************************************************************************************************/
	if (hasFriction)
		ApplyFriction();

	/***************************************************************************************************************************
	Vertical Force
	****************************************************************************************************************************/
	if (hasGravity)
		ApplyGravity();

	//Update Velocity and Position
	v_Force.SetZero();
	v_Velocity = v_Velocity + v_Acceleration;


	*v_Pos = (*v_Pos) + v_Velocity * dt;
}
Example #4
0
void Grenade::Update ( float dt )
{
	m_fRotation += dt;
	m_fDetonationTimer -= dt;

	if(m_fDetonationTimer < 0)
	{
		CreateExplosionMessage* exploMsg = new CreateExplosionMessage(m_ptPosition.x, m_ptPosition.y, m_fDamage, m_fRadius);
		exploMsg->QueueMessage();

		// Send the explosion event
		/*SGD::Event e("GRENADE_EXPLOSION", nullptr, this);
		e.SendEventNow();*/

		// Explode
		DestroyEntityMessage* pMsg = new DestroyEntityMessage(this);
		// Queue the message
		pMsg->QueueMessage();
		pMsg = nullptr;
	}

	if(m_fRotation > 2 * SGD::PI)
		m_fRotation = 0.0f;

	// Compute object speed, that is the norm of the velocity
	m_fSpeed = m_vtVelocity.ComputeLength ();
	// Compute the aerodynamic drag force
	m_vDragForce = m_vtVelocity * (-.5f * m_fSpeed * m_fDragCoefficient * 64);
	// Apply Friction
	ApplyFriction ( dt );
	// Compute the acceleration using Newton's 2nd Law
	m_vAcceleration = m_vTotalForces / m_fMass;
	// Compute the velocity
	m_vtVelocity += m_vAcceleration * dt;

	Entity::Update ( dt );
}
Example #5
0
void CBE_Floater::SearchManeuver(CCopyEntity* pCopyEnt, SBE_EnemyExtraData *pExtraData)
{
	Vector3& rvDesiredDirection  = pCopyEnt->v1;
	Vector3& rvTargetPosition    = pExtraData->vTargetPosition;
	float& rfSensoringInterval2      = pExtraData->fSensoringInterval2;
	float& rfCurrentManeuverTime     = pExtraData->fCurrentManeuverTime;
	float& rfTotalManeuverTime       = pExtraData->fTotalManeuverTime;
	Vector3& rvManeuverDir       = pExtraData->vManeuverDirection;
	float fWishSpeed = 6.0f;

	const float frametime = m_pStage->GetFrameTime();

//	if( pCopyEnt->vVelocity == Vector3(0,0,0) )
//		return;

	ApplyFriction( pCopyEnt, 1.5f );

	if( m_iRandomSearchManeuver != 0 )
	{
		Vector3 vFromCurrentPosToDest = rvTargetPosition - pCopyEnt->GetWorldPosition();
		float fDist = Vec3LengthSq( vFromCurrentPosToDest );

		if( 0.20f < rfCurrentManeuverTime - rfTotalManeuverTime ||
			rvManeuverDir == Vector3(0,0,0) || fDist < 0.2f )
		{
			rfCurrentManeuverTime = 0;
			rfTotalManeuverTime = 1.0f + 0.6f * (float)rand() / (float)RAND_MAX;

			// set up a target locaion
			rvTargetPosition
				= pExtraData->vOriginalPosition
				+ Vector3(1,0,0) * ( 12.0f * (float)rand()/(float)RAND_MAX - 6.0f )
				+ Vector3(0,1,0) * (  6.0f * (float)rand()/(float)RAND_MAX - 3.0f )
				+ Vector3(0,0,1) * ( 12.0f * (float)rand()/(float)RAND_MAX - 6.0f )
				+ pCopyEnt->GetDirection() * 2.5f;

			Vec3Normalize( rvManeuverDir, rvManeuverDir );
		}
		else
			rfCurrentManeuverTime += frametime;

		if( 0.16f < rfSensoringInterval2 )
		{
			rfSensoringInterval2 = 0.0f;
			Vec3Normalize( rvManeuverDir, vFromCurrentPosToDest );
		}
		else
			rfSensoringInterval2 += frametime;

		if( 0.1f < rfTotalManeuverTime - rfCurrentManeuverTime )
		{
			float fWishSpeed = 4.5f;
			Accelerate( pCopyEnt, rvManeuverDir, fWishSpeed, 2.0f );
		}

		UpdateDesiredYawAndPitch(pCopyEnt, rvManeuverDir);
		AimAlong(pCopyEnt, rvManeuverDir);
	}

	SlideMove( pCopyEnt );
}
Example #6
0
void C4Object::DoMovement()
{
	int32_t iContact=0;
	bool fAnyContact=false; int iContacts = 0;
	BYTE fTurned=0,fRedirectYR=0,fNoAttach=0;
	// Restrictions
	if (Def->NoHorizontalMove) xdir=0;
	// Dig free target area
	C4PropList* pActionDef = GetAction();
	if (pActionDef)
		if (pActionDef->GetPropertyInt(P_DigFree))
		{
			int ctcox, ctcoy;
			// Shape size square
			if (pActionDef->GetPropertyInt(P_DigFree)==1)
			{
				ctcox=fixtoi(fix_x+xdir); ctcoy=fixtoi(fix_y+ydir);
				::Landscape.DigFreeRect(ctcox+Shape.GetX(),ctcoy+Shape.GetY(),Shape.Wdt,Shape.Hgt,this);
			}
			// Free size round (variable size)
			else
			{
				ctcox=fixtoi(fix_x+xdir); ctcoy=fixtoi(fix_y+ydir);
				int32_t rad = pActionDef->GetPropertyInt(P_DigFree);
				if (Con<FullCon) rad = rad*6*Con/5/FullCon;
				::Landscape.DigFree(ctcox,ctcoy-1,rad,this);
			}
		}

	// store previous movement and ocf
	C4Real oldxdir(xdir), oldydir(ydir);
	uint32_t old_ocf = OCF;

	bool fMoved = false;
	C4Real new_x = fix_x + xdir;
	C4Real new_y = fix_y + ydir;
	SideBounds(new_x);

	if (!Action.t_attach) // Unattached movement  = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
	{
		// Horizontal movement - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
		// Move to target
		while (fixtoi(new_x) != fixtoi(fix_x))
		{
			// Next step
			int step = Sign(new_x - fix_x);
			uint32_t border_hack_contacts = 0;
			iContact=ContactCheck(GetX() + step, GetY(), &border_hack_contacts);
			if (iContact || border_hack_contacts)
			{
				fAnyContact=true; iContacts |= t_contact | border_hack_contacts;
			}
			if (iContact)
			{
				// Abort horizontal movement
				new_x = fix_x;
				// Vertical redirection (always)
				RedirectForce(xdir,ydir,-1);
				ApplyFriction(ydir,ContactVtxFriction(this));
			}
			else // Free horizontal movement
			{
				DoMotion(step, 0);
				fMoved = true;
			}
		}
		// Vertical movement - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
		// Movement target
		new_y = fix_y + ydir;
		// Movement bounds (vertical)
		VerticalBounds(new_y);
		// Move to target
		while (fixtoi(new_y) != fixtoi(fix_y))
		{
			// Next step
			int step = Sign(new_y - fix_y);
			if ((iContact=ContactCheck(GetX(), GetY() + step, nullptr, ydir > 0)))
			{
				fAnyContact=true; iContacts |= t_contact;
				new_y = fix_y;
				// Vertical contact horizontal friction
				ApplyFriction(xdir,ContactVtxFriction(this));
				// Redirection slide or rotate
				if (!ContactVtxCNAT(this,CNAT_Left))
					RedirectForce(ydir,xdir,-1);
				else if (!ContactVtxCNAT(this,CNAT_Right))
					RedirectForce(ydir,xdir,+1);
				else
				{
					// living things are always capable of keeping their rotation
					if (OCF & OCF_Rotate) if (iContact==1) if (!Alive)
							{
								RedirectForce(ydir,rdir,-ContactVtxWeight(this));
								fRedirectYR=1;
							}
					ydir=0;
				}
			}
			else // Free vertical movement
			{
				DoMotion(0,step);
				fMoved = true;
			}
		}
	}
	if (Action.t_attach) // Attached movement = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
	{
		VerticalBounds(new_y);
		// Move to target
		do
		{
			// Set next step target
			int step_x = 0, step_y = 0;
			if (fixtoi(new_x) != GetX())
				step_x = Sign(fixtoi(new_x) - GetX());
			else if (fixtoi(new_y) != GetY())
				step_y = Sign(fixtoi(new_y) - GetY());
			int32_t ctx = GetX() + step_x;
			int32_t cty = GetY() + step_y;
			// Attachment check
			if (!Shape.Attach(ctx,cty,Action.t_attach))
				fNoAttach=1;
			else
			{
				// Attachment change to ctx/cty overrides target
				if (ctx != GetX() + step_x)
				{
					xdir = Fix0; new_x = itofix(ctx);
				}
				if (cty != GetY() + step_y)
				{
					ydir = Fix0; new_y = itofix(cty);
				}
			}
			// Contact check & evaluation
			uint32_t border_hack_contacts = 0;
			iContact=ContactCheck(ctx,cty,&border_hack_contacts);
			if (iContact || border_hack_contacts)
			{
				fAnyContact=true; iContacts |= border_hack_contacts | t_contact;
			}
			if (iContact)
			{
				// Abort movement
				if (ctx != GetX())
				{
					ctx = GetX(); new_x = fix_x;
				}
				if (cty != GetY())
				{
					cty = GetY(); new_y = fix_y;
				}
			}
			DoMotion(ctx - GetX(), cty - GetY());
			fMoved = true;
		}
		while (fixtoi(new_x) != GetX() || fixtoi(new_y) != GetY());
	}

	if(fix_x != new_x || fix_y != new_y)
	{
		fMoved = true;
		if (pSolidMaskData) pSolidMaskData->Remove(true);
		fix_x = new_x;
		fix_y = new_y;
	}
	// Rotation  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	if (OCF & OCF_Rotate && !!rdir)
	{
		C4Real target_r = fix_r + rdir * 5;
		// Rotation limit
		if (Def->Rotateable>1)
		{
			if (target_r > itofix(Def->Rotateable))
				{ target_r = itofix(Def->Rotateable); rdir=0; }
			if (target_r < itofix(-Def->Rotateable))
				{ target_r = itofix(-Def->Rotateable); rdir=0; }
		}
		int32_t ctx=GetX(); int32_t cty=GetY();
		// Move to target
		while (fixtoi(fix_r) != fixtoi(target_r))
		{
			// Save step undos
			C4Real lcobjr = fix_r; C4Shape lshape=Shape;
			// Try next step
			fix_r += Sign(target_r - fix_r);
			UpdateShape();
			// attached rotation: rotate around attachment pos
			if (Action.t_attach && !fNoAttach)
			{
				// more accurately, attachment should be evaluated by a rotation around the attachment vertex
				// however, as long as this code is only used for some surfaces adjustment for large vehicles,
				// it's enough to assume rotation around the center
				ctx=GetX(); cty=GetY();
				// evaluate attachment, but do not bother about attachment loss
				// that will then be done in next execution cycle
				Shape.Attach(ctx,cty,Action.t_attach);
			}
			// check for contact
			if ((iContact=ContactCheck(ctx,cty))) // Contact
			{
				fAnyContact=true; iContacts |= t_contact;
				// Undo step and abort movement
				Shape=lshape;
				target_r = fix_r = lcobjr;
				// last UpdateShape-call might have changed sector lists!
				UpdatePos();
				// Redirect to GetY()
				if (iContact==1) if (!fRedirectYR)
						RedirectForce(rdir,ydir,-1);
				// Stop rotation
				rdir=0;
			}
			else
			{
				fTurned=1;
				if (ctx != GetX() || cty != GetY())
				{
					fix_x = itofix(ctx); fix_y = itofix(cty);
				}
			}
		}
		// Circle bounds
		if (target_r < -FixHalfCircle) { target_r += FixFullCircle; }
		if (target_r > +FixHalfCircle) { target_r -= FixFullCircle; }
		fix_r = target_r;
	}
	// Reput solid mask if moved by motion
	if (fMoved || fTurned) UpdateSolidMask(true);
	// Misc checks ===========================================================================================
	// InLiquid check
	// this equals C4Object::UpdateLiquid, but the "fNoAttach=false;"-line
	if (IsInLiquidCheck()) // In Liquid
	{
		if (!InLiquid) // Enter liquid
		{
			if (OCF & OCF_HitSpeed2) if (Mass>3)
					Splash(GetX(),GetY()+1,std::min(Shape.Wdt*Shape.Hgt/10,20),this);
			fNoAttach=false;
			InLiquid=1;
		}
	}
	else // Out of liquid
	{
		if (InLiquid) // Leave liquid
			InLiquid=0;
	}
	// Contact Action
	if (fAnyContact)
	{
		t_contact = iContacts;
		ContactAction();
	}
	// Attachment Loss Action
	if (fNoAttach)
		NoAttachAction();
	// Movement Script Execution
	if (fAnyContact)
	{
		C4AulParSet pars(C4VInt(fixtoi(oldxdir, 100)), C4VInt(fixtoi(oldydir, 100)));
		if (old_ocf & OCF_HitSpeed1) Call(PSF_Hit, &pars);
		if (old_ocf & OCF_HitSpeed2) Call(PSF_Hit2, &pars);
		if (old_ocf & OCF_HitSpeed3) Call(PSF_Hit3, &pars);
	}
	// Rotation gfx
	if (fTurned)
		UpdateFace(true);
	else
		// pos changed?
		if (fMoved) UpdatePos();
}
Example #7
0
/*
================
rvPhysics_Particle::Evaluate

  Evaluate the impulse based rigid body physics.
  When a collision occurs an impulse is applied at the moment of impact but
  the remaining time after the collision is ignored.
================
*/
bool rvPhysics_Particle::Evaluate( int timeStepMSec, int endTimeMSec ) {
	particlePState_t next;
	float			 timeStep;
	float			 upspeed;

	timeStep = MS2SEC( timeStepMSec );

	// if bound to a master
	if ( hasMaster ) {
		idVec3	masterOrigin;
		idMat3	masterAxis;
		idVec3	oldOrigin;		
		
		oldOrigin = current.origin;
		
		self->GetMasterPosition( masterOrigin, masterAxis );
		current.origin = masterOrigin + current.localOrigin * masterAxis;
// RAVEN BEGIN
// ddynerman: multiple clip worlds
		clipModel->Link( self, clipModel->GetId(), current.origin, current.localAxis * masterAxis );
// RAVEN END

		trace_t tr;
		gameLocal.Translation( self, tr, oldOrigin, current.origin, clipModel, clipModel->GetAxis(), clipMask, self );
		
		if ( tr.fraction < 1.0f ) {
			self->Collide ( tr, current.origin - oldOrigin );
		}
		
		DebugDraw();
		
		return true;
	}

	// if the body is at rest
	if ( current.atRest >= 0 || timeStep <= 0.0f ) {
		DebugDraw();
		return false;
	}

	// if putting the body to rest
	if ( dropToFloor ) {
		DropToFloorAndRest();
		return true;
	}

	clipModel->Unlink();

	// Determine if currently on the ground
	CheckGround ( );
	
	// Determine the current upward velocity
	if ( gravityNormal != vec3_zero ) {
		upspeed = -( current.velocity * gravityNormal );
	} else {
		upspeed = current.velocity.z;
	}

	// If not on the ground, or moving upwards, or bouncing and moving toward gravity then do a straight 
	// forward slide move and gravity.		
	if ( !current.onGround || upspeed > 1.0f || (bouncyness > 0.0f && upspeed < -PRT_BOUNCESTOP && !current.inWater) ) {
		// Force ground off when moving upward
		if ( upspeed > 0.0f ) {
			current.onGround = false;
		}
		SlideMove( current.origin, current.velocity, current.velocity * timeStep );		
		if ( current.onGround && upspeed < PRT_BOUNCESTOP ) {
			current.velocity -= ( current.velocity * gravityNormal ) * gravityNormal;
		} else {
			current.velocity += (gravityVector * timeStep);	
		}
	} else {
		idVec3 delta;

		// Slow down due to friction
		ApplyFriction ( timeStep );
	
		delta = current.velocity * timeStep;
		current.velocity -= ( current.velocity * gravityNormal ) * gravityNormal;
		if ( delta == vec3_origin ) {
			PutToRest( );
		} else {
			SlideMove( current.origin, current.velocity, delta );
		}
	}

	// update the position of the clip model
// RAVEN BEGIN
// ddynerman: multiple clip worlds
	clipModel->Link( self, clipModel->GetId(), current.origin, clipModel->GetAxis() );
// RAVEN END

	DebugDraw();

	// get all the ground contacts
	EvaluateContacts();

	current.pushVelocity.Zero();

	if ( IsOutsideWorld() ) {
		gameLocal.Warning( "clip model outside world bounds for entity '%s' at (%s)", self->name.c_str(), current.origin.ToString(0) );
		PutToRest();
	}

	return true;
}