-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
183 additions
and
42 deletions.
There are no files selected for viewing
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,3 @@ | ||
// Copyright Epic Games, Inc. All Rights Reserved. | ||
|
||
#pragma once | ||
|
||
#include "CoreMinimal.h" | ||
|
150 changes: 131 additions & 19 deletions
150
Source/Cloud9/Character/Components/Cloud9SpringArmComponent.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,35 +1,147 @@ | ||
#include "Cloud9SpringArmComponent.h" | ||
|
||
#include "Cloud9/Tools/Cloud9ToolsLibrary.h" | ||
|
||
|
||
UCloud9SpringArmComponent::UCloud9SpringArmComponent() | ||
{ | ||
RotationVerticalLagSpeed = 0.0f; | ||
CameraLagVector = FVector::OneVector; | ||
} | ||
|
||
void UCloud9SpringArmComponent::OnRegister() | ||
void UCloud9SpringArmComponent::UpdateDesiredArmLocation( | ||
bool bDoTrace, | ||
bool bDoLocationLag, | ||
bool bDoRotationLag, | ||
float DeltaTime) | ||
{ | ||
Super::OnRegister(); | ||
TargetRelativeRotation = RelativeSocketRotation.Rotator(); | ||
} | ||
FRotator DesiredRot = GetTargetRotation(); | ||
|
||
void UCloud9SpringArmComponent::TickComponent( | ||
float DeltaTime, | ||
ELevelTick TickType, | ||
FActorComponentTickFunction* ThisTickFunction) | ||
{ | ||
Super::TickComponent(DeltaTime, TickType, ThisTickFunction); | ||
// Apply 'lag' to rotation if desired | ||
if (bDoRotationLag) | ||
{ | ||
if (bUseCameraLagSubstepping && DeltaTime > CameraLagMaxTimeStep && CameraRotationLagSpeed > 0.f) | ||
{ | ||
const FRotator ArmRotStep = (DesiredRot - PreviousDesiredRot).GetNormalized() * (1.f / DeltaTime); | ||
FRotator LerpTarget = PreviousDesiredRot; | ||
float RemainingTime = DeltaTime; | ||
while (RemainingTime > KINDA_SMALL_NUMBER) | ||
{ | ||
const float LerpAmount = FMath::Min(CameraLagMaxTimeStep, RemainingTime); | ||
LerpTarget += ArmRotStep * LerpAmount; | ||
RemainingTime -= LerpAmount; | ||
|
||
DesiredRot = FRotator( | ||
FMath::QInterpTo( | ||
FQuat(PreviousDesiredRot), | ||
FQuat(LerpTarget), | ||
LerpAmount, | ||
CameraRotationLagSpeed) | ||
); | ||
|
||
PreviousDesiredRot = DesiredRot; | ||
} | ||
} | ||
else | ||
{ | ||
DesiredRot = FRotator( | ||
FMath::QInterpTo( | ||
FQuat(PreviousDesiredRot), | ||
FQuat(DesiredRot), | ||
DeltaTime, | ||
CameraRotationLagSpeed | ||
) | ||
); | ||
} | ||
} | ||
PreviousDesiredRot = DesiredRot; | ||
|
||
auto NewRotation = TargetRelativeRotation; | ||
if (RotationVerticalLagSpeed != 0.0f) | ||
// Get the spring arm 'origin', the target we want to look at | ||
FVector ArmOrigin = GetComponentLocation() + TargetOffset; | ||
// We lag the target, not the actual camera position, so rotating the camera around does not have lag | ||
FVector DesiredLoc = ArmOrigin; | ||
if (bDoLocationLag) | ||
{ | ||
const auto OldRotation = RelativeSocketRotation.Rotator(); | ||
NewRotation = FMath::Lerp( | ||
OldRotation, | ||
TargetRelativeRotation, | ||
DeltaTime / RotationVerticalLagSpeed * RotationScale); | ||
const auto LocationLag = CameraLagSpeed * CameraLagVector; | ||
|
||
if (bUseCameraLagSubstepping | ||
&& DeltaTime > CameraLagMaxTimeStep | ||
&& LocationLag != FVector::ZeroVector) | ||
{ | ||
const FVector ArmMovementStep = (DesiredLoc - PreviousDesiredLoc) * (1.f / DeltaTime); | ||
auto LerpTarget = PreviousDesiredLoc; | ||
|
||
float RemainingTime = DeltaTime; | ||
while (RemainingTime > KINDA_SMALL_NUMBER) | ||
{ | ||
const float LerpAmount = FMath::Min(CameraLagMaxTimeStep, RemainingTime); | ||
LerpTarget += ArmMovementStep * LerpAmount; | ||
RemainingTime -= LerpAmount; | ||
|
||
DesiredLoc = UCloud9ToolsLibrary::VInterpTo(PreviousDesiredLoc, LerpTarget, LerpAmount, LocationLag); | ||
PreviousDesiredLoc = DesiredLoc; | ||
} | ||
} | ||
else | ||
{ | ||
DesiredLoc = UCloud9ToolsLibrary::VInterpTo(PreviousDesiredLoc, DesiredLoc, DeltaTime, LocationLag); | ||
} | ||
|
||
if (const auto FromOrigin = DesiredLoc - ArmOrigin; | ||
CameraLagMaxDistance > 0.f && FromOrigin.SizeSquared() > FMath::Square(CameraLagMaxDistance)) | ||
{ | ||
DesiredLoc = ArmOrigin + FromOrigin.GetClampedToMaxSize(CameraLagMaxDistance); | ||
} | ||
} | ||
|
||
RelativeSocketRotation = NewRotation.Quaternion(); | ||
PreviousArmOrigin = ArmOrigin; | ||
PreviousDesiredLoc = DesiredLoc; | ||
|
||
// Now offset camera position back along our rotation | ||
DesiredLoc -= DesiredRot.Vector() * TargetArmLength; | ||
// Add socket offset in local space | ||
DesiredLoc += FRotationMatrix(DesiredRot).TransformVector(SocketOffset); | ||
|
||
// Do a sweep to ensure we are not penetrating the world | ||
FVector ResultLoc; | ||
if (bDoTrace && TargetArmLength != 0.0f) | ||
{ | ||
bIsCameraFixed = true; | ||
FCollisionQueryParams QueryParams(SCENE_QUERY_STAT(SpringArm), false, GetOwner()); | ||
|
||
FHitResult Result; | ||
GetWorld()->SweepSingleByChannel( | ||
Result, | ||
ArmOrigin, | ||
DesiredLoc, | ||
FQuat::Identity, | ||
ProbeChannel, | ||
FCollisionShape::MakeSphere(ProbeSize), | ||
QueryParams); | ||
|
||
UnfixedCameraPosition = DesiredLoc; | ||
|
||
ResultLoc = BlendLocations(DesiredLoc, Result.Location, Result.bBlockingHit, DeltaTime); | ||
|
||
if (ResultLoc == DesiredLoc) | ||
{ | ||
bIsCameraFixed = false; | ||
} | ||
} | ||
else | ||
{ | ||
ResultLoc = DesiredLoc; | ||
bIsCameraFixed = false; | ||
UnfixedCameraPosition = ResultLoc; | ||
} | ||
|
||
// Form a transform for new world transform for camera | ||
FTransform WorldCamTM(DesiredRot, ResultLoc); | ||
// Convert to relative to component | ||
FTransform RelCamTM = WorldCamTM.GetRelativeTransform(GetComponentTransform()); | ||
|
||
// Update socket location/rotation | ||
RelativeSocketLocation = RelCamTM.GetLocation(); | ||
RelativeSocketRotation = RelCamTM.GetRotation(); | ||
|
||
UpdateChildTransforms(); | ||
} |
38 changes: 17 additions & 21 deletions
38
Source/Cloud9/Character/Components/Cloud9SpringArmComponent.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,36 +1,32 @@ | ||
#pragma once | ||
|
||
#include "CoreMinimal.h" | ||
#include "Cloud9CharacterComponent.h" | ||
#include "GameFramework/SpringArmComponent.h" | ||
#include "Cloud9SpringArmComponent.generated.h" | ||
|
||
|
||
UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) | ||
class CLOUD9_API UCloud9SpringArmComponent | ||
: public USpringArmComponent | ||
, public ICloud9CharacterComponent | ||
UCLASS(ClassGroup=(Camera), meta=(BlueprintSpawnableComponent)) | ||
class CLOUD9_API UCloud9SpringArmComponent : public USpringArmComponent | ||
{ | ||
GENERATED_BODY() | ||
|
||
public: | ||
UCloud9SpringArmComponent(); | ||
|
||
virtual void TickComponent( | ||
float DeltaTime, | ||
ELevelTick TickType, | ||
FActorComponentTickFunction* ThisTickFunction | ||
) override; | ||
|
||
virtual void OnRegister() override; | ||
// TODO: CameraLagRotator | ||
|
||
private: | ||
static constexpr float RotationScale = 360.0f; | ||
/** | ||
* If bEnableCameraLag is true, controls how quickly camera reaches target position by each axis. | ||
* Values of this vector multiplies with @CameraLagSpeed. | ||
*/ | ||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Lag, meta=(editcondition="bEnableCameraLag")) | ||
FVector CameraLagVector; | ||
|
||
/** Vertical rotation speed lag for camera*/ | ||
UPROPERTY(EditDefaultsOnly, Category=Lag, | ||
meta=(ClampMin="0.0", ClampMax="10000.0", UIMin = "0.0", UIMax = "10000.0")) | ||
float RotationVerticalLagSpeed; | ||
public: | ||
UCloud9SpringArmComponent(); | ||
|
||
FRotator TargetRelativeRotation; | ||
virtual void UpdateDesiredArmLocation( | ||
bool bDoTrace, | ||
bool bDoLocationLag, | ||
bool bDoRotationLag, | ||
float DeltaTime | ||
) override; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters