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#include "Components/StaticMeshComponent.h"
15
16#include <vector>
17
21#include "InstancedActorData.h"
22#include "InstancedActor.h"
23
24#include "InstancedRenderer.generated.h"
25
26USTRUCT(Blueprintable)
27struct AGRARSENSE_API FInstanceEntry
28{
29 GENERATED_BODY()
30
31 UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
32 UInstancedStaticMeshComponent* InstancedStaticMeshComponent;
33
34 UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
35 TArray<FInstancedActorData> ActorData;
36
37 UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
38 TWeakObjectPtr<UStaticMesh> Mesh;
39
40 UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
41 TArray<UMaterialInterface*> Materials;
42
43 UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
44 FString MeshName;
45
46 UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
47 int32 InstanceEntryIndex = 0;
48
49 UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
50 bool AllowWorldPositionOffsetDisable = false;
51};
52
63UCLASS()
64class AGRARSENSE_API AInstancedRenderer : public AActor
65{
66 GENERATED_BODY()
67
68public:
69
70 AInstancedRenderer(const FObjectInitializer& ObjectInitializer);
71
72 /*
73 * Try to add AInstancedActor into instanced rendering. This is only callable from C++ by design.
74 * @param AInstancedActor AInstancedActor pointer
75 */
76 bool AddActorToInstancedRendering(AInstancedActor* InstancedActor);
77
78 /*
79 * Remove instance from this Renderer.
80 * @param ComponentIndex index to TArray<UInstancedStaticMeshComponent*>
81 * @param InstanceNumber instance number
82 */
83 UFUNCTION(BlueprintCallable, Category = "Instanced Renderer")
84 void RemoveInstance(int32 ComponentIndex, int32 InstanceNumber);
85
91 void AddOrRemoveActorFromAutomaticTransformUpdates(bool Add, AInstancedActor* InstancedActor);
92
93 /*
94 * Update one of the instances transform
95 * @param ComponentIndex index to TArray<UInstancedStaticMeshComponent*>
96 * @param InstanceNumber instance number
97 * @param NewTransform Transform to move the instance
98 */
99 void UpdateInstanceTransform(int32 ComponentIndex, int32 InstanceNumber, const FTransform& NewTransform);
100
101 /*
102 * Is this renderer currently rendering all InstancedStaticMeshComponents
103 */
104 UFUNCTION(BlueprintPure, Category = "Instanced Renderer")
105 bool IsRendering() const
106 {
107 return Rendering;
108 }
109
110 /*
111 * Get number of total instances
112 * @return TotalInstanceCount number of total instances
113 */
114 UFUNCTION(BlueprintCallable, Category = "Instanced Renderer")
115 int32 GetTotalInstanceCount() const
116 {
117 return TotalInstanceCount;
118 }
119
120 /*
121 * Get number of unique instances
122 * @return number of InstancedStaticMeshComponents
123 */
124 UFUNCTION(BlueprintCallable, Category = "Instanced Renderer")
125 int32 GetUniqueInstancesCount() const
126 {
127 return InstanceEntries.Num();
128 }
129
130 /*
131 * Get Mesh entries TArray
132 * @return TArray<FMeshEntry>
133 */
134 UFUNCTION(BlueprintCallable, Category = "Instanced Renderer")
135 TArray<FInstanceEntry> GetInstanceEntries() const
136 {
137 return InstanceEntries;
138 }
139
140 /*
141 * Set Instanced Rendering on/off. Debugging purposes.
142 */
143 UFUNCTION(BlueprintCallable, Category = "Instanced Renderer")
144 void SetInstancedRendering(bool ShouldRender);
145
151 UFUNCTION(BlueprintCallable, Category = "Instanced Renderer")
152 void SetComponentIndexVisibility(int32 Index, bool Visible);
153
158 UFUNCTION(BlueprintCallable, Category = "Instanced Renderer")
159 void SetRenderCustomDepth(bool Enabled);
160
165 UFUNCTION(BlueprintCallable, Category = "Instanced Renderer")
166 void SetWorldPositionOffsetDistance(int32 NewWPODistance);
167
172 UFUNCTION(BlueprintCallable, Category = "Instanced Renderer")
173 void SetShadowCacheBehaviour(EShadowCacheInvalidationBehavior ShadowCacheInvalidationBehaviour);
174
179 UFUNCTION(BlueprintCallable, Category = "Instanced Renderer")
180 void SetRenderWorldPositionOffet(bool RenderWPO);
181
182 /*
183 * Log renderer info to console. Debugging purposes.
184 */
185 UFUNCTION(BlueprintCallable, Category = "Instanced Renderer")
186 void LogInfo() const;
187
188 /*
189 * Toggles instanced static mesh materials between Unreal's default and their original. Debugging purposes.
190 * @param SetUnrealDefaultMaterial - If true, uses the default material; if false, restores original materials.
191 */
192 UFUNCTION(BlueprintCallable, Category = "Instanced Renderer")
193 void DebugMaterialImpact(bool SetUnrealDefaultMaterial);
194
195private:
196
197 static AInstancedRenderer* Instance;
198
199 void BeginPlay() override;
200
201 void Tick(float DeltaTime) override;
202
203 void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
204
205 UFUNCTION()
206 void OnGraphicsSettingsChanged(FGlobalGraphicsSettings GraphicsSettings);
207
208 UFUNCTION()
209 void OnWeatherParametersChanged(FWeatherParameters WeatherParameters);
210
211 bool AreTransformsEqual(const FTransform& TransformA, const FTransform& TransformB) const;
212
213 /*
214 * Update all AInstancedActors that have UpdateTransformAutomatically set to true
215 */
216 void UpdateInstancedActors();
217
218 /*
219 * Find existing InstancedStaticMeshComponents array index or create new one for the mesh and its materials
220 * @return index to InstancedStaticMeshComponents array
221 */
222 int32 FindOrAddUniqueMesh(UStaticMeshComponent* StaticMeshComponent, AInstancedActor* InstancedActor);
223
228 UPROPERTY(VisibleAnywhere)
229 TArray<FInstanceEntry> InstanceEntries;
230
234 int32 WorldPositionOffsetDistance = 30000;
235
236 std::vector<FInstancedActorData> InstancedActorsToUpdate;
237
238 FWeatherParameters CurrentWeatherParameters;
239
240 int32 TotalInstanceCount;
241
242 bool Rendering = true;
243
244 bool RenderingWPO = true;
245};