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;