Skip to content
Snippets Groups Projects
Commit 8897d993 authored by Timon Römer's avatar Timon Römer
Browse files

Completes MetaCast

parent 074f176b
No related branches found
No related tags found
No related merge requests found
No preview for this file type
No preview for this file type
......@@ -104,6 +104,72 @@ void FDensityField::CalculateVoxelDensities(const APointCloud* PointCloud, const
}
void FDensityField::CalculateVoxelDensitiesByNumber(const APointCloud* PointCloud, const float InfluenceRadius)
{
if (!PointCloud)
return;
const double StartTime = FPlatformTime::Seconds(); // Start timing
UE_LOG(LogTemp, Log, TEXT("Starting density calculation."));
// Clear existing densities
for (auto& Node : VoxelList)
{
Node.SetVoxelDensity(0.0); // Reset the density counter
}
UE_LOG(LogTemp, Log, TEXT("Cleared previous densities."));
// Iterate over each particle
for (const FVector& ParticlePosition : PointCloud->PositionVectors)
{
// Calculate which voxels the particle influences
const int32 StartX = FMath::Max(0, static_cast<int32>((ParticlePosition.X - InfluenceRadius - GridOrigin.X) / XStep));
const int32 EndX = FMath::Min(XNum - 1, static_cast<int32>((ParticlePosition.X + InfluenceRadius - GridOrigin.X) / XStep));
const int32 StartY = FMath::Max(0, static_cast<int32>((ParticlePosition.Y - InfluenceRadius - GridOrigin.Y) / YStep));
const int32 EndY = FMath::Min(YNum - 1, static_cast<int32>((ParticlePosition.Y + InfluenceRadius - GridOrigin.Y) / YStep));
const int32 StartZ = FMath::Max(0, static_cast<int32>((ParticlePosition.Z - InfluenceRadius - GridOrigin.Z) / ZStep));
const int32 EndZ = FMath::Min(ZNum - 1, static_cast<int32>((ParticlePosition.Z + InfluenceRadius - GridOrigin.Z) / ZStep));
// Update densities within the influence radius
for (int32 Z = StartZ; Z <= EndZ; ++Z)
{
for (int32 Y = StartY; Y <= EndY; ++Y)
{
for (int32 X = StartX; X <= EndX; ++X)
{
const int32 Index = GridPositionToIndex(X, Y, Z);
if (IsValidIndex(Index))
{
FVector VoxelPosition = IndexToVoxelPosition(Index);
const float Distance = FVector::Dist(VoxelPosition, ParticlePosition);
if (Distance < InfluenceRadius)
{
VoxelList[Index].AddToVoxelDensity(1.0); // Simply increment the density count
}
}
}
}
}
}
double MaxDensity = 0.0;
for (const auto& Node : VoxelList)
{
if (Node.GetVoxelDensity() > MaxDensity)
{
MaxDensity = Node.GetVoxelDensity();
}
}
UE_LOG(LogTemp, Log, TEXT("Maximum density found: %f"), MaxDensity);
const double EndTime = FPlatformTime::Seconds(); // End timing
const double ElapsedTime = EndTime - StartTime; // Calculate elapsed time
UE_LOG(LogTemp, Log, TEXT("Density calculation completed in %f seconds."), ElapsedTime);
}
void FDensityField::CalculateAndStoreGradients()
{
UE_LOG(LogTemp, Log, TEXT("Starting gradient calculation."));
......@@ -182,6 +248,8 @@ void FDensityField::DrawDebugVoxelDensity(const UWorld* World, const AActor* Act
UE_LOG(LogTemp, Log, TEXT("DensityField drawn with gradient colors using logarithmic scaling!"));
}
// WORLD POSITION CONVERSION FUNCTIONS
int32 FDensityField::WorldPositionToIndex(const FVector &Position) const {
......@@ -354,6 +422,21 @@ double FDensityField::IndexToVoxelDensity(const int32 Index) const
return 0.0;
}
void FDensityField::IndexToVoxelBounds(const int32 Index, FVector& OutMinBounds, FVector& OutMaxBounds) const
{
if (!IsValidIndex(Index)) {
UE_LOG(LogTemp, Warning, TEXT("Invalid voxel index provided: %d"), Index);
return;
}
// Calculate the bounds
const FVector VoxelCenter = IndexToVoxelPosition(Index);
OutMinBounds = VoxelCenter - GetStep() * 0.5f;
OutMaxBounds = VoxelCenter + GetStep() * 0.5f;
//UE_LOG(LogTemp, Log, TEXT("Voxel %d Bounds: Min(%s), Max(%s)"), Index, *OutMinBounds.ToString(), *OutMaxBounds.ToString());
}
// VALIDITY FUNCTIONS
bool FDensityField::IsValidIndex(const int32 Index) const {
......
......@@ -60,12 +60,14 @@ class FDensityField
FVector GridOrigin;
public:
mutable FCriticalSection DataGuard;
// CONSTRUCTOR
FDensityField();
// INITIALIZATION FUNCTIONS
void InitializeDensityField(const FVector& MinBounds, const FVector& MaxBounds, const int32 XAxisNum, const int32 YAxisNum, const int32 ZAxisNum);
void CalculateVoxelDensities(const APointCloud* PointCloud, float InfluenceRadius, float Sigma);
void CalculateVoxelDensitiesByNumber(const APointCloud* PointCloud, float InfluenceRadius);
void CalculateAndStoreGradients();
// DEBUG FUNCTIONS
......@@ -85,6 +87,7 @@ public:
FIntVector3 IndexToGridPosition(int32 Index) const;
int32 GetVoxelNumber() const;
double IndexToVoxelDensity(int32 Index) const;
void IndexToVoxelBounds(int32 Index, FVector& OutMinBounds, FVector& OutMaxBounds) const;
double GridPositionToVoxelDensity(int32 XBin, int32 YBin, int32 ZBin) const;
FVector GridPositionToVoxelGradient(int32 XBin, int32 YBin, int32 ZBin) const;
FVector GetStep() const;
......@@ -94,6 +97,7 @@ public:
bool IsValidWorldPosition(const FVector& Position) const;
TArray<int32> IndexToVoxelNeighbors(const int32 Index) const;
bool IsValidIndex(int32 Index) const;
bool IsValid();
void SetVoxelDensityByIndex(int32 Index, double Density);
void SetVoxelGradientByIndex(int32 Index, const FVector& Gradient);
};
......@@ -99,6 +99,7 @@ void UMetaCastBaseline::InitInputBindings()
EnhancedInputComponent->BindAction(MetaSelectAction, ETriggerEvent::Started, this, &UMetaCastBaseline::HandleMetaSelectPressed);
EnhancedInputComponent->BindAction(MetaSelectAction, ETriggerEvent::Completed, this, &UMetaCastBaseline::HandleMetaSelectReleased);
EnhancedInputComponent->BindAction(MetaSelectAction, ETriggerEvent::Canceled, this, &UMetaCastBaseline::HandleMetaSelectReleased);
EnhancedInputComponent->BindAction(MetaEraseAction, ETriggerEvent::Started, this, &UMetaCastBaseline::HandleMetaErasePressed);
EnhancedInputComponent->BindAction(MetaEraseAction, ETriggerEvent::Completed, this, &UMetaCastBaseline::HandleMetaEraseReleased);
......
#include "MetaPoint.h"
#include "Utilities.h"
UMetaPoint::UMetaPoint() : Index(0), MyDensityField(nullptr), Threshold(0), World(nullptr), MyProceduralMesh(nullptr)
UMetaPoint::UMetaPoint() : LocalMaximumIndex(0), MyDensityField(nullptr), MetaPointThreshold(0), World(nullptr)
{
// Initialize the Marching Cubes algorithm
MyMarchingCubes = new MarchingCubes();
......@@ -26,6 +26,13 @@ void UMetaPoint::BeginPlay()
ProceduralMesh->SetMaterial(2, SelectionVolumeMat);
}
void UMetaPoint::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
AccumulatedTime += DeltaTime;
}
void UMetaPoint::EraseParticles(const FVector& InputPosition)
{
......@@ -34,92 +41,83 @@ void UMetaPoint::EraseParticles(const FVector& InputPosition)
void UMetaPoint::HandleMetaSelectReleased(const FInputActionInstance& Instance)
{
Super::HandleMetaSelectReleased(Instance);
ProceduralMesh->ClearAllMeshSections();
ProceduralMesh->SetVisibility(false);
AsyncTask(ENamedThreads::Type::AnyBackgroundHiPriTask, [this]()
{
MyPointCloud->ColorPointsInVoxels(FloodedIndices);
});
}
void UMetaPoint::HandleMetaSelectPressed(const FInputActionInstance& Instance)
{
Super::HandleMetaSelectPressed(Instance);
FindAndMarkLocalMaximum();
InitMetaPointSelection();
}
// Method to perform gradient ascent to find the local maximum density starting from a given position.
void UMetaPoint::FindAndMarkLocalMaximum()
void UMetaPoint::InitMetaPointSelection()
{
const FVector WorldPosition = SelectionObject->GetComponentLocation();
const FVector SelectionWorldPosition = SelectionObject->GetComponentLocation();
MyDensityField = MyPointCloud->MyDensityField;
// Convert the world position of the selection object to the local position relative to the point cloud
const FVector StartPosition = MyPointCloud->PointCloudVisualizer->GetComponentTransform().InverseTransformPosition(WorldPosition);
const FVector SelectionLocalPosition = MyPointCloud->PointCloudVisualizer->GetComponentTransform().InverseTransformPosition(SelectionWorldPosition);
// Perform gradient ascent to find the local maximum starting from the converted local position
LocalMaximum = FUtilities::FollowGradientToMaximum(MyDensityField, StartPosition);
LocalMaximum = FUtilities::FollowGradientToMaximum(MyDensityField, SelectionLocalPosition);
// Convert the local maximum back to world coordinates
Index = MyDensityField->WorldPositionToIndex(LocalMaximum);
LocalMaximumIndex = MyDensityField->WorldPositionToIndex(LocalMaximum);
Threshold = FUtilities::InterpolateDensityAtPosition(MyDensityField, LocalMaximum);
TestingThresholdFactor = 1;
MetaPointThreshold = FUtilities::InterpolateDensityAtPosition(MyDensityField, SelectionLocalPosition);
// Initialize Visited array to false for all voxels
Visited.Init(false, MyDensityField->GetVoxelNumber());
// Initialize IndicesToVisit with the starting index
IndicesToVisit.Empty();
IndicesToVisit.Add(Index);
IndicesToVisit.Add(LocalMaximumIndex);
// Clear FloodedIndices
FloodedIndices.Empty();
RevisitIndices.Empty();
ProceduralMesh->ClearAllMeshSections();
World = GetWorld();
}
void UMetaPoint::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
//TestingThresholdFactor -= DeltaTime * 0.1f;
AccumulatedTime += DeltaTime;
constexpr float DecayRate = 0.1f; // Adjust this value to control the rate of decay
TestingThresholdFactor *= FMath::Exp(-DecayRate * DeltaTime);
// Ensure TestingThresholdFactor never goes below a small threshold to prevent it from becoming zero
constexpr float MinThreshold = 0.001f; // Adjust as needed
if (TestingThresholdFactor < MinThreshold)
{
TestingThresholdFactor = MinThreshold;
}
}
void UMetaPoint::SelectParticles(const FVector& InputPosition)
{
//WorldMaximum = MyPointCloud->PointCloudVisualizer->GetComponentTransform().TransformPosition(LocalMaximum);
// Draw a debug sphere at the location of the local maximum in the world
//DrawDebugSphere(World, WorldMaximum, SelectionRadius / 2, 32, FColor::Red, false, 0);
if (AccumulatedTime >= 0.1f)
if (AccumulatedTime >= 1 / MetaCastPerSecond)
{
AccumulatedTime = -10.0f;
AccumulatedTime = -1000;
AsyncTask(ENamedThreads::AnyBackgroundThreadNormalTask, [this]()
{
//TArray<int32> Voxels = FUtilities::FloodFilling(MyDensityField, Index, Threshold * TestingThresholdFactor);
FUtilities::FloodFilling_2(MyDensityField, Threshold * TestingThresholdFactor, Visited, IndicesToVisit, FloodedIndices, IndicesToVisit);
const FVector SelectionWorldPosition = SelectionObject->GetComponentLocation();
// Convert the world position of the selection object to the local position relative to the point cloud
const FVector SelectionLocalPosition = MyPointCloud->PointCloudVisualizer->GetComponentTransform().InverseTransformPosition(SelectionWorldPosition);
// Perform gradient ascent to find the local maximum starting from the converted local position
LocalMaximum = FUtilities::FollowGradientToMaximum(MyDensityField, SelectionLocalPosition);
// Convert the local maximum back to world coordinates
LocalMaximumIndex = MyDensityField->WorldPositionToIndex(LocalMaximum);
MetaPointThreshold = FUtilities::InterpolateDensityAtPosition(MyDensityField, SelectionLocalPosition);
FloodedIndices = FUtilities::FloodFilling(MyDensityField, LocalMaximumIndex, MetaPointThreshold);
auto Voxels = FloodedIndices;
AsyncTask(ENamedThreads::GameThread, [this, Voxels]()
{
GenerateVoxelMesh(FloodedIndices);
AccumulatedTime = 0.0f;
});
});
}
}
void UMetaPoint::GenerateVoxelMesh(const TArray<int32>& Voxels) const
void UMetaPoint::GenerateVoxelMesh(const TArray<int32> Voxels) const
{
TArray<FVector> Vertices;
TArray<int32> Triangles;
......@@ -135,12 +133,6 @@ void UMetaPoint::GenerateVoxelMesh(const TArray<int32>& Voxels) const
TArray<FVector> VoxelCorners = MyDensityField->IndexToVoxelCornersWorld(VoxelIndex);
// Convert corners to world space
for (FVector& Corner : VoxelCorners)
{
//Corner = MyPointCloud->PointCloudVisualizer->GetComponentTransform().TransformPosition(Corner);
}
// Add vertices for the voxel
const int32 BaseIndex = Vertices.Num();
Vertices.Append(VoxelCorners);
......@@ -159,10 +151,48 @@ void UMetaPoint::GenerateVoxelMesh(const TArray<int32>& Voxels) const
// Add red color for each corner vertex
for (int32 i = 0; i < 8; ++i)
{
VertexColors.Add(FColor::Red);
VertexColors.Add(FColor::Green);
}
}
// Create the mesh section
ProceduralMesh->CreateMeshSection(0, Vertices, Triangles, TArray<FVector>(), TArray<FVector2D>(), VertexColors, TArray<FProcMeshTangent>(), true);
AsyncTask(ENamedThreads::Type::GameThread, [this, Vertices, Triangles, VertexColors]()
{
//CreateMeshSections(Vertices, Triangles, VertexColors, 1000);
ProceduralMesh->CreateMeshSection(0, Vertices, Triangles, TArray<FVector>(), TArray<FVector2D>(), VertexColors, TArray<FProcMeshTangent>(), false);
ProceduralMesh->SetVisibility(true);
});
}
void UMetaPoint::CreateMeshSections(const TArray<FVector>& Vertices, const TArray<int32>& Triangles, const TArray<FColor>& VertexColors, const int32 MaxVerticesPerSection) const
{
const int32 NumVertices = Vertices.Num();
const int32 NumTriangles = Triangles.Num() / 3;
for (int32 SectionIndex = 0, VertexIndex = 0, TriangleIndex = 0; VertexIndex < NumVertices && TriangleIndex < NumTriangles;
++SectionIndex, VertexIndex += MaxVerticesPerSection, TriangleIndex += MaxVerticesPerSection / 3)
{
const int32 NumVerticesInSection = FMath::Min(MaxVerticesPerSection, NumVertices - VertexIndex);
const int32 NumTrianglesInSection = FMath::Min(MaxVerticesPerSection / 3, NumTriangles - TriangleIndex);
TArray<FVector> SectionVertices;
TArray<FColor> SectionVertexColors;
SectionVertices.Reserve(NumVerticesInSection);
SectionVertexColors.Reserve(NumVerticesInSection);
for (int32 i = 0; i < NumVerticesInSection; ++i)
{
SectionVertices.Add(Vertices[VertexIndex + i]);
SectionVertexColors.Add(VertexColors[VertexIndex + i]);
}
TArray<int32> SectionTriangles;
SectionTriangles.Reserve(NumTrianglesInSection * 3);
for (int32 i = 0; i < NumTrianglesInSection * 3; ++i)
{
SectionTriangles.Add(Triangles[TriangleIndex * 3 + i] - VertexIndex);
}
// Create or update the mesh section
ProceduralMesh->CreateMeshSection(SectionIndex, SectionVertices, SectionTriangles, TArray<FVector>(), TArray<FVector2D>(), SectionVertexColors, TArray<FProcMeshTangent>(), false);
}
}
\ No newline at end of file
......@@ -14,10 +14,10 @@ class UMetaPoint : public UMetaCastBaseline
MarchingCubes* MyMarchingCubes;
FVector WorldMaximum;
int32 Index;
int32 LocalMaximumIndex;
FVector LocalMaximum;
FDensityField* MyDensityField;
float Threshold;
float MetaPointThreshold;
UPROPERTY()
UWorld* World;
float AccumulatedTime = 0.0;
......@@ -33,14 +33,10 @@ class UMetaPoint : public UMetaCastBaseline
TArray<int32> FloodedIndices;
TArray<int32> RevisitIndices;
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite)
UProceduralMeshComponent* MyProceduralMesh;
UPROPERTY(EditAnywhere)
float TestingThresholdFactor = 2.0;
int MetaCastPerSecond = 10;
public:
UMetaPoint();
virtual void BeginPlay() override;
......@@ -50,9 +46,10 @@ public:
virtual void HandleMetaSelectReleased(const FInputActionInstance& Instance) override;
virtual void HandleMetaSelectPressed(const FInputActionInstance& Instance) override;
void FindAndMarkLocalMaximum();
void InitMetaPointSelection();
void GenerateVoxelMesh(const TArray<int32>& Voxels) const;
void GenerateVoxelMesh(const TArray<int32> Voxels) const;
void CreateMeshSections(const TArray<FVector>& Vertices, const TArray<int32>& Triangles, const TArray<FColor>& VertexColors, int32 MaxVerticesPerSection) const;
virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
};
......
......@@ -22,7 +22,7 @@ void APointCloud::BeginPlay()
void APointCloud::ReadPointCloudFromFile(const FFilePath FileNamePoints, const FFilePath FileNameFlags)
{
TArray<FVector> LoadedPointCloud = PointCloudDataReader::LoadPointCloudData(FileNamePoints.FilePath);
const TArray<FVector> LoadedPointCloud = PointCloudDataReader::LoadPointCloudData(FileNamePoints.FilePath);
TArray<int32> LoadedPointCloudFlags = PointCloudDataReader::LoadFlags(FileNameFlags.FilePath);
// Initialize the boolean array for flags with all elements set to false
......@@ -30,7 +30,7 @@ void APointCloud::ReadPointCloudFromFile(const FFilePath FileNamePoints, const F
BooleanFlags.Init(false, LoadedPointCloud.Num());
// Set true for indices that are included in the flags array
for (int32 FlagIndex : LoadedPointCloudFlags)
for (const int32 FlagIndex : LoadedPointCloudFlags)
{
if (FlagIndex < BooleanFlags.Num())
{
......@@ -91,10 +91,10 @@ void APointCloud::SetupDensityFieldFromPointCloud() const
constexpr int32 ZAxisNum = 100; // Number of divisions in the grid along the Z-axis
MyDensityField->InitializeDensityField(MinBounds, MaxBounds, XAxisNum, YAxisNum, ZAxisNum);
constexpr float InfluenceRadius = 5.0f; // Half the size of a voxel
constexpr float Sigma = 3.0f; // Standard deviation for the Gaussian kernel
MyDensityField->CalculateVoxelDensities(this, InfluenceRadius, Sigma);
constexpr float InfluenceRadius = 2.0f; // Half the size of a voxel
constexpr float Sigma = 0.5f; // Standard deviation for the Gaussian kernel
MyDensityField->CalculateVoxelDensitiesByNumber(this, InfluenceRadius);
MyDensityField->CalculateAndStoreGradients();
if (const UWorld* World = GetWorld())
......@@ -106,6 +106,17 @@ void APointCloud::SetupDensityFieldFromPointCloud() const
void APointCloud::UpdateSelection()
{
for (int32 i = 0; i < PositionVectors.Num(); i++)
{
if(DefaultFlags[i])
{
if (SelectionFlags[i])
{
PointColors[i] = FColor::Red;
}else
{
PointColors[i] = FColor::Orange;
}
}else
{
if (SelectionFlags[i])
{
......@@ -115,6 +126,7 @@ void APointCloud::UpdateSelection()
PointColors[i] = FColor::Blue;
}
}
}
PointCloudVisualizer->SetInputAndConvert2(PositionVectors, PointColors);
}
......@@ -135,10 +147,59 @@ void APointCloud::DrawVoxel(const int Index, const float Time) const
}
void APointCloud::ColorPointsInVoxels(const TArray<int32> VoxelIndices)
{
if (!MyDensityField)
{
UE_LOG(LogTemp, Warning, TEXT("DensityField is not initialized."));
return;
}
TArray<FVector> MyPositionVectors = PositionVectors;
FScopeLock Lock(&DataGuard);
FScopeLock Lock2(&MyDensityField->DataGuard);
// Iterate through each index in VoxelIndices
for (const int32 VoxelIndex : VoxelIndices)
{
// Ensure the voxel index is valid
if (!MyDensityField || !MyDensityField->IsValidIndex(VoxelIndex))
{
UE_LOG(LogTemp, Warning, TEXT("Invalid voxel index: %d"), VoxelIndex);
continue;
}
// Get the bounds of the voxel
FVector VoxelMin, VoxelMax;
MyDensityField->IndexToVoxelBounds(VoxelIndex, VoxelMin, VoxelMax);
// Iterate over all points to check if they are within this voxel
for (int32 i = 0; i < MyPositionVectors.Num(); ++i)
{
if(!MyPositionVectors.IsValidIndex(i))
{
continue;
}
const FVector Point = MyPositionVectors[i];
// Check if the point is within the voxel bounds
if (Point.X >= VoxelMin.X && Point.X <= VoxelMax.X &&
Point.Y >= VoxelMin.Y && Point.Y <= VoxelMax.Y &&
Point.Z >= VoxelMin.Z && Point.Z <= VoxelMax.Z)
{
SelectionFlags[i] = true;
}
}
}
//UpdateSelection();
}
// Called every frame
void APointCloud::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
UpdateSelection();
}
......@@ -17,6 +17,7 @@ public:
TArray<bool> DefaultFlags;
TArray<bool> SelectionFlags;
TArray<FColor> PointColors;
mutable FCriticalSection DataGuard;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Bounds")
FVector MinBounds;
......@@ -59,6 +60,7 @@ public:
void UpdateSelection();
void DrawVoxel(const int Index, float Time) const;
void ColorPointsInVoxels(const TArray<int32> VoxelIndices);
UFUNCTION(BlueprintCallable)
void ReadPointCloudFromFile(FFilePath FileNamePoints, FFilePath FileNameFlags);
......
......@@ -138,7 +138,7 @@ FVector FUtilities::FollowGradientToMaximum(const FDensityField* DensityField, c
//UE_LOG(LogTemp, Log, TEXT("Iteration %d: CurrentPos = %s, Gradient = %s, NextPos = %s, NewDensity = %f, CurrentDensity = %f"), Iterations, *CurrentPosition.ToString(), *Gradient.ToString(), *NextPosition.ToString(), NewDensity, CurrentDensity);
if (NewDensity <= CurrentDensity) { // Check if density has increased
UE_LOG(LogTemp, Log, TEXT("Density did not increase; stopping at position %s with density %f"), *CurrentPosition.ToString(), CurrentDensity);
//UE_LOG(LogTemp, Log, TEXT("Density did not increase; stopping at position %s with density %f"), *CurrentPosition.ToString(), CurrentDensity);
break; // No improvement in density, stop iteration
}
......@@ -203,38 +203,6 @@ TArray<int32> FUtilities::FloodFilling(const FDensityField* DensityField, const
return VisitedIndices;
}
/*
TArray<int32> FUtilities::FloodFilling_2(const FDensityField* DensityField, const float Threshold, TArray<bool>& Visited, TArray<int32>& IndicesToVisit, TArray<int32>& FloodedIndices)
{
if (!DensityField) {
UE_LOG(LogTemp, Warning, TEXT("DensityField is null."));
return FloodedIndices;
}
while (IndicesToVisit.Num() > 0)
{
int32 CurrentIndex = IndicesToVisit.Pop();
if (!Visited[CurrentIndex])
{
Visited[CurrentIndex] = true;
FloodedIndices.Add(CurrentIndex);
TArray<int32> Neighbors = DensityField->IndexToVoxelNeighbors(CurrentIndex);
for (int32 NeighborIndex : Neighbors)
{
const double NeighborDensity = DensityField->IndexToVoxelDensity(NeighborIndex);
if (NeighborDensity > Threshold && !Visited[NeighborIndex]) {
IndicesToVisit.Push(NeighborIndex);
}
}
}
}
return FloodedIndices;
}*/
void FUtilities::FloodFilling_2(const FDensityField* DensityField, const float Threshold, TArray<bool>& VisitedIndices, TArray<int32>& IndicesToVisit, TArray<int32>& FloodedIndices, TArray<int32>& PotentialRevisit)
{
if (!DensityField) {
......@@ -244,10 +212,13 @@ void FUtilities::FloodFilling_2(const FDensityField* DensityField, const float T
TArray<int32> CurrentPotentialRevisit;
constexpr int MaxIterations = 100;
constexpr int MaxIterations = 2000;
int IterationCount = 0;
while (IndicesToVisit.Num() > 0)
{
IterationCount++;
if(IterationCount > MaxIterations)
{
......@@ -258,6 +229,9 @@ void FUtilities::FloodFilling_2(const FDensityField* DensityField, const float T
}
int32 CurrentIndex = IndicesToVisit.Pop();
if(DensityField->IsValidIndex(CurrentIndex))
{
VisitedIndices[CurrentIndex] = true;
const double CurrentDensity = DensityField->IndexToVoxelDensity(CurrentIndex);
......@@ -276,10 +250,8 @@ void FUtilities::FloodFilling_2(const FDensityField* DensityField, const float T
CurrentPotentialRevisit.Add(CurrentIndex);
}
}
}
// Update PotentialRevisit with the new list from this run
PotentialRevisit = CurrentPotentialRevisit;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment