Files
UnrealEngine/Engine/Source/Runtime/GeometryFramework/Private/Changes/MeshVertexChange.cpp
2025-05-18 13:04:45 +08:00

339 lines
8.3 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "Changes/MeshVertexChange.h"
#include "DynamicMesh/DynamicMesh3.h"
#include "Components/BaseDynamicMeshComponent.h"
#include UE_INLINE_GENERATED_CPP_BY_NAME(MeshVertexChange)
using namespace UE::Geometry;
void FMeshVertexChange::Apply(UObject* Object)
{
IMeshVertexCommandChangeTarget* ChangeTarget = CastChecked<IMeshVertexCommandChangeTarget>(Object);
ChangeTarget->ApplyChange(this, false);
}
void FMeshVertexChange::Revert(UObject* Object)
{
IMeshVertexCommandChangeTarget* ChangeTarget = CastChecked<IMeshVertexCommandChangeTarget>(Object);
ChangeTarget->ApplyChange(this, true);
}
void FMeshVertexChange::ProcessChangeVertices(const FDynamicMesh3* ChangedMesh, TFunctionRef<void(TConstArrayView<int32>)> ProcessFn, bool bRevert) const
{
// Note: Since the FMeshVertexChange doesn't change vertex IDs, we don't need to look at ChangedMesh or bRevert and can just pass the Vertices array
ProcessFn(Vertices);
}
FString FMeshVertexChange::ToString() const
{
return FString(TEXT("Mesh Vertex Change"));
}
FMeshVertexChangeBuilder::FMeshVertexChangeBuilder()
{
Change = MakeUnique<FMeshVertexChange>();
}
FMeshVertexChangeBuilder::FMeshVertexChangeBuilder(EMeshVertexChangeComponents Components)
{
Change = MakeUnique<FMeshVertexChange>();
bSavePositions = ((Components & EMeshVertexChangeComponents::VertexPositions) != EMeshVertexChangeComponents::None);
Change->bHaveVertexPositions = bSavePositions;
bSaveColors = ((Components & EMeshVertexChangeComponents::VertexColors) != EMeshVertexChangeComponents::None);
Change->bHaveVertexColors = bSaveColors;
bSaveOverlayNormals = ((Components & EMeshVertexChangeComponents::OverlayNormals) != EMeshVertexChangeComponents::None);
Change->bHaveOverlayNormals = bSaveOverlayNormals;
bSaveOverlayUVs = ((Components & EMeshVertexChangeComponents::OverylayUVs) != EMeshVertexChangeComponents::None);
Change->bHaveOverlayUVs = bSaveOverlayUVs;
}
void FMeshVertexChangeBuilder::UpdateVertex(int VertexID, const FVector3d& OldPosition, const FVector3d& NewPosition)
{
const int* FoundIndex = SavedVertices.Find(VertexID);
if (FoundIndex == nullptr)
{
int NewIndex = Change->Vertices.Num();
SavedVertices.Add(VertexID, NewIndex);
Change->Vertices.Add(VertexID);
Change->OldPositions.Add(OldPosition);
Change->NewPositions.Add(NewPosition);
}
else
{
Change->NewPositions[*FoundIndex] = NewPosition;
}
}
void FMeshVertexChangeBuilder::UpdateVertexColor(int32 VertexID, const FVector3f& OldColor, const FVector3f& NewColor)
{
const int* FoundIndex = SavedVertices.Find(VertexID);
if (FoundIndex == nullptr)
{
int NewIndex = Change->Vertices.Num();
SavedVertices.Add(VertexID, NewIndex);
Change->Vertices.Add(VertexID);
Change->OldColors.Add(OldColor);
Change->NewColors.Add(NewColor);
}
else
{
Change->NewColors[*FoundIndex] = NewColor;
}
}
void FMeshVertexChangeBuilder::UpdateVertexFinal(int VertexID, const FVector3d& NewPosition)
{
check(SavedVertices.Contains(VertexID));
const int* Index = SavedVertices.Find(VertexID);
if ( Index != nullptr )
{
Change->NewPositions[*Index] = NewPosition;
}
}
void FMeshVertexChangeBuilder::SaveVertexInitial(const FDynamicMesh3* Mesh, int32 VertexID)
{
const int32* FoundIndex = SavedVertices.Find(VertexID);
if (FoundIndex == nullptr)
{
int32 Index = Change->Vertices.Num();
SavedVertices.Add(VertexID, Index);
Change->Vertices.Add(VertexID);
if (bSavePositions)
{
FVector3d Pos = Mesh->GetVertex(VertexID);
Change->OldPositions.Add(Pos);
Change->NewPositions.Add(Pos);
}
if (bSaveColors)
{
FVector3f Color = Mesh->GetVertexColor(VertexID);
Change->OldColors.Add(Color);
Change->NewColors.Add(Color);
}
if (OnNewVertexSaved)
{
OnNewVertexSaved(VertexID, Index);
}
}
else
{
int32 Index = *FoundIndex;
if (bSavePositions)
{
Change->NewPositions[Index] = Mesh->GetVertex(VertexID);
}
if (bSaveColors)
{
Change->NewColors[Index] = Mesh->GetVertexColor(VertexID);
}
}
}
void FMeshVertexChangeBuilder::SaveVertexFinal(const FDynamicMesh3* Mesh, int32 VertexID)
{
const int32* FoundIndex = SavedVertices.Find(VertexID);
if (FoundIndex != nullptr)
{
int32 Index = *FoundIndex;
if (bSavePositions)
{
Change->NewPositions[Index] = Mesh->GetVertex(VertexID);
}
if (bSaveColors)
{
Change->NewColors[Index] = Mesh->GetVertexColor(VertexID);
}
}
}
void FMeshVertexChangeBuilder::UpdateOverlayNormal(int ElementID, const FVector3f& OldNormal, const FVector3f& NewNormal)
{
const int* FoundIndex = SavedNormalElements.Find(ElementID);
if (FoundIndex == nullptr)
{
int NewIndex = Change->Normals.Num();
SavedNormalElements.Add(ElementID, NewIndex);
Change->Normals.Add(ElementID);
Change->OldNormals.Add(OldNormal);
Change->NewNormals.Add(NewNormal);
}
else
{
Change->NewNormals[*FoundIndex] = NewNormal;
}
}
void FMeshVertexChangeBuilder::UpdateOverlayNormalFinal(int ElementID, const FVector3f& NewNormal)
{
check(SavedNormalElements.Contains(ElementID));
const int* Index = SavedNormalElements.Find(ElementID);
if (Index != nullptr)
{
Change->NewNormals[*Index] = NewNormal;
}
}
void FMeshVertexChangeBuilder::SaveOverlayNormals(const FDynamicMesh3* Mesh, const TArray<int>& ElementIDs, bool bInitial)
{
if (Mesh->HasAttributes() == false || Mesh->Attributes()->PrimaryNormals() == nullptr)
{
return;
}
const FDynamicMeshNormalOverlay* Overlay = Mesh->Attributes()->PrimaryNormals();
int Num = ElementIDs.Num();
if (bInitial)
{
for (int k = 0; k < Num; ++k)
{
FVector3f Normal = Overlay->GetElement(ElementIDs[k]);
UpdateOverlayNormal(ElementIDs[k], Normal, Normal);
}
}
else
{
for (int k = 0; k < Num; ++k)
{
FVector3f Normal = Overlay->GetElement(ElementIDs[k]);
UpdateOverlayNormalFinal(ElementIDs[k], Normal);
}
}
}
void FMeshVertexChangeBuilder::SaveOverlayNormals(const FDynamicMesh3* Mesh, const TSet<int>& ElementIDs, bool bInitial)
{
if (Mesh->HasAttributes() == false || Mesh->Attributes()->PrimaryNormals() == nullptr)
{
return;
}
const FDynamicMeshNormalOverlay* Overlay = Mesh->Attributes()->PrimaryNormals();
if (bInitial)
{
for (int ElementID : ElementIDs)
{
FVector3f Normal = Overlay->GetElement(ElementID);
UpdateOverlayNormal(ElementID, Normal, Normal);
}
}
else
{
for (int ElementID : ElementIDs)
{
FVector3f Normal = Overlay->GetElement(ElementID);
UpdateOverlayNormalFinal(ElementID, Normal);
}
}
}
void FMeshVertexChangeBuilder::UpdateOverlayUV(int ElementID, const FVector2f& OldUV, const FVector2f& NewUV)
{
const int* FoundIndex = SavedUVElements.Find(ElementID);
if (FoundIndex == nullptr)
{
int NewIndex = Change->UVs.Num();
SavedUVElements.Add(ElementID, NewIndex);
Change->UVs.Add(ElementID);
Change->OldUVs.Add(OldUV);
Change->NewUVs.Add(NewUV);
}
else
{
Change->NewUVs[*FoundIndex] = NewUV;
}
}
void FMeshVertexChangeBuilder::UpdateOverlayUVFinal(int ElementID, const FVector2f& NewUV)
{
check(SavedUVElements.Contains(ElementID));
const int* Index = SavedUVElements.Find(ElementID);
if (Index != nullptr)
{
Change->NewUVs[*Index] = NewUV;
}
}
void FMeshVertexChangeBuilder::SaveOverlayUVs(const FDynamicMesh3* Mesh, const TArray<int>& ElementIDs, bool bInitial)
{
if (Mesh->HasAttributes() == false || Mesh->Attributes()->PrimaryUV() == nullptr)
{
return;
}
const FDynamicMeshUVOverlay* Overlay = Mesh->Attributes()->PrimaryUV();
int Num = ElementIDs.Num();
if (bInitial)
{
for (int k = 0; k < Num; ++k)
{
FVector2f UV = Overlay->GetElement(ElementIDs[k]);
UpdateOverlayUV(ElementIDs[k], UV, UV);
}
}
else
{
for (int k = 0; k < Num; ++k)
{
FVector2f UV = Overlay->GetElement(ElementIDs[k]);
UpdateOverlayUVFinal(ElementIDs[k], UV);
}
}
}
void FMeshVertexChangeBuilder::SaveOverlayUVs(const FDynamicMesh3* Mesh, const TSet<int>& ElementIDs, bool bInitial)
{
if (Mesh->HasAttributes() == false || Mesh->Attributes()->PrimaryUV() == nullptr)
{
return;
}
const FDynamicMeshUVOverlay* Overlay = Mesh->Attributes()->PrimaryUV();
if (bInitial)
{
for (int ElementID : ElementIDs)
{
FVector2f UV = Overlay->GetElement(ElementID);
UpdateOverlayUV(ElementID, UV, UV);
}
}
else
{
for (int ElementID : ElementIDs)
{
FVector2f UV = Overlay->GetElement(ElementID);
UpdateOverlayUVFinal(ElementID, UV);
}
}
}