// Called every frame
void AMissleProjectile::Tick( float DeltaTime )
{
	Super::Tick(DeltaTime);

		if (TargetActor != nullptr)
		{
			NotifyTarget(this);

			FVector WantedDir = (TargetActor->GetActorLocation() - GetActorLocation()).GetSafeNormal();
			WantedDir += TargetActor->GetVelocity() * WantedDir.Size() / MissleMovement->MaxSpeed;
			
			MissleMovement->Velocity += WantedDir * MissleMovement->InitialSpeed * 100.0f * DeltaTime;
			MissleMovement->Velocity = MissleMovement->Velocity.GetSafeNormal() * MissleMovement->MaxSpeed;

			FVector Dis = GetActorLocation() - (TargetActor->GetActorLocation());
			if (Dis.Size() < 5)
			{
				Server_Explode(TargetActor, BP_Explosion.GetDefaultObject(), Damage);
			}
		}
		else
		{
			NotifyTarget(nullptr);
			SetLifeSpan(1.0f);
		}
}
int32 UTKMathFunctionLibrary::PointOnWhichSideOfLineSegment(FVector linePoint1, FVector linePoint2, FVector point)
{
	FVector lineVec = linePoint2 - linePoint1;
	FVector pointVec = point - linePoint1;

	float dot = FVector::DotProduct(pointVec, lineVec);

	//point is on side of linePoint2, compared to linePoint1
	if (dot > 0)
	{
		//point is on the line segment
		if (pointVec.Size() <= lineVec.Size())
		{
			return 0;
		}

		//point is not on the line segment and it is on the side of linePoint2
		else
		{
			return 2;
		}
	}

	//Point is not on side of linePoint2, compared to linePoint1.
	//Point is not on the line segment and it is on the side of linePoint1.
	else
	{
		return 1;
	}
}
void ABounceBlock::OnHit(class AActor* OtherActor, class UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit)
{
	//衝突された場合の判定
	UE_LOG(LogTemp, Log, TEXT("On Hit Call!"));

	//横方向に限定して弾き返す
	float speed = NormalImpulse.Size();
	NormalImpulse.Z = 0;

	//ベロシティを反射方向に導く
	FVector velocity = OtherComp->GetComponentVelocity();
	float power = velocity.Size();
	if (power > 0.0f){
		NormalImpulse.Normalize();
		NormalImpulse = velocity + 2 * (-velocity | NormalImpulse) * NormalImpulse;

		power = NormalImpulse.Size();
		NormalImpulse.Z = 0;
		NormalImpulse.Normalize();

		NormalImpulse *= power;

		OtherComp->SetPhysicsLinearVelocity(NormalImpulse);
	}

	//トルクを0にしてみる
	OtherComp->SetPhysicsAngularVelocity(FVector(0, 0, 0));

	//弾き返す!!
	//OtherComp->AddImpulseAtLocation(NormalImpulse * 2.0f, Hit.Location);

}
Beispiel #4
0
void UEditorEngine::polyTexScale( UModel* Model, float UU, float UV, float VU, float VV, bool Absolute )
{
	for( int32 i=0; i<Model->Surfs.Num(); i++ )
	{
		FBspSurf *Poly = &Model->Surfs[i];
		if (Poly->PolyFlags & PF_Selected)
		{
			FVector OriginalU = Model->Vectors[Poly->vTextureU];
			FVector OriginalV = Model->Vectors[Poly->vTextureV];

			if( Absolute )
			{
				OriginalU *= 1.0/OriginalU.Size();
				OriginalV *= 1.0/OriginalV.Size();
			}

			// Calc new vectors.
			Model->Vectors[Poly->vTextureU] = OriginalU * UU + OriginalV * UV;
			Model->Vectors[Poly->vTextureV] = OriginalU * VU + OriginalV * VV;

			// Update generating brush poly.
			polyUpdateMaster( Model, i, 1 );
		}
	}
}
// Weisstein, Eric W. "Point-Line Distance--3-Dimensional." From MathWorld--A Wolfram Web Resource. http://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html 
static float DistanceToLine(const FVector& LineStart, const FVector& LineEnd, const FVector& Point)
{
	const FVector StartToEnd = LineEnd - LineStart;
	const FVector PointToStart = LineStart - Point;

	const FVector Cross = StartToEnd ^ PointToStart;
	return Cross.Size()/StartToEnd.Size();
}
FVector2D FSingleTileEditorViewportClient::SelectedItemConvertWorldSpaceDeltaToLocalSpace(const FVector& WorldSpaceDelta) const
{
	const FVector ProjectionX = WorldSpaceDelta.ProjectOnTo(PaperAxisX);
	const FVector ProjectionY = WorldSpaceDelta.ProjectOnTo(PaperAxisY);

	const float XValue = FMath::Sign(ProjectionX | PaperAxisX) * ProjectionX.Size();
	const float YValue = FMath::Sign(ProjectionY | PaperAxisY) * ProjectionY.Size();

	return FVector2D(XValue, YValue);
}
FVector2D FSingleTileEditorViewportClient::WorldSpaceToTextureSpace(const FVector& SourcePoint) const
{
	const FVector ProjectionX = SourcePoint.ProjectOnTo(PaperAxisX);
	const FVector ProjectionY = -SourcePoint.ProjectOnTo(PaperAxisY);

	const float XValue = FMath::Sign(ProjectionX | PaperAxisX) * ProjectionX.Size();
	const float YValue = FMath::Sign(ProjectionY | PaperAxisY) * ProjectionY.Size();

	return FVector2D(XValue, YValue);
}
FVector UFlareSpacecraftNavigationSystem::GetAngularVelocityToAlignAxis(FVector LocalShipAxis, FVector TargetAxis, FVector TargetAngularVelocity, float DeltaSeconds) const
{
	TArray<UActorComponent*> Engines = Spacecraft->GetComponentsByClass(UFlareEngine::StaticClass());

	FVector AngularVelocity = Spacecraft->Airframe->GetPhysicsAngularVelocity();
	FVector WorldShipAxis = Spacecraft->Airframe->GetComponentToWorld().GetRotation().RotateVector(LocalShipAxis);

	WorldShipAxis.Normalize();
	TargetAxis.Normalize();

	FVector RotationDirection = FVector::CrossProduct(WorldShipAxis, TargetAxis);
	RotationDirection.Normalize();
	float Dot = FVector::DotProduct(WorldShipAxis, TargetAxis);
	float angle = FMath::RadiansToDegrees(FMath::Acos(Dot));

	FVector DeltaVelocity = TargetAngularVelocity - AngularVelocity;
	FVector DeltaVelocityAxis = DeltaVelocity;
	DeltaVelocityAxis.Normalize();

	float TimeToFinalVelocity;

	if (FMath::IsNearlyZero(DeltaVelocity.SizeSquared()))
	{
		TimeToFinalVelocity = 0;
	}
	else {
		FVector SimpleAcceleration = DeltaVelocityAxis * GetAngularAccelerationRate();
		// Scale with damages
		float DamageRatio = GetTotalMaxTorqueInAxis(Engines, DeltaVelocityAxis, true) / GetTotalMaxTorqueInAxis(Engines, DeltaVelocityAxis, false);
		FVector DamagedSimpleAcceleration = SimpleAcceleration * DamageRatio;

		FVector Acceleration = DamagedSimpleAcceleration;
		float AccelerationInAngleAxis =  FMath::Abs(FVector::DotProduct(DamagedSimpleAcceleration, RotationDirection));

		TimeToFinalVelocity = (DeltaVelocity.Size() / AccelerationInAngleAxis);
	}

	float AngleToStop = (DeltaVelocity.Size() / 2) * (FMath::Max(TimeToFinalVelocity,DeltaSeconds));

	FVector RelativeResultSpeed;

	if (AngleToStop > angle) {
		RelativeResultSpeed = TargetAngularVelocity;
	}
	else
	{
		float MaxPreciseSpeed = FMath::Min((angle - AngleToStop) / (DeltaSeconds * 0.75f), GetAngularMaxVelocity());

		RelativeResultSpeed = RotationDirection;
		RelativeResultSpeed *= MaxPreciseSpeed;
	}

	return RelativeResultSpeed;
}
Beispiel #9
0
void AGameObject::Walk( float t )
{
  CheckWaypoint();

  // Alter destination based on locations of other units.
  FVector ToDest = Dest - Pos;
  
  // Clamp travel length so that we can't overshoot destination
  if( float Len = ToDest.Size() )
  {
    Dir = ToDest / Len; // normalize
    if( !Stats.SpeedMax )  error( FS("%s had 0 speed", *GetName()) );
    
    // I am maxing out the speed here.
    Speed = Stats.SpeedMax;

    // The direction of travel is modified by repulsion forces
    FVector repulsionForces = GetRepulsionForcesFromOverlappedUnits();
    FVector modDir = Dir + repulsionForces;
    modDir.Normalize();
    FVector Vel = modDir*Speed;
    //Game->flycam->DrawDebug( Pos, Pos + Vel, 5.f, FLinearColor::Red, 0.f );
    FVector travel = Vel*t;

    // If travel exceeds destination, then jump to dest,
    // so we don't jitter over the final position.
    if( Len < travel.Size() )
    {
      // snap to position & stop moving.
      Pos = Dest; // we are @ destination.
      travel = ToDest; // This is the displacement we actually moved.
      Speed = 0;
    }
    else
    {
      Pos += travel;
      if( Grounds )
      {
        FVector newPos = Pos + UnitZ * 10.f;
        // Travel in direction plus some amount straight up.
        // The straight up amount ensures that the unit doesn't sink underground
        if( Game->flycam->SetOnGround( newPos ) )  Pos = newPos;
        else  error( FS( "%s Object was trying to leave the ground plane.", *GetName() ) );
      }
      SetRot( Dir.Rotation() );
    }
  }
  else
  {
    // We're at the destination, so the velocity becomes 0
    Speed = 0.f;
  }
}
void FIndirectLightingCache::UpdateTransitionsOverTime(const TArray<FIndirectLightingCacheAllocation*>& TransitionsOverTimeToUpdate, float DeltaWorldTime) const
{
	for (int32 AllocationIndex = 0; AllocationIndex < TransitionsOverTimeToUpdate.Num(); AllocationIndex++)
	{
		FIndirectLightingCacheAllocation* Allocation = TransitionsOverTimeToUpdate[AllocationIndex];
		const float TransitionDistance = (Allocation->SingleSamplePosition - Allocation->TargetPosition).Size();

		if (TransitionDistance > DELTA)
		{
			// Compute a frame rate independent transition by maintaining a constant world space speed between the current sample position and the target position
			const float LerpFactor = FMath::Clamp(GSingleSampleTransitionSpeed * DeltaWorldTime / TransitionDistance, 0.0f, 1.0f);
			Allocation->SingleSamplePosition = FMath::Lerp(Allocation->SingleSamplePosition, Allocation->TargetPosition, LerpFactor);

			for (int32 VectorIndex = 0; VectorIndex < ARRAY_COUNT(Allocation->SingleSamplePacked); VectorIndex++)
			{
				Allocation->SingleSamplePacked[VectorIndex] = FMath::Lerp(Allocation->SingleSamplePacked[VectorIndex], Allocation->TargetSamplePacked[VectorIndex], LerpFactor);
			}

			Allocation->CurrentDirectionalShadowing = FMath::Lerp(Allocation->CurrentDirectionalShadowing, Allocation->TargetDirectionalShadowing, LerpFactor);

			const FVector CurrentSkyBentNormal = FMath::Lerp(
				FVector(Allocation->CurrentSkyBentNormal) * Allocation->CurrentSkyBentNormal.W, 
				FVector(Allocation->TargetSkyBentNormal) * Allocation->TargetSkyBentNormal.W, 
				LerpFactor);

			const float BentNormalLength = CurrentSkyBentNormal.Size();

			Allocation->CurrentSkyBentNormal = FVector4(CurrentSkyBentNormal / FMath::Max(BentNormalLength, .0001f), BentNormalLength);
		}
	}
}
Beispiel #11
0
	void SetParameters(FRHICommandList& RHICmdList, const FViewInfo& View)
	{
		FGlobalShader::SetParameters(RHICmdList, GetVertexShader(),View);

		{
			// The fog can be set to start at a certain euclidean distance.
			// clamp the value to be behind the near plane z
			float FogStartDistance = FMath::Max(30.0f, View.ExponentialFogParameters.W);

			// Here we compute the nearest z value the fog can start
			// to render the quad at this z value with depth test enabled.
			// This means with a bigger distance specified more pixels are
			// are culled and don't need to be rendered. This is faster if
			// there is opaque content nearer than the computed z.

			FMatrix InvProjectionMatrix = View.ViewMatrices.GetInvProjMatrix();

			FVector ViewSpaceCorner = InvProjectionMatrix.TransformFVector4(FVector4(1, 1, 1, 1));

			float Ratio = ViewSpaceCorner.Z / ViewSpaceCorner.Size();

			FVector ViewSpaceStartFogPoint(0.0f, 0.0f, FogStartDistance * Ratio);
			FVector4 ClipSpaceMaxDistance = View.ViewMatrices.ProjMatrix.TransformPosition(ViewSpaceStartFogPoint);

			float FogClipSpaceZ = ClipSpaceMaxDistance.Z / ClipSpaceMaxDistance.W;

			SetShaderValue(RHICmdList, GetVertexShader(),FogStartZ, FogClipSpaceZ);
		}
	}
Beispiel #12
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());
}
FVector UTKMathFunctionLibrary::GetVelocityAtPoint(UPrimitiveComponent* Target, FVector Point, FName BoneName, bool DrawDebugInfo)
{
	
	//FTransform Transform = Target->GetComponentTransform();
	//FVector LocalLinearVelocity = Transform.InverseTransformVectorNoScale(Target->GetPhysicsLinearVelocity());
	//FVector LocalAngularVelocity = Transform.InverseTransformVectorNoScale(Target->GetPhysicsAngularVelocity());
	//FVector ResultPointVelocity = LocalLinearVelocity + FVector::CrossProduct(FVector::DegreesToRadians(LocalAngularVelocity), Transform.InverseTransformVectorNoScale(Point - Target->GetCenterOfMass()));
	

	if (!Target) return FVector::ZeroVector;

	//You can actually get it from the physx body instance instead.
	FBodyInstance* BI = Target->GetBodyInstance(BoneName);
	if (BI && BI->IsValidBodyInstance())
	{
		FVector PointVelocity = BI->GetUnrealWorldVelocityAtPoint(Point);

		UWorld* TheWorld = Target->GetWorld();
		if (DrawDebugInfo && TheWorld)
		{ 
			FColor DefaultColor(255,200,0);
			DrawDebugPoint(TheWorld, Point, 10, DefaultColor);
			DrawDebugString(TheWorld, Point, FString::SanitizeFloat(PointVelocity.Size()), NULL, FColor::White, 0.0f);
		}

		return PointVelocity;
	}
	return FVector::ZeroVector;
}
Beispiel #14
0
// Called every frame
void AMonster::Tick( float DeltaTime )
{
	Super::Tick( DeltaTime );

	ARaiderCharacter *avatar = Cast<ARaiderCharacter>(UGameplayStatics::GetPlayerPawn(GetWorld(), 0));
	if (!avatar) return;
	FVector toPlayer = avatar->GetActorLocation() -	GetActorLocation();
	
	this->GetCharacterMovement()->bOrientRotationToMovement = true; // Rotate character to moving direction

	float distanceToPlayer = toPlayer.Size();
	// If the player is not in the SightSphere of the monster,
	// go back
	if (distanceToPlayer > SightSphere->GetScaledSphereRadius())
	{
		// If the player is out of sight,
		// then the enemy cannot chase
		return;
	}
	toPlayer /= distanceToPlayer; // normalizes the vector
	
	FRotator Rotation = toPlayer.Rotation();
	const FVector Direction = FRotationMatrix(Rotation).GetScaledAxis(EAxis::X);
	AddMovementInput(Direction, m_fSpeed * DeltaTime);
}
void FIndirectLightingCache::UpdateTransitionsOverTime(const TArray<FIndirectLightingCacheAllocation*>& TransitionsOverTimeToUpdate, float DeltaWorldTime) const
{
	for (int32 AllocationIndex = 0; AllocationIndex < TransitionsOverTimeToUpdate.Num(); AllocationIndex++)
	{
		FIndirectLightingCacheAllocation* Allocation = TransitionsOverTimeToUpdate[AllocationIndex];
		const float TransitionDistance = (Allocation->SingleSamplePosition - Allocation->TargetPosition).Size();

		if (TransitionDistance > DELTA)
		{
			// Transition faster for unbuilt meshes which is important for meshing visualization
			const float EffectiveTransitionSpeed = GSingleSampleTransitionSpeed * (Allocation->bUnbuiltPreview ? 4 : 1);
			const float LerpFactor = FMath::Clamp(GSingleSampleTransitionSpeed * DeltaWorldTime / TransitionDistance, 0.0f, 1.0f);
			Allocation->SingleSamplePosition = FMath::Lerp(Allocation->SingleSamplePosition, Allocation->TargetPosition, LerpFactor);

			for (int32 VectorIndex = 0; VectorIndex < 3; VectorIndex++) // RGB
			{
				Allocation->SingleSamplePacked0[VectorIndex] = FMath::Lerp(Allocation->SingleSamplePacked0[VectorIndex], Allocation->TargetSamplePacked0[VectorIndex], LerpFactor);
				Allocation->SingleSamplePacked1[VectorIndex] = FMath::Lerp(Allocation->SingleSamplePacked1[VectorIndex], Allocation->TargetSamplePacked1[VectorIndex], LerpFactor);
			}
			Allocation->SingleSamplePacked2 = FMath::Lerp(Allocation->SingleSamplePacked2, Allocation->TargetSamplePacked2, LerpFactor);
			Allocation->CurrentDirectionalShadowing = FMath::Lerp(Allocation->CurrentDirectionalShadowing, Allocation->TargetDirectionalShadowing, LerpFactor);

			const FVector CurrentSkyBentNormal = FMath::Lerp(
				FVector(Allocation->CurrentSkyBentNormal) * Allocation->CurrentSkyBentNormal.W, 
				FVector(Allocation->TargetSkyBentNormal) * Allocation->TargetSkyBentNormal.W, 
				LerpFactor);

			const float BentNormalLength = CurrentSkyBentNormal.Size();

			Allocation->CurrentSkyBentNormal = FVector4(CurrentSkyBentNormal / FMath::Max(BentNormalLength, .0001f), BentNormalLength);
		}
	}
}
Beispiel #16
0
void ACloud10Character::bounceJump(float Value)
{
	float curJumpVelocity = Value;
	float jumpVelocity;
	GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, TEXT("bounceJump"));
	const FVector ForwardDir = GetActorForwardVector();
	/*bounceCount++;
	if(bounceCount > 1)
	{
		jumpVelocity = jumpVelocity * 1.3;
	}*/
	//if player has landed, reset jumpVelocity
	/*if (curJumpVelocity < baseJumpForce)
		jumpVelocity = baseJumpForce;*/

	//thresholds for jump velocity's that convert to force?
	//max jump?
	if (curJumpVelocity >= 3000)
	{
		curJumpVelocity = 3000;
	}
	//add only player's vertical speed to the last jump Velocity
	jumpVelocity = FMath().Abs(curJumpVelocity) + baseJumpForce;
	FVector AddForce = FVector(0, 0, 1) * jumpVelocity;
	//separate max walk speed from max fall speed
		//GetCharacterMovement()->MaxWalkSpeed = AddForce.Size();
	//convert float to string
	FString tempString = FString::SanitizeFloat(AddForce.Size());
	GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, *tempString);
	LaunchCharacter(AddForce, false, true);
	//bPressedJump = true;
	//jumpVelocity = 600;
}
Beispiel #17
0
void UAirBlueprintLib::FollowActor(AActor* follower, const AActor* followee, const FVector& offset, bool fixed_z, float fixed_z_val)
{
    //can we see followee?
    FHitResult hit;
    if (followee == nullptr) {
        return;
    }
    FVector actor_location = followee->GetActorLocation() + FVector(0, 0, 4);
    FVector next_location = actor_location + offset;
    if (fixed_z)
        next_location.Z = fixed_z_val;

    if (GetObstacle(follower, next_location, actor_location, hit, followee)) {
        next_location = hit.ImpactPoint + offset;

        if (GetObstacle(follower, next_location, actor_location, hit, followee)) {
            float next_z = next_location.Z;
            next_location = hit.ImpactPoint - offset;
            next_location.Z = next_z;
        }
    }

    float dist = (follower->GetActorLocation() - next_location).Size();
    float offset_dist = offset.Size();
    float dist_offset = (dist - offset_dist) / offset_dist;
    float lerp_alpha = common_utils::Utils::clip((dist_offset*dist_offset) * 0.01f + 0.01f, 0.0f, 1.0f);
    next_location = FMath::Lerp(follower->GetActorLocation(), next_location, lerp_alpha);
    follower->SetActorLocation(next_location);

    FRotator next_rot = UKismetMathLibrary::FindLookAtRotation(follower->GetActorLocation(), followee->GetActorLocation());
    next_rot = FMath::Lerp(follower->GetActorRotation(), next_rot, 0.5f);
    follower->SetActorRotation(next_rot);
}
void AVehiclePawn::ReceiveHit(class UPrimitiveComponent* MyComp, class AActor* Other, class UPrimitiveComponent* OtherComp, bool bSelfMoved, FVector HitLocation, FVector HitNormal, FVector NormalForce, const FHitResult& Hit)
{
	Super::ReceiveHit(MyComp, Other, OtherComp, bSelfMoved, HitLocation, HitNormal, NormalForce, Hit);

	if (ImpactTemplate && NormalForce.Size() > ImpactEffectNormalForceThreshold)
	{
		AVehicleImpactEffect* EffectActor = GetWorld()->SpawnActorDeferred<AVehicleImpactEffect>(ImpactTemplate, HitLocation, HitNormal.Rotation());
		if (EffectActor)
		{
			float DotBetweenHitAndUpRotation = FVector::DotProduct(HitNormal, GetMesh()->GetUpVector());
			EffectActor->HitSurface = Hit;
			EffectActor->HitForce = NormalForce;
			EffectActor->bWheelLand = DotBetweenHitAndUpRotation > 0.8;
			UGameplayStatics::FinishSpawningActor(EffectActor, FTransform(HitNormal.Rotation(), HitLocation));
		}
	}

	if (ImpactCameraShake)
	{
		AVehiclePlayerController* PC = Cast<AVehiclePlayerController>(Controller);
		if (PC != NULL && PC->IsLocalController())
		{
			PC->ClientPlayCameraShake(ImpactCameraShake, 1);
		}
	}
}
FVector FGeomEdge::GetWidgetLocation()
{
	FVector dir = (GetParentObject()->VertexPool[ VertexIndices[1] ] - GetParentObject()->VertexPool[ VertexIndices[0] ]);
	const float dist = dir.Size() / 2;
	dir.Normalize();
	const FVector loc = GetParentObject()->VertexPool[ VertexIndices[0] ] + (dir * dist);
	return GetParentObject()->GetActualBrush()->ActorToWorld().TransformPosition( loc );
}
/** 
 * Convert Convex Normal to Capsule Normal
 * For capsule, we'd like to get normal of capsule rather than convex, so the normal can be smooth when we move character
 * 
 * @param HalfHeight	: HalfHeight of the capsule
 * @param Radius		: Radius of the capsule
 * @param OutHit		: The result of hit from physX
 @ @param PointOnGeom	: If not null, use this point and the impact normal to recompute the impact point (which can yield a better normal).
 * @result OutHit.Normal is converted to Capsule Normal
 */
static void ConvertConvexNormalToCapsuleNormal(float HalfHeight, float Radius, struct FHitResult& OutHit, const FVector* PointOnGeom)
{
	if ( OutHit.Time > 0.f )
	{
		// Impact point is contact point where it meet 
		const float ContactZ = OutHit.ImpactPoint.Z;
		// Hit.Location is center of the object
		const FVector CenterOfCapsule = OutHit.Location; 
		// We're looking for end of the normal for this capsule
		FVector NormalEnd = CenterOfCapsule;

		// see if it's upper hemisphere 
		if (ContactZ > CenterOfCapsule.Z + HalfHeight)
		{
			// if upper hemisphere, the normal should point to the center of upper hemisphere
			NormalEnd.Z = CenterOfCapsule.Z + HalfHeight;
		}
		else if (ContactZ < CenterOfCapsule.Z - HalfHeight)
		{
			// if lower hemisphere, the normal should point to the center of lower hemisphere	
			NormalEnd.Z = CenterOfCapsule.Z - HalfHeight;
		}
		else
		{
			// otherwise, normal end is going to be same as contact point 
			// since it's the tube section of the capsule
			NormalEnd.Z = ContactZ;
		}

		// Recompute ImpactPoint if requested
		if (PointOnGeom)
		{
			const FPlane GeomPlane(*PointOnGeom, OutHit.ImpactNormal);
			const float DistToPlane = GeomPlane.PlaneDot(NormalEnd);
			if (DistToPlane >= Radius)
			{
				OutHit.ImpactPoint = NormalEnd - DistToPlane * OutHit.ImpactNormal;
			}
		}

		//DrawDebugLine(ContactPoint, NormalEnd, FColor(0, 255, 0), true);
		//DrawDebugLine(NormalEnd, CenterOfCapsule, FColor(0, 0, 255), true);

		FVector ContactNormal = (NormalEnd - OutHit.ImpactPoint);
		// if ContactNormal is not nearly zero, set it
		// otherwise use previous normal
		const float Size = ContactNormal.Size();
		if (Size >= KINDA_SMALL_NUMBER)
		{
			ContactNormal /= Size;
			OutHit.Normal = ContactNormal;
		}

#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST || !WITH_EDITOR)
		CheckHitResultNormal(OutHit, TEXT("ConvertConvexNormalToCapsuleNormal"));
#endif
	}
}
float USplineComponent::GetSegmentLength(const int32 Index, const float Param) const
{
	const int32 NumPoints = SplineInfo.Points.Num();
	const int32 LastPoint = NumPoints - 1;

	check(Index >= 0 && ((bClosedLoop && Index < NumPoints) || (!bClosedLoop && Index < LastPoint)));
	check(Param >= 0.0f && Param <= 1.0f);

	// Evaluate the length of a Hermite spline segment.
	// This calculates the integral of |dP/dt| dt, where P(t) is the spline equation with components (x(t), y(t), z(t)).
	// This isn't solvable analytically, so we use a numerical method (Legendre-Gauss quadrature) which performs very well
	// with functions of this type, even with very few samples.  In this case, just 5 samples is sufficient to yield a
	// reasonable result.

	struct FLegendreGaussCoefficient
	{
		float Abscissa;
		float Weight;
	};

	static const FLegendreGaussCoefficient LegendreGaussCoefficients[] =
	{
		{ 0.0f, 0.5688889f },
		{ -0.5384693f, 0.47862867f },
		{ 0.5384693f, 0.47862867f },
		{ -0.90617985f, 0.23692688f },
		{ 0.90617985f, 0.23692688f }
	};

	const auto& StartPoint = SplineInfo.Points[Index];
	const auto& EndPoint = SplineInfo.Points[Index == LastPoint ? 0 : Index + 1];
	check(Index == LastPoint || (static_cast<int32>(EndPoint.InVal) - static_cast<int32>(StartPoint.InVal) == 1));

	const auto& P0 = StartPoint.OutVal;
	const auto& T0 = StartPoint.LeaveTangent;
	const auto& P1 = EndPoint.OutVal;
	const auto& T1 = EndPoint.ArriveTangent;

	// Cache the coefficients to be fed into the function to calculate the spline derivative at each sample point as they are constant.
	const FVector Coeff1 = ((P0 - P1) * 2.0f + T0 + T1) * 3.0f;
	const FVector Coeff2 = (P1 - P0) * 6.0f - T0 * 4.0f - T1 * 2.0f;
	const FVector Coeff3 = T0;

	const float HalfParam = Param * 0.5f;

	float Length = 0.0f;
	for (const auto& LegendreGaussCoefficient : LegendreGaussCoefficients)
	{
		// Calculate derivative at each Legendre-Gauss sample, and perform a weighted sum
		const float Alpha = HalfParam * (1.0f + LegendreGaussCoefficient.Abscissa);
		const FVector Derivative = ((Coeff1 * Alpha + Coeff2) * Alpha + Coeff3) * ComponentToWorld.GetScale3D();
		Length += Derivative.Size() * LegendreGaussCoefficient.Weight;
	}
	Length *= HalfParam;

	return Length;
}
void AFlappyBirdCharacter::UpdateAnimation()
{
	const FVector PlayerVelocity = GetVelocity();
	const float PlayerSpeed = PlayerVelocity.Size();

	// Are we moving or standing still?
	UPaperFlipbook* DesiredAnimation = (PlayerSpeed > 0.0f) ? RunningAnimation : IdleAnimation;

	GetSprite()->SetFlipbook(DesiredAnimation);
}
/**
* Draws a line with an arrow at the end.
*
* @param Start		Starting point of the line.
* @param End		Ending point of the line.
* @param Color		Color of the line.
* @param Mag		Size of the arrow.
*/
void FDebugRenderSceneProxy::DrawLineArrow(FPrimitiveDrawInterface* PDI,const FVector &Start,const FVector &End,const FColor &Color,float Mag) const
{
	// draw a pretty arrow
	FVector Dir = End - Start;
	const float DirMag = Dir.Size();
	Dir /= DirMag;
	FVector YAxis, ZAxis;
	Dir.FindBestAxisVectors(YAxis,ZAxis);
	FMatrix ArrowTM(Dir,YAxis,ZAxis,Start);
	DrawDirectionalArrow(PDI,ArrowTM,Color,DirMag,Mag,SDPG_World);
}
Beispiel #24
0
bool AMonster::isInAttackRangeOfPlayer()
{
	ARaiderCharacter *avatar = Cast<ARaiderCharacter>(UGameplayStatics::GetPlayerPawn(GetWorld(), 0));
	if (!avatar) return false;

	FVector playerPos = avatar->GetActorLocation();
	FVector toPlayer = playerPos - GetActorLocation();
	float distanceToPlayer = toPlayer.Size();

	return distanceToPlayer < AttackRangeSphere->GetScaledSphereRadius();
}
void ARadialForceActor::EditorApplyScale(const FVector& DeltaScale, const FVector* PivotLocation, bool bAltDown, bool bShiftDown, bool bCtrlDown)
{
	FVector ModifiedScale = DeltaScale * ( AActor::bUsePercentageBasedScaling ? 500.0f : 5.0f );

	const float Multiplier = ( ModifiedScale.X > 0.0f || ModifiedScale.Y > 0.0f || ModifiedScale.Z > 0.0f ) ? 1.0f : -1.0f;
	if(ForceComponent)
	{
		ForceComponent->Radius += Multiplier * ModifiedScale.Size();
		ForceComponent->Radius = FMath::Max( 0.f, ForceComponent->Radius );
	}
}
void UBTTask_FlyTo::TickPathNavigation(UBehaviorTreeComponent& OwnerComp, FBT_FlyToTarget* MyMemory, float DeltaSeconds)
{
	const auto& queryResults = MyMemory->QueryResults;

	APawn* pawn = OwnerComp.GetAIOwner()->GetPawn();
	
	if (DebugParams.bVisualizePawnAsVoxels)
		NavigationManager->Debug_DrawVoxelCollisionProfile(Cast<UPrimitiveComponent>(pawn->GetRootComponent()));
	
	FVector flightDirection = queryResults.PathSolutionOptimized[MyMemory->solutionTraversalIndex] - pawn->GetActorLocation();

	//auto navigator = Cast<IDonNavigator>(pawn);

	// Add movement input:
	if (MyMemory->bIsANavigator)
	{
		// Customized movement handling for advanced users:
		IDonNavigator::Execute_AddMovementInputCustom(pawn, flightDirection, 1.f);
	}
	else
	{
		// Default movement (handled by Pawn or Character class)
		pawn->AddMovementInput(flightDirection, 1.f);
	}


	FVector test = FVector(10,10,100);
	//test.
		

	// Reached next segment:
	if (flightDirection.Size() <= MinimumProximityRequired)
	{
		// Goal reached?
		if (MyMemory->solutionTraversalIndex == queryResults.PathSolutionOptimized.Num() - 1)
		{
			UBlackboardComponent* blackboard = pawn->GetController()->FindComponentByClass<UBlackboardComponent>();
			blackboard->SetValueAsBool(FlightResultKey.SelectedKeyName, true);
			blackboard->SetValueAsBool(KeyToFlipFlopWhenTaskExits.SelectedKeyName, !blackboard->GetValueAsBool(KeyToFlipFlopWhenTaskExits.SelectedKeyName));

			// Unregister all dynamic collision listeners. We've completed our task and are no longer interested in listening to these:
			NavigationManager->StopListeningToDynamicCollisionsForPath(MyMemory->DynamicCollisionListener, queryResults);

			FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded);

			return;
		}
		else
		{
			MyMemory->solutionTraversalIndex++;
		}
	}
}
void UFlareSpacecraftNavigationSystem::UpdateAngularBraking(float DeltaSeconds)
{
	AngularTargetVelocity = FVector::ZeroVector;
	FVector AngularVelocity = Spacecraft->Airframe->GetPhysicsAngularVelocity();
	// Null speed detection
	if (AngularVelocity.Size() < NegligibleSpeedRatio * AngularMaxVelocity)
	{
		AngularTargetVelocity = FVector::ZeroVector;
		Spacecraft->Airframe->SetPhysicsAngularVelocity(FVector::ZeroVector, false); // TODO remove
		ClearCurrentCommand();
	}
}
void UFlareSpacecraftNavigationSystem::UpdateLinearBraking(float DeltaSeconds, FVector TargetVelocity)
{
	LinearTargetVelocity = TargetVelocity;
	FVector DeltaLinearVelocity = TargetVelocity*100 - Spacecraft->Airframe->GetPhysicsLinearVelocity();

	// Null speed detection
	if (DeltaLinearVelocity.Size() < NegligibleSpeedRatio * LinearMaxVelocity)
	{
		Spacecraft->Airframe->SetAllPhysicsLinearVelocity(TargetVelocity*100);
		ClearCurrentCommand();
	}
}
void ATP_2DSideScrollerCharacter::UpdateAnimation()
{
	const FVector PlayerVelocity = GetVelocity();
	const float PlayerSpeed = PlayerVelocity.Size();

	// Are we moving or standing still?
	UPaperFlipbook* DesiredAnimation = (PlayerSpeed > 0.0f) ? RunningAnimation : IdleAnimation;
	if( GetSprite()->GetFlipbook() != DesiredAnimation 	)
	{
		GetSprite()->SetFlipbook(DesiredAnimation);
	}
}
static bool GetBarycentricWeights(
	const FVector& Position0,
	const FVector& Position1,
	const FVector& Position2,
	FVector InterpolatePosition,
	float Tolerance,
	FVector& BarycentricWeights
	)
{
	BarycentricWeights = FVector::ZeroVector;
	FVector TriangleNormal = (Position0 - Position1) ^ (Position2 - Position0);
	float ParallelogramArea = TriangleNormal.Size();
	FVector UnitTriangleNormal = TriangleNormal / ParallelogramArea;
	float PlaneDistance = UnitTriangleNormal | (InterpolatePosition - Position0);

	// Only continue if the position to interpolate to is in the plane of the triangle (within some error)
	if (FMath::Abs(PlaneDistance) < Tolerance)
	{
		// Move the position to interpolate to into the plane of the triangle along the normal, 
		// Otherwise there will be error in our barycentric coordinates
		InterpolatePosition -= UnitTriangleNormal * PlaneDistance;

		FVector NormalU = (InterpolatePosition - Position1) ^ (Position2 - InterpolatePosition);
		// Signed area, if negative then InterpolatePosition is not in the triangle
		float ParallelogramAreaU = NormalU.Size() * FMath::FloatSelect(NormalU | TriangleNormal, 1.0f, -1.0f);
		float BaryCentricU = ParallelogramAreaU / ParallelogramArea;

		FVector NormalV = (InterpolatePosition - Position2) ^ (Position0 - InterpolatePosition);
		float ParallelogramAreaV = NormalV.Size() * FMath::FloatSelect(NormalV | TriangleNormal, 1.0f, -1.0f);
		float BaryCentricV = ParallelogramAreaV / ParallelogramArea;

		float BaryCentricW = 1.0f - BaryCentricU - BaryCentricV;
		if (BaryCentricU > -Tolerance && BaryCentricV > -Tolerance && BaryCentricW > -Tolerance)
		{
			BarycentricWeights = FVector(BaryCentricU, BaryCentricV, BaryCentricW);
			return true;
		}
	}
	return false;
}