From 219b291feca32a2d4266007e42be7d6b9acefa46 Mon Sep 17 00:00:00 2001
From: David Gilbert <david.gilbert@rwth-aachen.de>
Date: Fri, 18 Sep 2020 10:28:52 +0200
Subject: [PATCH] - Blueprints work now I think, there's a few weird things
happening still but at least memory isn't exploding anymore. - Serialization
is not working correctly, a property needs to be changed for lines to
display.
---
.../InstancedMeshLineRendering.Build.cs | 3 +-
.../Private/GPUInstancedLineComponent.cpp | 193 ++++++++----------
.../Public/GPUInstancedLineComponent.h | 92 ++++++---
3 files changed, 154 insertions(+), 134 deletions(-)
diff --git a/Source/InstancedMeshLineRendering/InstancedMeshLineRendering.Build.cs b/Source/InstancedMeshLineRendering/InstancedMeshLineRendering.Build.cs
index 3b05bab..e5c8687 100644
--- a/Source/InstancedMeshLineRendering/InstancedMeshLineRendering.Build.cs
+++ b/Source/InstancedMeshLineRendering/InstancedMeshLineRendering.Build.cs
@@ -37,8 +37,7 @@ public class InstancedMeshLineRendering : ModuleRules
{
"CoreUObject",
"Engine",
- "Slate",
- "SlateCore",
+ "RenderCore"
// ... add private dependencies that you statically link with here ...
}
);
diff --git a/Source/InstancedMeshLineRendering/Private/GPUInstancedLineComponent.cpp b/Source/InstancedMeshLineRendering/Private/GPUInstancedLineComponent.cpp
index 247356b..3be69d7 100644
--- a/Source/InstancedMeshLineRendering/Private/GPUInstancedLineComponent.cpp
+++ b/Source/InstancedMeshLineRendering/Private/GPUInstancedLineComponent.cpp
@@ -9,6 +9,19 @@
UGPUInstancedLineComponent::UGPUInstancedLineComponent(const FObjectInitializer& ObjectInitializer)
{
+ NumCustomDataFloats = 5;
+
+ CurrentTextureMarker = FIntPoint(0, 0);
+ CurrentTextureIndex = 0,
+ NextFreeId = 0;
+
+ TextureWidth = 1024;
+ TextureHeight = 1024;
+
+ //PrimaryComponentTick.bCanEverTick = true;
+ //bTickInEditor = true;
+ //bAutoActivate = true;
+
SetWorldTransform(FTransform::Identity);
SetUsingAbsoluteLocation(true);
@@ -26,27 +39,10 @@ UGPUInstancedLineComponent::UGPUInstancedLineComponent(const FObjectInitializer&
SetMaterial(0, LineMaterial);
- UMaterialInterface* LineMaterialInterface = LoadObject<UMaterialInterface>(NULL, TEXT("/InstancedMeshLineRendering/DynamicLineMaterial.DynamicLineMaterial"), NULL, LOAD_None, NULL);
- DynamicLineMaterial = UMaterialInstanceDynamic::Create(LineMaterialInterface, GetTransientPackage());
- check(DynamicLineMaterial);
-
-
- // three color values + width + 1 texture index value
- // r | g | b | w | i_T
- NumCustomDataFloats = 5;
-
- CurrentTextureMarker = FIntPoint(0, 0);
- CurrentTextureIndex = 0,
- NextFreeId = 0;
-
- TextureWidth = 2048;
- TextureHeight = 2048;
-
+ LineMaterialInterface = LoadObject<UMaterialInterface>(NULL, TEXT("/InstancedMeshLineRendering/DynamicLineMaterial.DynamicLineMaterial"), NULL, LOAD_None, NULL);
+ //DynamicLineMaterial = UMaterialInstanceDynamic::Create(LineMaterialInterface, GetTransientPackage());
+ SetMaterial(0, DynamicLineMaterial);
SetMobility(EComponentMobility::Static);
-
-
- //DynamicLineMaterial = nullptr;
- //PositionTexture = nullptr;
}
UGPUInstancedLineComponent::~UGPUInstancedLineComponent()
@@ -89,68 +85,35 @@ void UGPUInstancedLineComponent::UpdateWholeTexture()
}
void UGPUInstancedLineComponent::Init()
-{
- if(PositionTexture != nullptr)
+{
+ if (PositionTexture == nullptr)
{
- UE_LOG(LogLineRendering, Error, TEXT("UGPUInstancedLineComponent::Init PositionTexture already exists!"));
+ UE_LOG(LogLineRendering, Display, TEXT("UGPUInstancedLineComponent::Init Creating Texture"));
+ PositionTexture = UTexture2D::CreateTransient(TextureWidth, TextureHeight, PF_A32B32G32R32F);
+ //// Allocate the texture RHI
+ PositionTexture->UpdateResource();
+ UpdateWholeTexture();
}
- UE_LOG(LogLineRendering, Display, TEXT("UGPUInstancedLineComponent::Init Creating Texture"));
- PositionTexture = UTexture2D::CreateTransient(TextureWidth, TextureHeight, PF_A32B32G32R32F);
- // Allocate the texture RHI
- PositionTexture->UpdateResource();
-
if (DynamicLineMaterial == nullptr) // FOR WHATEVER REASON I HAVE NO IDEA
{
- UE_LOG(LogLineRendering, Fatal, TEXT("UGPUInstancedLineComponent::Init MID was nullptr!"));
- }
- else
- {
- UE_LOG(LogLineRendering, Display, TEXT("UGPUInstancedLineComponent::Init Setting MID"));
-
+ //UE_LOG(LogLineRendering, Display, TEXT("UGPUInstancedLineComponent::Init MID was nullptr!"));
+ DynamicLineMaterial = UMaterialInstanceDynamic::Create(LineMaterialInterface, GetTransientPackage());
SetMaterial(0, DynamicLineMaterial);
- DynamicLineMaterial->SetTextureParameterValue("PositionTexture", PositionTexture);
- DynamicLineMaterial->SetScalarParameterValue("TextureWidth", TextureWidth);
- }
+ //check(DynamicLineMaterial);
- //UE_LOG(LogLineRendering, Display, TEXT("UGPUInstancedLineComponent::Init Resetting Data"));
- //LineMap.Empty();
- //LinearLineData.Empty();
- //NextFreeId = 0;
- //CurrentTextureIndex = 0;
- //CurrentTextureMarker = FIntPoint(0, 0);
- //ClearInstances();
+ //DynamicLineMaterial = CreateAndSetMaterialInstanceDynamic(0);
+ //DynamicLineMaterial->SetTextureParameterValue("PositionTexture", PositionTexture);
+ //DynamicLineMaterial->SetScalarParameterValue("TextureWidth", TextureWidth);
+ }
- //RegisterSerializedEditorLines();
+ DynamicLineMaterial->SetTextureParameterValue("PositionTexture", PositionTexture);
+ DynamicLineMaterial->SetScalarParameterValue("TextureWidth", TextureWidth);
+ //UpdateWholeTexture();
bIsInitialized = true;
-
- //// Add serialized lines to be rendered immediately - pretty sure this could and should be done differently.
- //for (FEditorLineData& EditorLine : EditorLines)
- //{
- // AddLineFromEditorData(EditorLine);
- //}
-
- // Update the texture
-
- // Theoretically we could serialize the texture as well, but that seems like too much work
- UpdateWholeTexture();
}
-//void UGPUInstancedLineComponent::RegisterSerializedEditorLines()
-//{
-//
-// // Here's to hoping the respective id field doesn't get serialized...
-//
-// for (FEditorLineData& EditorLine : EditorLines)
-// {
-// if(EditorLine.RespectiveLineId == -1 || !LineMap.Contains(EditorLine.RespectiveLineId))
-// {
-// AddLineFromEditorData(EditorLine);
-// }
-// }
-//}
-
void UGPUInstancedLineComponent::UpdateAllEditorLines()
{
for (const FEditorLineData& EditorLine : EditorLines)
@@ -235,14 +198,11 @@ FUpdateTextureRegion2D* UGPUInstancedLineComponent::CalculateTextureRegions(cons
void UGPUInstancedLineComponent::BeginPlay()
{
Super::BeginPlay();
-
- // todo don't think this is needed here
- //RegisterSerializedEditorLines();
- //Init();
- if(!bIsInitialized)
+ if(!PositionTexture)
{
- UE_LOG(LogLineRendering, Fatal, TEXT("UGPUInstancedLineComponent::BeginPlay: FATAL ERROR - Component is not initialized on BeginPlay!"));
+ UE_LOG(LogLineRendering, Warning, TEXT("UGPUInstancedLineComponent::BeginPlay: Component is not initialized on BeginPlay, Initializing..."));
+ Init();
}
}
@@ -250,15 +210,16 @@ void UGPUInstancedLineComponent::BeginPlay()
void UGPUInstancedLineComponent::PostInitProperties()
{
Super::PostInitProperties();
- if (FApp::CanEverRender() && !HasAnyFlags(RF_ClassDefaultObject | RF_ArchetypeObject))
- UE_LOG(LogLineRendering, Display, TEXT("UGPUInstancedLineComponent::PostInitProperties IF"));
-
+ //if (FApp::CanEverRender() && !HasAnyFlags(RF_ClassDefaultObject | RF_ArchetypeObject))
+ //UE_LOG(LogLineRendering, Display, TEXT("UGPUInstancedLineComponent::PostInitProperties IF"));
}
#if WITH_EDITOR
void UGPUInstancedLineComponent::PostEditChangeChainProperty(FPropertyChangedChainEvent& PropertyChangedEvent)
{
- if (PropertyChangedEvent.Property != NULL && bIsInitialized)
+ Init();
+
+ if (PropertyChangedEvent.Property != NULL)
{
if (PropertyChangedEvent.Property->GetFName() == GET_MEMBER_NAME_CHECKED(UGPUInstancedLineComponent, EditorLines))
{
@@ -419,6 +380,7 @@ void UGPUInstancedLineComponent::PostEditChangeChainProperty(FPropertyChangedCha
void UGPUInstancedLineComponent::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
+ Init();
const FName PropertyName = PropertyChangedEvent.GetPropertyName();
if (PropertyChangedEvent.Property != NULL)
@@ -444,34 +406,65 @@ void UGPUInstancedLineComponent::OnUpdateTransform(EUpdateTransformFlags UpdateT
{
SetWorldTransform(FTransform::Identity);
}
+
+TStructOnScope<FActorComponentInstanceData> UGPUInstancedLineComponent::GetComponentInstanceData() const
+{
+ TStructOnScope<FActorComponentInstanceData> InstanceData;
+#if WITH_EDITOR
+ InstanceData.InitializeAs<FUGPUInstancedLineComponentInstanceData>(this);
+ FUGPUInstancedLineComponentInstanceData* LineInstanceData = InstanceData.Cast<FUGPUInstancedLineComponentInstanceData>();
+
+ //LineInstanceData->PositionTexture = PositionTexture;
+ //LineInstanceData->DynamicMaterial = DynamicLineMaterial;
+ //LineInstanceData->LineMap = LineMap;
+
+#endif
+ return InstanceData;
+}
#endif
+void UGPUInstancedLineComponent::ApplyComponentInstanceData(FUGPUInstancedLineComponentInstanceData* ComponentInstanceData)
+{
+#if WITH_EDITOR
+ //check(ComponentInstanceData);
+ //if(ComponentInstanceData->PositionTexture != nullptr)
+ // PositionTexture = ComponentInstanceData->PositionTexture;
+ //if (ComponentInstanceData->DynamicMaterial != nullptr)
+ //{
+ // DynamicLineMaterial = ComponentInstanceData->DynamicMaterial;
+ // DynamicLineMaterial->SetTextureParameterValue("PositionTexture", PositionTexture);
+ // DynamicLineMaterial->SetScalarParameterValue("TextureWidth", TextureWidth);
+ // SetMaterial(0, DynamicLineMaterial);
+ //}
+ //if (ComponentInstanceData->LineMap.Num() > 0)
+ // LineMap = ComponentInstanceData->LineMap;
+
+
+#endif
+}
+
// Doesn't do anything yet, just as a testing function to see execution order on Unreal startup.
void UGPUInstancedLineComponent::PostLoad()
{
Super::PostLoad();
- UE_LOG(LogLineRendering, Display, TEXT("UGPUInstancedLineComponent::PostLoad"));
- if (FApp::CanEverRender() && !HasAnyFlags(RF_ClassDefaultObject | RF_ArchetypeObject))
- {
- UE_LOG(LogLineRendering, Display, TEXT("UGPUInstancedLineComponent::PostLoad IF"));
-
- if (!bIsInitialized)
- Init();
- }
+ //UE_LOG(LogLineRendering, Display, TEXT("UGPUInstancedLineComponent::PostLoad"));
+ //if (FApp::CanEverRender() && !IsTemplate())
+ //{
+ //DynamicLineMaterial = UMaterialInstanceDynamic::Create(LineMaterialInterface, this);
+ //SetMaterial(0, DynamicLineMaterial);
+ //}
}
// Doesn't do anything yet, just as a testing function to see execution order on Unreal startup.
void UGPUInstancedLineComponent::OnComponentCreated()
{
Super::OnComponentCreated();
- UE_LOG(LogLineRendering, Display, TEXT("UGPUInstancedLineComponent::OnComponentCreated"));
- if (FApp::CanEverRender() && !HasAnyFlags(RF_ClassDefaultObject | RF_ArchetypeObject))
- {
- UE_LOG(LogLineRendering, Display, TEXT("UGPUInstancedLineComponent::OnComponentCreated IF"));
-
- if (!bIsInitialized)
- Init();
- }
+ //UE_LOG(LogLineRendering, Display, TEXT("UGPUInstancedLineComponent::OnComponentCreated"));
+ //if (FApp::CanEverRender() && !IsTemplate())
+ //{
+ // DynamicLineMaterial = UMaterialInstanceDynamic::Create(LineMaterialInterface, this);
+ // SetMaterial(0, DynamicLineMaterial);
+ //}
}
void UGPUInstancedLineComponent::BeginDestroy()
@@ -483,9 +476,6 @@ void UGPUInstancedLineComponent::BeginDestroy()
void UGPUInstancedLineComponent::Serialize(FArchive& Ar)
{
Super::Serialize(Ar);
-
-
-
}
void UGPUInstancedLineComponent::ReserveMemory(int32 NumberOfSegments, int32 NumberOfLines)
@@ -493,10 +483,7 @@ void UGPUInstancedLineComponent::ReserveMemory(int32 NumberOfSegments, int32 Num
const int32 Total = NumberOfSegments * NumberOfLines;
PreAllocateInstancesMemory(Total);
LineMap.Reserve(Total);
- LinearLineData.Reserve(NumberOfLines * (NumberOfSegments + 1));
-
- // TODO: Texture size
-
+ LinearLineData.Reserve(NumberOfLines * (NumberOfSegments + 1));
}
bool UGPUInstancedLineComponent::ResizeTexture(int32 Width, int32 Height)
diff --git a/Source/InstancedMeshLineRendering/Public/GPUInstancedLineComponent.h b/Source/InstancedMeshLineRendering/Public/GPUInstancedLineComponent.h
index c9e7e5a..c026ebf 100644
--- a/Source/InstancedMeshLineRendering/Public/GPUInstancedLineComponent.h
+++ b/Source/InstancedMeshLineRendering/Public/GPUInstancedLineComponent.h
@@ -6,27 +6,6 @@
#include "Components/InstancedStaticMeshComponent.h"
#include "GPUInstancedLineComponent.generated.h"
-/**
- *
- */
-
-//typedef TPair<FVector, TTuple<int32, int32, int32>> GPULineSegment;
-
-// Pair of InstanceId and LinearData index.
-//
-
-
-
-// LineArray that contains indices into the instance list and the linear data.
-
-typedef TPair<int32, int32> GPULineIndices;
-
-typedef TArray<GPULineIndices> GPULineArray;
-
-// Maps a LineId to a LineArray.
-typedef TMap<int32, GPULineArray> GPULinesMap;
-
-
USTRUCT(BlueprintType)
struct FEditorPoint
@@ -62,7 +41,7 @@ struct FEditorLineData
UPROPERTY(EditAnywhere)
FColor Color;
- UPROPERTY()
+ UPROPERTY(VisibleAnywhere)
int32 RespectiveLineId = -1;
FEditorLineData()
@@ -116,7 +95,7 @@ class INSTANCEDMESHLINERENDERING_API UGPUInstancedLineComponent : public UInstan
public:
UGPUInstancedLineComponent(const FObjectInitializer& ObjectInitializer);
- ~UGPUInstancedLineComponent();
+ virtual ~UGPUInstancedLineComponent();
virtual void BeginPlay() override;
@@ -125,10 +104,14 @@ public:
virtual void PostEditChangeChainProperty(FPropertyChangedChainEvent& PropertyChangedEvent) override;
virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override; // need this for the widget as for some godforsaken reason the Chain event doesn't fire...
// This is ABSURDLY hacky
- virtual void OnUpdateTransform(EUpdateTransformFlags UpdateTransformFlags, ETeleportType Teleport = ETeleportType::None) override;
-
+ virtual void OnUpdateTransform(EUpdateTransformFlags UpdateTransformFlags, ETeleportType Teleport = ETeleportType::None) override;
#endif
+ virtual TStructOnScope<FActorComponentInstanceData> GetComponentInstanceData() const override;
+
+ /** Applies the cached component instance data to a newly blueprint constructed component. */
+ virtual void ApplyComponentInstanceData(struct FUGPUInstancedLineComponentInstanceData* ComponentInstanceData);
+
virtual void PostLoad() override;
virtual void OnComponentCreated() override;
virtual void BeginDestroy() override;
@@ -148,7 +131,6 @@ private:
}
}
- void UpdateWholeTexture();
void Init();
@@ -162,6 +144,9 @@ public:
// todo
void ReleaseData();
+ void UpdateWholeTexture();
+
+
/**
* Reserves internal memory for a given amount of Lines and Segments per Line.
*/
@@ -458,17 +443,20 @@ public:
UPROPERTY(BlueprintReadOnly, EditAnywhere)
int32 TextureHeight;
- UPROPERTY(transient)
+ UPROPERTY(Transient)
UMaterialInstanceDynamic* DynamicLineMaterial;
UPROPERTY(EditAnywhere, DisplayName = "Lines", meta = (MakeEditWidget = true, EditFixedOrder))
TArray<FEditorLineData> EditorLines;
-private:
-
+ UPROPERTY()
+ UMaterialInterface* LineMaterialInterface;
+
UPROPERTY()
TMap<int32, FGPULineArray> LineMap;
+//private:
+
UPROPERTY()
TArray<FVector4> LinearLineData;
@@ -487,5 +475,51 @@ private:
UPROPERTY()
FIntPoint CurrentTextureMarker;
+ UPROPERTY(Transient)
bool bIsInitialized = false;
+};
+
+
+/** Helper class used to preserve texture pointer across blueprint reinstancing */
+USTRUCT()
+struct FUGPUInstancedLineComponentInstanceData : public FSceneComponentInstanceData
+{
+ GENERATED_BODY()
+public:
+ FUGPUInstancedLineComponentInstanceData() = default;
+ FUGPUInstancedLineComponentInstanceData(const UGPUInstancedLineComponent* InComponent)
+ : FSceneComponentInstanceData(InComponent)
+ , PositionTexture(InComponent->PositionTexture), LineMap(InComponent->LineMap)
+ {}
+ virtual ~FUGPUInstancedLineComponentInstanceData() = default;
+
+ virtual bool ContainsData() const override
+ {
+ return true;
+ }
+
+ virtual void ApplyToComponent(UActorComponent* Component, const ECacheApplyPhase CacheApplyPhase) override
+ {
+ Super::ApplyToComponent(Component, CacheApplyPhase);
+ CastChecked<UGPUInstancedLineComponent>(Component)->ApplyComponentInstanceData(this);
+ }
+
+ virtual void AddReferencedObjects(FReferenceCollector& Collector) override
+ {
+ Super::AddReferencedObjects(Collector);
+ Collector.AddReferencedObject(PositionTexture);
+ }
+
+public:
+
+
+
+ //UPROPERTY()
+ UTexture2D* PositionTexture;
+
+ //UPROPERTY()
+ UMaterialInstanceDynamic* DynamicMaterial;
+
+ //UPROPERTY()
+ TMap<int32, FGPULineArray> LineMap;
};
\ No newline at end of file
--
GitLab