Agrarsense
InstancedRenderer.h
Go to the documentation of this file.
1// Copyright (c) 2023 FrostBit Software Lab at the Lapland University of Applied Sciences
2//
3// This work is licensed under the terms of the MIT license.
4// For a copy, see <https://opensource.org/licenses/MIT>.
5
6#pragma once
7
8#include "CoreMinimal.h"
9#include "GameFramework/Actor.h"
10#include "Engine/EngineTypes.h"
11#include "Engine/StaticMesh.h"
12#include "Materials/MaterialInterface.h"
13#include "Components/InstancedStaticMeshComponent.h"
14
15#include <vector>
16
20#include "InstancedActorData.h"
21
22#include "InstancedRenderer.generated.h"
23
24class UStaticMeshComponent;
25class AInstancedActor;
26
27USTRUCT(Blueprintable)
28struct AGRARSENSE_API FInstanceEntry
29{
30 GENERATED_BODY()
31
32 UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
33 UInstancedStaticMeshComponent* InstancedStaticMeshComponent;
34
35 UPROPERTY(EditAnywhere, BlueprintReadWrite)
36 TSubclassOf<AActor> ActorClass;
37
38 UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
39 TWeakObjectPtr<UStaticMesh> Mesh;
40
41 UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
42 TArray<UMaterialInterface*> Materials;
43
44 UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
45 int32 InstanceEntryIndex = 0;
46
47 UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
48 int32 CustomDepthStencilValue = 0;
49
50 UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
52
53 UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
54 bool IsTree = false;
55
56 UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
57 bool UsingProxy = false;
58};
59
75UCLASS()
76class AGRARSENSE_API AInstancedRenderer : public AActor
77{
78 GENERATED_BODY()
79
80public:
81
82 AInstancedRenderer(const FObjectInitializer& ObjectInitializer);
83
84 /*
85 * Try to add AInstancedActor into instanced rendering. This is only callable from C++ by design.
86 * @param AInstancedActor AInstancedActor pointer
87 */
88 UFUNCTION(BlueprintCallable, Category = "Instanced Renderer")
89 bool AddActorToInstancedRendering(AInstancedActor* InstancedActor);
90
91 /*
92 * Remove instance from this Renderer.
93 * @param ComponentIndex index to TArray<UInstancedStaticMeshComponent*>
94 * @param InstanceNumber instance number
95 */
96 UFUNCTION(BlueprintCallable, Category = "Instanced Renderer")
97 void RemoveInstance(int32 ComponentIndex, int32 InstanceNumber);
98
99 /*
100 * Update one of the instances transform
101 * @param ComponentIndex index to TArray<UInstancedStaticMeshComponent*>
102 * @param InstanceNumber instance number
103 * @param NewTransform Transform to move the instance
104 */
105 void UpdateInstanceTransform(int32 ComponentIndex, int32 InstanceNumber, const FTransform& NewTransform);
106
107 /*
108 * Is this renderer currently rendering all InstancedStaticMeshComponents
109 */
110 UFUNCTION(BlueprintPure, Category = "Instanced Renderer")
111 bool IsRendering() const
112 {
113 return Rendering;
114 }
115
116 /*
117 * Get number of total instances
118 * @return TotalInstanceCount number of total instances
119 */
120 UFUNCTION(BlueprintCallable, Category = "Instanced Renderer")
121 int32 GetTotalInstanceCount() const
122 {
123 return TotalInstanceCount;
124 }
125
126 /*
127 * Get number of unique instances
128 * @return number of InstancedStaticMeshComponents
129 */
130 UFUNCTION(BlueprintCallable, Category = "Instanced Renderer")
131 int32 GetUniqueInstancesCount() const
132 {
133 return InstanceEntries.Num();
134 }
135
136 /*
137 * Get Mesh entries TArray
138 * @return TArray<FMeshEntry>
139 */
140 UFUNCTION(BlueprintCallable, Category = "Instanced Renderer")
141 TArray<FInstanceEntry> GetInstanceEntries() const
142 {
143 return InstanceEntries;
144 }
145
146 /*
147 * Set Instanced Rendering on/off. Debugging purposes.
148 */
149 UFUNCTION(BlueprintCallable, Category = "Instanced Renderer")
150 void SetInstancedRendering(bool ShouldRender);
151
157 UFUNCTION(BlueprintCallable, Category = "Instanced Renderer")
158 void SetComponentIndexVisibility(int32 Index, bool Visible);
159
164 UFUNCTION(BlueprintCallable, Category = "Instanced Renderer")
165 void SetRenderCustomDepth(bool Enabled);
166
171 UFUNCTION(BlueprintCallable, Category = "Instanced Renderer")
172 void SetWorldPositionOffsetDistance(int32 NewWPODistance);
173
178 UFUNCTION(BlueprintCallable, Category = "Instanced Renderer")
179 void SetShadowCacheBehaviour(EShadowCacheInvalidationBehavior ShadowCacheInvalidationBehaviour);
180
185 UFUNCTION(BlueprintCallable, Category = "Instanced Renderer")
186 void SetRenderWorldPositionOffet(bool RenderWPO);
187
188 /*
189 * Log renderer info to console. Debugging purposes.
190 */
191 UFUNCTION(BlueprintCallable, Category = "Instanced Renderer")
192 void LogInfo() const;
193
194 /*
195 * Toggles instanced static mesh materials between Unreal's default and their original. Debugging purposes.
196 * @param SetUnrealDefaultMaterial - If true, uses the default material; if false, restores original materials.
197 */
198 UFUNCTION(BlueprintCallable, Category = "Instanced Renderer")
199 void DebugMaterialImpact(bool SetUnrealDefaultMaterial);
200
201 /*
202 * Toggles between cube and actual ISM mesh. Can be used to improve editor performance.
203 */
204 UFUNCTION(BlueprintCallable, Category = "Instanced Renderer")
205 void ToggleProxyMesh();
206
207 /*
208 * Spawn all ISM instances back to original Actor and clear all instances.
209 * Editor only. Can be very slow with lots of instances.
210 */
211 UFUNCTION(BlueprintCallable, Category = "Instanced Renderer")
212 void SpawnAllInstancesBackActors();
213
214 /*
215 * Update/Reset render distances by
216 * spawning back original InstancedActor and checking set render distances from it.
217 */
218 UFUNCTION(BlueprintCallable, Category = "Instanced Renderer")
219 void UpdateRenderDistances();
220
227 void DestroyOverlappingInstancesBox(UInstancedStaticMeshComponent* ISM, FBox AreaBox, bool OnlyTrees);
228
236 UFUNCTION(BlueprintCallable, Category = "Instanced Renderer")
237 bool SpawnInstanceBackToActor(UInstancedStaticMeshComponent* ISM, int32 Index, bool OnlyTree);
238
239 static AInstancedRenderer* Get()
240 {
241 return Instance;
242 }
243
244protected:
245
250 UPROPERTY(VisibleAnywhere, AdvancedDisplay, BlueprintReadWrite)
251 TArray<FInstanceEntry> InstanceEntries;
252
253 UPROPERTY(BlueprintReadWrite)
254 TArray<UInstancedStaticMeshComponent*> InstancesStaticMeshComponents;
255
256 UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
257 int32 TotalInstanceCount = 0;
258
259private:
260
261 TWeakObjectPtr<UStaticMesh> CubeMesh;
262
263 static AInstancedRenderer* Instance;
264
265 virtual void BeginPlay() override;
266
267 virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
268
269 UFUNCTION()
270 void OnGraphicsSettingsChanged(FGlobalGraphicsSettings GraphicsSettings);
271
272 UFUNCTION()
273 void OnWeatherParametersChanged(FWeatherParameters WeatherParameters);
274
275 /*
276 * Find existing InstancedStaticMeshComponents array index or create new one for the mesh and its materials
277 * @return index to InstancedStaticMeshComponents array
278 */
279 bool FindOrAddUniqueMesh(UStaticMeshComponent* StaticMeshComponent, AInstancedActor* InstancedActor, int32& InstanceNum);
280
284 int32 WorldPositionOffsetDistance = 30000;
285
286 FWeatherParameters CurrentWeatherParameters;
287
288 bool Rendering = true;
289
290 bool RenderingWPO = false;
291};
UStaticMeshComponent * StaticMeshComponent
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override
bool AllowWorldPositionOffsetDisable
virtual void BeginPlay() override