게임 엔진/Unreal

[Unreal] [Example] Transform

AlgorFati 2020. 9. 7. 23:57

언리얼 Transform 관련 예제이다

 

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "TestActor.generated.h"

UCLASS()
class PHYSICSANIMATIONCPP_API ATestActor : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	ATestActor();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;


    void PrintData();

    void DrawTransform(FTransform T);


private :

    int DrawCnt;
};

 

// Fill out your copyright notice in the Description page of Project Settings.


#include "TestActor.h"
#include "DrawDebugHelpers.h"

// Sets default values
ATestActor::ATestActor()
{
 	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

    DrawCnt = 0;
}

// Called when the game starts or when spawned
void ATestActor::BeginPlay()
{
	Super::BeginPlay();
	

    FTransform Current = GetActorTransform();

    UE_LOG(LogTemp, Warning, TEXT("Current    transform : %s"), *Current.ToString());
    DrawTransform(Current);

    FTransform A = Current;
    FTransform B = Current;
    FVector AddLoc = FVector(100, 0, -100);
    FQuat AddRot = FQuat::MakeFromEuler(FVector(0, 30, 15));
    FTransform AddTrans = FTransform(AddRot, AddLoc);

    B.Accumulate(AddTrans);
    UE_LOG(LogTemp, Warning, TEXT("Add Loc : %s  Add Rot : %s"), *AddLoc.ToString(), *AddRot.Euler().ToString());


    UE_LOG(LogTemp, Warning, TEXT("Moved    transform : %s"), *B.ToString());
    DrawTransform(B);

    FTransform Relative = B.GetRelativeTransform(A);

    UE_LOG(LogTemp, Warning, TEXT("Relative    transform : %s"), *Relative.ToString());
    

    A = Relative * A;

    UE_LOG(LogTemp, Warning, TEXT("Restore    transform : %s"), *A.ToString());
    DrawTransform(A);


}

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

void ATestActor::PrintData()
{
    UE_LOG(LogTemp, Warning, TEXT("Print    transform : %s"), *GetActorTransform().ToString());
}

void ATestActor::DrawTransform(FTransform T)
{
    FVector Loc = T.GetLocation();
    if (DrawCnt == 0)
    {
        DrawDebugSphere(GetWorld(), Loc, 10, 26, FColor::Black, true, -1, 0, 2);
    }
    else
    {
        DrawDebugSphere(GetWorld(), Loc, 10, 26, FColor::White, true, -1, 0, 2);
    }
    DrawCnt++;

    FVector Forward = T.GetUnitAxis(EAxis::X);
    FVector Right = T.GetUnitAxis(EAxis::Y);
    FVector Up = T.GetUnitAxis(EAxis::Z);

    float Length = 100 + DrawCnt * 25;

    DrawDebugDirectionalArrow(GetWorld(), Loc, Loc + Forward * Length, 50.f, FColor::Red, true, -1.f, 0, 5.f);
    DrawDebugDirectionalArrow(GetWorld(), Loc, Loc + Right * Length, 50.f, FColor::Green, true, -1.f, 0, 5.f);
    DrawDebugDirectionalArrow(GetWorld(), Loc, Loc + Up * Length, 50.f, FColor::Blue, true, -1.f, 0, 5.f);
}

 

Location, Rotation 간의 차이를 구하는 방법과, Transform 사이의 Blend 값을 구하는 방법이다.

void ATestActor::Test2()
{
    FTransform Current = GetActorTransform();

    UE_LOG(LogTemp, Warning, TEXT("Current    transform : %s"), *Current.ToString());

    FTransform A = Current;
    FTransform B = Current;
    FTransform C = Current;

    FVector AddLoc = FVector(100, 0, -100);
    FQuat AddRot = FQuat::MakeFromEuler(FVector(0, 45, 30));
    FTransform AddTrans = FTransform(AddRot, AddLoc);

    UE_LOG(LogTemp, Warning, TEXT("AddTrans    transform : %s"), *AddTrans.ToString());

    B.SetLocation(B.GetLocation() + AddLoc);
    B.SetRotation(B.GetRotation() * AddRot);

    DrawTransform(A);
    DrawTransform(B);

    FVector DeltaLoc = B.GetLocation() - A.GetLocation();
    FQuat DeltaRot = A.GetRotation().Inverse() * B.GetRotation();
    // Lerp


    C.SetLocation(C.GetLocation() + DeltaLoc);
    C.SetRotation(C.GetRotation() * DeltaRot);
    DrawTransform(C);
    
    // delta
    for (int i = 1; i <= 4; ++i)
    {
        float Size = i * 0.2f;
        FTransform D = Current;

        D.FTransform::Blend(A, B, Size);

        DrawTransform(D);
    }
    

    UE_LOG(LogTemp, Warning, TEXT("DeltaLoc : %s   DeltaRot : %s"), 
        *DeltaLoc.ToString(), *DeltaRot.Rotator().ToString()  );

}

 

Transform을 이용하여 Vector를 변환하는 예제이다.

void AMathTestGameMode::TransformVectorExample(const FTransform& T)
{
	FVector Direction = (FVector::ForwardVector + FVector::RightVector).GetSafeNormal();
    // T를 World로 하는 변환 
	FVector Transformed = T.TransformVector(Direction);
    
    // T를 Local로 하는 변환
    FVector InverseTransformed = T.InverseTransformVector(Direction);

	FVector Start = FVector::ZeroVector + FVector(0, 0, 100);
	FVector SourceEnd = Start + Direction * 100.0f;
	FVector TransformedEnd = Start + Transformed * 100.0f;
	UWorld* World = GetWorld();

	GameUtils::DrawArrow(GetWorld(), Start, SourceEnd, FColor::Blue);
	GameUtils::DrawArrow(GetWorld(), Start, TransformedEnd);
}