Agrarsense
Public Member Functions | Static Public Member Functions | Protected Attributes | 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 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)
 
void ToggleProxyMesh ()
 
void SpawnAllInstancesBackActors ()
 
bool SpawnInstanceBackToActor (UInstancedStaticMeshComponent *ISM, int32 Index)
 

Static Public Member Functions

static AInstancedRendererGet ()
 

Protected Attributes

TArray< FInstanceEntryInstanceEntries
 
TArray< UInstancedStaticMeshComponent * > InstancesStaticMeshComponents
 
int32 TotalInstanceCount = 0
 

Private Member Functions

virtual void BeginPlay () override
 
virtual void EndPlay (const EEndPlayReason::Type EndPlayReason) override
 
void OnGraphicsSettingsChanged (FGlobalGraphicsSettings GraphicsSettings)
 
void OnWeatherParametersChanged (FWeatherParameters WeatherParameters)
 
int32 FindOrAddUniqueMesh (UStaticMeshComponent *StaticMeshComponent, AInstancedActor *InstancedActor)
 

Private Attributes

TWeakObjectPtr< UStaticMesh > ProxyMesh
 
int32 WorldPositionOffsetDistance = 30000
 
FWeatherParameters CurrentWeatherParameters
 
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 UInstancedStaticMeshComponents.

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.

Or you can setup AInstancedActor based actors in your level and then go to BP_InstancedRenderer Actor and click "AddExistingActorsToRenderer" button to turn AInstancedActors into BP_InstancedRenderer ISM instances. This reduces the amount of Actors in the level and should speed up loading times.

AInstancedActors marked as "TreeActor" can be turned back into regular Actor at runtime when vehicle gets close.

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

Definition at line 75 of file InstancedRenderer.h.

Constructor & Destructor Documentation

◆ AInstancedRenderer()

AInstancedRenderer::AInstancedRenderer ( const FObjectInitializer &  ObjectInitializer)

Definition at line 19 of file InstancedRenderer.cpp.

19 : Super(ObjectInitializer)
20{
21 RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("SceneRoot"));
22 RootComponent->SetMobility(EComponentMobility::Static);
23 PrimaryActorTick.bCanEverTick = false;
24
25 // Load a default cube mesh asset
26 static ConstructorHelpers::FObjectFinder<UStaticMesh> DefaultMesh(TEXT("/Engine/BasicShapes/Cube.Cube"));
27 if (DefaultMesh.Succeeded())
28 {
29 ProxyMesh = DefaultMesh.Object;
30 }
31}
TWeakObjectPtr< UStaticMesh > ProxyMesh

References ProxyMesh.

Member Function Documentation

◆ AddActorToInstancedRendering()

bool AInstancedRenderer::AddActorToInstancedRendering ( AInstancedActor InstancedActor)

Definition at line 129 of file InstancedRenderer.cpp.

130{
131 if (InstancedActor == nullptr)
132 {
133#if WITH_EDITOR
134 UE_LOG(LogTemp, Warning, TEXT("InstancedRenderer.cpp: Actor is null!"));
135#endif
136 return false;
137 }
138
139 UStaticMeshComponent* StaticMeshComponent = InstancedActor->GetStaticMeshComponent();
140 if (StaticMeshComponent == nullptr)
141 {
142#if WITH_EDITOR
143 UE_LOG(LogTemp, Warning, TEXT("InstancedRenderer.cpp: AInstancedActor %s UStaticMeshComponent is null!"), *InstancedActor->GetName());
144#endif
145 return false;
146 }
147
148 UStaticMesh* Mesh = StaticMeshComponent->GetStaticMesh();
149 if (Mesh == nullptr)
150 {
151#if WITH_EDITOR
152 UE_LOG(LogTemp, Warning, TEXT("InstancedRenderer.cpp: AInstancedActor %s UStaticMeshComponent mesh is null!"), *InstancedActor->GetName());
153#endif
154 return false;
155 }
156
157 // Find or create InstancedStaticMeshComponents array index for this instance
158 int32 ComponentIndex = FindOrAddUniqueMesh(StaticMeshComponent, InstancedActor);
159
160 // Check index validity
161 if (!InstanceEntries.IsValidIndex(ComponentIndex))
162 {
163#if WITH_EDITOR
164 UE_LOG(LogTemp, Warning, TEXT("InstancedRenderer.cpp: ComponentIndex is not valid!"));
165#endif
166 return false;
167 }
168
169 UInstancedStaticMeshComponent* InstancedStaticMeshComponent = InstanceEntries[ComponentIndex].InstancedStaticMeshComponent;
170 if (!InstancedStaticMeshComponent)
171 {
172#if WITH_EDITOR
173 UE_LOG(LogTemp, Warning, TEXT("InstancedRenderer.cpp: UInstancedStaticMeshComponent is nullptr!"));
174#endif
175 return false;
176 }
177
178 // Get the StaticMeshComponent transform and add instance
179 FTransform ActorTransform = StaticMeshComponent->GetComponentTransform();
180 InstancedStaticMeshComponent->AddInstance(ActorTransform);
181
182 int32 InstanceIndex = InstancedStaticMeshComponent->GetNumRenderInstances() - 1;
183
184 // Notify the actor that instance has been added successfully.
185 InstancedActor->InstanceAdded(ComponentIndex, InstanceIndex);
186 //InstancedActor->Destroy();
187
189
190 return true;
191}
void InstanceAdded(int32 CompIndex, int32 InstanceNum)
UStaticMeshComponent * GetStaticMeshComponent() const
TArray< FInstanceEntry > InstanceEntries
int32 FindOrAddUniqueMesh(UStaticMeshComponent *StaticMeshComponent, AInstancedActor *InstancedActor)

References FindOrAddUniqueMesh(), AInstancedActor::GetStaticMeshComponent(), AInstancedActor::InstanceAdded(), InstanceEntries, and TotalInstanceCount.

Referenced by AInstancedActor::AddToInstancedRendering().

◆ BeginPlay()

void AInstancedRenderer::BeginPlay ( )
overrideprivatevirtual

Definition at line 33 of file InstancedRenderer.cpp.

34{
35 Super::BeginPlay();
36
37 SetActorEnableCollision(false);
38
39 if (Instance == nullptr)
40 {
41 Instance = this;
42 }
43 else
44 {
45#if WITH_EDITOR
46 UE_LOG(LogTemp, Warning, TEXT("InstancedRenderer.cpp: Instance already exists. Destroying this actor.."));
47#endif
48 Destroy();
49 }
50
51 UWorld* World = GetWorld();
52
54 if (Settings)
55 {
58 }
59
61 if (Weather)
62 {
65 }
66
67#if WITH_EDITOR
68 FTimerHandle Handle;
69 World->GetTimerManager().SetTimer(Handle, FTimerDelegate::CreateLambda([this]
70 {
71 LogInfo();
72 }), 1.0f, false);
73#endif
74}
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 481 of file InstancedRenderer.cpp.

482{
483 UMaterialInterface* DefaultMaterial = nullptr;
484 if (SetUnrealDefaultMaterial)
485 {
486 DefaultMaterial = UMaterial::GetDefaultMaterial(EMaterialDomain(0));
487 }
488
489 for (FInstanceEntry& Entry : InstanceEntries)
490 {
491 if (Entry.AllowWorldPositionOffsetDisable && Entry.InstancedStaticMeshComponent)
492 {
493 if (SetUnrealDefaultMaterial)
494 {
495 for (int32 i = 0; i < Entry.InstancedStaticMeshComponent->GetNumMaterials(); ++i)
496 {
497 UMaterialInterface* CurrentMaterial = Entry.InstancedStaticMeshComponent->GetMaterial(i);
498 Entry.Materials.Add(CurrentMaterial);
499 }
500 for (int32 i = 0; i < Entry.InstancedStaticMeshComponent->GetNumMaterials(); ++i)
501 {
502 Entry.InstancedStaticMeshComponent->SetMaterial(i, DefaultMaterial);
503 }
504 }
505 else
506 {
507 if (Entry.Materials.Num() > 0)
508 {
509 for (int32 i = 0; i < Entry.Materials.Num(); ++i)
510 {
511 UMaterialInterface* OriginalMaterial = Entry.Materials[i];
512 Entry.InstancedStaticMeshComponent->SetMaterial(i, OriginalMaterial);
513 }
514 }
515 }
516 }
517 }
518}

References InstanceEntries.

◆ EndPlay()

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

Definition at line 83 of file InstancedRenderer.cpp.

84{
85 Super::EndPlay(EndPlayReason);
86
87 if (Instance == this)
88 {
89 Instance = nullptr;
90 }
91 else
92 {
93 return;
94 }
95
96 UWorld* World = GetWorld();
97
99 if (Settings)
100 {
102 }
103
105 if (Weather)
106 {
108 }
109
110 // Destroy all Instanced entries
111 for (FInstanceEntry& Entry : InstanceEntries)
112 {
113 if (Entry.InstancedStaticMeshComponent)
114 {
115 Entry.InstancedStaticMeshComponent->ClearInstances();
116 Entry.InstancedStaticMeshComponent->UnregisterComponent();
117 Entry.InstancedStaticMeshComponent->DetachFromComponent(FDetachmentTransformRules::KeepRelativeTransform);
118 Entry.InstancedStaticMeshComponent->DestroyComponent();
119 Entry.InstancedStaticMeshComponent = nullptr;
120 }
121
122 Entry.Materials.Empty();
123 Entry.Mesh.Reset();
124 }
125
126 InstanceEntries.Empty();
127}

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

◆ FindOrAddUniqueMesh()

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

Definition at line 193 of file InstancedRenderer.cpp.

194{
195 if (InstancedActor == nullptr || StaticMeshComponent == nullptr)
196 {
197#if WITH_EDITOR
198 UE_LOG(LogTemp, Warning, TEXT("StaticInstancedRenderer.cpp: StaticMeshComponent or InstancedActor is null!"));
199#endif
200 // return absurd number which should fail adding this instance to this renderer in above function.
201 return 99999999;
202 }
203
204 UStaticMesh* Mesh = StaticMeshComponent->GetStaticMesh();
205
206 if (!InstancedActor->HasAlternativeMaterial())
207 {
208 const int num = InstanceEntries.Num();
209 for (int32 Index = 0; Index < num; ++Index)
210 {
211 if (InstanceEntries[Index].Mesh == Mesh)
212 {
213 return Index;
214 }
215 }
216 }
217
218 const int count = StaticMeshComponent->GetNumMaterials();
219
220 TArray<UMaterialInterface*> MeshMaterials;
221 MeshMaterials.Reserve(count);
222
223 for (int32 i = 0; i < count; i++)
224 {
225 MeshMaterials.Add(StaticMeshComponent->GetMaterial(i));
226 }
227
228 const int Size = InstanceEntries.Num();
229 for (int32 Index = 0; Index < Size; ++Index)
230 {
231 if (InstanceEntries[Index].Mesh == Mesh)
232 {
233 bool bMaterialsMatch = true;
234
235 for (int32 MaterialIndex = 0; MaterialIndex < InstanceEntries[Index].Materials.Num(); ++MaterialIndex)
236 {
237 UMaterialInterface* UniqueMeshMaterial = InstanceEntries[Index].Materials[MaterialIndex];
238 UMaterialInterface* MeshMaterial = MeshMaterials[MaterialIndex];
239 if (UniqueMeshMaterial != MeshMaterial)
240 {
241 bMaterialsMatch = false;
242 }
243 }
244
245 if (bMaterialsMatch)
246 {
247 return Index;
248 }
249 }
250 }
251
252 // Else this is completely new mesh and/or mesh with alternative material,
253 // we need to create new FInstanceEntry and UInstancedStaticMeshComponent for it
254
255 // Create and setup new UInstancedStaticMeshComponent
256 UInstancedStaticMeshComponent* InstancedStaticMeshComponent = NewObject<UInstancedStaticMeshComponent>(this);
257
258 // Add Actor component list
259 InstancedStaticMeshComponent->AttachToComponent(GetRootComponent(), FAttachmentTransformRules::KeepRelativeTransform);
260 AddInstanceComponent(InstancedStaticMeshComponent);
261
262 InstancedStaticMeshComponent->bEditableWhenInherited = false;
263 InstancedStaticMeshComponent->RegisterComponent();
264 InstancedStaticMeshComponent->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
265 InstancedStaticMeshComponent->CreatePhysicsState(false);
266 InstancedStaticMeshComponent->SetSimulatePhysics(false);
267 InstancedStaticMeshComponent->SetStaticMesh(Mesh);
268 InstancedStaticMeshComponent->SetMobility(EComponentMobility::Static);
269 InstancedStaticMeshComponent->SetHiddenInGame(false);
270 InstancedStaticMeshComponent->SetVisibility(true);
271 InstancedStaticMeshComponent->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepWorldTransform);
272 InstancedStaticMeshComponent->InstanceStartCullDistance = InstancedActor->GetInstanceStartCullDistance();
273 InstancedStaticMeshComponent->InstanceEndCullDistance = InstancedActor->GetInstanceEndCullDistance();
274
275 // Set WPO distance and evaluation
276 InstancedStaticMeshComponent->SetWorldPositionOffsetDisableDistance(WorldPositionOffsetDistance);
277 /*InstancedStaticMeshComponent->SetEvaluateWorldPositionOffset(true);
278 InstancedStaticMeshComponent->SetEvaluateWorldPositionOffsetInRayTracing(true);*/
279
280 bool AllowWorldPositionOffsetDisable = InstancedActor->GetAllowWorldPositionOffsetDisable();
281
282 // For whatever reason this only works when done a bit later..
283 FTimerHandle Handle;
284 GetWorld()->GetTimerManager().SetTimer(Handle, FTimerDelegate::CreateLambda([this, InstancedStaticMeshComponent, AllowWorldPositionOffsetDisable]
285 {
286 if (InstancedStaticMeshComponent && AllowWorldPositionOffsetDisable && CurrentWeatherParameters.WindIntensity < 0.05f)
287 {
288 InstancedStaticMeshComponent->SetEvaluateWorldPositionOffset(false);
289 InstancedStaticMeshComponent->SetEvaluateWorldPositionOffsetInRayTracing(false);
290 }
291 }), 0.350f, false);
292
293 // Thermal and Semantic camera use custom depth.
294 // RenderCustomDepth is set to false, if no Thermal or Semantic camera exists in the level,
295 // and is automatically set to true/false for all instances when they are spawned/destroyed.
296 // Doing this saves a lot rendering performance.
297 InstancedStaticMeshComponent->SetRenderCustomDepth(true);
298 InstancedStaticMeshComponent->SetCustomDepthStencilValue(StaticMeshComponent->CustomDepthStencilValue);
299
300 // Huge performance implication, recommend is Rigid (especially for Foliage with WPO).
301 // https://docs.unrealengine.com/5.3/en-US/PythonAPI/class/ShadowCacheInvalidationBehavior.html
302 InstancedStaticMeshComponent->ShadowCacheInvalidationBehavior = EShadowCacheInvalidationBehavior::Rigid;
303
304 // Create new FInstanceEntry
305 FInstanceEntry InstanceEntry;
306 InstanceEntry.InstancedStaticMeshComponent = InstancedStaticMeshComponent;
307 InstanceEntry.ActorClass = InstancedActor->GetClass();
308 InstanceEntry.Mesh = Mesh;
309 InstanceEntry.Materials = MeshMaterials;
310 InstanceEntry.InstanceEntryIndex = InstanceEntries.Num();
311 InstanceEntry.CustomDepthStencilValue = StaticMeshComponent->CustomDepthStencilValue;
312 InstanceEntry.AllowWorldPositionOffsetDisable = AllowWorldPositionOffsetDisable;
313 InstanceEntry.IsTree = InstancedActor->IsTreeActor();
314
315 // Set materials to newly created UInstancedStaticMeshComponent
316 const int32 MaterialCount = MeshMaterials.Num();
317 for (int32 MaterialIndex = 0; MaterialIndex < MaterialCount; ++MaterialIndex)
318 {
319 UMaterialInterface* MaterialInterface = InstanceEntry.Materials[MaterialIndex];
320
321 if (MaterialInterface)
322 {
323 InstancedStaticMeshComponent->SetMaterial(MaterialIndex, MaterialInterface);
324
325#if WITH_EDITOR
326 // Validate in Editor that material has bUsedWithInstancedStaticMeshes on
327 UMaterial* Material = Cast<UMaterial>(MaterialInterface);
328 if (Material)
329 {
330 if (!Material->bUsedWithInstancedStaticMeshes)
331 {
332 UE_LOG(LogTemp, Warning, TEXT("InstancedRenderer.cpp: Material '%s' bUsedWithInstancedStaticMeshes is not set to true!"), *Material->GetName());
333 }
334 }
335#endif
336 }
337 }
338
339 InstanceEntries.Add(InstanceEntry);
340
341 return InstanceEntries.Num() - 1;
342}
int GetInstanceEndCullDistance() const
int GetInstanceStartCullDistance() const
bool HasAlternativeMaterial() const
bool GetAllowWorldPositionOffsetDisable() const
bool IsTreeActor() const
TWeakObjectPtr< UStaticMesh > Mesh
TArray< UMaterialInterface * > Materials
int32 CustomDepthStencilValue
bool AllowWorldPositionOffsetDisable
TSubclassOf< AActor > ActorClass
UInstancedStaticMeshComponent * InstancedStaticMeshComponent

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

Referenced by AddActorToInstancedRendering().

◆ Get()

static AInstancedRenderer * AInstancedRenderer::Get ( )
inlinestatic

Definition at line 212 of file InstancedRenderer.h.

213 {
214 return Instance;
215 }

◆ GetInstanceEntries()

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

Definition at line 140 of file InstancedRenderer.h.

141 {
142 return InstanceEntries;
143 }

◆ GetTotalInstanceCount()

int32 AInstancedRenderer::GetTotalInstanceCount ( ) const
inline

Definition at line 120 of file InstancedRenderer.h.

121 {
122 return TotalInstanceCount;
123 }

◆ GetUniqueInstancesCount()

int32 AInstancedRenderer::GetUniqueInstancesCount ( ) const
inline

Definition at line 130 of file InstancedRenderer.h.

131 {
132 return InstanceEntries.Num();
133 }

◆ IsRendering()

bool AInstancedRenderer::IsRendering ( ) const
inline

Definition at line 110 of file InstancedRenderer.h.

111 {
112 return Rendering;
113 }

◆ LogInfo()

void AInstancedRenderer::LogInfo ( ) const

Definition at line 76 of file InstancedRenderer.cpp.

77{
78#if WITH_EDITOR
79 UE_LOG(LogTemp, Warning, TEXT("InstancedRenderer.cpp: Unique mesh entries: %d | Total Instance Count: %d"), InstanceEntries.Num(), TotalInstanceCount);
80#endif
81}

References InstanceEntries, and TotalInstanceCount.

Referenced by BeginPlay().

◆ OnGraphicsSettingsChanged()

void AInstancedRenderer::OnGraphicsSettingsChanged ( FGlobalGraphicsSettings  GraphicsSettings)
private

Definition at line 410 of file InstancedRenderer.cpp.

411{
414}
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 416 of file InstancedRenderer.cpp.

417{
418 // When weather changes, we check current wind intensity to
419 // enable or disable certain instances world position offset evaluation.
420 // Disabling WPO completely when wind is 0.0 saves a lot of performance with foliage.
422 {
423 CurrentWeatherParameters = WeatherParameters;
424 bool ShouldRenderWPO = CurrentWeatherParameters.WindIntensity > 0.05f;
425 SetRenderWorldPositionOffet(ShouldRenderWPO);
426 }
427}
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 359 of file InstancedRenderer.cpp.

360{
361 if (!InstanceEntries.IsValidIndex(ComponentIndex))
362 {
363 return;
364 }
365
366 FInstanceEntry& Entry = InstanceEntries[ComponentIndex];
367
369 {
370 Entry.InstancedStaticMeshComponent->RemoveInstance(InstanceNumber);
371 }
372
374}

References FInstanceEntry::InstancedStaticMeshComponent, InstanceEntries, and TotalInstanceCount.

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 392 of file InstancedRenderer.cpp.

393{
394 if (!InstanceEntries.IsValidIndex(Index))
395 {
396#if WITH_EDITOR
397 UE_LOG(LogTemp, Warning, TEXT("InstancedRenderer.cpp: Index %d is not valid!"), Index);
398#endif
399 return;
400 }
401
402 FInstanceEntry& Entry = InstanceEntries[Index];
403
405 {
406 Entry.InstancedStaticMeshComponent->SetVisibility(Visible);
407 }
408}

References FInstanceEntry::InstancedStaticMeshComponent, and InstanceEntries.

◆ SetInstancedRendering()

void AInstancedRenderer::SetInstancedRendering ( bool  ShouldRender)

Definition at line 376 of file InstancedRenderer.cpp.

377{
378 Rendering = ShouldRender;
379 for (const FInstanceEntry& Entry : InstanceEntries)
380 {
381 if (Entry.InstancedStaticMeshComponent)
382 {
383 Entry.InstancedStaticMeshComponent->SetVisibility(Rendering);
384 }
385 }
386
387#if WITH_EDITOR
388 UE_LOG(LogTemp, Warning, TEXT("InstancedRenderer.cpp: Rendering: %s"), (Rendering ? TEXT("true") : TEXT("false")));
389#endif
390}

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 429 of file InstancedRenderer.cpp.

430{
431 for (FInstanceEntry& Entry : InstanceEntries)
432 {
433 if (Entry.InstancedStaticMeshComponent)
434 {
435 Entry.InstancedStaticMeshComponent->SetRenderCustomDepth(Enabled);
436 }
437 }
438}

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 469 of file InstancedRenderer.cpp.

470{
471 for (FInstanceEntry& Entry : InstanceEntries)
472 {
473 if (Entry.AllowWorldPositionOffsetDisable && Entry.InstancedStaticMeshComponent)
474 {
475 Entry.InstancedStaticMeshComponent->SetEvaluateWorldPositionOffset(RenderWPO);
476 Entry.InstancedStaticMeshComponent->SetEvaluateWorldPositionOffsetInRayTracing(RenderWPO);
477 }
478 }
479}

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 458 of file InstancedRenderer.cpp.

459{
460 for (FInstanceEntry& Entry : InstanceEntries)
461 {
462 if (Entry.InstancedStaticMeshComponent)
463 {
464 Entry.InstancedStaticMeshComponent->ShadowCacheInvalidationBehavior = ShadowCacheInvalidationBehaviour;
465 }
466 }
467}

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 440 of file InstancedRenderer.cpp.

441{
442 if (WorldPositionOffsetDistance == NewWPODistance)
443 {
444 return;
445 }
446
447 WorldPositionOffsetDistance = NewWPODistance;
448
449 for (FInstanceEntry& Entry : InstanceEntries)
450 {
451 if (Entry.InstancedStaticMeshComponent)
452 {
453 Entry.InstancedStaticMeshComponent->SetWorldPositionOffsetDisableDistance(WorldPositionOffsetDistance);
454 }
455 }
456}

References InstanceEntries, and WorldPositionOffsetDistance.

Referenced by OnGraphicsSettingsChanged().

◆ SpawnAllInstancesBackActors()

void AInstancedRenderer::SpawnAllInstancesBackActors ( )

Definition at line 544 of file InstancedRenderer.cpp.

545{
546#if WITH_EDITOR
547 UWorld* World = GetWorld();
548
549 if (InstanceEntries.IsEmpty())
550 {
551 return;
552 }
553
554 for (FInstanceEntry& Entry : InstanceEntries)
555 {
556 UInstancedStaticMeshComponent* ISMComponent = Entry.InstancedStaticMeshComponent;
557 if (!ISMComponent)
558 {
559 continue;
560 }
561
562 ISMComponent->SetVisibility(false);
563
564 // Extract transforms from ISM component into TArray
565 TArray<FTransform> Transforms;
566
567 const int32 InstanceCount = ISMComponent->GetInstanceCount();
568
569 for (int32 i = 0; i < InstanceCount; i++)
570 {
571 FTransform Transform;
572 ISMComponent->GetInstanceTransform(i, Transform);
573 Transforms.Add(Transform);
574 }
575
576 // Spawn actors to level
577 UClass* Class = Entry.ActorClass;
578 for (const FTransform& Transform : Transforms)
579 {
580 AActor* SpawnedActor = World->SpawnActorDeferred<AActor>(Class, Transform);
581 if (SpawnedActor)
582 {
583 SpawnedActor->FinishSpawning(Transform);
584 }
585 }
586
587 ISMComponent->DestroyComponent();
588 }
589
590 InstanceEntries.Empty();
591#endif
592}

References InstanceEntries, and Transform.

◆ SpawnInstanceBackToActor()

bool AInstancedRenderer::SpawnInstanceBackToActor ( UInstancedStaticMeshComponent *  ISM,
int32  Index 
)

Definition at line 594 of file InstancedRenderer.cpp.

595{
596 if (!ISM || Index < 0 || Index >= ISM->GetInstanceCount())
597 {
598 return false;
599 }
600
601 UWorld* World = GetWorld();
602 if (!World)
603 {
604 return false;
605 }
606
607 // Get the transform for the specified instance
608 FTransform InstanceTransform;
609 ISM->GetInstanceTransform(Index, InstanceTransform);
610
611 // Get the actor class from the associated entry
612 FInstanceEntry* Entry = InstanceEntries.FindByPredicate([ISM](const FInstanceEntry& InEntry)
613 {
614 return InEntry.InstancedStaticMeshComponent == ISM;
615 });
616
617 if (!Entry)
618 {
619 return false;
620 }
621
622 UClass* ActorClass = Entry->ActorClass;
623 if (!ActorClass)
624 {
625 return false;
626 }
627
628 // Spawn the actor
629 AActor* SpawnedActor = World->SpawnActorDeferred<AActor>(ActorClass, InstanceTransform);
630 if (SpawnedActor)
631 {
632 AInstancedActor* InstancedActor = Cast<AInstancedActor>(SpawnedActor);
633 if (InstancedActor)
634 {
635 InstancedActor->AddToInstancedRenderer = false;
636 }
637
638 SpawnedActor->FinishSpawning(InstanceTransform);
639
640 // Remove this ISM instance.
641 return ISM->RemoveInstance(Index);
642 }
643
644 return false;
645}

References FInstanceEntry::ActorClass, AInstancedActor::AddToInstancedRenderer, FInstanceEntry::InstancedStaticMeshComponent, and InstanceEntries.

◆ ToggleProxyMesh()

void AInstancedRenderer::ToggleProxyMesh ( )

Definition at line 520 of file InstancedRenderer.cpp.

521{
522#if WITH_EDITOR
523 for (FInstanceEntry& Entry : InstanceEntries)
524 {
525 auto& ISMComponent = Entry.InstancedStaticMeshComponent;
526
527 if (ISMComponent)
528 {
529 if (!Entry.UsingProxy)
530 {
531 ISMComponent->SetStaticMesh(ProxyMesh.Get());
532 Entry.UsingProxy = true;
533 }
534 else
535 {
536 ISMComponent->SetStaticMesh(Entry.Mesh.Get());
537 Entry.UsingProxy = false;
538 }
539 }
540 }
541#endif
542}

References InstanceEntries, and ProxyMesh.

◆ UpdateInstanceTransform()

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

Definition at line 344 of file InstancedRenderer.cpp.

345{
346 if (!InstanceEntries.IsValidIndex(ComponentIndex))
347 {
348 return;
349 }
350
351 FInstanceEntry& Entry = InstanceEntries[ComponentIndex];
352
354 {
355 Entry.InstancedStaticMeshComponent->UpdateInstanceTransform(InstanceNumber, NewTransform, true, true);
356 }
357}

References FInstanceEntry::InstancedStaticMeshComponent, and InstanceEntries.

Referenced by AInstancedActor::UpdateTransformPosition().

Member Data Documentation

◆ CurrentWeatherParameters

FWeatherParameters AInstancedRenderer::CurrentWeatherParameters
private

Definition at line 259 of file InstancedRenderer.h.

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

◆ Instance

AInstancedRenderer * AInstancedRenderer::Instance = nullptr
staticprivate

Definition at line 236 of file InstancedRenderer.h.

Referenced by BeginPlay(), and EndPlay().

◆ InstanceEntries

TArray<FInstanceEntry> AInstancedRenderer::InstanceEntries
protected

◆ InstancesStaticMeshComponents

TArray<UInstancedStaticMeshComponent*> AInstancedRenderer::InstancesStaticMeshComponents
protected

Definition at line 227 of file InstancedRenderer.h.

◆ ProxyMesh

TWeakObjectPtr<UStaticMesh> AInstancedRenderer::ProxyMesh
private

Definition at line 234 of file InstancedRenderer.h.

Referenced by AInstancedRenderer(), and ToggleProxyMesh().

◆ Rendering

bool AInstancedRenderer::Rendering = true
private

Definition at line 261 of file InstancedRenderer.h.

Referenced by SetInstancedRendering().

◆ RenderingWPO

bool AInstancedRenderer::RenderingWPO = true
private

Definition at line 263 of file InstancedRenderer.h.

◆ TotalInstanceCount

int32 AInstancedRenderer::TotalInstanceCount = 0
protected

Definition at line 230 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 257 of file InstancedRenderer.h.

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


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