diff --git a/Content/MetaPointMap.umap b/Content/MetaPointMap.umap
index 7e4733c7f9d52777e794102217da9ff21ea628ba..a90f205a3061d3582938745c1b4c3550588e57fa 100644
Binary files a/Content/MetaPointMap.umap and b/Content/MetaPointMap.umap differ
diff --git a/Source/MetaCastBachelor/DensityField.cpp b/Source/MetaCastBachelor/DensityField.cpp
index ab49740d352689c4683859bce08b5445cde2753b..6c6af6b8a896b8c791f2ee8170ca6e2ceccfb4ba 100644
--- a/Source/MetaCastBachelor/DensityField.cpp
+++ b/Source/MetaCastBachelor/DensityField.cpp
@@ -13,15 +13,13 @@ FDensityField::FDensityField(): XNum(0), YNum(0), ZNum(0), XStep(0), YStep(0), Z
 void FDensityField::InitializeDensityField(const APointCloud* PointCloud, const FVector& MinBounds, const FVector& MaxBounds, const FIntVector AxisNumbers)
 {
 	InitializeDataStructures(MinBounds, MaxBounds, AxisNumbers.X, AxisNumbers.Y, AxisNumbers.Z);
-
-	constexpr float InfluenceRadius = 1.0f; // Size of a voxel
-	constexpr float Sigma = 1.0f;  // Standard deviation for the Gaussian kernel
 	
-	CalculateVoxelDensities(PointCloud, InfluenceRadius, Sigma);
-	CalculateAndStoreGradients();
-
 	VoxelPointLookupTable = new FVoxelPointLookupTable();
 	VoxelPointLookupTable->Initialize(PointCloud->PositionVectors, this);
+	
+	CalculateVoxelDensities_2(PointCloud, PointCloud->InfluenceRadius);
+	//CalculateVoxelDensitiesByNumber(PointCloud, 4);
+	CalculateAndStoreGradients();
 }
 
 void FDensityField::InitializeDataStructures(const FVector& MinBounds, const FVector& MaxBounds, const int32 XAxisNum, const int32 YAxisNum, const int32 ZAxisNum)
@@ -185,6 +183,196 @@ void FDensityField::CalculateVoxelDensitiesByNumber(const APointCloud* PointClou
 
 	UE_LOG(LogTemp, Log, TEXT("Density calculation completed in %f seconds."), ElapsedTime);
 }
+/*
+void FDensityField::CalculateVoxelDensities_2(const APointCloud* PointCloud, const float InfluenceRadius)
+{
+    if (!PointCloud)
+        return;
+
+    const double StartTime = FPlatformTime::Seconds();
+    UE_LOG(LogTemp, Log, TEXT("Starting density calculation."));
+
+    TArray<float> SmoothingLengths;
+    SmoothingLengths.Init(InfluenceRadius, PointCloud->PositionVectors.Num());
+
+    // Clear existing densities
+    for (auto& Node : VoxelList)
+    {
+        Node.SetVoxelDensity(0.0);
+        Node.SetClosePointsNumber(0.0);
+    }
+
+    // Iterate over each particle to update smoothing lengths based on local densities
+    UpdateSmoothingLengths(PointCloud, SmoothingLengths, InfluenceRadius);
+
+    // Iterate over each particle for density calculation
+    for (int i = 0; i < PointCloud->PositionVectors.Num(); i++)
+    {
+        const FVector& ParticlePosition = PointCloud->PositionVectors[i];
+        const float ParticleSmoothingLength = SmoothingLengths[i];
+        const float ParticleGaussianDenominator = 2 * ParticleSmoothingLength * ParticleSmoothingLength;
+
+    	const int32 StartX = FMath::Max(0, FMath::FloorToInt((ParticlePosition.X - ParticleSmoothingLength - PointCloud->MinBounds.X) / XStep));
+    	const int32 EndX = FMath::Min(XNum - 1, FMath::FloorToInt((ParticlePosition.X + ParticleSmoothingLength - PointCloud->MinBounds.X) / XStep));
+    	const int32 StartY = FMath::Max(0, FMath::FloorToInt((ParticlePosition.Y - ParticleSmoothingLength - PointCloud->MinBounds.Y) / YStep));
+    	const int32 EndY = FMath::Min(YNum - 1, FMath::FloorToInt((ParticlePosition.Y + ParticleSmoothingLength - PointCloud->MinBounds.Y) / YStep));
+    	const int32 StartZ = FMath::Max(0, FMath::FloorToInt((ParticlePosition.Z - ParticleSmoothingLength - PointCloud->MinBounds.Z) / ZStep));
+    	const int32 EndZ = FMath::Min(ZNum - 1, FMath::FloorToInt((ParticlePosition.Z + ParticleSmoothingLength - PointCloud->MinBounds.Z) / ZStep));
+
+        for (int32 Z = StartZ; Z <= EndZ; ++Z)
+            for (int32 Y = StartY; Y <= EndY; ++Y)
+                for (int32 X = StartX; X <= EndX; ++X)
+                {
+                    const int32 Index = GridPositionToIndex(X, Y, Z);
+                    if (VoxelList.IsValidIndex(Index))
+                    {
+                        FVector NodePosition = VoxelList[Index].GetVoxelPosition();
+                        const float Distance = FVector::Dist(NodePosition, ParticlePosition);
+                        if (Distance <= ParticleSmoothingLength)
+                        {
+	                        const float Weight = exp(-(Distance * Distance) / ParticleGaussianDenominator);
+                            VoxelList[Index].AddToVoxelDensity(Weight);
+                            VoxelList[Index].SetClosePointsNumber(VoxelList[Index].GetClosePointsNumber() + 1.0);
+                        }
+                    }
+                }
+    }
+
+    double MaxDensity = 0.0;
+    for (const auto& Node : VoxelList)
+        if (Node.GetVoxelDensity() > MaxDensity)
+            MaxDensity = Node.GetVoxelDensity();
+
+    const double EndTime = FPlatformTime::Seconds();
+    const double ElapsedTime = EndTime - StartTime;
+    UE_LOG(LogTemp, Log, TEXT("Density calculation completed in %f seconds."), ElapsedTime);
+}*/
+
+void FDensityField::SetInitialDensityEstimates(const APointCloud* PointCloud, const float InfluenceRadius)
+{
+   // Iterate over each particle
+	for (const FVector& ParticlePosition : PointCloud->PositionVectors)
+	{
+		const int32 StartX = FMath::Max(0, FMath::FloorToInt((ParticlePosition.X - InfluenceRadius - PointCloud->MinBounds.X) / XStep));
+	    const int32 EndX = FMath::Min(XNum - 1, FMath::FloorToInt((ParticlePosition.X + InfluenceRadius - PointCloud->MinBounds.X) / XStep));
+	    const int32 StartY = FMath::Max(0, FMath::FloorToInt((ParticlePosition.Y - InfluenceRadius - PointCloud->MinBounds.Y) / YStep));
+	    const int32 EndY = FMath::Min(YNum - 1, FMath::FloorToInt((ParticlePosition.Y + InfluenceRadius - PointCloud->MinBounds.Y) / YStep));
+	    const int32 StartZ = FMath::Max(0, FMath::FloorToInt((ParticlePosition.Z - InfluenceRadius - PointCloud->MinBounds.Z) / ZStep));
+	    const int32 EndZ = FMath::Min(ZNum - 1, FMath::FloorToInt((ParticlePosition.Z + InfluenceRadius - PointCloud->MinBounds.Z) / ZStep));
+
+	    for (int32 Z = StartZ; Z <= EndZ; ++Z)
+	    {
+	        for (int32 Y = StartY; Y <= EndY; ++Y)
+	        {
+	            for (int32 X = StartX; X <= EndX; ++X)
+	            {
+	                const int32 Index = GridPositionToIndex(X, Y, Z);
+	                if (Index >= 0 && Index < VoxelList.Num())
+	                {
+	                    FVector NodePosition = VoxelList[Index].GetVoxelPosition();
+	                    const float Distance = FVector::Dist(NodePosition, ParticlePosition);
+
+	                    if (Distance <= InfluenceRadius)
+	                    {
+		                    const float NormalizedDistance = Distance / InfluenceRadius;
+	                    	
+	                        double Weight =  1- (NormalizedDistance * NormalizedDistance);
+
+	                    	Weight *= 0.5968310365946 / (InfluenceRadius * InfluenceRadius * InfluenceRadius);
+	                        VoxelList[Index].AddToVoxelDensity(Weight);
+	                    }
+	                }
+	            }
+	        }
+	    }
+	}
+}
+
+void FDensityField::CalculateVoxelDensities_2(const APointCloud* PointCloud, const float InfluenceRadius)
+{
+	if (!PointCloud)
+	    return;
+
+	// Clear existing densities and counts
+	for (auto& Node : VoxelList)
+	{
+	    Node.SetVoxelDensity(0.0);
+	    Node.SetClosePointsNumber(0.0);
+	}
+	
+	SetInitialDensityEstimates(PointCloud, InfluenceRadius);
+	
+	TArray<float> SmoothingLengths;
+	SmoothingLengths.Init(InfluenceRadius, PointCloud->PositionVectors.Num());
+
+	// Iterate over each particle
+	int Count = 0;
+	for (const FVector& ParticlePosition : PointCloud->PositionVectors)
+	{
+		const int VoxelIndex = WorldPositionToIndex(ParticlePosition);
+		const float TotalVoxelDensity = IndexToVoxelDensity(VoxelIndex);
+		const int NumberInVoxel = VoxelPointLookupTable->GetPointsInVoxel(VoxelIndex).Num();
+		const float InterpolatedDensity = FUtilities::InterpolateDensityAtPosition(this, ParticlePosition);
+
+		const float SmoothingLength = FMath::Min(FMathf::Pow(TotalVoxelDensity / NumberInVoxel / InterpolatedDensity,(1.0 / 3.0)), 5 * GetStep().X);
+		SmoothingLengths[Count] = SmoothingLength;
+
+		Count++;
+	}
+
+	for (int i = 0; i < 100; i++)
+	{
+		UE_LOG(LogTemp, Log, TEXT("Smoothing Length: %f"), SmoothingLengths[i]);
+	}
+
+	for (auto& Node : VoxelList)
+	{
+		Node.SetVoxelDensity(0.0);
+		Node.SetClosePointsNumber(0.0);
+	}
+	
+	// Iterate over each particle
+	Count = 0;
+	for (const FVector& ParticlePosition : PointCloud->PositionVectors)
+	{
+		const float NewInfluenceRadius = SmoothingLengths[Count];
+		const int32 StartX = FMath::Max(0, FMath::FloorToInt((ParticlePosition.X - NewInfluenceRadius - PointCloud->MinBounds.X) / XStep));
+		const int32 EndX = FMath::Min(XNum - 1, FMath::FloorToInt((ParticlePosition.X + NewInfluenceRadius - PointCloud->MinBounds.X) / XStep));
+		const int32 StartY = FMath::Max(0, FMath::FloorToInt((ParticlePosition.Y - NewInfluenceRadius - PointCloud->MinBounds.Y) / YStep));
+		const int32 EndY = FMath::Min(YNum - 1, FMath::FloorToInt((ParticlePosition.Y + NewInfluenceRadius - PointCloud->MinBounds.Y) / YStep));
+		const int32 StartZ = FMath::Max(0, FMath::FloorToInt((ParticlePosition.Z - NewInfluenceRadius - PointCloud->MinBounds.Z) / ZStep));
+		const int32 EndZ = FMath::Min(ZNum - 1, FMath::FloorToInt((ParticlePosition.Z + NewInfluenceRadius - PointCloud->MinBounds.Z) / ZStep));
+
+		for (int32 Z = StartZ; Z <= EndZ; ++Z)
+		{
+			for (int32 Y = StartY; Y <= EndY; ++Y)
+			{
+				for (int32 X = StartX; X <= EndX; ++X)
+				{
+					const int32 Index = GridPositionToIndex(X, Y, Z);
+					if (Index >= 0 && Index < VoxelList.Num())
+					{
+						FVector NodePosition = VoxelList[Index].GetVoxelPosition();
+						const float Distance = FVector::Dist(NodePosition, ParticlePosition);
+
+						if (Distance <= NewInfluenceRadius)
+						{
+							const float NormalizedDistance = Distance / NewInfluenceRadius;
+	                    	
+							double Weight =  1 - (NormalizedDistance * NormalizedDistance);
+
+							Weight *= (NewInfluenceRadius * NewInfluenceRadius * NewInfluenceRadius);
+							VoxelList[Index].AddToVoxelDensity(FUtilities::SmoothingKernel(Distance, NewInfluenceRadius));
+						}
+					}
+				}
+			}
+		}
+
+		Count++;
+	}
+}
+
 
 void FDensityField::CalculateAndStoreGradients()
 {
diff --git a/Source/MetaCastBachelor/DensityField.h b/Source/MetaCastBachelor/DensityField.h
index c854dcdecc9bbb3e0fbf913733f6f46cbbdee95e..5a3cd269d9704f36933c56edfb8e44e5c564eaf4 100644
--- a/Source/MetaCastBachelor/DensityField.h
+++ b/Source/MetaCastBachelor/DensityField.h
@@ -55,6 +55,8 @@ public:
 
 	// INITIALIZATION FUNCTIONS
 	void InitializeDensityField(const APointCloud* PointCloud, const FVector& MinBounds, const FVector& MaxBounds, const FIntVector AxisNumbers);
+	void CalculateVoxelDensities_2(const APointCloud* PointCloud, const float InfluenceRadius);
+	void SetInitialDensityEstimates(const APointCloud* PointCloud, const float InfluenceRadius);
 
 	//	DEBUG FUNCTIONS
     void DrawDebugVoxelDensity(const UWorld* World, const AActor* Actor, float Duration, float Scale, float DensityThreshold) const;
diff --git a/Source/MetaCastBachelor/MetaPoint.cpp b/Source/MetaCastBachelor/MetaPoint.cpp
index cde81c999f8b30ab9f8e5808b402b6e4983f317c..6b45ec3eb10b7998cb43a397de22dac85c24867f 100644
--- a/Source/MetaCastBachelor/MetaPoint.cpp
+++ b/Source/MetaCastBachelor/MetaPoint.cpp
@@ -55,9 +55,11 @@ void UMetaPoint::HandleMetaSelectReleased(const FInputActionInstance& Instance)
 	//ProceduralMesh->ClearAllMeshSections();
 	//ProceduralMesh->SetVisibility(false);
 
+	MyPointCloud->ColorPointsInVoxels(FloodedIndices);
+
 	AsyncTask(ENamedThreads::Type::AnyBackgroundHiPriTask, [this]()
 	{
-		MyPointCloud->ColorPointsInVoxels(FloodedIndices);
+		
 	});
 }
 
@@ -101,14 +103,17 @@ void UMetaPoint::InitMetaPointSelection()
 	World = GetWorld();
 
 	LastHandInput = SelectionWorldPosition;
+	AbortMarchingCubes = true;
+	AccumulatedTime = 0.0f;
 }
 
 void UMetaPoint::SelectParticles(const FVector& InputPosition)
 {
 	if (AccumulatedTime >=  1 / MetaCastPerSecond)
 	{
-		AccumulatedTime = -1000;
-		
+		AccumulatedTime = -10000;
+
+		FScopeLock Lock(&FloodFillingGuard); 
 		AsyncTask(ENamedThreads::AnyBackgroundThreadNormalTask, [this]()
 		{
 			const FVector SelectionWorldPosition = SelectionObject->GetComponentLocation();
@@ -187,8 +192,14 @@ void UMetaPoint::GenerateVoxelMeshWithCubes(const TArray<int32> Voxels) const
 	});
 }
 
-void UMetaPoint::GenerateVoxelMeshSmooth(TArray<int32> Voxels)
+void UMetaPoint::GenerateVoxelMeshSmooth(const TArray<int32> Voxels)
 {
+	if(IsMarchingCubesRunning)
+		return;
+
+	IsMarchingCubesRunning = true;
+	
+	FScopeLock Lock(&ProceduralMeshGuard);
 	AsyncTask(ENamedThreads::AnyBackgroundThreadNormalTask, [this, Voxels]()
 	{
 		FVector Min(FLT_MAX, FLT_MAX, FLT_MAX);
@@ -202,9 +213,13 @@ void UMetaPoint::GenerateVoxelMeshSmooth(TArray<int32> Voxels)
 
 		UE::Geometry::FMarchingCubes MarchingCubes;
 		MarchingCubes.Bounds = UE::Geometry::TAxisAlignedBox3(Min, Max);
-		MarchingCubes.CubeSize = MyDensityField->GetStep().X;
+		MarchingCubes.CubeSize = MarchingCubeSize == 0 ? MyDensityField->GetStep().X : MarchingCubeSize;
+		MarchingCubes.CancelF = [this]() {
+			return AbortMarchingCubes;
+		};
 		MarchingCubes.IsoValue = 0;
 
+		AbortMarchingCubes = false;
 		// Define the implicit function
 		MarchingCubes.Implicit = [this, Voxels](const FVector3d& Pos) {
 			const FVector PosConverted = FVector(Pos.X, Pos.Y, Pos.Z);
@@ -254,12 +269,11 @@ void UMetaPoint::GenerateVoxelMeshSmooth(TArray<int32> Voxels)
 
 		AsyncTask(ENamedThreads::Type::GameThread, [this, Vertices, Indices, Normals, VertexColors]()
 		{
+			FScopeLock MeshLock(&ProceduralMeshGuard);
 			ProceduralMesh->CreateMeshSection(0, Vertices, Indices, Normals, TArray<FVector2D>(), VertexColors, TArray<FProcMeshTangent>(), false);
 			ProceduralMesh->SetVisibility(true);
 			AccumulatedTime = 0.0f;
+			IsMarchingCubesRunning = false;
 		});
 	});
-	
-
-	
 }
\ No newline at end of file
diff --git a/Source/MetaCastBachelor/MetaPoint.h b/Source/MetaCastBachelor/MetaPoint.h
index ecb85c63abdc3ef3818c920993345c2302df7df8..20cd30ed39349630e349e66a2d68736b6683695b 100644
--- a/Source/MetaCastBachelor/MetaPoint.h
+++ b/Source/MetaCastBachelor/MetaPoint.h
@@ -24,6 +24,12 @@ class UMetaPoint : public UMetaCastBaseline
 	FVector LastHandInput;
 	UPROPERTY(EditAnywhere)
 	float MinimalHandMovement = 0.01;
+	bool IsMarchingCubesRunning = false;
+	bool AbortMarchingCubes = false;
+
+	// Critical section to protect shared variables
+	mutable FCriticalSection FloodFillingGuard;
+	mutable FCriticalSection ProceduralMeshGuard;
 
 	UPROPERTY()
 	UProceduralMeshComponent* ProceduralMesh;
@@ -36,8 +42,11 @@ class UMetaPoint : public UMetaCastBaseline
 	TArray<int32> FloodedIndices;
 	TArray<int32> RevisitIndices;
 
+
 	UPROPERTY(EditAnywhere)
-	int MetaCastPerSecond = 1;
+	float MarchingCubeSize = 0;
+	UPROPERTY(EditAnywhere)
+	int MetaCastPerSecond = 10;
 	
 public:
 	UMetaPoint();
@@ -55,5 +64,4 @@ public:
 	void GenerateVoxelMeshSmooth(const TArray<int32> Voxels);
 
 	virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
-};
-
+};
\ No newline at end of file
diff --git a/Source/MetaCastBachelor/PointCloud.cpp b/Source/MetaCastBachelor/PointCloud.cpp
index d319ce91f39e29ecdb9443e723229bac0bd796cc..aad4992d3ac917b71487bc944061f228b45301f8 100644
--- a/Source/MetaCastBachelor/PointCloud.cpp
+++ b/Source/MetaCastBachelor/PointCloud.cpp
@@ -134,7 +134,7 @@ void APointCloud::DrawVoxel(const int Index, const float Time) const
 
 }
 
-void APointCloud::ColorPointsInVoxels(const TArray<int32> VoxelIndices)
+void APointCloud::ColorPointsInVoxels(const TArray<int32>& VoxelIndices)
 {
 	FScopeLock Lock(&DataGuard);
 	if (!MyDensityField)
diff --git a/Source/MetaCastBachelor/PointCloud.h b/Source/MetaCastBachelor/PointCloud.h
index 6aae1269053c7110a6e69381a2e2bea7bb3600cf..90e89d217240ff7301b4135764d0527b2c1df935 100644
--- a/Source/MetaCastBachelor/PointCloud.h
+++ b/Source/MetaCastBachelor/PointCloud.h
@@ -12,6 +12,9 @@ class APointCloud : public AActor
 	GENERATED_BODY()
 	
 public:
+	UPROPERTY(EditAnywhere)
+	float InfluenceRadius = 3.0f;
+
 	FDensityField* MyDensityField;
 	UPROPERTY()
 	TArray<FVector> PositionVectors;
@@ -64,7 +67,7 @@ public:
 
 	void UpdateSelection();
 	void DrawVoxel(const int Index, float Time) const;
-	void ColorPointsInVoxels(const TArray<int32> VoxelIndices);
+	void ColorPointsInVoxels(const TArray<int32>& VoxelIndices);
 
 	UFUNCTION(BlueprintCallable)
 	void ReadPointCloudFromFile(FFilePath FileNamePoints, FFilePath FileNameFlags);
diff --git a/Source/MetaCastBachelor/Utilities.cpp b/Source/MetaCastBachelor/Utilities.cpp
index 91ab449b6ad2f9f62b3a0a4295633ab4c3af2e30..76b42e35cda7a3a9d9cb502a09d6f3188a2160dd 100644
--- a/Source/MetaCastBachelor/Utilities.cpp
+++ b/Source/MetaCastBachelor/Utilities.cpp
@@ -116,7 +116,7 @@ FVector FUtilities::FollowGradientToMaximum(const FDensityField* DensityField, c
 
 	int Iterations = 0;
 	constexpr int MaxIterations = 100;  // Prevent infinite loops
-	constexpr float StepSize = 0.005f;  // Define a reasonable step size
+	constexpr float StepSize = 0.05f;  // Define a reasonable step size
 
 	while (Iterations < MaxIterations)
 	{
@@ -250,7 +250,7 @@ TArray<int32> FUtilities::FloodFilling_2(const FDensityField* DensityField, cons
 
 					}else
 					{
-						const float Multiplier = 1 + FMath::Pow(DistanceToStart - MaxDistance, 2);
+						const float Multiplier = 1 + FMath::Pow(DistanceToStart - MaxDistance, 1.1);
 						if(NeighborDensity > Threshold * Multiplier)
 						{
 							Stack.Push(NeighborIndex);