Esempio n. 1
0
void FSceneView::DeprojectScreenToWorld(const FVector2D& ScreenPos, const FIntRect& ViewRect, const FMatrix& InvViewMatrix, const FMatrix& InvProjectionMatrix, FVector& out_WorldOrigin, FVector& out_WorldDirection)
{
	int32 PixelX = FMath::TruncToInt(ScreenPos.X);
	int32 PixelY = FMath::TruncToInt(ScreenPos.Y);

	// Get the eye position and direction of the mouse cursor in two stages (inverse transform projection, then inverse transform view).
	// This avoids the numerical instability that occurs when a view matrix with large translation is composed with a projection matrix

	// Get the pixel coordinates into 0..1 normalized coordinates within the constrained view rectangle
	const float NormalizedX = (PixelX - ViewRect.Min.X) / ((float)ViewRect.Width());
	const float NormalizedY = (PixelY - ViewRect.Min.Y) / ((float)ViewRect.Height());

	// Get the pixel coordinates into -1..1 projection space
	const float ScreenSpaceX = (NormalizedX - 0.5f) * 2.0f;
	const float ScreenSpaceY = ((1.0f - NormalizedY) - 0.5f) * 2.0f;

	// The start of the raytrace is defined to be at mousex,mousey,1 in projection space (z=1 is near, z=0 is far - this gives us better precision)
	// To get the direction of the raytrace we need to use any z between the near and the far plane, so let's use (mousex, mousey, 0.5)
	const FVector4 RayStartProjectionSpace = FVector4(ScreenSpaceX, ScreenSpaceY, 1.0f, 1.0f);
	const FVector4 RayEndProjectionSpace = FVector4(ScreenSpaceX, ScreenSpaceY, 0.5f, 1.0f);

	// Projection (changing the W coordinate) is not handled by the FMatrix transforms that work with vectors, so multiplications
	// by the projection matrix should use homogeneous coordinates (i.e. FPlane).
	const FVector4 HGRayStartViewSpace = InvProjectionMatrix.TransformFVector4(RayStartProjectionSpace);
	const FVector4 HGRayEndViewSpace = InvProjectionMatrix.TransformFVector4(RayEndProjectionSpace);
	FVector RayStartViewSpace(HGRayStartViewSpace.X, HGRayStartViewSpace.Y, HGRayStartViewSpace.Z);
	FVector RayEndViewSpace(HGRayEndViewSpace.X,   HGRayEndViewSpace.Y,   HGRayEndViewSpace.Z);
	// divide vectors by W to undo any projection and get the 3-space coordinate 
	if (HGRayStartViewSpace.W != 0.0f)
	{
		RayStartViewSpace /= HGRayStartViewSpace.W;
	}
	if (HGRayEndViewSpace.W != 0.0f)
	{
		RayEndViewSpace /= HGRayEndViewSpace.W;
	}
	FVector RayDirViewSpace = RayEndViewSpace - RayStartViewSpace;
	RayDirViewSpace = RayDirViewSpace.GetSafeNormal();

	// The view transform does not have projection, so we can use the standard functions that deal with vectors and normals (normals
	// are vectors that do not use the translational part of a rotation/translation)
	const FVector RayStartWorldSpace = InvViewMatrix.TransformPosition(RayStartViewSpace);
	const FVector RayDirWorldSpace = InvViewMatrix.TransformVector(RayDirViewSpace);

	// Finally, store the results in the hitcheck inputs.  The start position is the eye, and the end position
	// is the eye plus a long distance in the direction the mouse is pointing.
	out_WorldOrigin = RayStartWorldSpace;
	out_WorldDirection = RayDirWorldSpace.GetSafeNormal();
}
void UTankAimingComponent::AimAt(const FVector& HitLocation)
{
	AActor* const Owner = GetOwner();
	if (IsInitialised())
	{
		FVector OutLaunchVelocity;
		FVector StartLocation = Barrel->GetSocketLocation(FName(TEXT("Projectile"))); 

		// Only for DebugTrace purpose - if not ignore them
		FCollisionResponseParams DummyParams; TArray<AActor*> DummyIgnores;
		
		// Calculate the OutLaunchVelocity
		bool bHaveAimSolution = UGameplayStatics::SuggestProjectileVelocity
		(
			this,
			OutLaunchVelocity,
			StartLocation,
			HitLocation,
			LaunchSpeed,
			false, 
			10.f, 
			0.f, 
			ESuggestProjVelocityTraceOption::DoNotTrace
			//, DummyParams, DummyIgnores, true			// comment line to remove Debug DrawLine
		);

		if (bHaveAimSolution)
		{
			AimForwardDirection = OutLaunchVelocity.GetSafeNormal();
		
			MoveBarrelTowards(AimForwardDirection);
		}
	}
}
void UTankAimingComponent::AimAt(FVector HitLocation, float LaunchSpeed)
{
	if (!Barrel) { return; }
	FVector OutLaunchVelocity;
	FVector StartLocation = Barrel->GetSocketLocation(FName("Projectile"));
	//FVector AimDirection;
	bool bHaveAimSolution = UGameplayStatics::SuggestProjectileVelocity
		(
			this,
			OutLaunchVelocity,
			StartLocation,
			HitLocation,
			LaunchSpeed,
			false,
			0,
			0,
			ESuggestProjVelocityTraceOption::DoNotTrace // Paramater must be present to prevent bug
			);
	auto timestamp = GetWorld()->GetTimeSeconds();

	if (bHaveAimSolution)
	{
		FVector AimDirection = OutLaunchVelocity.GetSafeNormal();
		MoveBarrelTowards(AimDirection);
		
		//UE_LOG(LogTemp, Warning, TEXT("%f: We're aiming"), timestamp);
	}




}
void UTankAimingComponent::AimAt(FVector HitLocation, float LaunchSpeed) {
    if (!Barrel) { return; }

    FVector OutLaunchVelocity;
    FVector StartLocation = Barrel->GetSocketLocation(FName("End"));

    bool bHasAimSolution = UGameplayStatics::SuggestProjectileVelocity(
        this,
        OutLaunchVelocity,
        StartLocation,
        HitLocation,
        LaunchSpeed,
        false,
        0,
        0,
        ESuggestProjVelocityTraceOption::DoNotTrace
    );

    if (bHasAimSolution) {
        auto AimDirection = OutLaunchVelocity.GetSafeNormal();
        MoveBarrelTowards(AimDirection);
    }

    return;
}
void AMMO_Character::ShootArrow()
{
	if(Role<ROLE_Authority)
	ArrowsLeft--;

	FActorSpawnParameters spawnParams;
	spawnParams.Owner = this;
	spawnParams.Instigator = Instigator;

	FVector SpawnLoc = FVector(0);
	FVector DirHelper = FVector(0);
	if (LockedTarget)
	{
		SpawnLoc = Player_SkeletalMeshComponent->GetComponentLocation();
		DirHelper = LockedTarget->GetActorLocation() - SpawnLoc;
	}
	else
	{
		SpawnLoc = ShootingLocation->GetComponentLocation();
		DirHelper = LastKnownLocationOfTarget - SpawnLoc;
	}
	
	FRotator SpawnRot = Player_SpringArmComponent->GetComponentRotation() + FRotator(0,-90,0);

	if(Role == ROLE_Authority)
	FinalArrowDamage = BaseAttack + FMath::RandRange(AttackBonusMin, AttackBonusMax);

	AArcherArrow* OurNewObject = GetWorld()->SpawnActor<AArcherArrow>(MyArrowObject, SpawnLoc , SpawnRot, spawnParams);
	

	OurNewObject->ApplyForce(ArrowForce, this, DirHelper.GetSafeNormal());
}
Esempio n. 6
0
void AMagnetTile::PullBall( ABallPawn* ball )
{
	auto prim = Cast<UPrimitiveComponent>( ball->GetRootComponent() );
	UWorld* world = GetWorld();
	auto DeltaTime = world->DeltaTimeSeconds;
	AProjectTapGameState* gameState;
	if ( world != nullptr && ( gameState = world->GetGameState<AProjectTapGameState>() ) != nullptr && gameState->SetMagnetTile( this ) != this )
	{
		FVector angular = FVector::ZeroVector;
		prim->SetPhysicsAngularVelocity( angular );
		float distanceAtNormal = FVector::DotProduct( ball->GetActorLocation() - GetActorLocation() , GetActorForwardVector() );
		FVector normalLoc = ( distanceAtNormal * GetActorForwardVector() ) + GetActorLocation();
		FVector normalToBall = ball->GetActorLocation() - normalLoc;
		float dist = normalToBall.Size();
		if ( dist > centerTolerance )
		{
			FVector toAdd = dist * -normalToBall.GetSafeNormal();
			toAdd.Z = 0;
			prim->AddRelativeLocation( toAdd );
		}
	}
	if ( isVertical )
	{
		attractionSpeed *= verticalForceMultiplier;
	}
	float originalSpeed = prim->GetPhysicsLinearVelocity().Size();
	float newSpeed = attractionSpeed + originalSpeed;
	prim->SetPhysicsLinearVelocity(newSpeed * -GetActorForwardVector());
}
bool UTKMathFunctionLibrary::AreLineSegmentsCrossing(FVector pointA1, FVector pointA2, FVector pointB1, FVector pointB2)
{
	FVector closestPointA;
	FVector closestPointB;
	int32 sideA;
	int32 sideB;

	FVector lineVecA = pointA2 - pointA1;
	FVector lineVecB = pointB2 - pointB1;

	bool valid = ClosestPointsOnTwoLines(closestPointA, closestPointB, pointA1, lineVecA.GetSafeNormal(), pointB1, lineVecB.GetSafeNormal());

	//lines are not parallel
	if (valid)
	{
		sideA = PointOnWhichSideOfLineSegment(pointA1, pointA2, closestPointA);
		sideB = PointOnWhichSideOfLineSegment(pointB1, pointB2, closestPointB);

		if ((sideA == 0) && (sideB == 0))
		{
			return true;
		}
		else
		{
			return false;
		}
	}

	//lines are parallel
	else
	{
		return false;
	}
}
void UTankAimingComponent::AimAt(FVector HitLocation)
{
	if (!Barrel) { return; }

	FVector OutLaunchVelocity;
	FVector StartLocation = Barrel->GetSocketLocation(FName("Projectile"));
	bool bHaveAimSolution = UGameplayStatics::SuggestProjectileVelocity
	(
		this,
		OutLaunchVelocity,
		StartLocation,
		HitLocation,
		LaunchSpeed,
		false,
		0,
		0,
		ESuggestProjVelocityTraceOption::DoNotTrace // Paramater must be present to prevent bug
	);

	if (bHaveAimSolution)
	{
        AimDirection = OutLaunchVelocity.GetSafeNormal();
		MoveBarrelTowards(AimDirection);
	}
	// If no solution found do nothing
}
void UTankAimingComponent::AimAt(FVector HitLocation)
{
	if (!ensure(Barrel)) { return; }
		FVector OutLaunchVelocity;
		FVector StartLocation = Barrel->GetSocketLocation(FName("Projectile"));//This gets the socket location

	//Calculate the OutLaunchVelocity
		//The was a porblem with the code, even thought the default value was set we still must 
		//specify the parameter
		bool bHaveAimSolution = UGameplayStatics::SuggestProjectileVelocity
		(
			this,
			OutLaunchVelocity,
			StartLocation,
			HitLocation,
			LaunchSpeed,
			false,
			0,
			0,
			ESuggestProjVelocityTraceOption::DoNotTrace //Parameter must be present to prevent bug 
		);

		if(bHaveAimSolution)
		{
			AimDirection = OutLaunchVelocity.GetSafeNormal();
			MoveBarrelTowards(AimDirection);
			
		}
	
	
}
Esempio n. 10
0
void UTankAimingComponent::AimAt(FVector HitLocation)
{
	if (!ensure(Barrel)) { return; }

	FVector OutLaunchVelocity;
	FVector StartLocation = Barrel->GetSocketLocation(FName("Projectile"));

	//calculate the OutLaunchVelocity
	bool bHaveAimSolution = UGameplayStatics::SuggestProjectileVelocity
	(
		this,
		OutLaunchVelocity,
		StartLocation,
		HitLocation,
		LaunchSpeed,
		false,
		0,
		0,
		ESuggestProjVelocityTraceOption::DoNotTrace
	);

	if (bHaveAimSolution)
	{
		AimDirection = OutLaunchVelocity.GetSafeNormal();
		MoveBarrelTowards(AimDirection);
	}
	// no aim solution found, do nothing
}
void UAnimGraphNode_BoneDrivenController::Draw(FPrimitiveDrawInterface* PDI, USkeletalMeshComponent* SkelMeshComp) const
{	
	static const float ArrowHeadWidth = 5.0f;
	static const float ArrowHeadHeight = 8.0f;

	const int32 SourceIdx = SkelMeshComp->GetBoneIndex(Node.SourceBone.BoneName);
	const int32 TargetIdx = SkelMeshComp->GetBoneIndex(Node.TargetBone.BoneName);

	if ((SourceIdx != INDEX_NONE) && (TargetIdx != INDEX_NONE))
	{
		const FTransform SourceTM = SkelMeshComp->GetSpaceBases()[SourceIdx] * SkelMeshComp->ComponentToWorld;
		const FTransform TargetTM = SkelMeshComp->GetSpaceBases()[TargetIdx] * SkelMeshComp->ComponentToWorld;

		PDI->DrawLine(TargetTM.GetLocation(), SourceTM.GetLocation(), FLinearColor(0.0f, 0.0f, 1.0f), SDPG_Foreground, 0.5f);

		const FVector ToTarget = TargetTM.GetTranslation() - SourceTM.GetTranslation();
		const FVector UnitToTarget = ToTarget.GetSafeNormal();
		FVector Midpoint = SourceTM.GetTranslation() + 0.5f * ToTarget + 0.5f * UnitToTarget * ArrowHeadHeight;

		FVector YAxis;
		FVector ZAxis;
		UnitToTarget.FindBestAxisVectors(YAxis, ZAxis);
		const FMatrix ArrowMatrix(UnitToTarget, YAxis, ZAxis, Midpoint);

		DrawConnectedArrow(PDI, ArrowMatrix, FLinearColor(0.0f, 1.0f, 0.0), ArrowHeadHeight, ArrowHeadWidth, SDPG_Foreground);

		PDI->DrawPoint(SourceTM.GetTranslation(), FLinearColor(0.8f, 0.8f, 0.2f), 5.0f, SDPG_Foreground);
		PDI->DrawPoint(SourceTM.GetTranslation() + ToTarget, FLinearColor(0.8f, 0.8f, 0.2f), 5.0f, SDPG_Foreground);
	}
}
void UMovementComponent::TwoWallAdjust(FVector& OutDelta, const FHitResult& Hit, const FVector& OldHitNormal) const
{
	FVector Delta = OutDelta;
	const FVector HitNormal = Hit.Normal;

	if ((OldHitNormal | HitNormal) <= 0.f) //90 or less corner, so use cross product for direction
	{
		const FVector DesiredDir = Delta;
		FVector NewDir = (HitNormal ^ OldHitNormal);
		NewDir = NewDir.GetSafeNormal();
		Delta = (Delta | NewDir) * (1.f - Hit.Time) * NewDir;
		if ((DesiredDir | Delta) < 0.f)
		{
			Delta = -1.f * Delta;
		}
	}
	else //adjust to new wall
	{
		const FVector DesiredDir = Delta;
		Delta = ComputeSlideVector(Delta, 1.f - Hit.Time, HitNormal, Hit);
		if ((Delta | DesiredDir) <= 0.f)
		{
			Delta = FVector::ZeroVector;
		}
		else if ( FMath::Abs((HitNormal | OldHitNormal) - 1.f) < KINDA_SMALL_NUMBER )
		{
			// we hit the same wall again even after adjusting to move along it the first time
			// nudge away from it (this can happen due to precision issues)
			Delta += HitNormal * 0.01f;
		}
	}

	OutDelta = Delta;
}
bool UProjectileMovementComponent::HandleSliding(FHitResult& Hit, float& SubTickTimeRemaining)
{
	FHitResult InitialHit(Hit);
	const FVector OldHitNormal = ConstrainDirectionToPlane(Hit.Normal);

	// Velocity is now parallel to the impact surface.
	// Perform the move now, before adding gravity/accel again, so we don't just keep hitting the surface.
	SafeMoveUpdatedComponent(Velocity * SubTickTimeRemaining, UpdatedComponent->GetComponentQuat(), true, Hit);

	if (HasStoppedSimulation())
	{
		return false;
	}

	// A second hit can deflect the velocity (through the normal bounce code), for the next iteration.
	if (Hit.bBlockingHit)
	{
		const float TimeTick = SubTickTimeRemaining;
		SubTickTimeRemaining = TimeTick * (1.f - Hit.Time);
		
		if (HandleBlockingHit(Hit, TimeTick, Velocity * TimeTick, SubTickTimeRemaining) == EHandleBlockingHitResult::Abort ||
			HasStoppedSimulation())
		{
			return false;
		}
	}
	else
	{
		// Find velocity after elapsed time
		const FVector PostTickVelocity = ComputeVelocity(Velocity, SubTickTimeRemaining);

		// If pointing back into surface, apply friction and acceleration.
		const FVector Force = (PostTickVelocity - Velocity);
		const float ForceDotN = (Force | OldHitNormal);
		if (ForceDotN < 0.f)
		{
			const FVector ProjectedForce = FVector::VectorPlaneProject(Force, OldHitNormal);
			const FVector NewVelocity = Velocity + ProjectedForce;

			const FVector FrictionForce = -NewVelocity.GetSafeNormal() * FMath::Min(-ForceDotN * Friction, NewVelocity.Size());
			Velocity = ConstrainDirectionToPlane(NewVelocity + FrictionForce);
		}
		else
		{
			Velocity = PostTickVelocity;
		}

		// Check min velocity
		if (Velocity.SizeSquared() < FMath::Square(BounceVelocityStopSimulatingThreshold))
		{
			StopSimulating(InitialHit);
			return false;
		}

		SubTickTimeRemaining = 0.f;
	}

	return true;
}
void UTankMovementComponent::RequestDirectMove(const FVector& MoveVelocity, bool bForceMaxSpeed) 
{
	auto TankForward = GetOwner()->GetActorForwardVector().GetSafeNormal();
	auto AIForwardIntention = MoveVelocity.GetSafeNormal();

	auto ForwardThrow = FVector::DotProduct(TankForward, AIForwardIntention);
	auto RightThrow = FVector::CrossProduct(AIForwardIntention, TankForward);
	IntendMoveForward(ForwardThrow);
	IntendTurnRight(RightThrow.GetSafeNormal().Z);
}
void AMMO_Character::TakeDamageFromEnemy(int32 Damage, AActor* Monster)
{
	FRotator Rot = Player_SkeletalMeshComponent->GetSocketRotation(TEXT("Head"));
	Rot = FRotator(0, Rot.Yaw, 0);
	Rot += FRotator(0, 90, 0);

	FVector ForwardVector =  (Rot.Vector() * 500);
	FVector DirToGobo = Monster->GetActorLocation() - GetActorLocation();
	ForwardVector = FVector(ForwardVector.X, ForwardVector.Y, 0);
	DirToGobo = FVector(DirToGobo.X, DirToGobo.Y, 0);

	float DotProduct = FVector::DotProduct(ForwardVector.GetSafeNormal(), DirToGobo.GetSafeNormal());
	
	float Radians = FMath::RadiansToDegrees(acosf(DotProduct));

	if (Cast<AMMO_Mob_Character>(Monster))
	{
		Damage = Cast<AMMO_Mob_Character>(Monster)->Attack + FMath::RandRange(Cast<AMMO_Mob_Character>(Monster)->AttackBonusMin, Cast<AMMO_Mob_Character>(Monster)->AttackBonusMax);
		Multicast_PlaySound(GlobalPool->GenericSoundEffects.FindRef(ESoundEffectLibrary::SFX_DaggerHit), GetActorLocation());
	}
	else if(Cast<ABoss>(Monster))
	{
		Damage = Cast<ABoss>(Monster)->BaseDamage + FMath::RandRange(Cast<ABoss>(Monster)->BonusDamage_Min, Cast<ABoss>(Monster)->BonusDamage_Max);
		Multicast_PlaySound(GlobalPool->GenericSoundEffects.FindRef(ESoundEffectLibrary::SFX_BossHit), GetActorLocation());
	}

	Damage -= Damage*BaseDamageReduction;

	if (FMath::Abs(Radians) <= 55.f && bIsShieldBlocking)
	{
		Damage = FMath::DivideAndRoundDown(Damage, 3);
		Multicast_PlayAnimation(GetHurtMontageShield);
	}
	else
	{
		if (!(AnimInstance->Montage_IsPlaying(AttackMontage) || AnimInstance->Montage_IsPlaying(SecondAttackMontage)))
		{
			Multicast_PlayAnimation(GetHurtMontage);
		}
	}

	UpdateHealth(Damage);
}
Esempio n. 16
0
void UDestructibleComponent::ApplyDamage(float DamageAmount, const FVector& HitLocation, const FVector& ImpulseDir, float ImpulseStrength)
{
#if WITH_APEX
	if (ApexDestructibleActor != NULL)
	{
		const FVector& NormalizedImpactDir = ImpulseDir.GetSafeNormal();

		// Transfer damage information to the APEX NxDestructibleActor interface
		ApexDestructibleActor->applyDamage(DamageAmount, ImpulseStrength, U2PVector( HitLocation ), U2PVector( ImpulseDir ));
	}
#endif
}
Esempio n. 17
0
// Accepts a triangle (XYZ and UV values for each point) and returns a poly base and UV vectors
// NOTE : the UV coords should be scaled by the texture size
static inline void FTexCoordsToVectors(const FVector& V0, const FVector& UV0,
                                       const FVector& V1, const FVector& InUV1,
                                       const FVector& V2, const FVector& InUV2,
                                       FVector* InBaseResult, FVector* InUResult, FVector* InVResult )
{
    // Create polygon normal.
    FVector PN = FVector((V0-V1) ^ (V2-V0));
    PN = PN.GetSafeNormal();

    FVector UV1( InUV1 );
    FVector UV2( InUV2 );

    // Fudge UV's to make sure no infinities creep into UV vector math, whenever we detect identical U or V's.
    if( ( UV0.X == UV1.X ) || ( UV2.X == UV1.X ) || ( UV2.X == UV0.X ) ||
            ( UV0.Y == UV1.Y ) || ( UV2.Y == UV1.Y ) || ( UV2.Y == UV0.Y ) )
    {
        UV1 += FVector(0.004173f,0.004123f,0.0f);
        UV2 += FVector(0.003173f,0.003123f,0.0f);
    }

    //
    // Solve the equations to find our texture U/V vectors 'TU' and 'TV' by stacking them
    // into a 3x3 matrix , one for  u(t) = TU dot (x(t)-x(o) + u(o) and one for v(t)=  TV dot (.... ,
    // then the third assumes we're perpendicular to the normal.
    //
    FMatrix TexEqu = FMatrix::Identity;
    TexEqu.SetAxis( 0, FVector(	V1.X - V0.X, V1.Y - V0.Y, V1.Z - V0.Z ) );
    TexEqu.SetAxis( 1, FVector( V2.X - V0.X, V2.Y - V0.Y, V2.Z - V0.Z ) );
    TexEqu.SetAxis( 2, FVector( PN.X,        PN.Y,        PN.Z        ) );
    TexEqu = TexEqu.InverseFast();

    const FVector UResult( UV1.X-UV0.X, UV2.X-UV0.X, 0.0f );
    const FVector TUResult = TexEqu.TransformVector( UResult );

    const FVector VResult( UV1.Y-UV0.Y, UV2.Y-UV0.Y, 0.0f );
    const FVector TVResult = TexEqu.TransformVector( VResult );

    //
    // Adjust the BASE to account for U0 and V0 automatically, and force it into the same plane.
    //
    FMatrix BaseEqu = FMatrix::Identity;
    BaseEqu.SetAxis( 0, TUResult );
    BaseEqu.SetAxis( 1, TVResult );
    BaseEqu.SetAxis( 2, FVector( PN.X, PN.Y, PN.Z ) );
    BaseEqu = BaseEqu.InverseFast();

    const FVector BResult = FVector( UV0.X - ( TUResult|V0 ), UV0.Y - ( TVResult|V0 ),  0.0f );

    *InBaseResult = - 1.0f *  BaseEqu.TransformVector( BResult );
    *InUResult = TUResult;
    *InVResult = TVResult;

}
Esempio n. 18
0
void UTankMovementComponent::RequestDirectMove(const FVector & MoveVelocity, bool bForceMaxSpeed)
{
	auto MoveVelocityNormal = MoveVelocity.GetSafeNormal();
	auto AIForwardNormal = GetOwner()->GetActorForwardVector().GetSafeNormal();
	auto AIRightNormal = GetOwner()->GetActorRightVector().GetSafeNormal();

	auto ForwardSpeed = FVector::DotProduct(MoveVelocityNormal, AIForwardNormal);//[-1,1]
	auto RightSpeed = FVector::DotProduct(MoveVelocityNormal, AIRightNormal);//[-1,1]

	MoveForward(ForwardSpeed);
	MoveRight(RightSpeed);
}
void UTankMovementComponent::RequestDirectMove(const FVector& MoveVelocity, bool bForceMaxSpeed)
{
	//No reason to call super because we are replacing the functionality
	auto TankForward = GetOwner()->GetActorForwardVector().GetSafeNormal();//Gets the x vector of the tanks 
	auto AIForwardIntention = MoveVelocity.GetSafeNormal();//safe normal, gets you a normal vertor of of this move velocity with out changing it
	
	auto ForwardThrow = FVector::DotProduct(TankForward, AIForwardIntention); //
	auto RightThrow = FVector::CrossProduct(TankForward, AIForwardIntention).Z;// The sine Function //We ge the z component to get a float 
	
	IntendMoveForward(ForwardThrow);
	IntendTurnRight(RightThrow);
														   
}
Esempio n. 20
0
FVector UTKMathFunctionLibrary::ProjectPointOnLine(FVector LineOrigin, FVector LineDirection, FVector Point)
{
	//FVector linePointToPoint = point - linePoint;
	//float t = FVector::DotProduct(linePointToPoint, lineDir);
	//return linePoint + lineDir * t;

	//FVector closestPoint;
	//OutDistance = FMath::PointDistToLine(point, lineDir, linePoint, closestPoint);
	//return closestPoint;

	FVector SafeDir = LineDirection.GetSafeNormal();
	return LineOrigin + (SafeDir * ((Point - LineOrigin) | SafeDir));
}
void UTankMovementComponent::RequestDirectMove(const FVector & MoveVelocity, bool bForceMaxSpeed)
{
	// No need to call super as we replacing Parent method

	FVector TankForward = GetOwner()->GetActorForwardVector().GetSafeNormal();
	FVector AIForwardIntention = MoveVelocity.GetSafeNormal();

	float ForwardThrow = FVector::DotProduct(TankForward, AIForwardIntention);
	IntendMoveForward(ForwardThrow);

	float RightThrow = FVector::CrossProduct(TankForward, AIForwardIntention).Z;
	IntendTurnRight(RightThrow);
}
bool UProjectileMovementComponent::HandleDeflection(FHitResult& Hit, const FVector& OldVelocity, const uint32 NumBounces, float& SubTickTimeRemaining)
{
	const FVector Normal = ConstrainNormalToPlane(Hit.Normal);

	// Multiple hits within very short time period?
	const bool bMultiHit = (PreviousHitTime < 1.f && Hit.Time <= KINDA_SMALL_NUMBER);

	// if velocity still into wall (after HandleBlockingHit() had a chance to adjust), slide along wall
	const float DotTolerance = 0.01f;
	bIsSliding = (bMultiHit && FVector::Coincident(PreviousHitNormal, Normal)) ||
					((Velocity.GetSafeNormal() | Normal) <= DotTolerance);

	if (bIsSliding)
	{
		if (bMultiHit && (PreviousHitNormal | Normal) <= 0.f)
		{
			//90 degree or less corner, so use cross product for direction
			FVector NewDir = (Normal ^ PreviousHitNormal);
			NewDir = NewDir.GetSafeNormal();
			Velocity = Velocity.ProjectOnToNormal(NewDir);
			if ((OldVelocity | Velocity) < 0.f)
			{
				Velocity *= -1.f;
			}
			Velocity = ConstrainDirectionToPlane(Velocity);
		}
		else
		{
			//adjust to move along new wall
			Velocity = ComputeSlideVector(Velocity, 1.f, Normal, Hit);
		}

		// Check min velocity.
		if (Velocity.SizeSquared() < FMath::Square(BounceVelocityStopSimulatingThreshold))
		{
			StopSimulating(Hit);
			return false;
		}

		// Velocity is now parallel to the impact surface.
		if (SubTickTimeRemaining > KINDA_SMALL_NUMBER)
		{
			if (!HandleSliding(Hit, SubTickTimeRemaining))
			{
				return false;
			}
		}
	}

	return true;
}
void UTankMovementComponent::RequestDirectMove(const FVector & MoveVelocity, bool bForceMaxSpeed)
{
	auto tankForward = GetOwner()->GetActorForwardVector().GetSafeNormal();
	auto aiForwardIntention = MoveVelocity.GetSafeNormal();

	auto cosThrow = FVector::DotProduct(tankForward, aiForwardIntention);
	auto sinThrow = FVector::CrossProduct(tankForward, aiForwardIntention).Z;

	IntendMoveForward(cosThrow);
	IntendTurnRight(sinThrow);

	//UE_LOG(LogTemp, Warning, TEXT("cosThrow is %f"), cosThrow);
	//UE_LOG(LogTemp, Warning, TEXT("sinThrow is %f"), sinThrow);
}
Esempio n. 24
0
bool FVertexSnappingImpl::SnapDragLocationToNearestVertex( const FVector& BaseLocation, FVector& DragDelta, FLevelEditorViewportClient* ViewportClient )
{
	int32 MouseX = ViewportClient->Viewport->GetMouseX();
	int32 MouseY = ViewportClient->Viewport->GetMouseY();
	FVector2D MousePosition = FVector2D( MouseX, MouseY ) ;
	
	EAxisList::Type CurrentAxis = ViewportClient->GetCurrentWidgetAxis();

	bool bSnapped = false;
	if( !DragDelta.IsNearlyZero() )
	{
		FVector Direction = DragDelta.GetSafeNormal();

		FSceneViewFamilyContext ViewFamily(FSceneViewFamily::ConstructionValues(
			ViewportClient->Viewport, 
			ViewportClient->GetScene(),
			ViewportClient->EngineShowFlags )
			.SetRealtimeUpdate( ViewportClient->IsRealtime() ));
		FSceneView* View = ViewportClient->CalcSceneView( &ViewFamily );

		FVector DesiredUnsnappedLocation = BaseLocation+DragDelta;
		
		FBoxSphereBounds SnappingAreaBox( FBox( DesiredUnsnappedLocation-VertexSnappingConstants::MaxSnappingDistance, DesiredUnsnappedLocation+VertexSnappingConstants::MaxSnappingDistance )  );

		FBox AllowedSnappingBox = SnappingAreaBox.GetBox();
		
		AllowedSnappingBox += DragDelta;
			
		FPlane ActorPlane( DesiredUnsnappedLocation, Direction );

		TSet< TWeakObjectPtr<AActor> > NoActorsToIgnore;

		FVertexSnappingArgs Args
		( 
			ActorPlane, 
			DesiredUnsnappedLocation,
			ViewportClient,
			View,
			MousePosition,
			CurrentAxis,
			true
		);

		SnapDragDelta( Args, BaseLocation, AllowedSnappingBox, NoActorsToIgnore, DragDelta );
	}

	return bSnapped;
}
void UTankMovementComponent::RequestDirectMove(const FVector& MoveVelocity, bool bForceMaxSpeed)
{
	// No need to call super - we are replacing functionality

	auto TankForward = GetOwner()->GetActorForwardVector().GetSafeNormal();  // Current Heading - unit vector direction relative to the global
	auto AIForwardIntention = MoveVelocity.GetSafeNormal();                  // Direction we WANT to be heading    

	float ForwardVelocity = FVector::DotProduct(TankForward, AIForwardIntention);
	IntendMoveForward(ForwardVelocity);

	float RotateVelocity = FVector::CrossProduct(TankForward, AIForwardIntention).Z;
	IntendTurnRight(RotateVelocity);

//	auto TankName = GetOwner()->GetName();
//	UE_LOG(LogTemp, Warning, TEXT("%s   Rotating to: %f"), *TankName, RotateVelocity);
}
Esempio n. 26
0
void ABotController::SetEnemy(class APawn* InPawn)
{
	//Set the blackboard keys to the object and location of the found enemy, for use in the MoveTo behavior tree task
	BlackboardComp->SetValue<UBlackboardKeyType_Object>(EnemyKeyID, InPawn);
	BlackboardComp->SetValue<UBlackboardKeyType_Vector>(EnemyLocationID, InPawn->GetActorLocation());


	//Calculates and sets the direction for the AI bot's projectile
	ABot* ThisBot = Cast<ABot>(GetPawn());
	ATank *Enemy = Cast<ATank>(this->BestPawn);
	FVector dir;
	dir = Enemy->GetActorLocation() - ThisBot->GetActorLocation();	//Finds the vector between the AI bot and the player tank
	dir = dir.GetSafeNormal(1.0f) * 1000;							//Normalizes and scales the vector for a uniform speed
	ThisBot->Direction = FVector(dir.X, dir.Y, 0.f);				//Zeros out the Z value so the projectile moves solely on the horizontal plane

}
void UCrowdFollowingComponent::UpdateCachedDirections(const FVector& NewVelocity, const FVector& NextPathCorner, bool bTraversingLink)
{
	// MoveSegmentDirection = direction on string pulled path
	const FVector AgentLoc = GetCrowdAgentLocation();
	const FVector ToCorner = NextPathCorner - AgentLoc;
	if (ToCorner.SizeSquared() > FMath::Square(10.0f))
	{
		MoveSegmentDirection = ToCorner.GetSafeNormal();
	}

	// CrowdAgentMoveDirection either direction on path or aligned with current velocity
	if (!bTraversingLink)
	{
		CrowdAgentMoveDirection = bRotateToVelocity && (NewVelocity.SizeSquared() > KINDA_SMALL_NUMBER) ? NewVelocity.GetSafeNormal() : MoveSegmentDirection;
	}
}
void UTankAimingComponent::AimAt(FVector HitLocation)
{
	if (!ensure(Barrel)) { return; }
	FVector OutLaunchVelocity;
	FVector StartLocation = Barrel->GetSocketLocation(FName("Projectile"));
	bool bHaveAimSolution = UGameplayStatics::SuggestProjectileVelocity(this, OutLaunchVelocity, StartLocation, HitLocation, LaunchSpeed, false, 0, 0, ESuggestProjVelocityTraceOption::DoNotTrace);//Calculate the OutLauchVelocity
	if(bHaveAimSolution)
	{
		AimDirection = OutLaunchVelocity.GetSafeNormal();
		auto Time = GetWorld()->GetTimeSeconds();
		//UE_LOG(LogTemp, Warning, TEXT("%f Aim solution found"), Time);
		MoveBarrelTowards(AimDirection);
	}
	else
	{
		//if no solution found, do nothing
		//auto Time = GetWorld()->GetTimeSeconds();
		//UE_LOG(LogTemp, Warning, TEXT("%f No solution Found"), Time);
	}
	
}
void UTankMovementComponent::RequestDirectMove(const FVector & MoveVelocity,
	bool bForceMaxSpeed)
{
	/*auto AITankName = GetOwner()->GetName();*/
	auto TankForward = GetOwner()->GetActorForwardVector().GetSafeNormal();
	auto AIForwardIntention = MoveVelocity.GetSafeNormal();
	float FwdMove = FVector::DotProduct(TankForward, AIForwardIntention);
	float Rotate = FVector::CrossProduct(TankForward, AIForwardIntention).Z;
	if (GetOwner()->FindComponentByClass<UTankAimingComponent>()->
		GetFiringStatus() != EFiringStatus::Locked)
	{
		IntendMoveForwards(FwdMove);
		IntendMoveBackwards(FwdMove);
		IntendRotateCClockwise(Rotate);
		IntendRotateClockwise(Rotate);
	}
	/*UE_LOG(LogTemp, Warning, TEXT("%s moving @ vel %s"), *AITankName,
		*AIForwardIntention.ToString());*/


}
Esempio n. 30
0
// Gets a smoothed normal based on the 8 neighbouring vertices
FVector FZoneGeneratorWorker::GetNormalFromHeightMapForVertex(const int32 vertexX, const int32 vertexY)
{
	FVector result;

	int32 rowLength = MyLOD == 0 ? pZoneConfig->XUnits + 1 : (pZoneConfig->XUnits / (FMath::Pow(2, MyLOD)) + 1);
	int32 heightMapRowLength = rowLength + 2;

	// the heightmapIndex for this vertex index
	int32 heightMapIndex = vertexX + 1 + ((vertexY + 1) * heightMapRowLength);

	// Get the 8 neighbouring points
	FVector up, down, left, right, upleft, upright, downleft, downright;

	up		= (*pHeightMap)[heightMapIndex + heightMapRowLength] - (*pHeightMap)[heightMapIndex];
	down	= (*pHeightMap)[heightMapIndex - heightMapRowLength] - (*pHeightMap)[heightMapIndex];
	left	= (*pHeightMap)[heightMapIndex + 1] - (*pHeightMap)[heightMapIndex];
	right	= (*pHeightMap)[heightMapIndex - 1] - (*pHeightMap)[heightMapIndex];
	upleft = (*pHeightMap)[heightMapIndex + 1 + heightMapRowLength] - (*pHeightMap)[heightMapIndex];
	upright = (*pHeightMap)[heightMapIndex - 1 + heightMapRowLength] - (*pHeightMap)[heightMapIndex];
	downleft = (*pHeightMap)[heightMapIndex + 1 - heightMapRowLength] - (*pHeightMap)[heightMapIndex];
	downright = (*pHeightMap)[heightMapIndex - 1 - heightMapRowLength] - (*pHeightMap)[heightMapIndex];

	// Now the eight normals from the triangles this forms
	FVector n1, n2, n3, n4, n5, n6, n7, n8;

	n1 = FVector::CrossProduct(left, upleft);
	n2 = FVector::CrossProduct(upleft, up);
	n3 = FVector::CrossProduct(up, upright);
	n4 = FVector::CrossProduct(upright, right);
	n5 = FVector::CrossProduct(right, downright);
	n6 = FVector::CrossProduct(downright, down);
	n7 = FVector::CrossProduct(down, downleft);
	n8 = FVector::CrossProduct(downleft, left);

	
	result = n1 + n2 + n3 + n4 + n5 + n6 + n7 + n8;

	return result.GetSafeNormal();
}