diff --git a/Content/MagicWandMap.umap b/Content/MagicWandMap.umap index 432e39ca2127b23880bf35d2220201a73ca86de3..1db0e16a514f1f959cebb98ac2a2e703aacb7123 100644 Binary files a/Content/MagicWandMap.umap and b/Content/MagicWandMap.umap differ diff --git a/Source/MetaCastBachelor/MagicWand.cpp b/Source/MetaCastBachelor/MagicWand.cpp index 360602aa66886594847bc8a45cf18126066a2a36..85419994c0a810256f93296032dbcb11374cb068 100644 --- a/Source/MetaCastBachelor/MagicWand.cpp +++ b/Source/MetaCastBachelor/MagicWand.cpp @@ -39,91 +39,8 @@ void UMagicWand::TickComponent(float DeltaTime, ELevelTick TickType, FActorCompo AccumulatedTime += DeltaTime; ProceduralMesh->SetVisibility(Select); - - if (Select) - { - PerformMagicWandSelection(SelectionObject->GetComponentLocation()); - } } -void UMagicWand::PerformMagicWandSelection(const FVector& InputPosition) -{ - if (MyPointCloud->SelectionFlags.Num() != MyPointCloud->PositionVectors.Num()) - { - UE_LOG(LogTemp, Warning, TEXT("PerformMagicWandSelection: Positions and SelectionFlags array sizes do not match.")); - return; - } - - // Find the closest point to the input position as the seed - int32 SeedIndex = INDEX_NONE; - float MinDistance = FLT_MAX; - - for (int32 i = 0; i < MyPointCloud->PositionVectors.Num(); i++) - { - FVector CurrentPoint = MyPointCloud->PositionVectors[i]; - CurrentPoint = MyPointCloud->PointCloudVisualizer->GetComponentTransform().TransformPosition(CurrentPoint); - - const float Distance = FVector::Dist(InputPosition, CurrentPoint); - if (Distance < MinDistance) - { - MinDistance = Distance; - SeedIndex = i; - } - } - - if (SeedIndex != INDEX_NONE) - { - // Clear previous selection - SelectedClusterIndices.Empty(); - for (bool& Flag : MyPointCloud->SelectionFlags) - { - Flag = false; - } - - // Expand selection from the seed - 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) -{ - TQueue<int32> ToProcess; - ToProcess.Enqueue(SeedIndex); - SelectedClusterIndices.Add(SeedIndex); - MyPointCloud->SelectionFlags[SeedIndex] = true; - - while (!ToProcess.IsEmpty()) - { - int32 CurrentIndex; - ToProcess.Dequeue(CurrentIndex); - FVector CurrentPoint = MyPointCloud->PositionVectors[CurrentIndex]; - CurrentPoint = MyPointCloud->PointCloudVisualizer->GetComponentTransform().TransformPosition(CurrentPoint); - - for (int32 i = 0; i < MyPointCloud->PositionVectors.Num(); i++) - { - if (!MyPointCloud->SelectionFlags[i]) - { - FVector Point = MyPointCloud->PositionVectors[i]; - Point = MyPointCloud->PointCloudVisualizer->GetComponentTransform().TransformPosition(Point); - - if (FVector::Dist(CurrentPoint, Point) <= ProximityThreshold) - { - ToProcess.Enqueue(i); - SelectedClusterIndices.Add(i); - MyPointCloud->SelectionFlags[i] = true; - } - } - } - } -} - - void UMagicWand::EraseParticles(const FVector& InputPosition) { @@ -146,19 +63,27 @@ void UMagicWand::HandleMetaSelectReleased(const FInputActionInstance& Instance) void UMagicWand::HandleMetaSelectPressed(const FInputActionInstance& Instance) { Super::HandleMetaSelectPressed(Instance); - - UE_LOG(LogTemp, Warning, TEXT("PerformMagicWandSelection")); + 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 - const FVector SelectionLocalPosition = MyPointCloud->PointCloudVisualizer->GetComponentTransform().InverseTransformPosition(SelectionWorldPosition); - ProceduralMesh->ClearAllMeshSections(); World = GetWorld(); @@ -171,16 +96,171 @@ void UMagicWand::SelectParticles(const FVector& InputPosition) if (AccumulatedTime >= 1 / EvaluationsPerSecond) { AccumulatedTime = -10000; - - AsyncTask(ENamedThreads::AnyBackgroundThreadNormalTask, [this]() + + AsyncTask(ENamedThreads::Type::AnyBackgroundHiPriTask, [this]() { const FVector SelectionWorldPosition = SelectionObject->GetComponentLocation(); - - + const FVector SelectionLocalPosition = MyPointCloud->PointCloudVisualizer->GetComponentTransform().InverseTransformPosition(SelectionWorldPosition); + + PerformMagicWandSelection(SelectionLocalPosition); + + UE_LOG(LogTemp, Warning, TEXT("Calculations done!")); }); + } } +void UMagicWand::PerformMagicWandSelection(const FVector& InputPosition) +{ + if (MyPointCloud->SelectionFlags.Num() != MyPointCloud->PositionVectors.Num()) + { + UE_LOG(LogTemp, Warning, TEXT("PerformMagicWandSelection: Positions and SelectionFlags array sizes do not match.")); + return; + } + + //UE_LOG(LogTemp, Warning, TEXT("Looking for Seed Index:")); + // 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; + float MinDistance = FLT_MAX; + + for (const int CurrentNeighborIndex : Neighbors) + { + TArray<int32> PointIndices = MyDensityField->VoxelPointLookupTable->GetPointsInVoxel(CurrentNeighborIndex); + + for(const int32 CurrentIndex : PointIndices) + { + FVector CurrentPosition = MyDensityField->IndexToVoxelPosition(CurrentIndex); + const float Distance = FVector::Dist(InputPosition, CurrentPosition); + if (Distance < MinDistance) + { + MinDistance = Distance; + SeedIndex = CurrentIndex; + } + } + } + + if (SeedIndex != INDEX_NONE) + { + //const FVector WorldPos = MyPointCloud->PointCloudVisualizer->GetComponentTransform().TransformPosition(MyPointCloud->PositionVectors[SeedIndex]); + //DrawDebugSphere(World, WorldPos, 0.1f, 20, FColor::Green, false, 1, 0, 1.0f); + + //Expand selection from the seed + ExpandSelection(SeedIndex); + } + + +} + +void UMagicWand::ExpandSelection(const int32 SeedIndex) +{ + TQueue<int32> ToProcess; + ToProcess.Enqueue(SeedIndex); + + SelectedClusterIndices.Add(SeedIndex); + MyPointCloud->SelectionFlags[SeedIndex] = true; + + while (!ToProcess.IsEmpty()) + { + int32 CurrentQueuePointIndex; + ToProcess.Dequeue(CurrentQueuePointIndex); + + FVector CurrentQueuePointPosition = MyPointCloud->PositionVectors[CurrentQueuePointIndex]; + + const int32 CurrentVoxelQueueIndex = MyDensityField->WorldPositionToIndex(CurrentQueuePointPosition); + + /* + TArray<int32> Neighbors = MyDensityField->IndexToVoxelNeighbors(CurrentVoxelQueueIndex); + Neighbors.Add(CurrentVoxelQueueIndex); + + for (const int CurrentVoxelNeighborIndex : Neighbors) + { + TArray<int32> PointIndices = MyDensityField->VoxelPointLookupTable->GetPointsInVoxel(CurrentVoxelNeighborIndex); + + for(const int32 CurrentPointComparisonIndex : PointIndices) + { + if(MyPointCloud->SelectionFlags[CurrentPointComparisonIndex]) + { + continue; + } + FVector CurrentComparisonPosition = MyDensityField->IndexToVoxelPosition(CurrentPointComparisonIndex); + + if (FVector::Dist(CurrentQueuePointPosition, CurrentComparisonPosition) <= ProximityThreshold) + { + ToProcess.Enqueue(CurrentPointComparisonIndex); + SelectedClusterIndices.Add(CurrentPointComparisonIndex); + MyPointCloud->SelectionFlags[CurrentPointComparisonIndex] = true; + } + } + }*/ + // ------------------- + + 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 int32 StartY = FMath::Max(0, FMath::FloorToInt((CurrentQueuePointPosition.Y - ProximityThreshold - MyPointCloud->MinBounds.Y) / MyDensityField->GetStep().Y)); + 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)); + + + /* + 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);*/ + + ParallelFor(EndZ - StartZ + 1, [&](const int32 ZOffset) { + const int32 Z = StartZ + ZOffset; + + for (int32 Y = StartY; Y <= EndY; ++Y) + { + for (int32 X = StartX; X <= EndX; ++X) + { + const int32 CurrentVoxelComparisonIndex = MyDensityField->GridPositionToIndex(X, Y, Z); + + if(!MyDensityField->IsValidIndex(CurrentVoxelComparisonIndex)) + { + 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 { TArray<FVector> Vertices; diff --git a/Source/MetaCastBachelor/MagicWand.h b/Source/MetaCastBachelor/MagicWand.h index f20239e223f57bb4b4fa83fa02266b11195266b4..a59cde4361a78a9264d4b423cff265ffddc52c9b 100644 --- a/Source/MetaCastBachelor/MagicWand.h +++ b/Source/MetaCastBachelor/MagicWand.h @@ -46,6 +46,7 @@ public: virtual void HandleMetaSelectReleased(const FInputActionInstance& Instance) override; virtual void HandleMetaSelectPressed(const FInputActionInstance& Instance) override; + virtual void HandleMetaEraseReleased(const FInputActionInstance& Instance) override; void InitMagicWandSelection(); void GenerateVoxelMeshWithCubes(const TArray<int32> Voxels) const;