2024.07.26
이번 글에서는 블루프린트로 구현한 DynamicMeshComponent의 겹쳐진 영역 자르기 기능을 C++ 코드로 변환하여 최적화하는 방법을 설명합니다. 또한 AABB의 개념과 어떻게 사용할 수 있는지를 설명합니다.
블루프린트 로직 | 리팩토링 후 블루프린트 로직 |
BP_Wall과 BP_Boolean의 BoxCollision 컴포넌트가 겹치는 부분을 찾아 BP_Boolean의 Dynamic Mesh에서 해당 부분을 제거하려고 했습니다. 잘 동작하는지 블루프린트로 로직을 검증 해봤습니다. 잘 작동하는걸 확인 후에 C++로 구현했습니다.
블루프린트에서 InverseTransformLocation
의 결과와 일치하도록 C++ 코드에서 보정을 해주어야했습니다. Transform 위치를 올바르게 보정하여 Dynamic Mesh에서 겹치는 부분을 제거했습니다.
우선 이 기능을 구현하기 위해서는 AABB에 대해서 이해해야합니다.
AABB는 Axis-Aligned Bounding Box의 약자로, 3D 공간에서 객체를 둘러싸는 축에 맞춰진 직육면체를 의미합니다. 이는 객체의 위치와 크기를 기준으로 계산됩니다. AABB는 객체의 최소값(Min)과 최대값(Max)으로 정의되며, 이는 각각 객체의 좌표 중 가장 작은 값과 가장 큰 값을 의미합니다. AABB는 주로 충돌 감지, 렌더링 최적화, 물리 엔진 등에서 사용됩니다.
블루프린트 로직 |
이제 이 블루프린트 로직을 C++로 구현한 코드는 다음과 같습니다.
#pragma once
#include "CoreMinimal.h"
#include "DynamicMeshActor.h"
#include "Components/BoxComponent.h"
#include "DynamicBlockActor.generated.h"
UCLASS()
class STUDY002_API ADynamicBlockActor : public ADynamicMeshActor
{
GENERATED_BODY()
public:
ADynamicBlockActor();
private:
virtual void OnConstruction(const FTransform& Transform) override;
public:
UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
UBoxComponent* BoxCollision;
UPROPERTY(BlueprintReadWrite)
FVector MaxAxis1;
UPROPERTY(BlueprintReadWrite)
FVector MinAxis1;
UPROPERTY(BlueprintReadWrite)
FVector MaxAxis2;
UPROPERTY(BlueprintReadWrite)
FVector MinAxis2;
UFUNCTION(BlueprintCallable)
UDynamicMesh* GetOverlappedArea(UBoxComponent* TargetBoxComponent);
void SetOverlapExtentAndLocation(UBoxComponent* Box1, UBoxComponent* Box2);
private:
FVector OverlapLocationVector;
FVector OverlapExtentVector;
};
#include "DynamicBlockActor.h"
#include "AI/NavigationModifier.h"
#include "GeometryScript/MeshPrimitiveFunctions.h"
ADynamicBlockActor::ADynamicBlockActor()
{
BoxCollision = CreateDefaultSubobject<UBoxComponent>(TEXT("BoxCollision"));
BoxCollision->SetupAttachment(DynamicMeshComponent);
}
void ADynamicBlockActor::OnConstruction(const FTransform& Transform)
{
Super::OnConstruction(Transform);
UDynamicMesh* DynamicMesh = DynamicMeshComponent->GetDynamicMesh();
if(DynamicMesh)
{
DynamicMesh->Reset();
FTransform T;
FGeometryScriptPrimitiveOptions Options;
FVector Dimension = BoxCollision->GetScaledBoxExtent();
float DimensionX = Dimension.X * 2;
float DimensionY = Dimension.Y * 2;
float DimensionZ = Dimension.Z * 2;
float TransformLocationZ = Dimension.Z * -1;
T.SetLocation(FVector(0,0,TransformLocationZ));
UGeometryScriptLibrary_MeshPrimitiveFunctions::AppendBox(DynamicMesh, Options, T, DimensionX, DimensionY, DimensionZ);
DynamicMeshComponent->EnableComplexAsSimpleCollision();
}
}
void ADynamicBlockActor::SetOverlapExtentAndLocation(UBoxComponent* Box1, UBoxComponent* Box2)
{
FVector Box1Location = Box1->GetComponentLocation();
FVector Box1Extent = Box1->GetScaledBoxExtent();
FVector Box2Location = Box2->GetComponentLocation();
FVector Box2Extent = Box2->GetScaledBoxExtent();
FVector Max1 = Box1Location + Box1Extent;
FVector Min1 = Box1Location - Box1Extent;
FVector Max2 = Box2Location + Box2Extent;
FVector Min2 = Box2Location - Box2Extent;
FVector OverlapMax = FVector(FMath::Min(Max1.X, Max2.X), FMath::Min(Max1.Y, Max2.Y), FMath::Min(Max1.Z, Max2.Z));
FVector OverlapMin = FVector(FMath::Max(Min1.X, Min2.X), FMath::Max(Min1.Y, Min2.Y), FMath::Max(Min1.Z, Min2.Z));
OverlapLocationVector = (OverlapMin + OverlapMax) / 2.0f;
OverlapExtentVector = OverlapMax - OverlapMin;
}
UDynamicMesh* ADynamicBlockActor::GetOverlappedArea(UBoxComponent* TargetBoxComponent)
{
UDynamicMesh* TargetMesh = nullptr;
SetOverlapExtentAndLocation(BoxCollision, TargetBoxComponent);
UDynamicMesh* DynamicMesh = DynamicMeshComponent->GetDynamicMesh();
FTransform Transform = DynamicMeshComponent->GetComponentTransform();
FVector BoxTransform = Transform.InverseTransformPosition(OverlapLocationVector);
if(DynamicMesh)
{
UDynamicMesh* ComputeMesh = AllocateComputeMesh();
if(ComputeMesh)
{
FTransform T;
FGeometryScriptPrimitiveOptions Options;
FVector LocalOverlapLocation = FVector(BoxTransform.X, BoxTransform.Y, BoxTransform.Z - OverlapExtentVector.Z /2 );
T.SetLocation(LocalOverlapLocation);
TargetMesh = UGeometryScriptLibrary_MeshPrimitiveFunctions::AppendBox(
ComputeMesh,
Options,
T,
OverlapExtentVector.X,
OverlapExtentVector.Y,
OverlapExtentVector.Z
);
}
}
return TargetMesh;
}
블루프린트 로직 |
블루프린트 로직 검증
C++ 코드로 변환
문제 해결
InverseTransformLocation
의 결과를 정확히 반영하여 Transform 위치를 설정했습니다.이번 글에서는 DynamicMeshComponent의 겹치는 부분을 찾아 제거하는 방법을 다루었습니다. 블루프린트로 로직을 검증한 후, 이를 C++로 변환했습니다. 이 과정을 통해 Dynamic Mesh와 관련된 기능을 효율적으로 구현할 수 있었습니다. 추가적인 질문이나 수정이 필요하다면 언제든지 알려주세요!