diff --git a/Config/DefaultEngine.ini b/Config/DefaultEngine.ini
index f503eeba46be6f93f74b2f4f3a170f855e94b174..19b59fc6679ce83857ad5936b684a8ae7cbf3c46 100644
--- a/Config/DefaultEngine.ini
+++ b/Config/DefaultEngine.ini
@@ -122,8 +122,10 @@ r.DynamicGlobalIlluminationMethod = 1
 r.ReflectionMethod = 1
 
 r.Shadow.Virtual.Enable = 1
-r.Mobile.AntiAliasing=0
-r.AntiAliasingMethod=0
+r.Mobile.AntiAliasing=3
+r.AntiAliasingMethod=3
+vr.InstancedStereo=True
+r.MobileHDR=True
 
 [/Script/HardwareTargeting.HardwareTargetingSettings]
 TargetedHardwareClass = Mobile
diff --git a/Content/MetaPointMap.umap b/Content/MetaPointMap.umap
index 29279ebda45e68b55a53493d3d7ba85a1c563b49..add3f06500b1b576fa486e1ede28b8e2d591a298 100644
Binary files a/Content/MetaPointMap.umap and b/Content/MetaPointMap.umap differ
diff --git a/Content/MetaPointMap_BuiltData.uasset b/Content/MetaPointMap_BuiltData.uasset
index c34cc92efe7ae452c7cc0e5fc0848b52ea42c079..1bf02fa1814c30bc66b1c21252e01906ddb1ac28 100644
Binary files a/Content/MetaPointMap_BuiltData.uasset and b/Content/MetaPointMap_BuiltData.uasset differ
diff --git a/Source/MetaCastBachelor/DensityField.cpp b/Source/MetaCastBachelor/DensityField.cpp
index 803b67d0d04332c0d5c5a566f7e73a5fde764536..0cfcdc980f62fdcada431c3185338949ad7cb496 100644
--- a/Source/MetaCastBachelor/DensityField.cpp
+++ b/Source/MetaCastBachelor/DensityField.cpp
@@ -7,12 +7,12 @@
 
 FDensityField::FDensityField(): XNum(0), YNum(0), ZNum(0), XStep(0), YStep(0), ZStep(0)
 {
-	GridNodes = TArray<FVoxel>();
+	VoxelList = TArray<FVoxel>();
 }
 
 void FDensityField::InitializeDensityField(const FVector& MinBounds, const FVector& MaxBounds, const int32 XAxisNum, const int32 YAxisNum, const int32 ZAxisNum)
 {
-	GridNodes.Empty();
+	VoxelList.Empty();
 
 	XStep = (MaxBounds.X - MinBounds.X) / (XAxisNum - 1);
 	YStep = (MaxBounds.Y - MinBounds.Y) / (YAxisNum - 1);
@@ -26,7 +26,7 @@ void FDensityField::InitializeDensityField(const FVector& MinBounds, const FVect
 			{
 				FVector Position(MinBounds.X + X * XStep, MinBounds.Y + Y * YStep, MinBounds.Z + Z * ZStep);
 				FVector GridPosition(X, Y, Z);
-				GridNodes.Add(FVoxel(Position, GridPosition));
+				VoxelList.Add(FVoxel(Position, GridPosition));
 			}
 		}
 	}
@@ -46,10 +46,10 @@ void FDensityField::CalculateVoxelDensities(const APointCloud* PointCloud, const
 	UE_LOG(LogTemp, Log, TEXT("Starting density calculation."));
 
 	// Clear existing densities and counts
-	for (auto& Node : GridNodes)
+	for (auto& Node : VoxelList)
 	{
-	    Node.SetNodeDensity(0.0);
-	    Node.SetEnclosedParticleNum(0.0);  // Reset the counter
+	    Node.SetVoxelDensity(0.0);
+	    Node.SetClosePointsNumber(0.0);  // Reset the counter
 	}
 
 	UE_LOG(LogTemp, Log, TEXT("Cleared previous densities."));
@@ -70,17 +70,17 @@ void FDensityField::CalculateVoxelDensities(const APointCloud* PointCloud, const
 	        {
 	            for (int32 X = StartX; X <= EndX; ++X)
 	            {
-	                const int32 Index = GridPositionToIndex(Z, Y, X);
-	                if (Index >= 0 && Index < GridNodes.Num())
+	                const int32 Index = GridPositionToIndex(X, Y, Z);
+	                if (Index >= 0 && Index < VoxelList.Num())
 	                {
-	                    FVector NodePosition = GridNodes[Index].GetNodePosition();
+	                    FVector NodePosition = VoxelList[Index].GetVoxelPosition();
 	                    const float Distance = FVector::Dist(NodePosition, ParticlePosition);
 
 	                    if (Distance < InfluenceRadius)
 	                    {
 	                        const double Weight = FUtilities::GaussianKernel(Distance, Sigma);
-	                        GridNodes[Index].NodeDensityPlusDis(Weight);
-	                        GridNodes[Index].SetEnclosedParticleNum(GridNodes[Index].GetEnclosedParticleNum() + 1.0);
+	                        VoxelList[Index].AddToVoxelDensity(Weight);
+	                        VoxelList[Index].SetClosePointsNumber(VoxelList[Index].GetClosePointsNumber() + 1.0);
 	                    }
 	                }
 	            }
@@ -88,11 +88,11 @@ void FDensityField::CalculateVoxelDensities(const APointCloud* PointCloud, const
 	    }
 	}
 	double MaxDensity = 0.0;
-	for (const auto& Node : GridNodes)
+	for (const auto& Node : VoxelList)
 	{
-		if (Node.GetNodeDensity() > MaxDensity)
+		if (Node.GetVoxelDensity() > MaxDensity)
 		{
-			MaxDensity = Node.GetNodeDensity();
+			MaxDensity = Node.GetVoxelDensity();
 		}
 	}
 	UE_LOG(LogTemp, Log, TEXT("Maximum density found: %f"), MaxDensity);	
@@ -114,17 +114,17 @@ void FDensityField::CalculateAndStoreGradients()
 		{
 			for (int32 X = 0; X < XNum; X++)
 			{
-				const int32 Index = GridPositionToIndex(Z, Y, X);
-				if (!GridNodes.IsValidIndex(Index))
+				const int32 Index = GridPositionToIndex(X, Y, Z);
+				if (!VoxelList.IsValidIndex(Index))
 					continue;
 
 				// Use one-sided differences at the boundaries
-				const double DensityX1 = X < XNum - 1 ? GridNodes[GridPositionToIndex(Z, Y, X + 1)].GetNodeDensity() : GridNodes[Index].GetNodeDensity();
-				const double DensityX0 = X > 0 ? GridNodes[GridPositionToIndex(Z, Y, X - 1)].GetNodeDensity() : GridNodes[Index].GetNodeDensity();
-				const double DensityY1 = Y < YNum - 1 ? GridNodes[GridPositionToIndex(Z, Y + 1, X)].GetNodeDensity() : GridNodes[Index].GetNodeDensity();
-				const double DensityY0 = Y > 0 ? GridNodes[GridPositionToIndex(Z, Y - 1, X)].GetNodeDensity() : GridNodes[Index].GetNodeDensity();
-				const double DensityZ1 = Z < ZNum - 1 ? GridNodes[GridPositionToIndex(Z + 1, Y, X)].GetNodeDensity() : GridNodes[Index].GetNodeDensity();
-				const double DensityZ0 = Z > 0 ? GridNodes[GridPositionToIndex(Z - 1, Y, X)].GetNodeDensity() : GridNodes[Index].GetNodeDensity();
+				const double DensityX1 = X < XNum - 1 ? VoxelList[GridPositionToIndex(X + 1, Y, Z)].GetVoxelDensity() : VoxelList[Index].GetVoxelDensity();
+				const double DensityX0 = X > 0 ? VoxelList[GridPositionToIndex(X - 1, Y, Z)].GetVoxelDensity() : VoxelList[Index].GetVoxelDensity();
+				const double DensityY1 = Y < YNum - 1 ? VoxelList[GridPositionToIndex(X, Y + 1, Z)].GetVoxelDensity() : VoxelList[Index].GetVoxelDensity();
+				const double DensityY0 = Y > 0 ? VoxelList[GridPositionToIndex(X, Y - 1, Z)].GetVoxelDensity() : VoxelList[Index].GetVoxelDensity();
+				const double DensityZ1 = Z < ZNum - 1 ? VoxelList[GridPositionToIndex(X, Y, Z + 1)].GetVoxelDensity() : VoxelList[Index].GetVoxelDensity();
+				const double DensityZ0 = Z > 0 ? VoxelList[GridPositionToIndex(X, Y, Z - 1)].GetVoxelDensity() : VoxelList[Index].GetVoxelDensity();
 
 				FVector Gradient(
 					(DensityX1 - DensityX0) / (X == 0 || X == XNum - 1 ? XStep : 2 * XStep),
@@ -132,7 +132,7 @@ void FDensityField::CalculateAndStoreGradients()
 					(DensityZ1 - DensityZ0) / (Z == 0 || Z == ZNum - 1 ? ZStep : 2 * ZStep)
 				);
 
-				GridNodes[Index].SetNodeGradient(Gradient);
+				VoxelList[Index].SetVoxelGradient(Gradient);
 			}
 		}
 	}
@@ -151,18 +151,18 @@ void FDensityField::DrawDebugVoxelDensity(const UWorld* World, const AActor* Act
 	}
 
 	double MinDensity = DBL_MAX, MaxDensity = 0;
-	for (const FVoxel& Node : GridNodes)
+	for (const FVoxel& Node : VoxelList)
 	{
-		const double LogDensity = log10(Node.GetNodeDensity() + 1);  // Avoiding log(0)
+		const double LogDensity = log10(Node.GetVoxelDensity() + 1);  // Avoiding log(0)
 		if (LogDensity < MinDensity) MinDensity = LogDensity;
 		if (LogDensity > MaxDensity) MaxDensity = LogDensity;
 	}
 
 	const FTransform ActorTransform = Actor->GetActorTransform();
 
-	for (const FVoxel& Node : GridNodes)
+	for (const FVoxel& Node : VoxelList)
 	{
-		const double Density = Node.GetNodeDensity();
+		const double Density = Node.GetVoxelDensity();
 
 		const double LogDensity = log10(Density + 1);  // Normalize using logarithmic scale
 		const float NormalizedDensity = static_cast<float>((LogDensity - MinDensity) / (MaxDensity - MinDensity));
@@ -172,7 +172,7 @@ void FDensityField::DrawDebugVoxelDensity(const UWorld* World, const AActor* Act
 			FLinearColor VoxelColor = FLinearColor::LerpUsingHSV(FLinearColor::Green, FLinearColor::Red, NormalizedDensity);
 
 			FVector VoxelSize = FVector(Scale * XStep, Scale * YStep, Scale * ZStep) / 2.0f;
-			FVector WorldPosition = ActorTransform.TransformPosition(Node.GetNodePosition());
+			FVector WorldPosition = ActorTransform.TransformPosition(Node.GetVoxelPosition());
 			FVector ScaledVoxelSize = ActorTransform.TransformVector(VoxelSize);
 
 			DrawDebugBox(World, WorldPosition, 0.95 * ScaledVoxelSize, VoxelColor.ToFColor(true), false, Duration, 0, 0.1f);
@@ -185,30 +185,22 @@ void FDensityField::DrawDebugVoxelDensity(const UWorld* World, const AActor* Act
 
 //	CONVERSION FUNCTIONS
 
-int32 FDensityField::GridPositionToIndex(const int32 Z, const int32 Y, const int32 X) const
+int32 FDensityField::GridPositionToIndex(const int32 X, const int32 Y, const int32 Z) const
 {
     return Z * XNum * YNum + Y * XNum + X;
 }
 
-int32 FDensityField::WorldPositionToIndex(const FVector &Position, const APointCloud * PointCloud) const {
-	if (!PointCloud) {
-		UE_LOG(LogTemp, Warning, TEXT("PointCloud is null, cannot convert position to box index."));
-		return -1;
-	}
-
+int32 FDensityField::WorldPositionToIndex(const FVector &Position) const {
 	// Convert world position to grid position
-	FVector GridPosition = WorldToGridPosition(Position);
+	const FVector GridPosition = WorldToGridPosition(Position);
 
 	// Check if the grid position is valid
-	if (GridPosition.X < 0 || GridPosition.Y < 0 || GridPosition.Z < 0) {
+	if (!IsValidGridPosition(GridPosition.X, GridPosition.Y, GridPosition.Z)) {
 		UE_LOG(LogTemp, Warning, TEXT("Position out of grid bounds or invalid grid settings, cannot find box index."));
 		return -1;  // Grid position was invalid
 	}
 
-	// Calculate the linear index from grid position
-	const int32 Index = static_cast<int32>(GridPosition.Z) * XNum * YNum + static_cast<int32>(GridPosition.Y) * XNum + static_cast<int32>(GridPosition.X);
-
-	return Index;
+	return GridPositionToIndex(GridPosition.X, GridPosition.Y, GridPosition.Z);
 }
 
 FVector FDensityField::WorldToGridPosition(const FVector& Position) const
@@ -220,9 +212,9 @@ FVector FDensityField::WorldToGridPosition(const FVector& Position) const
 	}
 
 	// Calculate the grid coordinates by subtracting the grid origin and dividing by the grid step sizes
-	int32 GridX = static_cast<int32>((Position.X - GridOrigin.X) / XStep);
-	int32 GridY = static_cast<int32>((Position.Y - GridOrigin.Y) / YStep);
-	int32 GridZ = static_cast<int32>((Position.Z - GridOrigin.Z) / ZStep);
+	const int32 GridX = FMath::FloorToInt((Position.X - GridOrigin.X) / XStep);
+	const int32 GridY = FMath::FloorToInt((Position.Y - GridOrigin.Y) / YStep);
+	const int32 GridZ = FMath::FloorToInt((Position.Z - GridOrigin.Z) / ZStep);
 
 	// Check if the calculated grid coordinates are within the bounds
 	if (GridX < 0 || GridX >= XNum || GridY < 0 || GridY >= YNum || GridZ < 0 || GridZ >= ZNum)
@@ -234,7 +226,7 @@ FVector FDensityField::WorldToGridPosition(const FVector& Position) const
 	return FVector(GridX, GridY, GridZ);
 }
 
-bool FDensityField::IsValidIndex(const int32 XBin, const int32 YBin, const int32 ZBin) const
+bool FDensityField::IsValidGridPosition(const int32 XBin, const int32 YBin, const int32 ZBin) const
 {
 	// Check if the provided indices are within the grid bounds
 	return (XBin >= 0 && XBin < XNum) &&
@@ -242,103 +234,99 @@ bool FDensityField::IsValidIndex(const int32 XBin, const int32 YBin, const int32
 		   (ZBin >= 0 && ZBin < ZNum);
 }
 
-
-//	GETTER AND SETTER FUNCTIONS
-
-FVector FDensityField::GetGridOrigin() const
+FVector FDensityField::IndexToVoxelGradient(const int32 Index) const
 {
-	return GridOrigin;
+	if (VoxelList.IsValidIndex(Index))
+	{
+		return VoxelList[Index].GetVoxelGradient();
+	}
+	return FVector::ZeroVector;
 }
 
-FVector FDensityField::GetNodeGradient(const int32 Index) const
+FVector FDensityField::IndexToVoxelPosition(const int32 Index) const
 {
-    if (GridNodes.IsValidIndex(Index))
-    {
-        return GridNodes[Index].GetNodeGradient();
-    }
-    return FVector::ZeroVector;
+	if (VoxelList.IsValidIndex(Index))
+	{
+		return VoxelList[Index].GetVoxelPosition();
+	}
+	return -FVector::One();
 }
 
-FVector FDensityField::GetNodePosition(const int32 Index) const
+FVector FDensityField::IndexToGridPosition(const int32 Index) const
 {
-    if (GridNodes.IsValidIndex(Index))
-    {
-        return GridNodes[Index].GetNodePosition();
-    }
-    return FVector::ZeroVector;
+	if (IsValidIndex(Index))
+	{
+		return VoxelList[Index].GetVoxelGridPos();
+	}
+	return -FVector::One();
 }
 
-FVector FDensityField::GetNodeGridPos(const int32 Index) const
+
+//	GETTER AND SETTER FUNCTIONS
+
+FVector FDensityField::GetGridOrigin() const
 {
-    if (GridNodes.IsValidIndex(Index))
-    {
-        return GridNodes[Index].GetNodeGridPos();
-    }
-    return FVector::ZeroVector;
+	return GridOrigin;
 }
 
-double FDensityField::GetNodeDensity(const int32 Index) const
+double FDensityField::GetVoxelDensityFromIndex(const int32 Index) const
 {
-    if (GridNodes.IsValidIndex(Index))
+    if (VoxelList.IsValidIndex(Index))
     {
-        return GridNodes[Index].GetNodeDensity();
+        return VoxelList[Index].GetVoxelDensity();
     }
     return 0.0;
 }
 
-int32 FDensityField::GetNodeNum() const
+int32 FDensityField::GetVoxelNumber() const
 {
-    return GridNodes.Num();
+    return VoxelList.Num();
 }
 
-void FDensityField::SetNodeDensity(const int32 Index, const double Density)
+void FDensityField::SetVoxelDensity(const int32 Index, const double Density)
 {
-    if (GridNodes.IsValidIndex(Index))
+    if (VoxelList.IsValidIndex(Index))
     {
-        GridNodes[Index].SetNodeDensity(Density);
+        VoxelList[Index].SetVoxelDensity(Density);
     }
 }
 
-void FDensityField::SetNodeGradient(const int32 Index, const FVector& Gradient)
+void FDensityField::SetVoxelGradient(const int32 Index, const FVector& Gradient)
 {
-    if (GridNodes.IsValidIndex(Index))
+    if (VoxelList.IsValidIndex(Index))
     {
-        GridNodes[Index].SetNodeGradient(Gradient);
+        VoxelList[Index].SetVoxelGradient(Gradient);
     }
 }
 
-double FDensityField::GetDensity(const int32 XBin, const int32 YBin, const int32 ZBin) const
+double FDensityField::GetVoxelDensityFromGridPosition(const int32 XBin, const int32 YBin, const int32 ZBin) const
 {
 	// First, check if the provided indices are valid
-	if (IsValidIndex(XBin, YBin, ZBin))
+	if (IsValidGridPosition(XBin, YBin, ZBin))
 	{
 		// Convert 3D grid coordinates to a linear index
-		const int32 Index = GridPositionToIndex(ZBin, YBin, XBin);
+		const int32 Index = GridPositionToIndex(XBin, YBin, ZBin);
 		
-		// Ensure the index is within the valid range
-		if (GridNodes.IsValidIndex(Index))
-		{
-			// Return the density at the calculated index
-			return GridNodes[Index].GetNodeDensity();
-		}
+		return GetVoxelDensityFromIndex(Index);
 	}
+	
 	// Return 0 if the indices are out of bounds or the index is invalid
 	return 0.0;
 }
 
-FVector FDensityField::GetGradient(const int32 XBin, const int32 YBin, const int32 ZBin) const
+FVector FDensityField::GetVoxelGradientFromGridPosition(const int32 XBin, const int32 YBin, const int32 ZBin) const
 {
 	// First, check if the provided indices are valid
-	if (IsValidIndex(XBin, YBin, ZBin))
+	if (IsValidGridPosition(XBin, YBin, ZBin))
 	{
 		// Convert 3D grid coordinates to a linear index
-		const int32 Index = GridPositionToIndex(ZBin, YBin, XBin);
+		const int32 Index = GridPositionToIndex(XBin, YBin, ZBin);
 		
 		// Ensure the index is within the valid range
-		if (GridNodes.IsValidIndex(Index))
+		if (VoxelList.IsValidIndex(Index))
 		{
 			// Return the gradient at the calculated index
-			return GridNodes[Index].GetNodeGradient();
+			return VoxelList[Index].GetVoxelGradient();
 		}
 	}
 	// Return 0 if the indices are out of bounds or the index is invalid
@@ -362,13 +350,45 @@ int32 FDensityField::GetZNum() const {
 	return ZNum;
 }
 
-bool FDensityField::IsValidPosition(const FVector& Position) const
+bool FDensityField::IsValidWorldPosition(const FVector& Position) const
 {
 	// Convert the world position to grid coordinates
 	const FVector GridPosition = WorldToGridPosition(Position);
 
 	// Check if the grid position is within the valid bounds
-	return (GridPosition.X >= 0 && GridPosition.X < XNum) &&
-		   (GridPosition.Y >= 0 && GridPosition.Y < YNum) &&
-		   (GridPosition.Z >= 0 && GridPosition.Z < ZNum);
+	return IsValidGridPosition(GridPosition.X, GridPosition.Y, GridPosition.Z);
+}
+
+TArray<int32> FDensityField::GetNeighborsFromIndex(const int32 Index) const
+{
+	TArray<int32> Neighbors;
+	if (VoxelList.IsValidIndex(Index))
+	{
+		const int32 X = VoxelList[Index].GetVoxelGridPos().X;
+		const int32 Y = VoxelList[Index].GetVoxelGridPos().Y;
+		const int32 Z = VoxelList[Index].GetVoxelGridPos().Z;
+
+		// List all potential neighbors
+		TArray<FIntVector> PotentialNeighbors = {
+			FIntVector(X+1, Y, Z), FIntVector(X-1, Y, Z),
+			FIntVector(X, Y+1, Z), FIntVector(X, Y-1, Z),
+			FIntVector(X, Y, Z+1), FIntVector(X, Y, Z-1)
+		};
+
+		for (const FIntVector& NeighborPos : PotentialNeighbors)
+		{
+			if (NeighborPos.X >= 0 && NeighborPos.X < XNum &&
+				NeighborPos.Y >= 0 && NeighborPos.Y < YNum &&
+				NeighborPos.Z >= 0 && NeighborPos.Z < ZNum)
+			{
+				int NeighborIndex = GridPositionToIndex(NeighborPos.Z, NeighborPos.Y, NeighborPos.Z);
+				Neighbors.Add(NeighborIndex);
+			}
+		}
+	}
+	return Neighbors;
+}
+
+bool FDensityField::IsValidIndex(const int32 Index) const {
+	return VoxelList.IsValidIndex(Index);
 }
diff --git a/Source/MetaCastBachelor/DensityField.h b/Source/MetaCastBachelor/DensityField.h
index 79fb38d84bc6c4f8018f960ddeb196297faf2e2a..3e71da479c4f0d9aac7150ba865f808cf39928f1 100644
--- a/Source/MetaCastBachelor/DensityField.h
+++ b/Source/MetaCastBachelor/DensityField.h
@@ -15,22 +15,22 @@ private:
 	FVector GridPosition;
     double VoxelDensity;
     FVector VoxelGradient;
-	double EnclosedParticleNumber;
+	double ClosePointsNumber;
 
 public:
-    FVoxel() : WorldPosition(FVector::ZeroVector), GridPosition(FVector::ZeroVector), VoxelDensity(0.0), VoxelGradient(FVector::ZeroVector), EnclosedParticleNumber(0.0) {}
-    FVoxel(const FVector &InPosition, const FVector &InGridPos) : WorldPosition(InPosition), GridPosition(InGridPos), VoxelDensity(0.0), VoxelGradient(FVector::ZeroVector), EnclosedParticleNumber(0.0) {}
+    FVoxel() : WorldPosition(FVector::ZeroVector), GridPosition(FVector::ZeroVector), VoxelDensity(0.0), VoxelGradient(FVector::ZeroVector), ClosePointsNumber(0.0) {}
+    FVoxel(const FVector &InPosition, const FVector &InGridPos) : WorldPosition(InPosition), GridPosition(InGridPos), VoxelDensity(0.0), VoxelGradient(FVector::ZeroVector), ClosePointsNumber(0.0) {}
 	
-    double GetNodeDensity() const { return VoxelDensity; }
-	FVector GetNodeGridPos() const { return GridPosition; }
-    FVector GetNodePosition() const { return WorldPosition; }
-    FVector GetNodeGradient() const { return VoxelGradient; }
-	double GetEnclosedParticleNum() const { return EnclosedParticleNumber; }
+    double GetVoxelDensity() const { return VoxelDensity; }
+	FVector GetVoxelGridPos() const { return GridPosition; }
+    FVector GetVoxelPosition() const { return WorldPosition; }
+    FVector GetVoxelGradient() const { return VoxelGradient; }
+	double GetClosePointsNumber() const { return ClosePointsNumber; }
 	
-	void SetNodeDensity(const double Density) { this->VoxelDensity = Density; }
-    void SetNodeGradient(const FVector &Gradient) { this->VoxelGradient = Gradient; }
-	void SetEnclosedParticleNum(const double Dis) { EnclosedParticleNumber = Dis; }
-    void NodeDensityPlusDis(const double Dis) { VoxelDensity += Dis; }
+	void SetVoxelDensity(const double Density) { this->VoxelDensity = Density; }
+    void SetVoxelGradient(const FVector &Gradient) { this->VoxelGradient = Gradient; }
+	void SetClosePointsNumber(const double Dis) { ClosePointsNumber = Dis; }
+    void AddToVoxelDensity(const double Dis) { VoxelDensity += Dis; }
 };
 
 USTRUCT(BlueprintType)
@@ -54,7 +54,7 @@ struct FLUTUnit
 class FDensityField
 {
 	//	VARIABLES
-    TArray<FVoxel> GridNodes;
+    TArray<FVoxel> VoxelList;
     int32 XNum, YNum, ZNum;
     float XStep, YStep, ZStep;
 	FVector GridOrigin;
@@ -72,27 +72,27 @@ public:
     void DrawDebugVoxelDensity(const UWorld* World, const AActor* Actor, float Duration, float Scale, float DensityThreshold) const;
 
 	// CONVERSION FUNCTIONS
-	int32 WorldPositionToIndex(const FVector &Position, const APointCloud * PointCloud) const;
+	int32 WorldPositionToIndex(const FVector& Position) const;
 	FVector WorldToGridPosition(const FVector& Position) const;
-	bool IsValidIndex(int32 XBin, int32 YBin, int32 ZBin) const;
-	int32 GridPositionToIndex(int32 Z, int32 Y, int32 X) const;
+	bool IsValidGridPosition(int32 XBin, int32 YBin, int32 ZBin) const;
+	int32 GridPositionToIndex(int32 X, int32 Y, int32 Z) const;
 	
 	// GETTER AND SETTER FUNCTIONS
 	FVector GetGridOrigin() const;
-    FVector GetNodeGradient(int32 Index) const;
-    FVector GetNodePosition(int32 Index) const;
-    FVector GetNodeGridPos(int32 Index) const;
-	int32 GetNodeNum() const;
-    double GetNodeDensity(int32 Index) const;
-	double GetDensity(int32 XBin, int32 YBin, int32 ZBin) const;
-	FVector GetGradient(int32 XBin, int32 YBin, int32 ZBin) const;
+    FVector IndexToVoxelGradient(int32 Index) const;
+    FVector IndexToVoxelPosition(int32 Index) const;
+    FVector IndexToGridPosition(int32 Index) const;
+	int32 GetVoxelNumber() const;
+    double GetVoxelDensityFromIndex(int32 Index) const;
+	double GetVoxelDensityFromGridPosition(int32 XBin, int32 YBin, int32 ZBin) const;
+	FVector GetVoxelGradientFromGridPosition(int32 XBin, int32 YBin, int32 ZBin) const;
 	FVector GetStep() const;
 	int32 GetXNum() const;
 	int32 GetYNum() const;
 	int32 GetZNum() const;
-	bool IsValidPosition(const FVector& Position) const;
-
-
-	void SetNodeDensity(int32 Index, double Density);
-    void SetNodeGradient(int32 Index, const FVector& Gradient);
+	bool IsValidWorldPosition(const FVector& Position) const;
+	TArray<int32> GetNeighborsFromIndex(const int32 Index) const;
+	bool IsValidIndex(int32 Index) const;
+	void SetVoxelDensity(int32 Index, double Density);
+    void SetVoxelGradient(int32 Index, const FVector& Gradient);
 };
diff --git a/Source/MetaCastBachelor/MetaCastBaseline.cpp b/Source/MetaCastBachelor/MetaCastBaseline.cpp
index 7c3873630f136695c7c1781739d81a6420e1bd33..7d19389ca4d2712b00351abeee29e81d02e0d1d3 100644
--- a/Source/MetaCastBachelor/MetaCastBaseline.cpp
+++ b/Source/MetaCastBachelor/MetaCastBaseline.cpp
@@ -130,14 +130,12 @@ void UMetaCastBaseline::AttachToHand(const float DeltaTime) const
 	if (MyPointCloud && LeftHandComponent)
 	{
 		// Get the target position and rotation from the hand component, applying the offset
-		FVector TargetPosition = LeftHandComponent->GetComponentLocation() + PositionOffset;
-		FRotator TargetRotation = LeftHandComponent->GetComponentRotation() + RotationOffset;
+		const FVector TargetPosition = LeftHandComponent->GetComponentLocation() + PositionOffset;
+		const FRotator TargetRotation = LeftHandComponent->GetComponentRotation() + RotationOffset;
 
 		// Smoothly lerp the point cloud's position and rotation to the target values
-		FVector NewPosition =
-			FMath::VInterpTo(MyPointCloud->GetActorLocation(), TargetPosition, DeltaTime, PositionLerpSpeed);
-		FRotator NewRotation =
-			FMath::RInterpTo(MyPointCloud->GetActorRotation(), TargetRotation, DeltaTime, RotationLerpSpeed);
+		const FVector NewPosition = FMath::VInterpTo(MyPointCloud->GetActorLocation(), TargetPosition, DeltaTime, PositionLerpSpeed);
+		const FRotator NewRotation = FMath::RInterpTo(MyPointCloud->GetActorRotation(), TargetRotation, DeltaTime, RotationLerpSpeed);
 
 		// Apply the new position and rotation to the point cloud
 		MyPointCloud->SetActorLocation(NewPosition);
@@ -146,8 +144,7 @@ void UMetaCastBaseline::AttachToHand(const float DeltaTime) const
 }
 
 // Called every frame
-void UMetaCastBaseline::TickComponent(const float DeltaTime, const ELevelTick TickType,
-                                      FActorComponentTickFunction* ThisTickFunction)
+void UMetaCastBaseline::TickComponent(const float DeltaTime, const ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
 {
 	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
 
diff --git a/Source/MetaCastBachelor/MetaPoint.cpp b/Source/MetaCastBachelor/MetaPoint.cpp
index 1235280b564aa19a316c11bad99ad7adae6d9d64..2e920d0f027e3aac7dc5e336b74444c611bdf2d4 100644
--- a/Source/MetaCastBachelor/MetaPoint.cpp
+++ b/Source/MetaCastBachelor/MetaPoint.cpp
@@ -1,8 +1,8 @@
 #include "MetaPoint.h"
-#include "MaterialDomain.h"
 #include "Utilities.h"
 
-UMetaPoint::UMetaPoint() : MyProceduralMesh(nullptr) {
+UMetaPoint::UMetaPoint() : Index(0), MyDensityField(nullptr), Threshold(0), MyProceduralMesh(nullptr)
+{
 	// Initialize the Marching Cubes algorithm
 	MyMarchingCubes = new MarchingCubes();
 }
@@ -12,10 +12,7 @@ void UMetaPoint::BeginPlay()
 	Super::BeginPlay();
 }
 
-void UMetaPoint::SelectParticles(const FVector& InputPosition)
-{
 
-}
 
 void UMetaPoint::EraseParticles(const FVector& InputPosition)
 {
@@ -36,7 +33,7 @@ void UMetaPoint::HandleMetaSelectPressed(const FInputActionInstance& Instance)
 
 
 // Method to perform gradient ascent to find the local maximum density starting from a given position.
-void UMetaPoint::FindAndMarkLocalMaximum() const
+void UMetaPoint::FindAndMarkLocalMaximum()
 {
 	const UWorld* World = GetWorld();
 	
@@ -48,19 +45,46 @@ void UMetaPoint::FindAndMarkLocalMaximum() const
 	const FVector WorldPosition = SelectionObject->GetComponentLocation();
 	UE_LOG(LogTemp, Log, TEXT("World Position: %s"), *WorldPosition.ToString());
 
+	MyDensityField = MyPointCloud->MyDensityField;
+
 	// Convert the world position of the selection object to the local position relative to the point cloud
-	const FVector StartPosition = MyPointCloud->GetTransform().InverseTransformPosition(WorldPosition);
+	const FVector StartPosition = MyPointCloud->PointCloudVisualizer->GetComponentTransform().InverseTransformPosition(WorldPosition);
 
 	// Perform gradient ascent to find the local maximum starting from the converted local position
-	const FVector LocalMaximum = FUtilities::FollowGradientToMaximum(StartPosition, MyPointCloud->MyDensityField);
+	LocalMaximum = FUtilities::FollowGradientToMaximum(MyDensityField, StartPosition);
+	UE_LOG(LogTemp, Log, TEXT("Local maximum found at world position: %s"), *WorldMaximum.ToString());
 
 	// Convert the local maximum back to world coordinates
-	const FVector WorldMaximum = MyPointCloud->GetActorTransform().TransformPosition(LocalMaximum);
+	Index = MyDensityField->WorldPositionToIndex(LocalMaximum);
+
+	Threshold = FUtilities::InterpolateDensityAtPosition(MyDensityField, LocalMaximum);
+	TestingThresholdFactor = 1;
+}
+
+void UMetaPoint::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
+{
+	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
+
+	TestingThresholdFactor -= DeltaTime * 0.1f;
+}
 
+void UMetaPoint::SelectParticles(const FVector& InputPosition)
+{
+	const UWorld* World = GetWorld();
+	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, 10);
-	UE_LOG(LogTemp, Log, TEXT("Local maximum found at world position: %s"), *WorldMaximum.ToString());
+	DrawDebugSphere(World, WorldMaximum, SelectionRadius / 2, 32, FColor::Red, false, 0);
+	auto Voxels = FUtilities::FloodFilling(MyDensityField, Index, Threshold * TestingThresholdFactor);
 
+	for (const int32 Index2 : Voxels)
+	{
+		MyPointCloud->DrawVoxel(Index2, 0);
+	}
 }
 
 
+
+
+
+
diff --git a/Source/MetaCastBachelor/MetaPoint.h b/Source/MetaCastBachelor/MetaPoint.h
index 50bf21cb409f47d775b97b8a18ba2dafb9798e0f..c95ffd91893f145d901f80b2ad764472104b68f3 100644
--- a/Source/MetaCastBachelor/MetaPoint.h
+++ b/Source/MetaCastBachelor/MetaPoint.h
@@ -13,22 +13,31 @@ class UMetaPoint : public UMetaCastBaseline
 	GENERATED_BODY()
 	
 	MarchingCubes* MyMarchingCubes;
-	
+	FVector WorldMaximum;
+	int32 Index;
+	FVector LocalMaximum;
+	FDensityField* MyDensityField;
+	float Threshold;
 	
 public:
 
 	UPROPERTY(EditAnywhere, BlueprintReadWrite)
 	UProceduralMeshComponent* MyProceduralMesh;
+
+	UPROPERTY(EditAnywhere)
+	float TestingThresholdFactor = 2.0;
 	
 	UMetaPoint();
 	
 	virtual void BeginPlay() override;
-	
+		
 	virtual void SelectParticles(const FVector& InputPosition) override;
 	virtual void EraseParticles(const FVector& InputPosition) override;
 
 	virtual void HandleMetaSelectReleased(const FInputActionInstance& Instance) override;
 	virtual void HandleMetaSelectPressed(const FInputActionInstance& Instance) override;
-	void FindAndMarkLocalMaximum() const;
+	void FindAndMarkLocalMaximum();
+
+	virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
 };
 
diff --git a/Source/MetaCastBachelor/PointCloud.cpp b/Source/MetaCastBachelor/PointCloud.cpp
index 8d76f03326f55378a8a3bd7fa4d8ae93e1dfca7a..a5a93cf2dfb359253ef3d3c918e80dfee4409b63 100644
--- a/Source/MetaCastBachelor/PointCloud.cpp
+++ b/Source/MetaCastBachelor/PointCloud.cpp
@@ -91,7 +91,7 @@ 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 InfluenceRadius = 0.5f; // Half the size of a voxel
 	constexpr float Sigma = 3.0f;  // Standard deviation for the Gaussian kernel
 	MyDensityField->CalculateVoxelDensities(this, InfluenceRadius, Sigma);
 
@@ -99,10 +99,9 @@ void APointCloud::SetupDensityFieldFromPointCloud() const
 
 	if (const UWorld* World = GetWorld())
 	{
-		MyDensityField->DrawDebugVoxelDensity(World, this, 100.0f, 1.0f, 0.5f);
+		//MyDensityField->DrawDebugVoxelDensity(World, this, 100.0f, 1.0f, 0.8f);
 	}
 }
-
 void APointCloud::UpdateSelection()
 {
 	for (int32 i = 0; i < PositionVectors.Num(); i++)
@@ -119,6 +118,25 @@ void APointCloud::UpdateSelection()
 	PointCloudVisualizer->SetInputAndConvert2(PositionVectors, PointColors);
 }
 
+void APointCloud::DrawVoxel(const int Index, float Time) const
+{
+	if(!MyDensityField->IsValidIndex(Index))
+	{
+		return;
+	}
+
+	const FVector VoxelHalfExtents = MyDensityField->GetStep() / 2.0f;
+	const FVector VoxelWorldPosition = PointCloudVisualizer->GetComponentTransform().TransformPosition(MyDensityField->IndexToVoxelPosition(Index));
+	const FVector WorldScale = PointCloudVisualizer->GetComponentScale();
+
+	// Scale the voxel size by the component's world scale to ensure it reflects the actual dimensions
+	FVector ScaledVoxelSize = GetActorRightVector();
+
+	// Draw the debug box with the correct world space dimensions
+	DrawDebugBox(GetWorld(), VoxelWorldPosition, VoxelHalfExtents, this->GetActorQuat(), FColor::Green, false, Time, 0, 0.1f);
+
+}
+
 // Called every frame
 void APointCloud::Tick(float DeltaTime)
 {
diff --git a/Source/MetaCastBachelor/PointCloud.h b/Source/MetaCastBachelor/PointCloud.h
index 9c53726a9a7753b1e5261ef8ea97618728e24cc0..e22fd462812578614a97b6d4284ea46c5acc4348 100644
--- a/Source/MetaCastBachelor/PointCloud.h
+++ b/Source/MetaCastBachelor/PointCloud.h
@@ -13,7 +13,6 @@ class APointCloud : public AActor
 	
 public:
 	FDensityField* MyDensityField;
-	
 	TArray<FVector> PositionVectors;
 	TArray<bool> DefaultFlags;
 	TArray<bool> SelectionFlags;
@@ -59,6 +58,7 @@ public:
 	virtual void Tick(float DeltaTime) override;
 
 	void UpdateSelection();
+	void DrawVoxel(const int Index, float Time) const;
 
 	UFUNCTION(BlueprintCallable)
 	void ReadPointCloudFromFile(FFilePath FileNamePoints, FFilePath FileNameFlags);
diff --git a/Source/MetaCastBachelor/Utilities.cpp b/Source/MetaCastBachelor/Utilities.cpp
index e549e57ee4c03ad25a7cb6f8b47104c291f47177..939fe9769c638d432410ff049faa3f206a36b063 100644
--- a/Source/MetaCastBachelor/Utilities.cpp
+++ b/Source/MetaCastBachelor/Utilities.cpp
@@ -26,128 +26,94 @@ void FUtilities::QuickSort(TArray<float>& Array, const int32 Begin, const int32
 	}
 }
 
-double FUtilities::InterpolateDensityAtPosition(const FVector& Position, const FDensityField* DensityField)
+double FUtilities::InterpolateDensityAtPosition(const FDensityField* DensityField, const FVector& Position)
 {
     if (!DensityField)
         return 0.0;
 
-    // Convert position into grid coordinate space
     const FVector GridPos = (Position - DensityField->GetGridOrigin()) / DensityField->GetStep();
 
     const int32 XBin = FMath::FloorToInt(GridPos.X);
     const int32 YBin = FMath::FloorToInt(GridPos.Y);
     const int32 ZBin = FMath::FloorToInt(GridPos.Z);
 
-    // Calculate fractional components for interpolation
-    const double XFraction = GridPos.X - XBin;
-    const double YFraction = GridPos.Y - YBin;
-    const double ZFraction = GridPos.Z - ZBin;
-
-    // Ensure indices are within the valid range
-    if (!DensityField->IsValidIndex(XBin, YBin, ZBin) ||
-        !DensityField->IsValidIndex(XBin + 1, YBin, ZBin) ||
-        !DensityField->IsValidIndex(XBin, YBin + 1, ZBin) ||
-        !DensityField->IsValidIndex(XBin, YBin, ZBin + 1) ||
-        !DensityField->IsValidIndex(XBin + 1, YBin + 1, ZBin) ||
-        !DensityField->IsValidIndex(XBin + 1, YBin, ZBin + 1) ||
-        !DensityField->IsValidIndex(XBin, YBin + 1, ZBin + 1) ||
-        !DensityField->IsValidIndex(XBin + 1, YBin + 1, ZBin + 1))
-    {
-        return 0.0;
-    }
-
-    // Fetch the densities from the surrounding voxel corners
-    const double D000 = DensityField->GetDensity(XBin, YBin, ZBin);
-    const double D100 = DensityField->GetDensity(XBin + 1, YBin, ZBin);
-    const double D010 = DensityField->GetDensity(XBin, YBin + 1, ZBin);
-    const double D001 = DensityField->GetDensity(XBin, YBin, ZBin + 1);
-    const double D110 = DensityField->GetDensity(XBin + 1, YBin + 1, ZBin);
-    const double D101 = DensityField->GetDensity(XBin + 1, YBin, ZBin + 1);
-    const double D011 = DensityField->GetDensity(XBin, YBin + 1, ZBin + 1);
-    const double D111 = DensityField->GetDensity(XBin + 1, YBin + 1, ZBin + 1);
-
-    // Interpolate along x for each of the pairs
-    const double D00 = D000 * (1 - XFraction) + D100 * XFraction;
-    const double D01 = D001 * (1 - XFraction) + D101 * XFraction;
-    const double D10 = D010 * (1 - XFraction) + D110 * XFraction;
-    const double D11 = D011 * (1 - XFraction) + D111 * XFraction;
-
-    // Interpolate along y
-    const double D0 = D00 * (1 - YFraction) + D10 * YFraction;
-    const double D1 = D01 * (1 - YFraction) + D11 * YFraction;
-
-    // Final interpolation along z
-    const double Density = D0 * (1 - ZFraction) + D1 * ZFraction;
-
-    return Density;
-}
+    const float XFraction = GridPos.X - XBin;
+    const float YFraction = GridPos.Y - YBin;
+    const float ZFraction = GridPos.Z - ZBin;
 
+    const double D000 = DensityField->GetVoxelDensityFromGridPosition(XBin, YBin, ZBin);
+    const double D100 = DensityField->GetVoxelDensityFromGridPosition(XBin + 1, YBin, ZBin);
+    const double D010 = DensityField->GetVoxelDensityFromGridPosition(XBin, YBin + 1, ZBin);
+    const double D001 = DensityField->GetVoxelDensityFromGridPosition(XBin, YBin, ZBin + 1);
+    const double D101 = DensityField->GetVoxelDensityFromGridPosition(XBin + 1, YBin, ZBin + 1);
+    const double D011 = DensityField->GetVoxelDensityFromGridPosition(XBin, YBin + 1, ZBin + 1);
+    const double D110 = DensityField->GetVoxelDensityFromGridPosition(XBin + 1, YBin + 1, ZBin);
+    const double D111 = DensityField->GetVoxelDensityFromGridPosition(XBin + 1, YBin + 1, ZBin + 1);
 
-FVector FUtilities::InterpolateGradientAtPosition(const FVector& Position, const FDensityField* DensityField)
-{
-    if (!DensityField)
-        return FVector::ZeroVector;
+    // Trilinear interpolation
+    const double DX00 = FMath::Lerp(D000, D100, XFraction);
+    const double DX01 = FMath::Lerp(D001, D101, XFraction);
+    const double DX10 = FMath::Lerp(D010, D110, XFraction);
+    const double DX11 = FMath::Lerp(D011, D111, XFraction);
 
-    // Convert position into grid coordinate space
-    const FVector GridPos = (Position - DensityField->GetGridOrigin()) / DensityField->GetStep();
+    const double DY0 = FMath::Lerp(DX00, DX10, YFraction);
+    const double DY1 = FMath::Lerp(DX01, DX11, YFraction);
 
-    const int32 XBin = FMath::FloorToInt(GridPos.X);
-    const int32 YBin = FMath::FloorToInt(GridPos.Y);
-    const int32 ZBin = FMath::FloorToInt(GridPos.Z);
+    const double DZ = FMath::Lerp(DY0, DY1, ZFraction);
 
-    // Calculate fractional components for interpolation
-    const double XFraction = GridPos.X - XBin;
-    const double YFraction = GridPos.Y - YBin;
-    const double ZFraction = GridPos.Z - ZBin;
-
-    // Ensure indices are within the valid range
-    if (!DensityField->IsValidIndex(XBin, YBin, ZBin) ||
-        !DensityField->IsValidIndex(XBin + 1, YBin, ZBin) ||
-        !DensityField->IsValidIndex(XBin, YBin + 1, ZBin) ||
-        !DensityField->IsValidIndex(XBin, YBin, ZBin + 1) ||
-        !DensityField->IsValidIndex(XBin + 1, YBin + 1, ZBin) ||
-        !DensityField->IsValidIndex(XBin + 1, YBin, ZBin + 1) ||
-        !DensityField->IsValidIndex(XBin, YBin + 1, ZBin + 1) ||
-        !DensityField->IsValidIndex(XBin + 1, YBin + 1, ZBin + 1))
-    {
-        return FVector::ZeroVector;
-    }
-
-    // Fetch the gradients from the surrounding voxel corners
-    const FVector G000 = DensityField->GetGradient(XBin, YBin, ZBin);
-    const FVector G100 = DensityField->GetGradient(XBin + 1, YBin, ZBin);
-    const FVector G010 = DensityField->GetGradient(XBin, YBin + 1, ZBin);
-    const FVector G001 = DensityField->GetGradient(XBin, YBin, ZBin + 1);
-    const FVector G110 = DensityField->GetGradient(XBin + 1, YBin + 1, ZBin);
-    const FVector G101 = DensityField->GetGradient(XBin + 1, YBin, ZBin + 1);
-    const FVector G011 = DensityField->GetGradient(XBin, YBin + 1, ZBin + 1);
-    const FVector G111 = DensityField->GetGradient(XBin + 1, YBin + 1, ZBin + 1);
-
-    // Interpolate along x for each of the pairs
-    const FVector G00 = G000 * (1 - XFraction) + G100 * XFraction;
-    const FVector G01 = G001 * (1 - XFraction) + G101 * XFraction;
-    const FVector G10 = G010 * (1 - XFraction) + G110 * XFraction;
-    const FVector G11 = G011 * (1 - XFraction) + G111 * XFraction;
-
-    // Interpolate along y
-    const FVector G0 = G00 * (1 - YFraction) + G10 * YFraction;
-    const FVector G1 = G01 * (1 - YFraction) + G11 * YFraction;
-
-    // Final interpolation along z
-    const FVector Gradient = G0 * (1 - ZFraction) + G1 * ZFraction;
-
-    return Gradient;
+    return DZ;
 }
 
+FVector FUtilities::InterpolateGradientAtPosition(const FDensityField* DensityField, const FVector& Position)
+{
+	if (!DensityField)
+		return FVector::ZeroVector;
+
+	FVector GridPos = (Position - DensityField->GetGridOrigin()) / DensityField->GetStep();
+
+	int32 XBin = FMath::FloorToInt(GridPos.X);
+	int32 YBin = FMath::FloorToInt(GridPos.Y);
+	int32 ZBin = FMath::FloorToInt(GridPos.Z);
+
+	// Fractional parts to interpolate
+	float XFraction = GridPos.X - XBin;
+	float YFraction = GridPos.Y - YBin;
+	float ZFraction = GridPos.Z - ZBin;
+
+	// Fetch gradients from corners of the cell
+	FVector G000 = DensityField->GetVoxelGradientFromGridPosition(XBin, YBin, ZBin);
+	FVector G100 = DensityField->GetVoxelGradientFromGridPosition(XBin + 1, YBin, ZBin);
+	FVector G010 = DensityField->GetVoxelGradientFromGridPosition(XBin, YBin + 1, ZBin);
+	FVector G001 = DensityField->GetVoxelGradientFromGridPosition(XBin, YBin, ZBin + 1);
+	FVector G110 = DensityField->GetVoxelGradientFromGridPosition(XBin + 1, YBin + 1, ZBin);
+	FVector G101 = DensityField->GetVoxelGradientFromGridPosition(XBin + 1, YBin, ZBin + 1);
+	FVector G011 = DensityField->GetVoxelGradientFromGridPosition(XBin, YBin + 1, ZBin + 1);
+	FVector G111 = DensityField->GetVoxelGradientFromGridPosition(XBin + 1, YBin + 1, ZBin + 1);
+
+	// Interpolate along x for each of the yz pairs
+	FVector G00 = FMath::Lerp(G000, G100, XFraction);
+	FVector G01 = FMath::Lerp(G001, G101, XFraction);
+	FVector G10 = FMath::Lerp(G010, G110, XFraction);
+	FVector G11 = FMath::Lerp(G011, G111, XFraction);
+
+	// Interpolate along y
+	FVector G0 = FMath::Lerp(G00, G10, YFraction);
+	FVector G1 = FMath::Lerp(G01, G11, YFraction);
+
+	// Final interpolation along z
+	FVector Gradient = FMath::Lerp(G0, G1, ZFraction);
+
+	return Gradient;
+}
 
 float FUtilities::GaussianKernel(const float Distance, const float Sigma) {
 	return FMath::Exp(-0.5 * FMath::Square(Distance / Sigma));
 }
 
-FVector FUtilities::FollowGradientToMaximum(const FVector& StartPosition, const FDensityField* DensityField)
+FVector FUtilities::FollowGradientToMaximum(const FDensityField* DensityField, const FVector& StartPosition)
 {
 	FVector CurrentPosition = StartPosition;
-	double CurrentDensity = InterpolateDensityAtPosition(CurrentPosition, DensityField);
+	double CurrentDensity = InterpolateDensityAtPosition(DensityField, CurrentPosition);
 
 	int Iterations = 0;
 	constexpr int MaxIterations = 100;  // Prevent infinite loops
@@ -155,22 +121,21 @@ FVector FUtilities::FollowGradientToMaximum(const FVector& StartPosition, const
 
 	while (Iterations < MaxIterations)
 	{
-		FVector Gradient = InterpolateGradientAtPosition(CurrentPosition, DensityField);
+		FVector Gradient = InterpolateGradientAtPosition(DensityField, CurrentPosition);
 		if (Gradient.IsNearlyZero()) {
 			UE_LOG(LogTemp, Log, TEXT("Gradient is zero at position %s"), *CurrentPosition.ToString());
 			break;  // Gradient is zero, likely at a local maximum
 		}
 
 		// Move towards the direction of the gradient
-		FVector NextPosition = CurrentPosition + StepSize * Gradient.GetSafeNormal();
-		if (!DensityField->IsValidPosition(NextPosition)) {
+		FVector NextPosition = CurrentPosition + (StepSize * Gradient.GetSafeNormal());
+		if (!DensityField->IsValidWorldPosition(NextPosition)) {
 			UE_LOG(LogTemp, Warning, TEXT("Next position out of bounds: %s"), *NextPosition.ToString());
 			break;  // Next position is out of valid bounds
 		}
 
-		const double NewDensity = InterpolateDensityAtPosition(NextPosition, DensityField);
-		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);
+		const double NewDensity = InterpolateDensityAtPosition(DensityField, NextPosition);
+		//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);
@@ -185,3 +150,51 @@ FVector FUtilities::FollowGradientToMaximum(const FVector& StartPosition, const
 	return CurrentPosition;
 }
 
+TArray<int32> FUtilities::FloodFilling(const FDensityField* DensityField, const int32 StartIndex, const float Threshold)
+{
+	UE_LOG(LogTemp, Warning, TEXT("T: %f"), Threshold);
+	
+	TArray<int32> VisitedIndices;
+	if (!DensityField) {
+		UE_LOG(LogTemp, Warning, TEXT("DensityField is null."));
+		return VisitedIndices;
+	}
+
+	if (!DensityField->IsValidIndex(StartIndex)) {
+		UE_LOG(LogTemp, Warning, TEXT("Start index %d is invalid."), StartIndex);
+		return VisitedIndices;
+	}
+
+	TArray<int32> Stack;
+	Stack.Push(StartIndex);
+	TArray<bool> Visited;
+	Visited.Init(false, DensityField->GetVoxelNumber());
+
+	while (Stack.Num() > 0)
+	{
+		int32 CurrentIndex = Stack.Pop();
+		if (!Visited[CurrentIndex])
+		{
+			Visited[CurrentIndex] = true;
+			VisitedIndices.Add(CurrentIndex);
+
+			TArray<int32> Neighbors = DensityField->GetNeighborsFromIndex(CurrentIndex);
+			UE_LOG(LogTemp, Log, TEXT("Visiting Node %d at Position %s with %d neighbors."), CurrentIndex, *DensityField->IndexToGridPosition(CurrentIndex).ToString(), Neighbors.Num());
+            
+			for (int32 NeighborIndex : Neighbors)
+			{
+				if (DensityField->GetVoxelDensityFromIndex(NeighborIndex) > Threshold && !Visited[NeighborIndex]) {
+					Stack.Push(NeighborIndex);
+				}
+			}
+		}
+	}
+
+	// Logging final details
+	UE_LOG(LogTemp, Log, TEXT("Flood filling completed from start index %d. Total voxels selected: %d"), StartIndex, VisitedIndices.Num());
+	for (const int32 idx : VisitedIndices) {
+		UE_LOG(LogTemp, Log, TEXT("Selected Voxel Index: %d at Grid Position: %s"), idx, *DensityField->IndexToGridPosition(idx).ToString());
+	}
+
+	return VisitedIndices;
+}
diff --git a/Source/MetaCastBachelor/Utilities.h b/Source/MetaCastBachelor/Utilities.h
index bba7a43a98eefa6d5b13c3e6f3bdb17c3cb1bcd8..72313c10410e4cf42b9138d7e62023d5a9c58b72 100644
--- a/Source/MetaCastBachelor/Utilities.h
+++ b/Source/MetaCastBachelor/Utilities.h
@@ -6,8 +6,9 @@ class FUtilities
 {
 public:
 	static void QuickSort(TArray<float>& Array, int32 Begin, int32 End);
-	static double InterpolateDensityAtPosition(const FVector& Position, const FDensityField* DensityField);
-	static FVector InterpolateGradientAtPosition(const FVector& Position, const FDensityField* DensityField);
+	static double InterpolateDensityAtPosition(const FDensityField* DensityField, const FVector& Position);
+	static FVector InterpolateGradientAtPosition(const FDensityField* DensityField, const FVector& Position);
 	static float GaussianKernel(float Distance, float Sigma);
-	static FVector FollowGradientToMaximum(const FVector& StartPosition, const FDensityField* DensityField);
+	static FVector FollowGradientToMaximum(const FDensityField* DensityField, const FVector& StartPosition);
+	static TArray<int32> FloodFilling(const FDensityField* DensityField, const int32 StartIndex, const float Threshold);
 };