在UE中灵活使用矩阵修改变换信息并不方便,不过UE有ProceduralMeshComponent可以动态创建Mesh,可以通过这个组件应用矩阵进行变换测试。
1.平移矩阵
注意平移矩阵101里叫做Shear而不是Skew。
转换到3D空间需要注意a的位置放在哪里。
测试用.h文件:
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "ProceduralMeshComponent.h"
#include "MyActor.generated.h"
UCLASS()
class MYPROJECT6_API AMyActor : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
AMyActor();
UPROPERTY(EditAnywhere, BlueprintReadWrite)
UProceduralMeshComponent* MeshComponent;
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
};
测试用.cpp文件:
#include "MyActor.h"
AMyActor::AMyActor()
{
PrimaryActorTick.bCanEverTick = true;
MeshComponent = CreateDefaultSubobject<UProceduralMeshComponent>(TEXT("ProceduralMesh"));
RootComponent = MeshComponent;
}
void AMyActor::BeginPlay()
{
Super::BeginPlay();
TArray<FVector> Vertices;
Vertices.Add(FVector(0.0f, 0.0f, 0.0f));
Vertices.Add(FVector(0.0f, 100.0f, 0.0f));
Vertices.Add(FVector(100.0f, 100.0f, 0.0f));
Vertices.Add(FVector(100.0f, 0.0f, 0.0f));
TArray<int32> Triangles;
Triangles.Add(0);
Triangles.Add(1);
Triangles.Add(2);
Triangles.Add(0);
Triangles.Add(2);
Triangles.Add(3);
// 定义 UV 坐标
TArray<FVector2D> UV0;
UV0.Add(FVector2D(0.0f, 0.0f));
UV0.Add(FVector2D(0.0f, 1.0f));
UV0.Add(FVector2D(1.0f, 1.0f));
UV0.Add(FVector2D(1.0f, 0.0f));
// 法线
TArray<FVector> Normals;
Normals.Add(FVector(0.0f, 0.0f, 1.0f));
Normals.Add(FVector(0.0f, 0.0f, 1.0f));
Normals.Add(FVector(0.0f, 0.0f, 1.0f));
Normals.Add(FVector(0.0f, 0.0f, 1.0f));
// 切线
TArray<FProcMeshTangent> Tangents;
Tangents.Add(FProcMeshTangent(1.0f, 0.0f, 0.0f));
Tangents.Add(FProcMeshTangent(1.0f, 0.0f, 0.0f));
Tangents.Add(FProcMeshTangent(1.0f, 0.0f, 0.0f));
Tangents.Add(FProcMeshTangent(1.0f, 0.0f, 0.0f));
TArray<FColor> VertexColors;
VertexColors.Add(FLinearColor::White.ToFColor(true));
VertexColors.Add(FLinearColor::White.ToFColor(true));
VertexColors.Add(FLinearColor::White.ToFColor(true));
VertexColors.Add(FLinearColor::White.ToFColor(true));
// 平移矩阵
float a = 1.1f;
FMatrix SkewMatrix = FMatrix(
FPlane(1.0f, a, 0.0f, 0.0f),
FPlane(0.0f, 1.0f, 0.0f, 0.0f),
FPlane(0.0f, 0.0f, 1.0f, 0.0f),
FPlane(0.0f, 0.0f, 0.0f, 1.0f)
);
for (FVector& Vertex : Vertices)
{
FVector TransformedVertex = SkewMatrix.TransformPosition(Vertex);
Vertex = TransformedVertex;
}
MeshComponent->CreateMeshSection(0, Vertices, Triangles, Normals, UV0, VertexColors, Tangents, true);
}
效果:
2.旋转矩阵
为了更好的检验应用旋转矩阵后的效果,可以将创建Mesh的过程封装一下,先看下最终效果:
首先将创建Mesh的过程封装为一个函数:
void AMyActor::CreateQuadMesh(float zOffset, FMatrix TransformMatrix, int32 MeshSectionIndex)
{
// 顶点位置定义
TArray<FVector> Vertices;
Vertices.Add(FVector(0.0f, 0.0f, 0.0f + zOffset));
Vertices.Add(FVector(0.0f, 100.0f, 0.0f + zOffset));
Vertices.Add(FVector(100.0f, 100.0f, 0.0f + zOffset));
Vertices.Add(FVector(100.0f, 0.0f, 0.0f + zOffset));
// 使用传入的矩阵进行顶点变换
for (FVector& Vertex : Vertices)
{
Vertex = TransformMatrix.TransformPosition(Vertex);
}
// 三角形索引
TArray<int32> Triangles;
Triangles.Add(0);
Triangles.Add(1);
Triangles.Add(2);
Triangles.Add(0);
Triangles.Add(2);
Triangles.Add(3);
// UV 坐标
TArray<FVector2D> UV0;
UV0.Add(FVector2D(0.0f, 0.0f));
UV0.Add(FVector2D(0.0f, 1.0f));
UV0.Add(FVector2D(1.0f, 1.0f));
UV0.Add(FVector2D(1.0f, 0.0f));
// 法线
TArray<FVector> Normals;
Normals.Add(FVector(0.0f, 0.0f, 1.0f));
Normals.Add(FVector(0.0f, 0.0f, 1.0f));
Normals.Add(FVector(0.0f, 0.0f, 1.0f));
Normals.Add(FVector(0.0f, 0.0f, 1.0f));
// 切线
TArray<FProcMeshTangent> Tangents;
Tangents.Add(FProcMeshTangent(1.0f, 0.0f, 0.0f));
Tangents.Add(FProcMeshTangent(1.0f, 0.0f, 0.0f));
Tangents.Add(FProcMeshTangent(1.0f, 0.0f, 0.0f));
Tangents.Add(FProcMeshTangent(1.0f, 0.0f, 0.0f));
// 顶点颜色
TArray<FColor> VertexColors;
VertexColors.Add(FLinearColor::White.ToFColor(true));
VertexColors.Add(FLinearColor::White.ToFColor(true));
VertexColors.Add(FLinearColor::White.ToFColor(true));
VertexColors.Add(FLinearColor::White.ToFColor(true));
// 创建网格
MeshComponent->CreateMeshSection(MeshSectionIndex, Vertices, Triangles, Normals, UV0, VertexColors, Tangents, true);
}
然后在外部创建旋转矩阵即可:
void AMyActor::BeginPlay()
{
Super::BeginPlay();
for (int32 i = 0; i < 10; ++i)
{
float RotationAngle = i * 36.0f; // 每次旋转36度
FMatrix RotationMatrix = FRotationMatrix(FRotator(0.0f, RotationAngle, 0.0f));
CreateQuadMesh(i*100.0f, RotationMatrix, i);
}
}