Skip to content
Snippets Groups Projects
Commit 01357f06 authored by Timon Römer's avatar Timon Römer
Browse files

Adds MagicWand with KDTree

parent 17190a20
Branches
No related tags found
No related merge requests found
No preview for this file type
No preview for this file type
UEPlugin-Kdtree @ 94ef56d4
Subproject commit 94ef56d465cf19d96e17b6e34c3a3739e1384a7e
#include "MagicWand.h" #include "MagicWand.h"
#include "KdtreeBPLibrary.h"
#include "Utilities.h" #include "Utilities.h"
#include "Generators/MarchingCubes.h" #include "Generators/MarchingCubes.h"
...@@ -88,7 +90,7 @@ void UMagicWand::InitMagicWandSelection() ...@@ -88,7 +90,7 @@ void UMagicWand::InitMagicWandSelection()
World = GetWorld(); World = GetWorld();
AbortMarchingCubes = true; AbortMarchingCubes = true;
AccumulatedTime = 0.0f; //AccumulatedTime = 0.0f;
} }
void UMagicWand::SelectParticles(const FVector& InputPosition) void UMagicWand::SelectParticles(const FVector& InputPosition)
...@@ -97,6 +99,7 @@ void UMagicWand::SelectParticles(const FVector& InputPosition) ...@@ -97,6 +99,7 @@ void UMagicWand::SelectParticles(const FVector& InputPosition)
{ {
AccumulatedTime = -10000; AccumulatedTime = -10000;
UE_LOG(LogTemp, Warning, TEXT("Input recognized!"));
AsyncTask(ENamedThreads::Type::AnyBackgroundHiPriTask, [this]() AsyncTask(ENamedThreads::Type::AnyBackgroundHiPriTask, [this]()
{ {
const FVector SelectionWorldPosition = SelectionObject->GetComponentLocation(); const FVector SelectionWorldPosition = SelectionObject->GetComponentLocation();
...@@ -104,7 +107,7 @@ void UMagicWand::SelectParticles(const FVector& InputPosition) ...@@ -104,7 +107,7 @@ void UMagicWand::SelectParticles(const FVector& InputPosition)
PerformMagicWandSelection(SelectionLocalPosition); PerformMagicWandSelection(SelectionLocalPosition);
UE_LOG(LogTemp, Warning, TEXT("Calculations done!")); //UE_LOG(LogTemp, Warning, TEXT("Calculations done!"));
}); });
} }
...@@ -118,6 +121,8 @@ void UMagicWand::PerformMagicWandSelection(const FVector& InputPosition) ...@@ -118,6 +121,8 @@ void UMagicWand::PerformMagicWandSelection(const FVector& InputPosition)
return; return;
} }
UE_LOG(LogTemp, Warning, TEXT("Starting Selection!"));
//UE_LOG(LogTemp, Warning, TEXT("Looking for Seed Index:")); //UE_LOG(LogTemp, Warning, TEXT("Looking for Seed Index:"));
// Find the closest point to the input position as the seed // Find the closest point to the input position as the seed
const int32 InputVoxelIndex = MyDensityField->WorldPositionToIndex(InputPosition); const int32 InputVoxelIndex = MyDensityField->WorldPositionToIndex(InputPosition);
...@@ -126,6 +131,27 @@ void UMagicWand::PerformMagicWandSelection(const FVector& InputPosition) ...@@ -126,6 +131,27 @@ void UMagicWand::PerformMagicWandSelection(const FVector& InputPosition)
int32 SeedIndex = INDEX_NONE; int32 SeedIndex = INDEX_NONE;
float MinDistance = FLT_MAX; 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) for (const int CurrentNeighborIndex : Neighbors)
{ {
TArray<int32> PointIndices = MyDensityField->VoxelPointLookupTable->GetPointsInVoxel(CurrentNeighborIndex); TArray<int32> PointIndices = MyDensityField->VoxelPointLookupTable->GetPointsInVoxel(CurrentNeighborIndex);
...@@ -149,54 +175,51 @@ void UMagicWand::PerformMagicWandSelection(const FVector& InputPosition) ...@@ -149,54 +175,51 @@ void UMagicWand::PerformMagicWandSelection(const FVector& InputPosition)
//Expand selection from the seed //Expand selection from the seed
ExpandSelection(SeedIndex); ExpandSelection(SeedIndex);
}else
{
AccumulatedTime = 0;
} }
} }
void UMagicWand::ExpandSelection(const int32 SeedIndex) void UMagicWand::ExpandSelection(const int32 SeedIndex)
{ {
UE_LOG(LogTemp, Warning, TEXT("Expanding!"));
TQueue<int32> ToProcess; TQueue<int32> ToProcess;
ToProcess.Enqueue(SeedIndex); ToProcess.Enqueue(SeedIndex);
SelectedClusterIndices.Add(SeedIndex); SelectedClusterIndices.Add(SeedIndex);
MyPointCloud->SelectionFlags[SeedIndex] = true; MyPointCloud->SelectionFlags[SeedIndex] = true;
const float SquaredProximityThreshold = ProximityThreshold * ProximityThreshold;
TArray<int> Indices;
TArray<FVector> Data;
while (!ToProcess.IsEmpty()) while (!ToProcess.IsEmpty())
{ {
int32 CurrentQueuePointIndex; int32 CurrentQueuePointIndex;
ToProcess.Dequeue(CurrentQueuePointIndex); ToProcess.Dequeue(CurrentQueuePointIndex);
FVector CurrentQueuePointPosition = MyPointCloud->PositionVectors[CurrentQueuePointIndex]; const FVector CurrentQueuePointPosition = MyPointCloud->PositionVectors[CurrentQueuePointIndex];
const int32 CurrentVoxelQueueIndex = MyDensityField->WorldPositionToIndex(CurrentQueuePointPosition); Indices.Empty();
Data.Empty();
/* UKdtreeBPLibrary::CollectFromKdtree(MyPointCloud->MyKdTree, CurrentQueuePointPosition, MyPointCloud->InfluenceRadius, Indices, Data);
TArray<int32> Neighbors = MyDensityField->IndexToVoxelNeighbors(CurrentVoxelQueueIndex);
Neighbors.Add(CurrentVoxelQueueIndex);
for (const int CurrentVoxelNeighborIndex : Neighbors) for(int i = 0; i < Indices.Num(); ++i)
{ {
TArray<int32> PointIndices = MyDensityField->VoxelPointLookupTable->GetPointsInVoxel(CurrentVoxelNeighborIndex); const int CurrentPointComparisonIndex = Indices[i];
for(const int32 CurrentPointComparisonIndex : PointIndices)
{
if(MyPointCloud->SelectionFlags[CurrentPointComparisonIndex]) if(MyPointCloud->SelectionFlags[CurrentPointComparisonIndex])
{ {
continue; continue;
} }
FVector CurrentComparisonPosition = MyDensityField->IndexToVoxelPosition(CurrentPointComparisonIndex);
if (FVector::Dist(CurrentQueuePointPosition, CurrentComparisonPosition) <= ProximityThreshold)
{
ToProcess.Enqueue(CurrentPointComparisonIndex); ToProcess.Enqueue(CurrentPointComparisonIndex);
SelectedClusterIndices.Add(CurrentPointComparisonIndex);
MyPointCloud->SelectionFlags[CurrentPointComparisonIndex] = true; MyPointCloud->SelectionFlags[CurrentPointComparisonIndex] = true;
} }
}
}*/
// -------------------
/*
const int32 StartX = FMath::Max(0, FMath::FloorToInt((CurrentQueuePointPosition.X - ProximityThreshold - MyPointCloud->MinBounds.X) / MyDensityField->GetStep().X)); 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 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 StartY = FMath::Max(0, FMath::FloorToInt((CurrentQueuePointPosition.Y - ProximityThreshold - MyPointCloud->MinBounds.Y) / MyDensityField->GetStep().Y));
...@@ -205,24 +228,23 @@ void UMagicWand::ExpandSelection(const int32 SeedIndex) ...@@ -205,24 +228,23 @@ void UMagicWand::ExpandSelection(const int32 SeedIndex)
const int32 EndZ = FMath::Min(MyDensityField->GetZNum() - 1, 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("CurrentQueuePointPosition: %s"), *CurrentQueuePointPosition.ToString());
UE_LOG(LogTemp, Warning, TEXT("StartX: %d"), StartX); UE_LOG(LogTemp, Warning, TEXT("StartX: %d"), StartX);
UE_LOG(LogTemp, Warning, TEXT("EndX: %d"), EndX); UE_LOG(LogTemp, Warning, TEXT("EndX: %d"), EndX);
UE_LOG(LogTemp, Warning, TEXT("StartY: %d"), StartY); UE_LOG(LogTemp, Warning, TEXT("StartY: %d"), StartY);
UE_LOG(LogTemp, Warning, TEXT("EndY: %d"), EndY); UE_LOG(LogTemp, Warning, TEXT("EndY: %d"), EndY);
UE_LOG(LogTemp, Warning, TEXT("StartZ: %d"), StartZ); UE_LOG(LogTemp, Warning, TEXT("StartZ: %d"), StartZ);
UE_LOG(LogTemp, Warning, TEXT("EndZ: %d"), EndZ);*/ UE_LOG(LogTemp, Warning, TEXT("EndZ: %d"), EndZ);
ParallelFor(EndZ - StartZ + 1, [&](const int32 ZOffset) {
const int32 Z = StartZ + ZOffset;
for (int32 Z = StartZ; Z <= EndZ; ++Z)
{
for (int32 Y = StartY; Y <= EndY; ++Y) for (int32 Y = StartY; Y <= EndY; ++Y)
{ {
for (int32 X = StartX; X <= EndX; ++X) for (int32 X = StartX; X <= EndX; ++X)
{ {
const int32 CurrentVoxelComparisonIndex = MyDensityField->GridPositionToIndex(X, Y, Z); const int32 CurrentVoxelComparisonIndex = MyDensityField->GridPositionToIndex(X, Y, Z);
/*
if(!MyDensityField->IsValidIndex(CurrentVoxelComparisonIndex)) if(!MyDensityField->IsValidIndex(CurrentVoxelComparisonIndex))
{ {
continue; continue;
...@@ -238,26 +260,21 @@ void UMagicWand::ExpandSelection(const int32 SeedIndex) ...@@ -238,26 +260,21 @@ void UMagicWand::ExpandSelection(const int32 SeedIndex)
} }
FVector CurrentComparisonPosition = MyPointCloud->PositionVectors[CurrentPointComparisonIndex]; FVector CurrentComparisonPosition = MyPointCloud->PositionVectors[CurrentPointComparisonIndex];
const double Distance = FVector::Distance(CurrentQueuePointPosition, CurrentComparisonPosition); const double SquaredDistance = FVector::DistSquared(CurrentQueuePointPosition, CurrentComparisonPosition);
//UE_LOG(LogTemp, Warning, TEXT("CurrentQueuePointPosition: %s"), *CurrentQueuePointPosition.ToString());
//UE_LOG(LogTemp, Warning, TEXT("CurrentComparisonPosition: %s"), *CurrentComparisonPosition.ToString());
//UE_LOG(LogTemp, Warning, TEXT("Distance: %f"), Distance);
if (Distance <= ProximityThreshold) if (SquaredDistance <= SquaredProximityThreshold)
{ {
ToProcess.Enqueue(CurrentPointComparisonIndex); ToProcess.Enqueue(CurrentPointComparisonIndex);
SelectedClusterIndices.Add(CurrentPointComparisonIndex); //SelectedClusterIndices.Add(CurrentPointComparisonIndex);
MyPointCloud->SelectionFlags[CurrentPointComparisonIndex] = true; MyPointCloud->SelectionFlags[CurrentPointComparisonIndex] = true;
} }
} }
} }
} }
}); }*/
} }
UE_LOG(LogTemp, Warning, TEXT("Calculations done!"));
AccumulatedTime = 0; AccumulatedTime = 0;
} }
......
...@@ -30,6 +30,7 @@ class UMagicWand : public UMetaCastBaseline ...@@ -30,6 +30,7 @@ class UMagicWand : public UMetaCastBaseline
float MarchingCubeSize = 0; float MarchingCubeSize = 0;
UPROPERTY(EditAnywhere) UPROPERTY(EditAnywhere)
int EvaluationsPerSecond = 10; int EvaluationsPerSecond = 10;
UPROPERTY(EditAnywhere)
float AccumulatedTime = 0.0; float AccumulatedTime = 0.0;
UPROPERTY(EditAnywhere) UPROPERTY(EditAnywhere)
float ProximityThreshold = 0.1f; float ProximityThreshold = 0.1f;
......
...@@ -10,7 +10,7 @@ public class MetaCastBachelor : ModuleRules ...@@ -10,7 +10,7 @@ public class MetaCastBachelor : ModuleRules
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "ProceduralMeshComponent", "EnhancedInput"}); PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "ProceduralMeshComponent", "EnhancedInput"});
PrivateDependencyModuleNames.AddRange(new string[] {"GPUPointCloudRenderer", "GPUPointCloudRendererEditor", "RWTHVRToolkit", "ProceduralMeshComponent"}); PrivateDependencyModuleNames.AddRange(new string[] {"GPUPointCloudRenderer", "GPUPointCloudRendererEditor", "RWTHVRToolkit", "ProceduralMeshComponent", "Kdtree"});
// Uncomment if you are using Slate UI // Uncomment if you are using Slate UI
// PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" }); // PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });
......
#include "MetaPoint.h" #include "MetaPoint.h"
#include "Utilities.h" #include "Utilities.h"
#include "Generators/MarchingCubes.h" #include "Generators/MarchingCubes.h"
#include "UObject/GCObjectScopeGuard.h"
UMetaPoint::UMetaPoint() : LocalMaximumIndex(0), MyDensityField(nullptr), MetaPointThreshold(0), World(nullptr) UMetaPoint::UMetaPoint() : LocalMaximumIndex(0), MyDensityField(nullptr), MetaPointThreshold(0), World(nullptr)
{ {
......
#include "PointCloud.h" #include "PointCloud.h"
#include "KdtreeBPLibrary.h"
#include "PointCloudDataReader.h" #include "PointCloudDataReader.h"
// Sets default values // Sets default values
APointCloud::APointCloud() APointCloud::APointCloud()
: MyDensityField(nullptr), PointCloudVisualizer(nullptr), SelectedMaterial(nullptr), UnselectedMaterial(nullptr) : MyDensityField(nullptr), MyKdTree(), PointCloudVisualizer(nullptr), SelectedMaterial(nullptr), UnselectedMaterial(nullptr)
{ {
// Set this actor to call Tick() every frame. // Set this actor to call Tick() every frame.
PrimaryActorTick.bCanEverTick = true; PrimaryActorTick.bCanEverTick = true;
...@@ -18,6 +19,10 @@ void APointCloud::BeginPlay() ...@@ -18,6 +19,10 @@ void APointCloud::BeginPlay()
ReadPointCloudFromFile(PointInputData, FlagInputData); ReadPointCloudFromFile(PointInputData, FlagInputData);
InitPointCloudVisualizer(); InitPointCloudVisualizer();
SetupDensityFieldFromPointCloud(); SetupDensityFieldFromPointCloud();
UKdtreeBPLibrary::BuildKdtree(MyKdTree, PositionVectors);
//UKdtreeBPLibrary::DumpKdtreeToConsole(MyKdTree);
UKdtreeBPLibrary::ValidateKdtree(MyKdTree);
} }
void APointCloud::ReadPointCloudFromFile(const FFilePath FileNamePoints, const FFilePath FileNameFlags) void APointCloud::ReadPointCloudFromFile(const FFilePath FileNamePoints, const FFilePath FileNameFlags)
......
#pragma once #pragma once
#include "CoreMinimal.h" #include "CoreMinimal.h"
#include "GPUPointCloudRendererComponent.h" #include "GPUPointCloudRendererComponent.h"
#include "KdtreeCommon.h"
#include "GameFramework/Actor.h" #include "GameFramework/Actor.h"
#include "MetaCastBachelor/DensityField.h" #include "MetaCastBachelor/DensityField.h"
#include "PointCloud.generated.h" #include "PointCloud.generated.h"
...@@ -12,29 +13,30 @@ class APointCloud : public AActor ...@@ -12,29 +13,30 @@ class APointCloud : public AActor
GENERATED_BODY() GENERATED_BODY()
public: public:
UPROPERTY(EditAnywhere) mutable FCriticalSection DataGuard;
float InfluenceRadius = 3.0f;
FDensityField* MyDensityField; FDensityField* MyDensityField;
FVector MinBounds;
FVector MaxBounds;
FKdtree MyKdTree;
UPROPERTY() UPROPERTY()
TArray<FVector> PositionVectors; TArray<FVector> PositionVectors;
UPROPERTY() UPROPERTY()
TArray<bool> DefaultFlags; TArray<bool> DefaultFlags;
UPROPERTY() UPROPERTY()
TArray<bool> SelectionFlags; TArray<bool> SelectionFlags;
UPROPERTY() UPROPERTY()
TArray<FColor> PointColors; TArray<FColor> PointColors;
mutable FCriticalSection DataGuard;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Bounds")
FVector MinBounds;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Bounds")
FVector MaxBounds;
UPROPERTY() UPROPERTY()
UGPUPointCloudRendererComponent* PointCloudVisualizer; UGPUPointCloudRendererComponent* PointCloudVisualizer;
UPROPERTY(EditAnywhere)
float InfluenceRadius = 3.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Visualization") UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Visualization")
float SplatSize = 1.0f; float SplatSize = 1.0f;
...@@ -50,7 +52,6 @@ public: ...@@ -50,7 +52,6 @@ public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Materials") UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Materials")
UMaterialInterface* UnselectedMaterial; UMaterialInterface* UnselectedMaterial;
// Sets default values for this actor's properties
APointCloud(); APointCloud();
void InitPointCloudVisualizer(); void InitPointCloudVisualizer();
void UpdateBounds(); void UpdateBounds();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment