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

Adds MagicWand

parent ef697260
No related branches found
No related tags found
No related merge requests found
No preview for this file type
...@@ -39,10 +39,74 @@ void UMagicWand::TickComponent(float DeltaTime, ELevelTick TickType, FActorCompo ...@@ -39,10 +39,74 @@ void UMagicWand::TickComponent(float DeltaTime, ELevelTick TickType, FActorCompo
AccumulatedTime += DeltaTime; AccumulatedTime += DeltaTime;
ProceduralMesh->SetVisibility(Select); ProceduralMesh->SetVisibility(Select);
}
void UMagicWand::EraseParticles(const FVector& InputPosition)
{
}
void UMagicWand::HandleMetaSelectReleased(const FInputActionInstance& Instance)
{
Super::HandleMetaSelectReleased(Instance);
//ProceduralMesh->ClearAllMeshSections();
//ProceduralMesh->SetVisibility(false);
AsyncTask(ENamedThreads::Type::AnyBackgroundHiPriTask, [this]()
{
MyPointCloud->ColorPointsInVoxels(FloodedIndices);
});
}
void UMagicWand::HandleMetaSelectPressed(const FInputActionInstance& Instance)
{
Super::HandleMetaSelectPressed(Instance);
InitMagicWandSelection();
}
void UMagicWand::HandleMetaEraseReleased(const FInputActionInstance& Instance)
{
Super::HandleMetaEraseReleased(Instance);
//deselect all particles
for (int32 i = 0; i < MyPointCloud->SelectionFlags.Num(); ++i)
{
MyPointCloud->SelectionFlags[i] = false;
}
}
void UMagicWand::InitMagicWandSelection()
{
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
ProceduralMesh->ClearAllMeshSections();
World = GetWorld();
AbortMarchingCubes = true;
AccumulatedTime = 0.0f;
}
void UMagicWand::SelectParticles(const FVector& InputPosition)
{
if (AccumulatedTime >= 1 / EvaluationsPerSecond)
{
AccumulatedTime = -10000;
if (Select) AsyncTask(ENamedThreads::Type::AnyBackgroundHiPriTask, [this]()
{ {
PerformMagicWandSelection(SelectionObject->GetComponentLocation()); const FVector SelectionWorldPosition = SelectionObject->GetComponentLocation();
const FVector SelectionLocalPosition = MyPointCloud->PointCloudVisualizer->GetComponentTransform().InverseTransformPosition(SelectionWorldPosition);
PerformMagicWandSelection(SelectionLocalPosition);
UE_LOG(LogTemp, Warning, TEXT("Calculations done!"));
});
} }
} }
...@@ -54,131 +118,147 @@ void UMagicWand::PerformMagicWandSelection(const FVector& InputPosition) ...@@ -54,131 +118,147 @@ void UMagicWand::PerformMagicWandSelection(const FVector& InputPosition)
return; return;
} }
//UE_LOG(LogTemp, Warning, TEXT("Looking for Seed Index:"));
// Find the closest point to the input position as the seed // Find the closest point to the input position as the seed
const int32 InputVoxelIndex = MyDensityField->WorldPositionToIndex(InputPosition);
TArray<int32> Neighbors = MyDensityField->IndexToVoxelNeighbors(InputVoxelIndex);
Neighbors.Add(InputVoxelIndex);
int32 SeedIndex = INDEX_NONE; int32 SeedIndex = INDEX_NONE;
float MinDistance = FLT_MAX; float MinDistance = FLT_MAX;
for (int32 i = 0; i < MyPointCloud->PositionVectors.Num(); i++) for (const int CurrentNeighborIndex : Neighbors)
{ {
FVector CurrentPoint = MyPointCloud->PositionVectors[i]; TArray<int32> PointIndices = MyDensityField->VoxelPointLookupTable->GetPointsInVoxel(CurrentNeighborIndex);
CurrentPoint = MyPointCloud->PointCloudVisualizer->GetComponentTransform().TransformPosition(CurrentPoint);
const float Distance = FVector::Dist(InputPosition, CurrentPoint); for(const int32 CurrentIndex : PointIndices)
{
FVector CurrentPosition = MyDensityField->IndexToVoxelPosition(CurrentIndex);
const float Distance = FVector::Dist(InputPosition, CurrentPosition);
if (Distance < MinDistance) if (Distance < MinDistance)
{ {
MinDistance = Distance; MinDistance = Distance;
SeedIndex = i; SeedIndex = CurrentIndex;
}
} }
} }
if (SeedIndex != INDEX_NONE) if (SeedIndex != INDEX_NONE)
{ {
// Clear previous selection //const FVector WorldPos = MyPointCloud->PointCloudVisualizer->GetComponentTransform().TransformPosition(MyPointCloud->PositionVectors[SeedIndex]);
SelectedClusterIndices.Empty(); //DrawDebugSphere(World, WorldPos, 0.1f, 20, FColor::Green, false, 1, 0, 1.0f);
for (bool& Flag : MyPointCloud->SelectionFlags)
{
Flag = false;
}
//Expand selection from the seed //Expand selection from the seed
ExpandSelection(SeedIndex); ExpandSelection(SeedIndex);
for (int32 i = 0; i < SelectedClusterIndices.Num(); i++)
{
const int Index = SelectedClusterIndices[i];
MyPointCloud->SelectionFlags[Index] = true;
}
} }
} }
void UMagicWand::ExpandSelection(const int32 SeedIndex) void UMagicWand::ExpandSelection(const int32 SeedIndex)
{ {
TQueue<int32> ToProcess; TQueue<int32> ToProcess;
ToProcess.Enqueue(SeedIndex); ToProcess.Enqueue(SeedIndex);
SelectedClusterIndices.Add(SeedIndex); SelectedClusterIndices.Add(SeedIndex);
MyPointCloud->SelectionFlags[SeedIndex] = true; MyPointCloud->SelectionFlags[SeedIndex] = true;
while (!ToProcess.IsEmpty()) while (!ToProcess.IsEmpty())
{ {
int32 CurrentIndex; int32 CurrentQueuePointIndex;
ToProcess.Dequeue(CurrentIndex); ToProcess.Dequeue(CurrentQueuePointIndex);
FVector CurrentPoint = MyPointCloud->PositionVectors[CurrentIndex];
CurrentPoint = MyPointCloud->PointCloudVisualizer->GetComponentTransform().TransformPosition(CurrentPoint);
for (int32 i = 0; i < MyPointCloud->PositionVectors.Num(); i++) FVector CurrentQueuePointPosition = MyPointCloud->PositionVectors[CurrentQueuePointIndex];
{
if (!MyPointCloud->SelectionFlags[i])
{
FVector Point = MyPointCloud->PositionVectors[i];
Point = MyPointCloud->PointCloudVisualizer->GetComponentTransform().TransformPosition(Point);
if (FVector::Dist(CurrentPoint, Point) <= ProximityThreshold) const int32 CurrentVoxelQueueIndex = MyDensityField->WorldPositionToIndex(CurrentQueuePointPosition);
{
ToProcess.Enqueue(i);
SelectedClusterIndices.Add(i);
MyPointCloud->SelectionFlags[i] = true;
}
}
}
}
}
/*
TArray<int32> Neighbors = MyDensityField->IndexToVoxelNeighbors(CurrentVoxelQueueIndex);
Neighbors.Add(CurrentVoxelQueueIndex);
void UMagicWand::EraseParticles(const FVector& InputPosition) for (const int CurrentVoxelNeighborIndex : Neighbors)
{ {
TArray<int32> PointIndices = MyDensityField->VoxelPointLookupTable->GetPointsInVoxel(CurrentVoxelNeighborIndex);
} for(const int32 CurrentPointComparisonIndex : PointIndices)
void UMagicWand::HandleMetaSelectReleased(const FInputActionInstance& Instance)
{ {
Super::HandleMetaSelectReleased(Instance); if(MyPointCloud->SelectionFlags[CurrentPointComparisonIndex])
//ProceduralMesh->ClearAllMeshSections();
//ProceduralMesh->SetVisibility(false);
AsyncTask(ENamedThreads::Type::AnyBackgroundHiPriTask, [this]()
{ {
MyPointCloud->ColorPointsInVoxels(FloodedIndices); continue;
});
} }
FVector CurrentComparisonPosition = MyDensityField->IndexToVoxelPosition(CurrentPointComparisonIndex);
void UMagicWand::HandleMetaSelectPressed(const FInputActionInstance& Instance) if (FVector::Dist(CurrentQueuePointPosition, CurrentComparisonPosition) <= ProximityThreshold)
{ {
Super::HandleMetaSelectPressed(Instance); ToProcess.Enqueue(CurrentPointComparisonIndex);
SelectedClusterIndices.Add(CurrentPointComparisonIndex);
UE_LOG(LogTemp, Warning, TEXT("PerformMagicWandSelection")); MyPointCloud->SelectionFlags[CurrentPointComparisonIndex] = true;
InitMagicWandSelection(); }
} }
}*/
// -------------------
void UMagicWand::InitMagicWandSelection() const int32 StartX = FMath::Max(0, FMath::FloorToInt((CurrentQueuePointPosition.X - ProximityThreshold - MyPointCloud->MinBounds.X) / MyDensityField->GetStep().X));
{ const int32 EndX = FMath::Min(MyDensityField->GetXNum() - 1, FMath::FloorToInt((CurrentQueuePointPosition.X + ProximityThreshold - MyPointCloud->MinBounds.X) / MyDensityField->GetStep().X));
const FVector SelectionWorldPosition = SelectionObject->GetComponentLocation(); const int32 StartY = FMath::Max(0, FMath::FloorToInt((CurrentQueuePointPosition.Y - ProximityThreshold - MyPointCloud->MinBounds.Y) / MyDensityField->GetStep().Y));
MyDensityField = MyPointCloud->MyDensityField; const int32 EndY = FMath::Min(MyDensityField->GetYNum() - 1, FMath::FloorToInt((CurrentQueuePointPosition.Y + ProximityThreshold - MyPointCloud->MinBounds.Y) / MyDensityField->GetStep().Y));
const int32 StartZ = FMath::Max(0, FMath::FloorToInt((CurrentQueuePointPosition.Z - ProximityThreshold - MyPointCloud->MinBounds.Z) / MyDensityField->GetStep().Z));
const int32 EndZ = FMath::Min(MyDensityField->GetZNum() - 1, FMath::FloorToInt((CurrentQueuePointPosition.Z + ProximityThreshold - MyPointCloud->MinBounds.Z) / MyDensityField->GetStep().Z));
// 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);
ProceduralMesh->ClearAllMeshSections(); /*
World = GetWorld(); UE_LOG(LogTemp, Warning, TEXT("CurrentQueuePointPosition: %s"), *CurrentQueuePointPosition.ToString());
UE_LOG(LogTemp, Warning, TEXT("StartX: %d"), StartX);
UE_LOG(LogTemp, Warning, TEXT("EndX: %d"), EndX);
UE_LOG(LogTemp, Warning, TEXT("StartY: %d"), StartY);
UE_LOG(LogTemp, Warning, TEXT("EndY: %d"), EndY);
UE_LOG(LogTemp, Warning, TEXT("StartZ: %d"), StartZ);
UE_LOG(LogTemp, Warning, TEXT("EndZ: %d"), EndZ);*/
AbortMarchingCubes = true; ParallelFor(EndZ - StartZ + 1, [&](const int32 ZOffset) {
AccumulatedTime = 0.0f; const int32 Z = StartZ + ZOffset;
}
void UMagicWand::SelectParticles(const FVector& InputPosition) for (int32 Y = StartY; Y <= EndY; ++Y)
{ {
if (AccumulatedTime >= 1 / EvaluationsPerSecond) for (int32 X = StartX; X <= EndX; ++X)
{ {
AccumulatedTime = -10000; const int32 CurrentVoxelComparisonIndex = MyDensityField->GridPositionToIndex(X, Y, Z);
AsyncTask(ENamedThreads::AnyBackgroundThreadNormalTask, [this]() if(!MyDensityField->IsValidIndex(CurrentVoxelComparisonIndex))
{ {
const FVector SelectionWorldPosition = SelectionObject->GetComponentLocation(); continue;
}
TArray<int32> PointIndices = MyDensityField->VoxelPointLookupTable->GetPointsInVoxel(CurrentVoxelComparisonIndex);
for(const int32 CurrentPointComparisonIndex : PointIndices)
{
if(MyPointCloud->SelectionFlags[CurrentPointComparisonIndex])
{
continue;
}
FVector CurrentComparisonPosition = MyPointCloud->PositionVectors[CurrentPointComparisonIndex];
const double Distance = FVector::Distance(CurrentQueuePointPosition, CurrentComparisonPosition);
//UE_LOG(LogTemp, Warning, TEXT("CurrentQueuePointPosition: %s"), *CurrentQueuePointPosition.ToString());
//UE_LOG(LogTemp, Warning, TEXT("CurrentComparisonPosition: %s"), *CurrentComparisonPosition.ToString());
//UE_LOG(LogTemp, Warning, TEXT("Distance: %f"), Distance);
if (Distance <= ProximityThreshold)
{
ToProcess.Enqueue(CurrentPointComparisonIndex);
SelectedClusterIndices.Add(CurrentPointComparisonIndex);
MyPointCloud->SelectionFlags[CurrentPointComparisonIndex] = true;
}
}
}
}
}); });
} }
AccumulatedTime = 0;
} }
void UMagicWand::GenerateVoxelMeshWithCubes(const TArray<int32> Voxels) const void UMagicWand::GenerateVoxelMeshWithCubes(const TArray<int32> Voxels) const
......
...@@ -46,6 +46,7 @@ public: ...@@ -46,6 +46,7 @@ public:
virtual void HandleMetaSelectReleased(const FInputActionInstance& Instance) override; virtual void HandleMetaSelectReleased(const FInputActionInstance& Instance) override;
virtual void HandleMetaSelectPressed(const FInputActionInstance& Instance) override; virtual void HandleMetaSelectPressed(const FInputActionInstance& Instance) override;
virtual void HandleMetaEraseReleased(const FInputActionInstance& Instance) override;
void InitMagicWandSelection(); void InitMagicWandSelection();
void GenerateVoxelMeshWithCubes(const TArray<int32> Voxels) const; void GenerateVoxelMeshWithCubes(const TArray<int32> Voxels) const;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment