From 492eab0a00f40cbef2dc54b976ab0c8824ccd3ef Mon Sep 17 00:00:00 2001
From: Timon Roemer <t.roemer@vis.rwth-aachen.de>
Date: Mon, 22 Jul 2024 18:15:03 +0200
Subject: [PATCH] optimizes MagicWand by Paralellizing

---
 Content/MagicWandMap.umap                     | Bin 43681 -> 43795 bytes
 Source/MetaCastBachelor/MagicWand.cpp         | 540 ++++++++++--------
 Source/MetaCastBachelor/MagicWand.h           |  62 +-
 Source/MetaCastBachelor/MarchingCubes.compute | 449 +++++++++++++++
 Source/MetaCastBachelor/MetaCastBaseline.cpp  |  18 +-
 Source/MetaCastBachelor/MetaCastBaseline.h    |   1 +
 Source/MetaCastBachelor/PointCloud.cpp        |   2 +-
 7 files changed, 802 insertions(+), 270 deletions(-)
 create mode 100644 Source/MetaCastBachelor/MarchingCubes.compute

diff --git a/Content/MagicWandMap.umap b/Content/MagicWandMap.umap
index bd7492ae734fcd1e7e27825d4ae8845abe574fec..5abed2d8bc29ddf32c4cf888d4f03b16036d6e0a 100644
GIT binary patch
delta 14199
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
I<lI#z07(s*SO5S3

delta 13457
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
JlkcxG0RZ%CbU*+A

diff --git a/Source/MetaCastBachelor/MagicWand.cpp b/Source/MetaCastBachelor/MagicWand.cpp
index 4b2f64b..cda7616 100644
--- a/Source/MetaCastBachelor/MagicWand.cpp
+++ b/Source/MetaCastBachelor/MagicWand.cpp
@@ -1,26 +1,25 @@
 #include "MagicWand.h"
-
-#include "KdtreeBPLibrary.h"
 #include "Utilities.h"
 #include "Generators/MarchingCubes.h"
 
+//	INITIALIZATION
+
 UMagicWand::UMagicWand() : World(nullptr)
 {
 	// Create the procedural mesh component
 	ProceduralMesh = CreateDefaultSubobject<UProceduralMeshComponent>(TEXT("GeneratedMesh"));
-	SelectedClusterIndices.Reserve(100000);
 }
 
 void UMagicWand::BeginPlay()
 {
 	Super::BeginPlay();
 
-	World = GetWorld();
-	
-	if (!World) {
-		UE_LOG(LogTemp, Warning, TEXT("Invalid world provided."));
-	}
+	InitReferences();
+	InitProceduralMesh();
+}
 
+void UMagicWand::InitProceduralMesh() const
+{
 	ProceduralMesh->AttachToComponent(MyPointCloud->PointCloudVisualizer, FAttachmentTransformRules::SnapToTargetIncludingScale);
 	ProceduralMesh->SetMaterial(0, SelectionVolumeMat);
 	ProceduralMesh->SetMaterial(1, SelectionVolumeMat);
@@ -31,252 +30,30 @@ void UMagicWand::BeginPlay()
 	ProceduralMesh->SetCollisionEnabled(ECollisionEnabled::NoCollision);
 	ProceduralMesh->SetMobility(EComponentMobility::Movable);
 	ProceduralMesh->SetVisibility(true);
-
-}
-
-void UMagicWand::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
-{
-	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
-
-	AccumulatedTime += DeltaTime;
-
-	ProceduralMesh->SetVisibility(Select);
 }
 
-void UMagicWand::EraseParticles(const FVector& InputPosition)
+void UMagicWand::InitReferences()
 {
-	
-}
-
-void UMagicWand::HandleMetaSelectReleased(const FInputActionInstance& Instance)
-{
-	Super::HandleMetaSelectReleased(Instance);
-
-	//ProceduralMesh->ClearAllMeshSections();
-	//ProceduralMesh->SetVisibility(false);
-
-
-	AsyncTask(ENamedThreads::Type::AnyBackgroundHiPriTask, [this]()
+	if (!MyPointCloud || !MyPointCloud->MyDensityField) {
+		UE_LOG(LogTemp, Error, TEXT("Invalid Point Cloud or DensityField provided!"));
+	}else
 	{
-		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;
+		MyDensityField = MyPointCloud->MyDensityField;
 	}
-}
-
-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;
-
-		UE_LOG(LogTemp, Warning, TEXT("Input recognized!"));
-		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!"));
-		});
-		
+	if (!World) {
+		UE_LOG(LogTemp, Error, TEXT("Invalid world provided."));
 	}
 }
 
-void UMagicWand::PerformMagicWandSelection(const FVector& InputPosition)
+void UMagicWand::EraseParticles(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("Starting Selection!"));
-
-	//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(int NeighborDistance = 0; NeighborDistance < 3; ++NeighborDistance)
-	{
-		const int NumNeighbors = Neighbors.Num();
-
-		for (int i = 0; i < NumNeighbors; ++i)
-		{
-			const int CurrentNeighborIndex = Neighbors[i];
-			TArray<int32> NeighborsOfNeighbors = MyDensityField->IndexToVoxelNeighbors(CurrentNeighborIndex);
-
-			for (int CurrentNeighborOfNeighborIndex : NeighborsOfNeighbors)
-			{
-				if (!Neighbors.Contains(CurrentNeighborOfNeighborIndex))
-				{
-					Neighbors.Add(CurrentNeighborOfNeighborIndex);
-				}
-			}
-		}
-	}
 	
-    
-	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);
-    }else
-    {
-	    AccumulatedTime = 0;
-    }
 }
 
-void UMagicWand::ExpandSelection(const int32 SeedIndex)
-{
-	UE_LOG(LogTemp, Warning, TEXT("Expanding!"));
-    TQueue<int32> ToProcess;
-    ToProcess.Enqueue(SeedIndex);
-	
-    SelectedClusterIndices.Add(SeedIndex);
-    MyPointCloud->SelectionFlags[SeedIndex] = true;
-
-	const float SquaredProximityThreshold = ProximityThreshold * ProximityThreshold;
-	TArray<int> Indices;
-	TArray<FVector> Data;
-	
-    while (!ToProcess.IsEmpty())
-    {
-        int32 CurrentQueuePointIndex;
-        ToProcess.Dequeue(CurrentQueuePointIndex);
-
-        const FVector CurrentQueuePointPosition = MyPointCloud->PositionVectors[CurrentQueuePointIndex];
-
-    	Indices.Empty();
-    	Data.Empty();
-    	
-    	UKdtreeBPLibrary::CollectFromKdtree(MyPointCloud->MyKdTree, CurrentQueuePointPosition, MyPointCloud->InfluenceRadius, Indices, Data);
-
-		for(int i = 0; i < Indices.Num(); ++i)
-		{
-			const int CurrentPointComparisonIndex = Indices[i];
-			
-			if(MyPointCloud->SelectionFlags[CurrentPointComparisonIndex])
-			{
-				continue;
-			}
-			
-			ToProcess.Enqueue(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);
-
-    	for (int32 Z = StartZ; Z <= EndZ; ++Z)
-    	{			
-    		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 SquaredDistance = FVector::DistSquared(CurrentQueuePointPosition, CurrentComparisonPosition);
-
-						if (SquaredDistance <= SquaredProximityThreshold)
-						{
-							ToProcess.Enqueue(CurrentPointComparisonIndex);
-							//SelectedClusterIndices.Add(CurrentPointComparisonIndex);
-							MyPointCloud->SelectionFlags[CurrentPointComparisonIndex] = true;
-						}
-					}
-				}
-			}
-		}*/
-    }
-
-	UE_LOG(LogTemp, Warning, TEXT("Calculations done!"));
-	AccumulatedTime = 0;
-}
+//	VISUALIZATION
 
 void UMagicWand::GenerateVoxelMeshWithCubes(const TArray<int32> Voxels) const
 {
@@ -405,8 +182,289 @@ void UMagicWand::GenerateVoxelMeshSmooth(const TArray<int32> Voxels)
 			FScopeLock MeshLock(&ProceduralMeshGuard);
 			ProceduralMesh->CreateMeshSection(0, Vertices, Indices, Normals, TArray<FVector2D>(), VertexColors, TArray<FProcMeshTangent>(), false);
 			ProceduralMesh->SetVisibility(true);
-			AccumulatedTime = 0.0f;
+			AccumulatedTime.Store(0);
 			IsMarchingCubesRunning = false;
 		});
 	});
+}
+
+//	INPUT HANDLING
+
+void UMagicWand::HandleMetaSelectReleased(const FInputActionInstance& Instance)
+{
+	Super::HandleMetaSelectReleased(Instance);
+
+	const FVector SelectionWorldPosition = SelectionObject->GetComponentLocation();
+	const FVector SelectionLocalPosition = MyPointCloud->PointCloudVisualizer->GetComponentTransform().InverseTransformPosition(SelectionWorldPosition);
+
+	ProximityThreshold =  FMath::Clamp(FVector::Dist(SelectionStartPosition, SelectionLocalPosition) / 10, 0.1, 10);
+
+	InitMagicWandSelection();
+
+	AsyncTask(ENamedThreads::Type::AnyBackgroundHiPriTask, [this, &SelectionLocalPosition]()
+	{
+		PerformMagicWandSelection(SelectionStartPosition);
+	});
+}
+
+void UMagicWand::HandleMetaSelectPressed(const FInputActionInstance& Instance)
+{
+	Super::HandleMetaSelectPressed(Instance);
+	
+	const FVector SelectionWorldPosition = SelectionObject->GetComponentLocation();
+	SelectionStartPosition = MyPointCloud->PointCloudVisualizer->GetComponentTransform().InverseTransformPosition(SelectionWorldPosition);
+}
+
+void UMagicWand::HandleMetaEraseReleased(const FInputActionInstance& Instance)
+{
+	Super::HandleMetaEraseReleased(Instance);
+	
+	FScopeLock Lock(&ThreadNumberLock);
+	AbortMagicWand.Store(true);
+
+	//deselect all particles
+	for (int32 i = 0; i < MyPointCloud->SelectionFlags.Num(); ++i)
+	{
+		MyPointCloud->SelectionFlags[i] = false;
+	}
+}
+
+//	MAGIC WAND SELECTION
+
+void UMagicWand::InitMagicWandSelection()
+{	
+	ProceduralMesh->ClearAllMeshSections();
+	AbortMarchingCubes = true;
+	if(AccumulatedTime.Load() >= 0) AccumulatedTime.Store(1 / EvaluationsPerSecond);
+	AbortMagicWand.Store(false);
+}
+
+void UMagicWand::PerformMagicWandSelection(const FVector& InputPosition)
+{
+	if (MyPointCloud->SelectionFlags.Num() != MyPointCloud->PositionVectors.Num())
+	{
+		UE_LOG(LogTemp, Error, TEXT("PerformMagicWandSelection: Positions and SelectionFlags array sizes do not match."));
+		return;
+	}
+
+	//UE_LOG(LogTemp, Warning, TEXT("Starting MagicWand Selection!"));
+
+	// Find the closest point to the input position as the seed
+	int32 SeedIndex;
+	const int32 InputVoxelIndex = MyDensityField->WorldPositionToIndex(InputPosition);
+	FindSeedIndex(InputPosition, InputVoxelIndex, SeedIndex);
+
+	if (SeedIndex != INDEX_NONE)
+	{
+		ExpandSelectionFromPointIndex(SeedIndex);
+	}else
+	{
+		AccumulatedTime.Store( 0);
+	}
+}
+
+void UMagicWand::FindSeedIndex(const FVector& InputPosition, const int32 InputVoxelIndex, int32& SeedIndex) const
+{
+	TArray<int32> Neighbors = MyDensityField->IndexToVoxelNeighbors(InputVoxelIndex);
+	Neighbors.Add(InputVoxelIndex);
+
+	SeedIndex = INDEX_NONE;
+	float MinDistance = FLT_MAX;
+	
+	for(int NeighborDistance = 0; NeighborDistance < 4; ++NeighborDistance)
+	{
+		const int NumNeighbors = Neighbors.Num();
+
+		for (int i = 0; i < NumNeighbors; ++i)
+		{
+			const int CurrentNeighborIndex = Neighbors[i];
+			TArray<int32> NeighborsOfNeighbors = MyDensityField->IndexToVoxelNeighbors(CurrentNeighborIndex);
+
+			for (int CurrentNeighborOfNeighborIndex : NeighborsOfNeighbors)
+			{
+				if (!Neighbors.Contains(CurrentNeighborOfNeighborIndex))
+				{
+					Neighbors.Add(CurrentNeighborOfNeighborIndex);
+				}
+			}
+		}
+	}
+	
+    
+	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;
+			}
+		}
+	}
+}
+
+void UMagicWand::ExpandSelectionFromPointIndex(const int32 SeedIndex)
+{
+	{
+		FScopeLock Lock(&ThreadNumberLock);
+		NumberThreads.Increment();
+	}
+	
+	TQueue<int32>* ProcessQueue = new TQueue<int32>{};
+	ProcessQueue->Enqueue(SeedIndex);
+	MyPointCloud->SelectionFlags[SeedIndex] = true;
+
+	const float SquaredProximityThreshold = ProximityThreshold * ProximityThreshold;
+	int NumberToProcess = 0;
+	
+	while (!ProcessQueue->IsEmpty() && !AbortMagicWand.Load())
+	{
+		if(NumberToProcess > 1000 && NumberThreads.GetValue() < MaxThreadCount) CreateNewExpansionThread(ProcessQueue, NumberToProcess);
+
+		int32 CurrentQueuePointIndex;
+		ProcessQueue->Dequeue(CurrentQueuePointIndex);
+		const FVector CurrentQueuePointPosition = MyPointCloud->PositionVectors[CurrentQueuePointIndex];
+    	
+		ExpandThroughNeighborsInRange(ProcessQueue, SquaredProximityThreshold, NumberToProcess, CurrentQueuePointPosition);
+		NumberToProcess--;
+	}
+	
+	AbortSelection();
+}
+
+void UMagicWand::ExpandSelectionFromPointIndexQueue(TQueue<int32>* ProcessQueue)
+{
+	{
+		FScopeLock Lock(&ThreadNumberLock);
+		NumberThreads.Increment();
+	}
+	//UE_LOG(LogTemp, Warning, TEXT("Opened New Thread! Number of Threads now: %d"), NumberThreads.GetValue());
+	const float SquaredProximityThreshold = ProximityThreshold * ProximityThreshold;
+	int NumberToProcess = 0;
+	
+	while (!ProcessQueue->IsEmpty() && !AbortMagicWand.Load())
+	{    	
+		if(NumberToProcess > 1000  && NumberThreads.GetValue() < MaxThreadCount) CreateNewExpansionThread(ProcessQueue, NumberToProcess);
+
+		int32 CurrentQueuePointIndex;
+		ProcessQueue->Dequeue(CurrentQueuePointIndex);
+		const FVector CurrentQueuePointPosition = MyPointCloud->PositionVectors[CurrentQueuePointIndex];
+
+		ExpandThroughNeighborsInRange(ProcessQueue, SquaredProximityThreshold, NumberToProcess, CurrentQueuePointPosition);
+		NumberToProcess--;
+	}
+	
+	AbortSelection();
+}
+
+void UMagicWand::ExpandThroughNeighborsInRange(TQueue<int32>* ProcessQueue, const float SquaredProximityThreshold, int& NumberToProcess, const FVector& CurrentQueuePointPosition) const
+{
+	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));
+    	
+	for (int32 Z = StartZ; Z <= EndZ; ++Z)
+	{			
+		for (int32 Y = StartY; Y <= EndY; ++Y)
+		{
+			for (int32 X = StartX; X <= EndX; ++X)
+			{
+				if(AbortMagicWand.Load()) return;
+				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 SquaredDistance = FVector::DistSquared(CurrentQueuePointPosition, CurrentComparisonPosition);
+
+					if (SquaredDistance <= SquaredProximityThreshold)
+					{
+						ProcessQueue->Enqueue(CurrentPointComparisonIndex);
+						NumberToProcess++;
+							
+						if(AbortMagicWand.Load()) return;
+							
+						MyPointCloud->SelectionFlags[CurrentPointComparisonIndex] = true;
+					}
+				}
+			}
+		}
+	}
+}
+
+void UMagicWand::AbortSelection()
+{
+	NumberThreads.Decrement();
+		
+	//UE_LOG(LogTemp, Warning, TEXT("Thread Closed! Number of Threads now: %d"), NumberThreads.GetValue());
+	if(NumberThreads.GetValue() == 0)
+	{
+		AccumulatedTime.Store(0);
+		//AbortMagicWand.Store(false);
+		//UE_LOG(LogTemp, Warning, TEXT("Aborted!"));
+	}else if(NumberThreads.GetValue() < 0)
+	{
+		UE_LOG(LogTemp, Error, TEXT("More Threads closed than opened!"));
+	}
+}
+
+void UMagicWand::CreateNewExpansionThread(TQueue<int32>* ProcessQueue, int& NumberToProcess)
+{
+	TQueue<int32>* TempQueue = new TQueue<int32>{};
+	const int NumberRemove = NumberToProcess / 2;
+			
+	for(int i = 0; i < NumberRemove; ++i)
+	{
+		int32 CurrentQueuePointIndex;
+		ProcessQueue->Dequeue(CurrentQueuePointIndex);
+		NumberToProcess--;
+		TempQueue->Enqueue(CurrentQueuePointIndex);
+	}
+
+	AsyncTask(ENamedThreads::Type::AnyBackgroundHiPriTask, [this, TempQueue]()
+	{
+		ExpandSelectionFromPointIndexQueue(TempQueue);
+	});
+}
+
+//	TICK
+
+void UMagicWand::TickComponent(const float DeltaTime, const ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
+{
+	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
+
+	/*
+	AccumulatedTime.Store(AccumulatedTime.Load() + DeltaTime);
+	ProceduralMesh->SetVisibility(Select);*/
+}
+
+void UMagicWand::SelectParticles(const FVector& InputPosition)
+{
+	if (AccumulatedTime.Load() >=  1 / EvaluationsPerSecond)
+	{
+		AccumulatedTime.Store(FLT_MIN);
+	}
+
+	const FVector SelectionWorldPosition = SelectionObject->GetComponentLocation();
+	DrawDebugLine(World, SelectionWorldPosition, MyPointCloud->PointCloudVisualizer->GetComponentTransform().TransformPosition(SelectionStartPosition), FColor::Red, false, 0, 0, 0.1f);
 }
\ No newline at end of file
diff --git a/Source/MetaCastBachelor/MagicWand.h b/Source/MetaCastBachelor/MagicWand.h
index e84de2e..0037e3b 100644
--- a/Source/MetaCastBachelor/MagicWand.h
+++ b/Source/MetaCastBachelor/MagicWand.h
@@ -1,59 +1,79 @@
-
 #pragma once
 
 #include "CoreMinimal.h"
 #include "ProceduralMeshComponent.h"
 #include "MetaCastBaseline.h"
 #include "Generators/MarchingCubes.h"
+#include "Templates/Atomic.h"
 #include "MagicWand.generated.h"
 
 UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
 class UMagicWand : public UMetaCastBaseline
 {
 	GENERATED_BODY()
-	
+
+	//	INTERNAL
+
+	TAtomic<bool> AbortMagicWand = false;
 	FDensityField* MyDensityField;
-	UPROPERTY()
-	UWorld* World;
 	bool IsMarchingCubesRunning = false;
 	bool AbortMarchingCubes = false;
-
-	// Critical section to protect shared variables
+	FThreadSafeCounter NumberThreads = 0;
 	mutable FCriticalSection ProceduralMeshGuard;
-
+	mutable FCriticalSection ThreadNumberLock;
 	UPROPERTY()
 	UProceduralMeshComponent* ProceduralMesh;
-	UPROPERTY(EditAnywhere)
-	UMaterialInterface* SelectionVolumeMat;
-	TArray<int32> FloodedIndices;
+	UPROPERTY()
+	UWorld* World;
+	TAtomic<float> AccumulatedTime = 0.0;
+	FVector SelectionStartPosition;
+	
+	//	USER EXPORTED
+
 	UPROPERTY(EditAnywhere)
 	float MarchingCubeSize = 0;
 	UPROPERTY(EditAnywhere)
 	int EvaluationsPerSecond = 10;
 	UPROPERTY(EditAnywhere)
-	float AccumulatedTime = 0.0;
-	UPROPERTY(EditAnywhere)
 	float ProximityThreshold = 0.1f;
-	TArray<int32> SelectedClusterIndices;
-
+	UPROPERTY(EditAnywhere)
+	UMaterialInterface* SelectionVolumeMat;
+	UPROPERTY(EditAnywhere)
+	int MaxThreadCount = 100;
 	
 public:
-	UMagicWand();
+	//	INITIALIZATION
 	
+	UMagicWand();
 	virtual void BeginPlay() override;
-		
-	virtual void SelectParticles(const FVector& InputPosition) override;
-	virtual void EraseParticles(const FVector& InputPosition) override;
+	void InitReferences();
+	void InitProceduralMesh() const;
 
+	//	INPUT HANDLING
+	
 	virtual void HandleMetaSelectReleased(const FInputActionInstance& Instance) override;
 	virtual void HandleMetaSelectPressed(const FInputActionInstance& Instance) override;
 	virtual void HandleMetaEraseReleased(const FInputActionInstance& Instance) override;
-	void InitMagicWandSelection();
+	virtual void EraseParticles(const FVector& InputPosition) override;
 
+	//	VISUALIZATION
+	
 	void GenerateVoxelMeshWithCubes(const TArray<int32> Voxels) const;
 	void GenerateVoxelMeshSmooth(const TArray<int32> Voxels);
 
-	virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
+	//	MAGIC WAND SELECTION
+
+	void InitMagicWandSelection();
+	void FindSeedIndex(const FVector& InputPosition, int32 InputVoxelIndex, int32& SeedIndex) const;
 	void PerformMagicWandSelection(const FVector& InputPosition);
-	void ExpandSelection(int32 SeedIndex);
+	void ExpandSelectionFromPointIndex(int32 SeedIndex);
+	void ExpandSelectionFromPointIndexQueue(TQueue<int32>* ProcessQueue);
+	void ExpandThroughNeighborsInRange(TQueue<int32>* ProcessQueue, const float SquaredProximityThreshold, int& NumberToProcess, const FVector& CurrentQueuePointPosition) const;
+	void AbortSelection();
+	void CreateNewExpansionThread(TQueue<int32>* ProcessQueue, int& NumberToProcess);
+
+	//	TICK
+	
+	virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
+	virtual void SelectParticles(const FVector& InputPosition) override;
 };
\ No newline at end of file
diff --git a/Source/MetaCastBachelor/MarchingCubes.compute b/Source/MetaCastBachelor/MarchingCubes.compute
new file mode 100644
index 0000000..01628e5
--- /dev/null
+++ b/Source/MetaCastBachelor/MarchingCubes.compute
@@ -0,0 +1,449 @@
+//The following code is modified from "unity-marching-cubes-gpu" by Pavel Kouřil. Original at: "https://github.com/pavelkouril/unity-marching-cubes-gpu"
+
+/**
+ * Lookup tables and algorithm taken from "Polygonising a scalar field" by Paul Bourke
+ *
+ * Original at: http://paulbourke.net/geometry/polygonise/
+ */
+
+#pragma kernel MarchingCubes
+Texture3D<float4> _posTexture;
+Texture3D<float4> _densityTexture;
+Texture3D<float4> _mcFlagTexture;
+float _isoLevel;
+int _gridSize;
+
+struct Vertex
+{
+	float3 vPosition;
+	float3 vNormal;
+};
+
+struct Triangle
+{
+	Vertex v[3];
+};
+
+AppendStructuredBuffer<Triangle> triangleRW;
+
+SamplerState myLinearClampSampler;
+
+static const int edgeTable[256] = {
+	0x0  , 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c,
+	0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00,
+	0x190, 0x99 , 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c,
+	0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90,
+	0x230, 0x339, 0x33 , 0x13a, 0x636, 0x73f, 0x435, 0x53c,
+	0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30,
+	0x3a0, 0x2a9, 0x1a3, 0xaa , 0x7a6, 0x6af, 0x5a5, 0x4ac,
+	0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0,
+	0x460, 0x569, 0x663, 0x76a, 0x66 , 0x16f, 0x265, 0x36c,
+	0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60,
+	0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff , 0x3f5, 0x2fc,
+	0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0,
+	0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55 , 0x15c,
+	0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950,
+	0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc ,
+	0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0,
+	0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc,
+	0xcc , 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0,
+	0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c,
+	0x15c, 0x55 , 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650,
+	0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc,
+	0x2fc, 0x3f5, 0xff , 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0,
+	0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c,
+	0x36c, 0x265, 0x16f, 0x66 , 0x76a, 0x663, 0x569, 0x460,
+	0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac,
+	0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa , 0x1a3, 0x2a9, 0x3a0,
+	0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c,
+	0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33 , 0x339, 0x230,
+	0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c,
+	0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99 , 0x190,
+	0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c,
+	0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0 };
+
+static const int triTable[256][16] =
+{ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1 },
+{ 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1 },
+{ 3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1 },
+{ 3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1 },
+{ 9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1 },
+{ 1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1 },
+{ 9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1 },
+{ 2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1 },
+{ 8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1 },
+{ 9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1 },
+{ 4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1 },
+{ 3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1 },
+{ 1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1 },
+{ 4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1 },
+{ 4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1 },
+{ 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1 },
+{ 1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1 },
+{ 5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1 },
+{ 2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1 },
+{ 9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1 },
+{ 0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1 },
+{ 2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1 },
+{ 10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1 },
+{ 4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1 },
+{ 5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1 },
+{ 5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1 },
+{ 9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1 },
+{ 0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1 },
+{ 1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1 },
+{ 10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1 },
+{ 8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1 },
+{ 2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1 },
+{ 7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1 },
+{ 9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1 },
+{ 2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1 },
+{ 11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1 },
+{ 9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1 },
+{ 5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1 },
+{ 11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1 },
+{ 11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1 },
+{ 1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1 },
+{ 9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1 },
+{ 5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1 },
+{ 2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1 },
+{ 0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1 },
+{ 5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1 },
+{ 6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1 },
+{ 0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1 },
+{ 3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1 },
+{ 6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1 },
+{ 5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1 },
+{ 1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1 },
+{ 10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1 },
+{ 6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1 },
+{ 1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1 },
+{ 8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1 },
+{ 7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1 },
+{ 3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1 },
+{ 5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1 },
+{ 0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1 },
+{ 9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1 },
+{ 8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1 },
+{ 5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1 },
+{ 0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1 },
+{ 6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1 },
+{ 10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1 },
+{ 10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1 },
+{ 8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1 },
+{ 1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1 },
+{ 3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1 },
+{ 0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1 },
+{ 10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1 },
+{ 0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1 },
+{ 3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1 },
+{ 6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1 },
+{ 9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1 },
+{ 8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1 },
+{ 3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1 },
+{ 6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1 },
+{ 0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1 },
+{ 10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1 },
+{ 10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1 },
+{ 1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1 },
+{ 2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1 },
+{ 7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1 },
+{ 7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1 },
+{ 2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1 },
+{ 1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1 },
+{ 11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1 },
+{ 8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1 },
+{ 0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1 },
+{ 7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1 },
+{ 10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1 },
+{ 2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1 },
+{ 6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1 },
+{ 7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1 },
+{ 2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1 },
+{ 1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1 },
+{ 10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1 },
+{ 10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1 },
+{ 0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1 },
+{ 7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1 },
+{ 6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1 },
+{ 8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1 },
+{ 9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1 },
+{ 6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1 },
+{ 1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1 },
+{ 4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1 },
+{ 10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1 },
+{ 8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1 },
+{ 0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1 },
+{ 1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1 },
+{ 8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1 },
+{ 10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1 },
+{ 4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1 },
+{ 10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1 },
+{ 5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1 },
+{ 11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1 },
+{ 9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1 },
+{ 6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1 },
+{ 7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1 },
+{ 3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1 },
+{ 7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1 },
+{ 9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1 },
+{ 3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1 },
+{ 6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1 },
+{ 9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1 },
+{ 1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1 },
+{ 4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1 },
+{ 7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1 },
+{ 6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1 },
+{ 3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1 },
+{ 0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1 },
+{ 6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1 },
+{ 1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1 },
+{ 0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1 },
+{ 11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1 },
+{ 6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1 },
+{ 5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1 },
+{ 9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1 },
+{ 1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1 },
+{ 1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1 },
+{ 10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1 },
+{ 0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1 },
+{ 5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1 },
+{ 10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1 },
+{ 11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1 },
+{ 0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1 },
+{ 9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1 },
+{ 7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1 },
+{ 2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1 },
+{ 8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1 },
+{ 9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1 },
+{ 9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1 },
+{ 1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1 },
+{ 9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1 },
+{ 9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1 },
+{ 5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1 },
+{ 0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1 },
+{ 10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1 },
+{ 2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1 },
+{ 0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1 },
+{ 0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1 },
+{ 9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1 },
+{ 5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1 },
+{ 3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1 },
+{ 5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1 },
+{ 8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1 },
+{ 0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1 },
+{ 9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1 },
+{ 0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1 },
+{ 1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1 },
+{ 3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1 },
+{ 4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1 },
+{ 9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1 },
+{ 11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1 },
+{ 11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1 },
+{ 2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1 },
+{ 9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1 },
+{ 3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1 },
+{ 1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1 },
+{ 4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1 },
+{ 4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1 },
+{ 0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1 },
+{ 3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1 },
+{ 3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1 },
+{ 0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1 },
+{ 9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1 },
+{ 1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ 0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } };
+
+float SampleData(int3 pos) {       // read the val data from the texture
+	return _densityTexture.Load(int4(pos, 0)).x;
+}
+
+float3 SamplePosData(int3 pos) {       // read the pos data from the texture
+	return float3(_posTexture.Load(int4(pos, 0)).x, _posTexture.Load(int4(pos, 0)).y, _posTexture.Load(int4(pos, 0)).z);
+}
+float SampleFlagData(int3 pos) {       // read the pos data from the texture
+	return _mcFlagTexture.Load(int4(pos, 0)).x;
+}
+float SampleLinear(float3 p)
+{
+	// need to mitigate the offset in p[x], so +float3(0.5) to be in [0;1] range
+	return _densityTexture.SampleLevel(myLinearClampSampler, p + float3(0.5, 0.5, 0.5), 0).x;
+}
+
+float3 VertexInterp(float3 p1, float3 p2, float valp1, float valp2)
+{
+	return lerp(p1, p2, (_isoLevel - valp1) / (valp2 - valp1));
+}
+
+float3 CalculateGradient(float3 p)
+{
+	float ratio = 1.0 / (_gridSize );
+
+	return float3(
+		SampleLinear(p - float3(1.0, 0.0, 0.0) * ratio)
+		- SampleLinear(p + float3(1.0, 0.0, 0.0) * ratio),
+
+		SampleLinear(p - float3(0.0, 1.0, 0.0) * ratio)
+		- SampleLinear(p + float3(0.0, 1.0, 0.0) * ratio),
+
+		SampleLinear(p - float3(0.0, 0.0, 1.0) * ratio)
+		- SampleLinear(p + float3(0.0, 0.0, 1.0) * ratio)
+		);
+}
+
+[numthreads(8, 8, 8)]
+void MarchingCubes(uint3 threadId : SV_DispatchThreadID)
+{
+	if (SampleFlagData(threadId) == 0)
+		return;
+
+	float3 p[8] = {
+	    SamplePosData(threadId + int3(0, 0, 1)),
+		SamplePosData(threadId + int3(1, 0, 1)),
+		SamplePosData(threadId + int3(1, 0, 0)),
+		SamplePosData(threadId + int3(0, 0, 0)),
+		SamplePosData(threadId + int3(0, 1, 1)),
+		SamplePosData(threadId + int3(1, 1, 1)),
+		SamplePosData(threadId + int3(1, 1, 0)),
+		SamplePosData(threadId + int3(0, 1, 0))
+	};
+
+	float val[8] = {
+		SampleData(threadId + int3(0, 0, 1)),
+		SampleData(threadId + int3(1, 0, 1)),
+		SampleData(threadId + int3(1, 0, 0)),
+		SampleData(threadId + int3(0, 0, 0)),
+		SampleData(threadId + int3(0, 1, 1)),
+		SampleData(threadId + int3(1, 1, 1)),
+		SampleData(threadId + int3(1, 1, 0)),
+		SampleData(threadId + int3(0, 1, 0))
+	};
+
+	int cubeIndex = 0;
+	if (val[0] < _isoLevel) cubeIndex |= 1;
+	if (val[1] < _isoLevel) cubeIndex |= 2;
+	if (val[2] < _isoLevel) cubeIndex |= 4;
+	if (val[3] < _isoLevel) cubeIndex |= 8;
+	if (val[4] < _isoLevel) cubeIndex |= 16;
+	if (val[5] < _isoLevel) cubeIndex |= 32;
+	if (val[6] < _isoLevel) cubeIndex |= 64;
+	if (val[7] < _isoLevel) cubeIndex |= 128;
+
+	float3 vertlist[12];
+
+	if (edgeTable[cubeIndex] != 0)
+	{
+		if (edgeTable[cubeIndex] & 1)
+			vertlist[0] = VertexInterp(p[0], p[1], val[0], val[1]);
+		if (edgeTable[cubeIndex] & 2)
+			vertlist[1] = VertexInterp(p[1], p[2], val[1], val[2]);
+		if (edgeTable[cubeIndex] & 4)
+			vertlist[2] = VertexInterp(p[2], p[3], val[2], val[3]);
+		if (edgeTable[cubeIndex] & 8)
+			vertlist[3] = VertexInterp(p[3], p[0], val[3], val[0]);
+		if (edgeTable[cubeIndex] & 16)
+			vertlist[4] = VertexInterp(p[4], p[5], val[4], val[5]);
+		if (edgeTable[cubeIndex] & 32)
+			vertlist[5] = VertexInterp(p[5], p[6], val[5], val[6]);
+		if (edgeTable[cubeIndex] & 64)
+			vertlist[6] = VertexInterp(p[6], p[7], val[6], val[7]);
+		if (edgeTable[cubeIndex] & 128)
+			vertlist[7] = VertexInterp(p[7], p[4], val[7], val[4]);
+		if (edgeTable[cubeIndex] & 256)
+			vertlist[8] = VertexInterp(p[0], p[4], val[0], val[4]);
+		if (edgeTable[cubeIndex] & 512)
+			vertlist[9] = VertexInterp(p[1], p[5], val[1], val[5]);
+		if (edgeTable[cubeIndex] & 1024)
+			vertlist[10] = VertexInterp(p[2], p[6], val[2], val[6]);
+		if (edgeTable[cubeIndex] & 2048)
+			vertlist[11] = VertexInterp(p[3], p[7], val[3], val[7]);
+
+		for (int i = 0; triTable[cubeIndex][i] != -1; i += 3) {
+			Triangle t;
+
+			Vertex v0;
+			Vertex v1;
+			Vertex v2;
+
+			v0.vPosition = vertlist[triTable[cubeIndex][i]];
+			v1.vPosition = vertlist[triTable[cubeIndex][i + 1]];
+			v2.vPosition = vertlist[triTable[cubeIndex][i + 2]];
+
+			v0.vNormal = normalize(CalculateGradient(v0.vPosition));
+			v1.vNormal = normalize(CalculateGradient(v1.vPosition));
+			v2.vNormal = normalize(CalculateGradient(v2.vPosition));
+
+			t.v[0] = v0;
+			t.v[1] = v1;
+			t.v[2] = v2;
+
+			triangleRW.Append(t);
+		}
+	}
+}
\ No newline at end of file
diff --git a/Source/MetaCastBachelor/MetaCastBaseline.cpp b/Source/MetaCastBachelor/MetaCastBaseline.cpp
index f6bd224..6485e9d 100644
--- a/Source/MetaCastBachelor/MetaCastBaseline.cpp
+++ b/Source/MetaCastBachelor/MetaCastBaseline.cpp
@@ -10,6 +10,16 @@ UMetaCastBaseline::UMetaCastBaseline() :
 	PrimaryComponentTick.bCanEverTick = true;
 }
 
+void UMetaCastBaseline::InitLeftHand()
+{
+	//check if left hand is assigned otherwise assign it to self
+	if(!LeftHandComponent)
+	{
+		UE_LOG(LogTemp, Warning, TEXT("Left Hand not assigned. Please assign in Blueprint => Defaulting to self"));
+		LeftHandComponent = this;
+	}
+}
+
 // Called when the game starts
 void UMetaCastBaseline::BeginPlay()
 {
@@ -18,13 +28,7 @@ void UMetaCastBaseline::BeginPlay()
 	InitPointCloudReference();
 	InitInputBindings();
 	InitSelectionObject();
-
-	//check if left hand is assigned otherwise assign it to self
-	if(!LeftHandComponent)
-	{
-		UE_LOG(LogTemp, Warning, TEXT("Left Hand not assigned. Please assign in Blueprint => Defaulting to self"));
-		LeftHandComponent = this;
-	}
+	InitLeftHand();
 }
 
 void UMetaCastBaseline::InitPointCloudReference()
diff --git a/Source/MetaCastBachelor/MetaCastBaseline.h b/Source/MetaCastBachelor/MetaCastBaseline.h
index 5b3f4bd..c27aa36 100644
--- a/Source/MetaCastBachelor/MetaCastBaseline.h
+++ b/Source/MetaCastBachelor/MetaCastBaseline.h
@@ -60,6 +60,7 @@ public:
 		
 	// Sets default values for this component's properties
 	UMetaCastBaseline();
+	void InitLeftHand();
 	void InitInputBindings();
 	virtual void HandleMetaSelectPressed(const FInputActionInstance& Instance);
 	virtual void HandleMetaErasePressed(const FInputActionInstance& Instance);
diff --git a/Source/MetaCastBachelor/PointCloud.cpp b/Source/MetaCastBachelor/PointCloud.cpp
index a5f6813..284d3f9 100644
--- a/Source/MetaCastBachelor/PointCloud.cpp
+++ b/Source/MetaCastBachelor/PointCloud.cpp
@@ -91,7 +91,7 @@ void APointCloud::SetupDensityFieldFromPointCloud() const
 {
 	UE_LOG(LogTemp, Log, TEXT("Initializing DensityField!"));
 
-	const FIntVector AxisNumbers(100, 100, 100);
+	const FIntVector AxisNumbers(200, 200, 200);
 	MyDensityField->InitializeDensityField(this, MinBounds, MaxBounds, AxisNumbers);
 }
 
-- 
GitLab