Agrarsense
Public Member Functions | Protected Attributes | Private Member Functions | Private Attributes | Static Private Attributes | List of all members
AInstancedRendererManager Class Reference

#include <InstancedRendererManager.h>

Inheritance diagram for AInstancedRendererManager:
Inheritance graph
[legend]
Collaboration diagram for AInstancedRendererManager:
Collaboration graph
[legend]

Public Member Functions

 AInstancedRendererManager (const FObjectInitializer &ObjectInitializer)
 
virtual void BeginPlay () override
 
virtual void EndPlay (const EEndPlayReason::Type EndPlayReason) override
 
bool AddActorToInstancedRendering (AInstancedActor *InstancedActor)
 
bool AppendISM (UInstancedStaticMeshComponent *ISM)
 
bool AppendOrCreateISM (UInstancedStaticMeshComponent *ISM)
 
void SpawnAllInstancesBackToActors ()
 
bool SpawnInstanceBackToActor (UInstancedStaticMeshComponent *ISM, int32 Index, bool OnlyTree)
 
void ExportTreesAsCSV ()
 
void DestroyOverlappingInstancesBox (UInstancedStaticMeshComponent *ISM, FBox AreaBox, bool OnlyTrees)
 
void SetInstancedRendering (bool Visible)
 
TArray< AInstancedActorRenderer * > GetAllInstancedActorRendererActors () const
 
int32 GetTotalInstanceCount ()
 

Protected Attributes

TArray< AInstancedActorRenderer * > InstancedRenderers
 
int32 TotalInstanceCount = 0
 

Private Member Functions

void OnActorSpawned (AActor *Actor)
 

Private Attributes

FDelegateHandle ActorSpawnedDelegateHandle
 
bool AllowISMCreation = true
 

Static Private Attributes

static AInstancedRendererManagerInstance = nullptr
 

Detailed Description

Manages all AInstancedActorRenderer actors. Handles adding/removing instances, spawning them back into actors, and toggling visibility.

Definition at line 20 of file InstancedRendererManager.h.

Constructor & Destructor Documentation

◆ AInstancedRendererManager()

AInstancedRendererManager::AInstancedRendererManager ( const FObjectInitializer &  ObjectInitializer)

Definition at line 16 of file InstancedRendererManager.cpp.

16 : Super(ObjectInitializer)
17{
18 PrimaryActorTick.bCanEverTick = false;
19}

Member Function Documentation

◆ AddActorToInstancedRendering()

bool AInstancedRendererManager::AddActorToInstancedRendering ( AInstancedActor InstancedActor)

Adds an AInstancedActor to the appropriate instanced renderer.

Definition at line 92 of file InstancedRendererManager.cpp.

93{
95 {
96 return false;
97 }
98
99 if (!InstancedActor)
100 {
101#if WITH_EDITOR
102 UE_LOG(LogTemp, Warning, TEXT("InstancedRenderer.cpp: Actor is null!"));
103#endif
104 return false;
105 }
106
107 if (InstancedActor->UpdateTransformAutomatically())
108 {
109#if WITH_EDITOR
110 UE_LOG(LogTemp, Warning, TEXT("InstancedRenderer.cpp: AInstancedActor %s is set to update transform automatically."), *InstancedActor->GetName());
111#endif
112 return false;
113 }
114
115 UStaticMeshComponent* StaticMeshComponent = InstancedActor->GetStaticMeshComponent();
116 if (!StaticMeshComponent)
117 {
118#if WITH_EDITOR
119 UE_LOG(LogTemp, Warning, TEXT("InstancedRenderer.cpp: AInstancedActor %s UStaticMeshComponent is null!"), *InstancedActor->GetName());
120#endif
121 return false;
122 }
123
124 UStaticMesh* Mesh = StaticMeshComponent->GetStaticMesh();
125 if (!Mesh)
126 {
127#if WITH_EDITOR
128 UE_LOG(LogTemp, Warning, TEXT("InstancedRenderer.cpp: AInstancedActor %s UStaticMeshComponent mesh is null!"), *InstancedActor->GetName());
129#endif
130 return false;
131 }
132
133 // Loop throigh InstancedRenderers and check if we already have this type of instance in the world.
135 {
136 if (Renderer && Renderer->Matches(StaticMeshComponent, InstancedActor->AlternativeMaterial))
137 {
138 UInstancedStaticMeshComponent* Comp = Renderer->GetInstancedStaticMeshComponent();
139 if (Comp)
140 {
141 Comp->AddInstance(InstancedActor->GetActorTransform());
142 InstancedActor->InstanceAdded();
143 InstancedActor->Destroy();
144 return true;
145 }
146 }
147 }
148
149 // Else this is new instance, create new AInstancedActorRenderer Actor.
150 FTransform SpawnTransform = FTransform::Identity;
151 FActorSpawnParameters SpawnParams;
152
153 AInstancedActorRenderer* NewRenderer = GetWorld()->SpawnActor<AInstancedActorRenderer>(
154 AInstancedActorRenderer::StaticClass(),
155 SpawnTransform,
156 SpawnParams
157 );
158
159 InstancedRenderers.AddUnique(NewRenderer);
160 NewRenderer->SetupFromInstancedActor(InstancedActor);
161
162 return true;
163}
void SetupFromInstancedActor(AInstancedActor *InstancedActor)
bool UpdateTransformAutomatically() const
UStaticMeshComponent * GetStaticMeshComponent() const
TArray< AInstancedActorRenderer * > InstancedRenderers

References AllowISMCreation, AInstancedActor::AlternativeMaterial, AInstancedActor::GetStaticMeshComponent(), AInstancedActor::InstanceAdded(), InstancedRenderers, AInstancedActorRenderer::SetupFromInstancedActor(), and AInstancedActor::UpdateTransformAutomatically().

Referenced by BeginPlay(), and OnActorSpawned().

◆ AppendISM()

bool AInstancedRendererManager::AppendISM ( UInstancedStaticMeshComponent *  ISM)

Appends an existing Instanced Static Mesh (ISM) to a matching AInstancedActorRenderer instance.

Definition at line 165 of file InstancedRendererManager.cpp.

166{
167 if (!ISM)
168 {
169 return false;
170 }
171
173 {
174 if (!Renderer || !Renderer->Matches(ISM))
175 {
176 continue;
177 }
178
179 UInstancedStaticMeshComponent* Comp = Renderer->GetInstancedStaticMeshComponent();
180 if (!Comp)
181 {
182 continue;
183 }
184
185 const int32 InstanceCount = ISM->GetInstanceCount();
186 for (int32 i = 0; i < InstanceCount; ++i)
187 {
188 FTransform InstanceTransform;
189 if (ISM->GetInstanceTransform(i, InstanceTransform, true))
190 {
191 Comp->AddInstance(InstanceTransform);
192 }
193 }
194
195 return true;
196 }
197
198 return false;
199}

References InstancedRenderers.

Referenced by AppendOrCreateISM().

◆ AppendOrCreateISM()

bool AInstancedRendererManager::AppendOrCreateISM ( UInstancedStaticMeshComponent *  ISM)

Appends an existing Instanced Static Mesh (ISM) to a matching AInstancedActorRenderer instance. If no matching renderer exists, creates a new one.

Definition at line 201 of file InstancedRendererManager.cpp.

202{
203 if (!ISM)
204 {
205 return false;
206 }
207
208 if (!AppendISM(ISM))
209 {
210 FTransform SpawnTransform = FTransform::Identity;
211 FActorSpawnParameters SpawnParams;
212
213 AInstancedActorRenderer* NewRenderer = GetWorld()->SpawnActor<AInstancedActorRenderer>(
214 AInstancedActorRenderer::StaticClass(),
215 SpawnTransform,
216 SpawnParams
217 );
218
219 if (!NewRenderer)
220 {
221 return false;
222 }
223
224 InstancedRenderers.AddUnique(NewRenderer);
225
226 UInstancedStaticMeshComponent* Comp = NewRenderer->GetInstancedStaticMeshComponent();
227
228 if (Comp)
229 {
230 Comp->SetStaticMesh(ISM->GetStaticMesh());
231 const int32 NumberOfMaterials = ISM->GetNumMaterials();
232 for (int32 i = 0; i < NumberOfMaterials; i++)
233 {
234 Comp->SetMaterial(i, ISM->GetMaterial(i));
235 }
236
237 TArray<FTransform> InstanceTransforms;
238 for (int32 i = 0; i < ISM->GetInstanceCount(); i++)
239 {
240 FTransform InstanceTransform;
241 if (ISM->GetInstanceTransform(i, InstanceTransform, true))
242 {
243 InstanceTransforms.Add(InstanceTransform);
244 }
245 }
246
247 for (const FTransform& Transform : InstanceTransforms)
248 {
249 Comp->AddInstance(Transform);
250 }
251 }
252
253 return true;
254 }
255
256 return true;
257}
UInstancedStaticMeshComponent * GetInstancedStaticMeshComponent() const
bool AppendISM(UInstancedStaticMeshComponent *ISM)

References AppendISM(), AInstancedActorRenderer::GetInstancedStaticMeshComponent(), InstancedRenderers, and Transform.

◆ BeginPlay()

void AInstancedRendererManager::BeginPlay ( )
overridevirtual

Definition at line 21 of file InstancedRendererManager.cpp.

22{
23 Super::BeginPlay();
24
25 if (!Instance)
26 {
27 Instance = this;
28 }
29 else
30 {
31#if WITH_EDITOR
32 UE_LOG(LogTemp, Warning, TEXT("InstancedRenderer.cpp: Instance already exists. Destroying this actor.."));
33#endif
34 Destroy();
35 }
36
37 UWorld* World = GetWorld();
38
39
40 // Ensure we don't create ISM's for these maps.
41 // Instance Segmentation Camera sensor doesn't support ISM/HISM components (or non-nanite meshes).
42 FString MapName = World->GetMapName().ToLower();
43 if (MapName.Contains(TEXT("vindeln_dev")) || MapName.Contains(TEXT("rovaniemiforest_dev")))
44 {
45 AllowISMCreation = false;
46 }
47
49 {
50 // Get all existing AInstancedActor in the world and try to add them to instanced rendering.
51 TArray<AActor*> Actors;
52 UGameplayStatics::GetAllActorsOfClass(World, AInstancedActor::StaticClass(), Actors);
53
54 for (AActor* Actor : Actors)
55 {
56 AInstancedActor* InstancedActor = Cast<AInstancedActor>(Actor);
57 if (InstancedActor && InstancedActor->CanAddToInstancedRenderer())
58 {
59 AddActorToInstancedRendering(InstancedActor);
60 }
61 }
62
63 // Subscribe to OnActorSpawned event to catch any new AInstancedActor spawned in the world to add them to instanced rendering.
64 ActorSpawnedDelegateHandle = World->AddOnActorSpawnedHandler(FOnActorSpawned::FDelegate::CreateUObject(this, &AInstancedRendererManager::OnActorSpawned));
65 }
66}
bool CanAddToInstancedRenderer()
static AInstancedRendererManager * Instance
bool AddActorToInstancedRendering(AInstancedActor *InstancedActor)

References ActorSpawnedDelegateHandle, AddActorToInstancedRendering(), AllowISMCreation, AInstancedActor::CanAddToInstancedRenderer(), Destroy, Instance, and OnActorSpawned().

◆ DestroyOverlappingInstancesBox()

void AInstancedRendererManager::DestroyOverlappingInstancesBox ( UInstancedStaticMeshComponent *  ISM,
FBox  AreaBox,
bool  OnlyTrees 
)

Destroys all instances overlapping the specified Box area.

Parameters
ISM- The instanced static mesh component.
AreaBox- The bounding box defining the area to check.
OnlyTrees- Whether to limit destruction to tree instances only.

Definition at line 329 of file InstancedRendererManager.cpp.

330{
331 if (!ISM)
332 {
333 return;
334 }
335
337 {
338 if (!Renderer)
339 {
340 continue;
341 }
342
343 FInstancedActorParameters params = Renderer->GetInstancedActorParameters();
344 if (!params.IsTree && OnlyTrees)
345 {
346 continue;
347 }
348
349 UInstancedStaticMeshComponent* Comp = Renderer->GetInstancedStaticMeshComponent();
350 if (Comp && Comp == ISM)
351 {
352 TArray<int32> OverlappingInstances = Comp->GetInstancesOverlappingBox(AreaBox);
353
354 // Sort indices in descending order to avoid shifting issues
355 OverlappingInstances.Sort([](int32 A, int32 B)
356 {
357 return B < A;
358 });
359
360 for (int32 InstanceIndex : OverlappingInstances)
361 {
362 Comp->RemoveInstance(InstanceIndex);
363 }
364 }
365 }
366}

References InstancedRenderers, and FInstancedActorParameters::IsTree.

Referenced by ADeletionVolume::DestroyOverlappingActors().

◆ EndPlay()

void AInstancedRendererManager::EndPlay ( const EEndPlayReason::Type  EndPlayReason)
overridevirtual

Definition at line 80 of file InstancedRendererManager.cpp.

81{
82 Super::EndPlay(EndPlayReason);
83
85
86 if (Instance == this)
87 {
88 Instance = nullptr;
89 }
90}

References ActorSpawnedDelegateHandle, and Instance.

◆ ExportTreesAsCSV()

void AInstancedRendererManager::ExportTreesAsCSV ( )

Definition at line 383 of file InstancedRendererManager.cpp.

384{
385 AGeoReferencingSystem* GeoReferencingSystem = AGeoReferencingSystem::GetGeoReferencingSystem(GetWorld());
386 TArray<TArray<FString>> Rows;
387
389 {
390 if (Renderer && Renderer->GetInstancedActorParameters().IsTree)
391 {
392 UInstancedStaticMeshComponent* ISM = Renderer->GetInstancedStaticMeshComponent();
393 if (!ISM) continue;
394
395 const int32 InstanceCount = ISM->GetInstanceCount();
396 const FString MeshName = Renderer->GetStaticMesh() ? Renderer->GetStaticMesh()->GetName() : TEXT("Unknown");
397
398 for (int32 i = 0; i < InstanceCount; ++i)
399 {
400 FTransform Transform;
401 if (!ISM->GetInstanceTransform(i, Transform, true)) continue;
402
403 const FVector Location = Transform.GetLocation();
404 const FRotator Rotation = Transform.Rotator();
405
406 FString LatitudeStr = TEXT(""), LongitudeStr = TEXT(""), AltitudeStr = TEXT("");
407
408 if (GeoReferencingSystem)
409 {
410 const FGeographicCoordinates GeographicCoordinates = UCoordinateConversionUtilities::UnrealToGeographicCoordinates(GeoReferencingSystem, Location);
411 LatitudeStr = FString::Printf(TEXT("%.8f"), GeographicCoordinates.Latitude);
412 LongitudeStr = FString::Printf(TEXT("%.8f"), GeographicCoordinates.Longitude);
413 AltitudeStr = FString::Printf(TEXT("%.8f"), GeographicCoordinates.Altitude);
414 }
415
416 TArray<FString> Row;
417 Row.Add(MeshName);
418 Row.Add(FString::Printf(TEXT("%.2f"), Location.X));
419 Row.Add(FString::Printf(TEXT("%.2f"), Location.Y));
420 Row.Add(FString::Printf(TEXT("%.2f"), Location.Z));
421
422 if (GeoReferencingSystem)
423 {
424 Row.Add(LatitudeStr);
425 Row.Add(LongitudeStr);
426 Row.Add(AltitudeStr);
427 }
428
429 Rows.Add(Row);
430 }
431 }
432 }
433
434 if (Rows.IsEmpty())
435 {
436 return;
437 }
438
439 // CSV file settings
440 FCSVFileSettings Settings;
442 Settings.Append = false;
443 Settings.CreateUnique = true;
445
446 // Filename
447 FString MapName = GetWorld()->GetMapName();
448 FString FileName = MapName + TEXT("_TreeLocations");
449
450 // Create CSV file
451 UCSVFile* CSV = UCSVFile::CreateCSVFile(FileName, Settings);
452
453 // Create CSV Header row
454 TArray<FString> Header = { TEXT("name"), TEXT("x"), TEXT("y"), TEXT("z") };
455 if (GeoReferencingSystem)
456 {
457 Header.Append({ TEXT("latitude"), TEXT("longitude"), TEXT("altitude") });
458 }
459 CSV->WriteRow(Header);
460
461 // Write data rows
462 for (const TArray<FString>& Row : Rows)
463 {
464 CSV->WriteRow(Row);
465 }
466
467 // Finish writing and close the file
468 CSV->Destroy();
469}
static UCSVFile * CreateCSVFile(const FString &FileNameWithoutExtension, const FCSVFileSettings &Settings)
Definition: CSVFile.cpp:15
void WriteRow(const TArray< FString > &Cells)
Definition: CSVFile.cpp:78
void Destroy()
Definition: CSVFile.cpp:134
static FGeographicCoordinates UnrealToGeographicCoordinates(AGeoReferencingSystem *GeoReferencingSystem, const FVector &Position)
bool CreateUnique
Definition: CSVFile.h:42
ECSVDelimiter Delimiter
Definition: CSVFile.h:36
FCSVFileWriteOptions FileWriteOption
Definition: CSVFile.h:45

References FCSVFileSettings::Append, UCSVFile::CreateCSVFile(), FCSVFileSettings::CreateUnique, FCSVFileSettings::Delimiter, UCSVFile::Destroy(), FCSVFileSettings::FileWriteOption, InstancedRenderers, Queue, Semicolon, Transform, UCoordinateConversionUtilities::UnrealToGeographicCoordinates(), and UCSVFile::WriteRow().

◆ GetAllInstancedActorRendererActors()

TArray< AInstancedActorRenderer * > AInstancedRendererManager::GetAllInstancedActorRendererActors ( ) const

Definition at line 272 of file InstancedRendererManager.cpp.

273{
274 UWorld* World = GetWorld();
275 if (World && !World->IsGameWorld())
276 {
277 TArray<AActor*> FoundActors;
278 UGameplayStatics::GetAllActorsOfClass(World, AInstancedActorRenderer::StaticClass(), FoundActors);
279
280 TArray<AInstancedActorRenderer*> RendererActors;
281 for (AActor* Actor : FoundActors)
282 {
283 if (AInstancedActorRenderer* Renderer = Cast<AInstancedActorRenderer>(Actor))
284 {
285 RendererActors.AddUnique(Renderer);
286 }
287 }
288 return RendererActors;
289 }
290
291 // If running at runtime (including PIE), return InstancedRenderers
292 return InstancedRenderers;
293}

References InstancedRenderers.

◆ GetTotalInstanceCount()

int32 AInstancedRendererManager::GetTotalInstanceCount ( )

Definition at line 295 of file InstancedRendererManager.cpp.

296{
297 int32 total = 0;
299 {
300 if (Renderer)
301 {
302 UInstancedStaticMeshComponent* Comp = Renderer->GetInstancedStaticMeshComponent();
303 if (Comp)
304 {
305 total += Comp->GetInstanceCount();
306 }
307 }
308 }
309
310 TotalInstanceCount = total;
311
312 return TotalInstanceCount;
313}

References InstancedRenderers, and TotalInstanceCount.

◆ OnActorSpawned()

void AInstancedRendererManager::OnActorSpawned ( AActor *  Actor)
private

Definition at line 68 of file InstancedRendererManager.cpp.

69{
70 if (AInstancedActor* InstancedActor = Cast<AInstancedActor>(Actor))
71 {
72 // Try to add the newly spawned AInstancedActor to instanced rendering.
73 if (InstancedActor->CanAddToInstancedRenderer())
74 {
75 AddActorToInstancedRendering(InstancedActor);
76 }
77 }
78}

References AddActorToInstancedRendering().

Referenced by BeginPlay().

◆ SetInstancedRendering()

void AInstancedRendererManager::SetInstancedRendering ( bool  Visible)

Set all ISM components visibility.

Definition at line 368 of file InstancedRendererManager.cpp.

369{
371 {
372 if (Renderer)
373 {
374 UInstancedStaticMeshComponent* Comp = Renderer->GetInstancedStaticMeshComponent();
375 if (Comp)
376 {
377 Comp->SetVisibility(Visible);
378 }
379 }
380 }
381}

References InstancedRenderers.

Referenced by UAgrarsenseSettings::SetInstancedRenderingVisibility().

◆ SpawnAllInstancesBackToActors()

void AInstancedRendererManager::SpawnAllInstancesBackToActors ( )

Spawn all instanced back to actors.

Definition at line 259 of file InstancedRendererManager.cpp.

260{
261 for (int32 i = InstancedRenderers.Num() - 1; i >= 0; --i)
262 {
264 if (Renderer && Renderer->SpawnInstancesBackActors())
265 {
266 Renderer->Destroy();
267 InstancedRenderers.RemoveAt(i);
268 }
269 }
270}

References InstancedRenderers, and AInstancedActorRenderer::SpawnInstancesBackActors().

◆ SpawnInstanceBackToActor()

bool AInstancedRendererManager::SpawnInstanceBackToActor ( UInstancedStaticMeshComponent *  ISM,
int32  Index,
bool  OnlyTree 
)

Spawns a specific ISM instance back to its original Actor. Cannot be added back to ISM instance afterwards.

Parameters
ISMThe instanced static mesh component containing the instance.
IndexThe index of the instance to spawn back.
Returns
True if the instance was successfully spawned, false otherwise.

Definition at line 315 of file InstancedRendererManager.cpp.

316{
318 {
319 if (Renderer && Renderer->SpawnInstanceBackToActor(ISM, Index, OnlyTree))
320 {
321 return true;
322 }
323 }
324
325 // Didn't find instance or spawning instance back to actor failed.
326 return false;
327}

References InstancedRenderers.

Member Data Documentation

◆ ActorSpawnedDelegateHandle

FDelegateHandle AInstancedRendererManager::ActorSpawnedDelegateHandle
private

Definition at line 103 of file InstancedRendererManager.h.

Referenced by BeginPlay(), and EndPlay().

◆ AllowISMCreation

bool AInstancedRendererManager::AllowISMCreation = true
private

Definition at line 105 of file InstancedRendererManager.h.

Referenced by AddActorToInstancedRendering(), and BeginPlay().

◆ Instance

AInstancedRendererManager * AInstancedRendererManager::Instance = nullptr
staticprivate

Definition at line 101 of file InstancedRendererManager.h.

Referenced by BeginPlay(), and EndPlay().

◆ InstancedRenderers

TArray<AInstancedActorRenderer*> AInstancedRendererManager::InstancedRenderers
protected

◆ TotalInstanceCount

int32 AInstancedRendererManager::TotalInstanceCount = 0
protected

Definition at line 95 of file InstancedRendererManager.h.

Referenced by GetTotalInstanceCount().


The documentation for this class was generated from the following files: