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

#include <InstancedRenderer.h>

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

Public Member Functions

 AInstancedRenderer (const FObjectInitializer &ObjectInitializer)
 
bool AddActorToInstancedRendering (AInstancedActor *InstancedActor)
 
void RemoveInstance (int32 ComponentIndex, int32 InstanceNumber)
 
void AddOrRemoveActorFromAutomaticTransformUpdates (bool Add, AInstancedActor *InstancedActor)
 
void UpdateInstanceTransform (int32 ComponentIndex, int32 InstanceNumber, const FTransform &NewTransform)
 
bool IsRendering () const
 
int32 GetTotalInstanceCount () const
 
int32 GetUniqueInstancesCount () const
 
TArray< FInstanceEntryGetInstanceEntries () const
 
void SetInstancedRendering (bool ShouldRender)
 
void SetComponentIndexVisibility (int32 Index, bool Visible)
 
void SetRenderCustomDepth (bool Enabled)
 
void SetWorldPositionOffsetDistance (int32 NewWPODistance)
 
void SetShadowCacheBehaviour (EShadowCacheInvalidationBehavior ShadowCacheInvalidationBehaviour)
 
void SetRenderWorldPositionOffet (bool RenderWPO)
 
void LogInfo () const
 
void DebugMaterialImpact (bool SetUnrealDefaultMaterial)
 

Private Member Functions

void BeginPlay () override
 
void Tick (float DeltaTime) override
 
void EndPlay (const EEndPlayReason::Type EndPlayReason) override
 
void OnGraphicsSettingsChanged (FGlobalGraphicsSettings GraphicsSettings)
 
void OnWeatherParametersChanged (FWeatherParameters WeatherParameters)
 
bool AreTransformsEqual (const FTransform &TransformA, const FTransform &TransformB) const
 
void UpdateInstancedActors ()
 
int32 FindOrAddUniqueMesh (UStaticMeshComponent *StaticMeshComponent, AInstancedActor *InstancedActor)
 

Private Attributes

TArray< FInstanceEntryInstanceEntries
 
int32 WorldPositionOffsetDistance = 30000
 
std::vector< FInstancedActorDataInstancedActorsToUpdate
 
FWeatherParameters CurrentWeatherParameters
 
int32 TotalInstanceCount
 
bool Rendering = true
 
bool RenderingWPO = true
 

Static Private Attributes

static AInstancedRendererInstance = nullptr
 

Detailed Description

This Actor is responsible for rendering all added unique mesh entries with unique materials efficiently with UInstancedStaticMeshComponent.

The way this works is by creating blueprint based on AInstancedActor in Unreal Editor, setup the desired mesh and material in the blueprint and placing them in the level in any way. Then at runtime (AInstancedActor BeginPlay), its Mesh and Material is added to this Renderer.

Note. Mesh material(s) need to have bUsedWithInstancedStaticMeshes set to True to work with UInstancedStaticMeshComponent.

Definition at line 64 of file InstancedRenderer.h.

Constructor & Destructor Documentation

◆ AInstancedRenderer()

AInstancedRenderer::AInstancedRenderer ( const FObjectInitializer &  ObjectInitializer)

Definition at line 18 of file InstancedRenderer.cpp.

18 : Super(ObjectInitializer)
19{
20 RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("SceneRoot"));
21 RootComponent->SetMobility(EComponentMobility::Static);
22 PrimaryActorTick.bCanEverTick = true;
23}

Member Function Documentation

◆ AddActorToInstancedRendering()

bool AInstancedRenderer::AddActorToInstancedRendering ( AInstancedActor InstancedActor)

Definition at line 162 of file InstancedRenderer.cpp.

163{
164 if (InstancedActor == nullptr)
165 {
166#if WITH_EDITOR
167 UE_LOG(LogTemp, Warning, TEXT("InstancedRenderer.cpp: Actor is null!"));
168#endif
169 return false;
170 }
171
172 UStaticMeshComponent* StaticMeshComponent = InstancedActor->GetStaticMeshComponent();
173 if (StaticMeshComponent == nullptr)
174 {
175#if WITH_EDITOR
176 UE_LOG(LogTemp, Warning, TEXT("InstancedRenderer.cpp: AInstancedActor %s UStaticMeshComponent is null!"), *InstancedActor->GetName());
177#endif
178 return false;
179 }
180
181 UStaticMesh* Mesh = StaticMeshComponent->GetStaticMesh();
182 if (Mesh == nullptr)
183 {
184#if WITH_EDITOR
185 UE_LOG(LogTemp, Warning, TEXT("InstancedRenderer.cpp: AInstancedActor %s UStaticMeshComponent mesh is null!"), *InstancedActor->GetName());
186#endif
187 return false;
188 }
189
190 // Find or create InstancedStaticMeshComponents array index for this instance
191 int32 ComponentIndex = FindOrAddUniqueMesh(StaticMeshComponent, InstancedActor);
192
193 // Check index validity
194 if (!InstanceEntries.IsValidIndex(ComponentIndex))
195 {
196#if WITH_EDITOR
197 UE_LOG(LogTemp, Warning, TEXT("InstancedRenderer.cpp: ComponentIndex is not valid!"));
198#endif
199 return false;
200 }
201
202 UInstancedStaticMeshComponent* InstancedStaticMeshComponent = InstanceEntries[ComponentIndex].InstancedStaticMeshComponent;
203 if (!InstancedStaticMeshComponent)
204 {
205#if WITH_EDITOR
206 UE_LOG(LogTemp, Warning, TEXT("InstancedRenderer.cpp: UInstancedStaticMeshComponent is nullptr!"));
207#endif
208 return false;
209 }
210
211 // Add InstancedActor to TArray
212 FInstancedActorData InstancedData;
213 InstancedData.Actor = InstancedActor;
214 InstanceEntries[ComponentIndex].ActorData.Add(InstancedData);
215
216 // Get the StaticMeshComponent transform and add instance
217 FTransform ActorTransform = StaticMeshComponent->GetComponentTransform();
218 InstancedStaticMeshComponent->AddInstance(ActorTransform);
219
220 // If actor has bool UpdateTransformAutomatically true,
221 // add actor and its data to InstancedActorsToUpdate array
222 if (InstancedActor->UpdateTransformAutomatically())
223 {
224 InstancedStaticMeshComponent->SetMobility(EComponentMobility::Movable);
226 }
227
228 int32 InstanceIndex = InstancedStaticMeshComponent->GetNumRenderInstances() - 1;
229
230 // Notify the actor that instance has been added successfully.
231 InstancedActor->InstanceAdded(ComponentIndex, InstanceIndex);
232
234
235 return true;
236}
bool UpdateTransformAutomatically() const
void InstanceAdded(int32 CompIndex, int32 InstanceNum)
UStaticMeshComponent * GetStaticMeshComponent() const
void AddOrRemoveActorFromAutomaticTransformUpdates(bool Add, AInstancedActor *InstancedActor)
TArray< FInstanceEntry > InstanceEntries
int32 FindOrAddUniqueMesh(UStaticMeshComponent *StaticMeshComponent, AInstancedActor *InstancedActor)
TWeakObjectPtr< AInstancedActor > Actor

References FInstancedActorData::Actor, AddOrRemoveActorFromAutomaticTransformUpdates(), FindOrAddUniqueMesh(), AInstancedActor::GetStaticMeshComponent(), AInstancedActor::InstanceAdded(), InstanceEntries, TotalInstanceCount, and AInstancedActor::UpdateTransformAutomatically().

Referenced by AInstancedActor::AddToInstancedRendering().

◆ AddOrRemoveActorFromAutomaticTransformUpdates()

void AInstancedRenderer::AddOrRemoveActorFromAutomaticTransformUpdates ( bool  Add,
AInstancedActor InstancedActor 
)

Adds or removes an instanced actor from automatic transform updates.

Parameters
AddTrue to add the actor to automatic transform updates, false to remove.
InstancedActorPointer to the instanced actor being added or removed.

Definition at line 381 of file InstancedRenderer.cpp.

382{
383 if (!InstancedActor)
384 {
385 return;
386 }
387
388 if (Add)
389 {
390 FInstancedActorData InstancedData;
391 InstancedData.Actor = InstancedActor;
392 InstancedActor->UpdatePreviousTransform(InstancedActor->GetActorTransform());
393 InstancedActorsToUpdate.emplace_back(InstancedData);
394
395 // Set this Actor's tick to true.
396 SetActorTickEnabled(true);
397 }
398 else
399 {
400 auto it = std::remove_if(InstancedActorsToUpdate.begin(), InstancedActorsToUpdate.end(),
401 [InstancedActor](const FInstancedActorData& Data)
402 {
403 return Data.Actor == InstancedActor;
404 });
405
406 if (it != InstancedActorsToUpdate.end())
407 {
409 }
410 }
411}
void UpdatePreviousTransform(const FTransform &NewTransform)
std::vector< FInstancedActorData > InstancedActorsToUpdate

References FInstancedActorData::Actor, InstancedActorsToUpdate, and AInstancedActor::UpdatePreviousTransform().

Referenced by AddActorToInstancedRendering(), and AInstancedActor::SetUpdateTransformAutomatically().

◆ AreTransformsEqual()

bool AInstancedRenderer::AreTransformsEqual ( const FTransform &  TransformA,
const FTransform &  TransformB 
) const
private

Definition at line 472 of file InstancedRenderer.cpp.

473{
474 if (TransformA.GetTranslation() != TransformB.GetTranslation())
475 {
476 return false;
477 }
478
479 if (TransformA.GetRotation() != TransformB.GetRotation())
480 {
481 return false;
482 }
483
484 if (TransformA.GetScale3D() != TransformB.GetScale3D())
485 {
486 return false;
487 }
488
489 // else Transforms are equal
490 return true;
491}

Referenced by UpdateInstancedActors().

◆ BeginPlay()

void AInstancedRenderer::BeginPlay ( )
overrideprivate

Definition at line 25 of file InstancedRenderer.cpp.

26{
27 Super::BeginPlay();
28
29 // Disable collision for this actor. The instanced actor's themselves have their own collisions
30 SetActorEnableCollision(false);
31
32 if (Instance == nullptr)
33 {
34 Instance = this;
35 }
36 else
37 {
38#if WITH_EDITOR
39 UE_LOG(LogTemp, Warning, TEXT("InstancedRenderer.cpp: Instance already exists. Destroying this actor.."));
40#endif
41 Destroy();
42 }
43
44 UWorld* World = GetWorld();
45
47 if (Settings)
48 {
51 }
52
54 if (Weather)
55 {
58 }
59
60#if WITH_EDITOR
61 FTimerHandle Handle;
62 World->GetTimerManager().SetTimer(Handle, FTimerDelegate::CreateLambda([this]
63 {
64 LogInfo();
65 }), 1.0f, false);
66#endif
67}
void OnWeatherParametersChanged(FWeatherParameters WeatherParameters)
void OnGraphicsSettingsChanged(FGlobalGraphicsSettings GraphicsSettings)
FWeatherParameters CurrentWeatherParameters
static AInstancedRenderer * Instance
const FWeatherParameters & GetCurrentWeather() const
Definition: Weather.h:76
FLevelEventDelegate_WeatherChanged OnWeatherChanged
Definition: Weather.h:85
int32 GetWorldPositionOffsetRenderDistance() const
FGraphicsSettingsDelegate OnGraphicsSettingsChanged
static UAgrarsenseSettings * GetAgrarsenseSettings()
static AWeather * GetWeatherActor(const UObject *WorldContextObject)

References CurrentWeatherParameters, Destroy, UAgrarsenseStatics::GetAgrarsenseSettings(), AWeather::GetCurrentWeather(), UAgrarsenseStatics::GetWeatherActor(), UAgrarsenseSettings::GetWorldPositionOffsetRenderDistance(), Instance, LogInfo(), OnGraphicsSettingsChanged(), UAgrarsenseSettings::OnGraphicsSettingsChanged, AWeather::OnWeatherChanged, OnWeatherParametersChanged(), and WorldPositionOffsetDistance.

◆ DebugMaterialImpact()

void AInstancedRenderer::DebugMaterialImpact ( bool  SetUnrealDefaultMaterial)

Definition at line 598 of file InstancedRenderer.cpp.

599{
600 UMaterialInterface* DefaultMaterial = nullptr;
601 if (SetUnrealDefaultMaterial)
602 {
603 DefaultMaterial = UMaterial::GetDefaultMaterial(EMaterialDomain(0));
604 }
605
606 for (FInstanceEntry& Entry : InstanceEntries)
607 {
608 if (Entry.AllowWorldPositionOffsetDisable && Entry.InstancedStaticMeshComponent)
609 {
610 if (SetUnrealDefaultMaterial)
611 {
612 for (int32 i = 0; i < Entry.InstancedStaticMeshComponent->GetNumMaterials(); ++i)
613 {
614 UMaterialInterface* CurrentMaterial = Entry.InstancedStaticMeshComponent->GetMaterial(i);
615 Entry.Materials.Add(CurrentMaterial);
616 }
617 for (int32 i = 0; i < Entry.InstancedStaticMeshComponent->GetNumMaterials(); ++i)
618 {
619 Entry.InstancedStaticMeshComponent->SetMaterial(i, DefaultMaterial);
620 }
621 }
622 else
623 {
624 if (Entry.Materials.Num() > 0)
625 {
626 for (int32 i = 0; i < Entry.Materials.Num(); ++i)
627 {
628 UMaterialInterface* OriginalMaterial = Entry.Materials[i];
629 Entry.InstancedStaticMeshComponent->SetMaterial(i, OriginalMaterial);
630 }
631 }
632 }
633 }
634 }
635}

References InstanceEntries.

◆ EndPlay()

void AInstancedRenderer::EndPlay ( const EEndPlayReason::Type  EndPlayReason)
overrideprivate

Definition at line 76 of file InstancedRenderer.cpp.

77{
78 Super::EndPlay(EndPlayReason);
79
80 if (Instance == this)
81 {
82 Instance = nullptr;
83 }
84 else
85 {
86 return;
87 }
88
89 UWorld* World = GetWorld();
90
92 if (Settings)
93 {
95 }
96
98 if (Weather)
99 {
101 }
102
104
105 // Destroy all Instanced entries
106 for (FInstanceEntry& Entry : InstanceEntries)
107 {
108 if (Entry.InstancedStaticMeshComponent)
109 {
110 Entry.InstancedStaticMeshComponent->ClearInstances();
111 Entry.InstancedStaticMeshComponent->UnregisterComponent();
112 Entry.InstancedStaticMeshComponent->DetachFromComponent(FDetachmentTransformRules::KeepRelativeTransform);
113 Entry.InstancedStaticMeshComponent->DestroyComponent();
114 Entry.InstancedStaticMeshComponent = nullptr;
115 }
116
117 Entry.Materials.Empty();
118 Entry.ActorData.Empty();
119 Entry.Mesh.Reset();
120 }
121
122 InstanceEntries.Empty();
123}

References UAgrarsenseStatics::GetAgrarsenseSettings(), UAgrarsenseStatics::GetWeatherActor(), Instance, InstancedActorsToUpdate, InstanceEntries, OnGraphicsSettingsChanged(), UAgrarsenseSettings::OnGraphicsSettingsChanged, AWeather::OnWeatherChanged, and OnWeatherParametersChanged().

◆ FindOrAddUniqueMesh()

int32 AInstancedRenderer::FindOrAddUniqueMesh ( UStaticMeshComponent *  StaticMeshComponent,
AInstancedActor InstancedActor 
)
private

Definition at line 238 of file InstancedRenderer.cpp.

239{
240 if (InstancedActor == nullptr || StaticMeshComponent == nullptr)
241 {
242#if WITH_EDITOR
243 UE_LOG(LogTemp, Warning, TEXT("StaticInstancedRenderer.cpp: StaticMeshComponent or InstancedActor is null!"));
244#endif
245 // return absurd number which should fail adding this instance to this renderer in above function.
246 return 99999999;
247 }
248
249 UStaticMesh* Mesh = StaticMeshComponent->GetStaticMesh();
250
251 if (!InstancedActor->HasAlternativeMaterial())
252 {
253 const int num = InstanceEntries.Num();
254 for (int32 Index = 0; Index < num; ++Index)
255 {
256 if (InstanceEntries[Index].Mesh == Mesh)
257 {
258 return Index;
259 }
260 }
261 }
262
263 const int count = StaticMeshComponent->GetNumMaterials();
264
265 TArray<UMaterialInterface*> MeshMaterials;
266 MeshMaterials.Reserve(count);
267
268 for (int32 i = 0; i < count; i++)
269 {
270 MeshMaterials.Add(StaticMeshComponent->GetMaterial(i));
271 }
272
273 const int Size = InstanceEntries.Num();
274 for (int32 Index = 0; Index < Size; ++Index)
275 {
276 if (InstanceEntries[Index].Mesh == Mesh)
277 {
278 bool bMaterialsMatch = true;
279
280 for (int32 MaterialIndex = 0; MaterialIndex < InstanceEntries[Index].Materials.Num(); ++MaterialIndex)
281 {
282 UMaterialInterface* UniqueMeshMaterial = InstanceEntries[Index].Materials[MaterialIndex];
283 UMaterialInterface* MeshMaterial = MeshMaterials[MaterialIndex];
284 if (UniqueMeshMaterial != MeshMaterial)
285 {
286 bMaterialsMatch = false;
287 }
288 }
289
290 if (bMaterialsMatch)
291 {
292 return Index;
293 }
294 }
295 }
296
297 // Else this is completely new mesh and/or mesh with alternative material,
298 // we need to create new FInstanceEntry and UInstancedStaticMeshComponent for it
299
300 // Create and setup new UInstancedStaticMeshComponent
301 UInstancedStaticMeshComponent* InstancedStaticMeshComponent = NewObject<UInstancedStaticMeshComponent>(this);
302 InstancedStaticMeshComponent->RegisterComponent();
303 InstancedStaticMeshComponent->SetCollisionEnabled(ECollisionEnabled::NoCollision);
304 InstancedStaticMeshComponent->CreatePhysicsState(false);
305 InstancedStaticMeshComponent->SetSimulatePhysics(false);
306 InstancedStaticMeshComponent->SetStaticMesh(Mesh);
307 InstancedStaticMeshComponent->SetMobility(EComponentMobility::Static);
308 InstancedStaticMeshComponent->SetHiddenInGame(false);
309 InstancedStaticMeshComponent->SetVisibility(true);
310 InstancedStaticMeshComponent->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepWorldTransform);
311 InstancedStaticMeshComponent->InstanceStartCullDistance = InstancedActor->GetInstanceStartCullDistance();
312 InstancedStaticMeshComponent->InstanceEndCullDistance = InstancedActor->GetInstanceEndCullDistance();
313
314 // Set WPO distance and evaluation
315 InstancedStaticMeshComponent->SetWorldPositionOffsetDisableDistance(WorldPositionOffsetDistance);
316 /*InstancedStaticMeshComponent->SetEvaluateWorldPositionOffset(true);
317 InstancedStaticMeshComponent->SetEvaluateWorldPositionOffsetInRayTracing(true);*/
318
319 bool AllowWorldPositionOffsetDisable = InstancedActor->GetAllowWorldPositionOffsetDisable();
320
321 // For whatever reason this only works when done a bit later..
322 FTimerHandle Handle;
323 GetWorld()->GetTimerManager().SetTimer(Handle, FTimerDelegate::CreateLambda([this, InstancedStaticMeshComponent, AllowWorldPositionOffsetDisable]
324 {
325 if (InstancedStaticMeshComponent && AllowWorldPositionOffsetDisable && CurrentWeatherParameters.WindIntensity < 0.05f)
326 {
327 InstancedStaticMeshComponent->SetEvaluateWorldPositionOffset(false);
328 InstancedStaticMeshComponent->SetEvaluateWorldPositionOffsetInRayTracing(false);
329 }
330 }), 0.350f, false);
331
332 // Thermal and Semantic camera use custom depth.
333 // RenderCustomDepth is set to false, if no Thermal or Semantic camera exists in the level,
334 // and is automatically set to true/false for all instances when they are spawned/destroyed.
335 // Doing this saves a lot rendering performance.
336 InstancedStaticMeshComponent->SetRenderCustomDepth(true);
337 InstancedStaticMeshComponent->SetCustomDepthStencilValue(StaticMeshComponent->CustomDepthStencilValue);
338
339 // Huge performance implication, recommend is Rigid (especially for Foliage with WPO).
340 // https://docs.unrealengine.com/5.3/en-US/PythonAPI/class/ShadowCacheInvalidationBehavior.html
341 InstancedStaticMeshComponent->ShadowCacheInvalidationBehavior = EShadowCacheInvalidationBehavior::Rigid;
342
343 // Create new FInstanceEntry
344 FInstanceEntry InstanceEntry;
345 InstanceEntry.Mesh = Mesh;
346 InstanceEntry.Materials = MeshMaterials;
347 InstanceEntry.InstanceEntryIndex = InstanceEntries.Num();
348 InstanceEntry.MeshName = Mesh->GetName();
349 InstanceEntry.InstancedStaticMeshComponent = InstancedStaticMeshComponent;
350 InstanceEntry.AllowWorldPositionOffsetDisable = AllowWorldPositionOffsetDisable;
351
352 // Set materials to newly created UInstancedStaticMeshComponent
353 const int32 MaterialCount = MeshMaterials.Num();
354 for (int32 MaterialIndex = 0; MaterialIndex < MaterialCount; ++MaterialIndex)
355 {
356 UMaterialInterface* MaterialInterface = InstanceEntry.Materials[MaterialIndex];
357
358 if (MaterialInterface)
359 {
360 InstancedStaticMeshComponent->SetMaterial(MaterialIndex, MaterialInterface);
361
362#if WITH_EDITOR
363 // Validate in Editor that material has bUsedWithInstancedStaticMeshes on
364 UMaterial* Material = Cast<UMaterial>(MaterialInterface);
365 if (Material)
366 {
367 if (!Material->bUsedWithInstancedStaticMeshes)
368 {
369 UE_LOG(LogTemp, Warning, TEXT("InstancedRenderer.cpp: Material '%s' bUsedWithInstancedStaticMeshes is not set to true!"), *Material->GetName());
370 }
371 }
372#endif
373 }
374 }
375
376 InstanceEntries.Add(InstanceEntry);
377
378 return InstanceEntries.Num() - 1;
379}
int GetInstanceEndCullDistance() const
int GetInstanceStartCullDistance() const
bool HasAlternativeMaterial() const
bool GetAllowWorldPositionOffsetDisable() const
TWeakObjectPtr< UStaticMesh > Mesh
TArray< UMaterialInterface * > Materials
bool AllowWorldPositionOffsetDisable
UInstancedStaticMeshComponent * InstancedStaticMeshComponent

References FInstanceEntry::AllowWorldPositionOffsetDisable, CurrentWeatherParameters, AInstancedActor::GetAllowWorldPositionOffsetDisable(), AInstancedActor::GetInstanceEndCullDistance(), AInstancedActor::GetInstanceStartCullDistance(), AInstancedActor::HasAlternativeMaterial(), FInstanceEntry::InstancedStaticMeshComponent, InstanceEntries, FInstanceEntry::InstanceEntryIndex, FInstanceEntry::Materials, FInstanceEntry::Mesh, FInstanceEntry::MeshName, FWeatherParameters::WindIntensity, and WorldPositionOffsetDistance.

Referenced by AddActorToInstancedRendering().

◆ GetInstanceEntries()

TArray< FInstanceEntry > AInstancedRenderer::GetInstanceEntries ( ) const
inline

Definition at line 135 of file InstancedRenderer.h.

136 {
137 return InstanceEntries;
138 }

◆ GetTotalInstanceCount()

int32 AInstancedRenderer::GetTotalInstanceCount ( ) const
inline

Definition at line 115 of file InstancedRenderer.h.

116 {
117 return TotalInstanceCount;
118 }

◆ GetUniqueInstancesCount()

int32 AInstancedRenderer::GetUniqueInstancesCount ( ) const
inline

Definition at line 125 of file InstancedRenderer.h.

126 {
127 return InstanceEntries.Num();
128 }

◆ IsRendering()

bool AInstancedRenderer::IsRendering ( ) const
inline

Definition at line 105 of file InstancedRenderer.h.

106 {
107 return Rendering;
108 }

◆ LogInfo()

void AInstancedRenderer::LogInfo ( ) const

Definition at line 69 of file InstancedRenderer.cpp.

70{
71#if WITH_EDITOR
72 UE_LOG(LogTemp, Warning, TEXT("InstancedRenderer.cpp: Unique mesh entries: %d | Total Instance Count: %d"), InstanceEntries.Num(), TotalInstanceCount);
73#endif
74}

References InstanceEntries, and TotalInstanceCount.

Referenced by BeginPlay().

◆ OnGraphicsSettingsChanged()

void AInstancedRenderer::OnGraphicsSettingsChanged ( FGlobalGraphicsSettings  GraphicsSettings)
private

Definition at line 527 of file InstancedRenderer.cpp.

528{
531}
void SetShadowCacheBehaviour(EShadowCacheInvalidationBehavior ShadowCacheInvalidationBehaviour)
void SetWorldPositionOffsetDistance(int32 NewWPODistance)
EShadowCacheInvalidationBehavior FoliageShadowCacheInvalidationBehaviour

References FGlobalGraphicsSettings::FoliageShadowCacheInvalidationBehaviour, SetShadowCacheBehaviour(), SetWorldPositionOffsetDistance(), and FGlobalGraphicsSettings::WorldPositionOffsetDistance.

Referenced by BeginPlay(), and EndPlay().

◆ OnWeatherParametersChanged()

void AInstancedRenderer::OnWeatherParametersChanged ( FWeatherParameters  WeatherParameters)
private

Definition at line 533 of file InstancedRenderer.cpp.

534{
535 // When weather changes, we check current wind intensity to
536 // enable or disable certain instances world position offset evaluation.
537 // Disabling WPO completely when wind is 0.0 saves a lot of performance with foliage.
539 {
540 CurrentWeatherParameters = WeatherParameters;
541 bool ShouldRenderWPO = CurrentWeatherParameters.WindIntensity > 0.05f;
542 SetRenderWorldPositionOffet(ShouldRenderWPO);
543 }
544}
void SetRenderWorldPositionOffet(bool RenderWPO)

References CurrentWeatherParameters, SetRenderWorldPositionOffet(), and FWeatherParameters::WindIntensity.

Referenced by BeginPlay(), and EndPlay().

◆ RemoveInstance()

void AInstancedRenderer::RemoveInstance ( int32  ComponentIndex,
int32  InstanceNumber 
)

Definition at line 428 of file InstancedRenderer.cpp.

429{
430 if (!InstanceEntries.IsValidIndex(ComponentIndex))
431 {
432 return;
433 }
434
435 FInstanceEntry& Entry = InstanceEntries[ComponentIndex];
436
438 {
439 Entry.InstancedStaticMeshComponent->RemoveInstance(InstanceNumber);
440 }
441
442 auto& InstancedActors = InstanceEntries[ComponentIndex].ActorData;
443
444 // Remove instance if within range
445 if (InstanceNumber >= 0 && InstanceNumber < InstancedActors.Num())
446 {
447 // Is it necessary here to check the Actor validity?
448 AInstancedActor* InstanceToRemove = InstancedActors[InstanceNumber].Actor.Get();
449 if (InstanceToRemove)
450 {
451 InstancedActors.RemoveAt(InstanceNumber);
452 }
453 }
454
455 for (int32 i = 0; i < InstancedActors.Num(); i++)
456 {
457 AInstancedActor* InstanceActor = InstancedActors[i].Actor.Get();
458 if (InstanceActor)
459 {
460 // Notify all AInstancedActor that are part of this InstanceEntry
461 // that one of the InstancedActors has been removed,
462 // this is because we need to adjust each AInstancedActor* InstanceNumber,
463 // unless the removed instance number is smaller
464 // than AInstancedActor* InstanceNumber (handled in the UpdateIndex() function).
465 InstanceActor->UpdateIndex(InstanceNumber);
466 }
467 }
468
470}
void UpdateIndex(int32 UpdatedIndex)

References FInstanceEntry::InstancedStaticMeshComponent, InstanceEntries, TotalInstanceCount, and AInstancedActor::UpdateIndex().

Referenced by AInstancedActor::RemoveFromInstancedRendering().

◆ SetComponentIndexVisibility()

void AInstancedRenderer::SetComponentIndexVisibility ( int32  Index,
bool  Visible 
)

Set the visibility of a specific UInstancedStaticMeshComponent at the given index. Debugging purposes.

Parameters
IndexThe index of the UInstancedStaticMeshComponent to modify.
VisibleWhether to make the component visible (true) or hidden (false).

Definition at line 509 of file InstancedRenderer.cpp.

510{
511 if (!InstanceEntries.IsValidIndex(Index))
512 {
513#if WITH_EDITOR
514 UE_LOG(LogTemp, Warning, TEXT("InstancedRenderer.cpp: Index %d is not valid!"), Index);
515#endif
516 return;
517 }
518
519 FInstanceEntry& Entry = InstanceEntries[Index];
520
522 {
523 Entry.InstancedStaticMeshComponent->SetVisibility(Visible);
524 }
525}

References FInstanceEntry::InstancedStaticMeshComponent, and InstanceEntries.

◆ SetInstancedRendering()

void AInstancedRenderer::SetInstancedRendering ( bool  ShouldRender)

Definition at line 493 of file InstancedRenderer.cpp.

494{
495 Rendering = ShouldRender;
496 for (const FInstanceEntry& Entry : InstanceEntries)
497 {
498 if (Entry.InstancedStaticMeshComponent)
499 {
500 Entry.InstancedStaticMeshComponent->SetVisibility(Rendering);
501 }
502 }
503
504#if WITH_EDITOR
505 UE_LOG(LogTemp, Warning, TEXT("InstancedRenderer.cpp: Rendering: %s"), (Rendering ? TEXT("true") : TEXT("false")));
506#endif
507}

References InstanceEntries, and Rendering.

Referenced by UAgrarsenseSettings::SetInstancedRenderingVisibility().

◆ SetRenderCustomDepth()

void AInstancedRenderer::SetRenderCustomDepth ( bool  Enabled)

Sets whether the custom depth rendering is enabled or disabled.

Parameters
EnabledTrue to enable custom depth rendering, false to disable.

Definition at line 546 of file InstancedRenderer.cpp.

547{
548 for (FInstanceEntry& Entry : InstanceEntries)
549 {
550 if (Entry.InstancedStaticMeshComponent)
551 {
552 Entry.InstancedStaticMeshComponent->SetRenderCustomDepth(Enabled);
553 }
554 }
555}

References InstanceEntries.

◆ SetRenderWorldPositionOffet()

void AInstancedRenderer::SetRenderWorldPositionOffet ( bool  RenderWPO)

Sets whether the World Position Offset (WPO) rendering is enabled or disabled.

Parameters
RenderWPOTrue to enable World Position Offset rendering, false to disable.

Definition at line 586 of file InstancedRenderer.cpp.

587{
588 for (FInstanceEntry& Entry : InstanceEntries)
589 {
590 if (Entry.AllowWorldPositionOffsetDisable && Entry.InstancedStaticMeshComponent)
591 {
592 Entry.InstancedStaticMeshComponent->SetEvaluateWorldPositionOffset(RenderWPO);
593 Entry.InstancedStaticMeshComponent->SetEvaluateWorldPositionOffsetInRayTracing(RenderWPO);
594 }
595 }
596}

References InstanceEntries.

Referenced by OnWeatherParametersChanged().

◆ SetShadowCacheBehaviour()

void AInstancedRenderer::SetShadowCacheBehaviour ( EShadowCacheInvalidationBehavior  ShadowCacheInvalidationBehaviour)

Sets the behavior for shadow cache invalidation. Default Rigid.

Parameters
ShadowCacheInvalidationBehaviourThe new behavior for shadow cache invalidation.

Definition at line 575 of file InstancedRenderer.cpp.

576{
577 for (FInstanceEntry& Entry : InstanceEntries)
578 {
579 if (Entry.InstancedStaticMeshComponent)
580 {
581 Entry.InstancedStaticMeshComponent->ShadowCacheInvalidationBehavior = ShadowCacheInvalidationBehaviour;
582 }
583 }
584}

References InstanceEntries.

Referenced by OnGraphicsSettingsChanged().

◆ SetWorldPositionOffsetDistance()

void AInstancedRenderer::SetWorldPositionOffsetDistance ( int32  NewWPODistance)

Sets the distance for the World Position Offset (WPO) effect.

Parameters
NewWPODistanceThe new distance for the World Position Offset.

Definition at line 557 of file InstancedRenderer.cpp.

558{
559 if (WorldPositionOffsetDistance == NewWPODistance)
560 {
561 return;
562 }
563
564 WorldPositionOffsetDistance = NewWPODistance;
565
566 for (FInstanceEntry& Entry : InstanceEntries)
567 {
568 if (Entry.InstancedStaticMeshComponent)
569 {
570 Entry.InstancedStaticMeshComponent->SetWorldPositionOffsetDisableDistance(WorldPositionOffsetDistance);
571 }
572 }
573}

References InstanceEntries, and WorldPositionOffsetDistance.

Referenced by OnGraphicsSettingsChanged().

◆ Tick()

void AInstancedRenderer::Tick ( float  DeltaTime)
overrideprivate

Definition at line 125 of file InstancedRenderer.cpp.

126{
128}

References UpdateInstancedActors().

◆ UpdateInstancedActors()

void AInstancedRenderer::UpdateInstancedActors ( )
private

Definition at line 130 of file InstancedRenderer.cpp.

131{
132 int NumberOfActorsToUpdate = InstancedActorsToUpdate.size();
133 if (InstancedActorsToUpdate.size() == 0)
134 {
135 SetActorTickEnabled(false);
136 return;
137 }
138
139 for (int32 i = 0; i < NumberOfActorsToUpdate; i++)
140 {
142 AInstancedActor* ActorPtr = InstancedData.Actor.Get();
143 if (ActorPtr)
144 {
145 FTransform CurrentActorTransform = ActorPtr->GetActorTransform();
146 if (!AreTransformsEqual(ActorPtr->GetPreviousTransform(), CurrentActorTransform))
147 {
148 UpdateInstanceTransform(ActorPtr->GetComponentIndex(), ActorPtr->GetInstanceIndex(), CurrentActorTransform);
149 ActorPtr->UpdatePreviousTransform(CurrentActorTransform);
150 }
151 }
152 else
153 {
154 // Remove InstancedData from std::vector InstancedActorsToUpdate
156 NumberOfActorsToUpdate--;
157 i--;
158 }
159 }
160}
int GetInstanceIndex() const
FTransform GetPreviousTransform() const
int GetComponentIndex() const
void UpdateInstanceTransform(int32 ComponentIndex, int32 InstanceNumber, const FTransform &NewTransform)
bool AreTransformsEqual(const FTransform &TransformA, const FTransform &TransformB) const

References FInstancedActorData::Actor, AreTransformsEqual(), AInstancedActor::GetComponentIndex(), AInstancedActor::GetInstanceIndex(), AInstancedActor::GetPreviousTransform(), InstancedActorsToUpdate, UpdateInstanceTransform(), and AInstancedActor::UpdatePreviousTransform().

Referenced by Tick().

◆ UpdateInstanceTransform()

void AInstancedRenderer::UpdateInstanceTransform ( int32  ComponentIndex,
int32  InstanceNumber,
const FTransform &  NewTransform 
)

Definition at line 413 of file InstancedRenderer.cpp.

414{
415 if (!InstanceEntries.IsValidIndex(ComponentIndex))
416 {
417 return;
418 }
419
420 FInstanceEntry& Entry = InstanceEntries[ComponentIndex];
421
423 {
424 Entry.InstancedStaticMeshComponent->UpdateInstanceTransform(InstanceNumber, NewTransform, true, true);
425 }
426}

References FInstanceEntry::InstancedStaticMeshComponent, and InstanceEntries.

Referenced by UpdateInstancedActors(), and AInstancedActor::UpdateTransformPosition().

Member Data Documentation

◆ CurrentWeatherParameters

FWeatherParameters AInstancedRenderer::CurrentWeatherParameters
private

Definition at line 238 of file InstancedRenderer.h.

Referenced by BeginPlay(), FindOrAddUniqueMesh(), and OnWeatherParametersChanged().

◆ Instance

AInstancedRenderer * AInstancedRenderer::Instance = nullptr
staticprivate

Definition at line 197 of file InstancedRenderer.h.

Referenced by BeginPlay(), and EndPlay().

◆ InstancedActorsToUpdate

std::vector<FInstancedActorData> AInstancedRenderer::InstancedActorsToUpdate
private

◆ InstanceEntries

TArray<FInstanceEntry> AInstancedRenderer::InstanceEntries
private

Array containing instance entries for each unique mesh and material combination. Each entry represents an instance of a mesh with associated actors and properties.

Definition at line 229 of file InstancedRenderer.h.

Referenced by AddActorToInstancedRendering(), DebugMaterialImpact(), EndPlay(), FindOrAddUniqueMesh(), LogInfo(), RemoveInstance(), SetComponentIndexVisibility(), SetInstancedRendering(), SetRenderCustomDepth(), SetRenderWorldPositionOffet(), SetShadowCacheBehaviour(), SetWorldPositionOffsetDistance(), and UpdateInstanceTransform().

◆ Rendering

bool AInstancedRenderer::Rendering = true
private

Definition at line 242 of file InstancedRenderer.h.

Referenced by SetInstancedRendering().

◆ RenderingWPO

bool AInstancedRenderer::RenderingWPO = true
private

Definition at line 244 of file InstancedRenderer.h.

◆ TotalInstanceCount

int32 AInstancedRenderer::TotalInstanceCount
private

Definition at line 240 of file InstancedRenderer.h.

Referenced by AddActorToInstancedRendering(), LogInfo(), and RemoveInstance().

◆ WorldPositionOffsetDistance

int32 AInstancedRenderer::WorldPositionOffsetDistance = 30000
private

World Position Offset (WPO) render distance in cm

Definition at line 234 of file InstancedRenderer.h.

Referenced by BeginPlay(), FindOrAddUniqueMesh(), and SetWorldPositionOffsetDistance().


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