113 UPROPERTY(EditAnywhere, Category =
"IVSmoke | Debug")
114 bool bDebugEnabled =
true;
117 UPROPERTY(EditAnywhere, Category =
"IVSmoke | Debug", meta = (EditCondition =
"bDebugEnabled"))
118 bool bRenderSmokeInPreview = true;
120 UPROPERTY(EditAnywhere, Category = "
IVSmoke | Debug", meta = (EditCondition = "bDebugEnabled"))
121 EIVSmokeDebugViewMode ViewMode = EIVSmokeDebugViewMode::SolidColor;
123 UPROPERTY(EditAnywhere, Category = "
IVSmoke | Debug", meta = (EditCondition = "bDebugEnabled"))
124 bool bShowVolumeBounds = true;
126 UPROPERTY(EditAnywhere, Category = "
IVSmoke | Debug", meta = (EditCondition = "bDebugEnabled"))
127 bool bShowVoxelMesh = false;
129 UPROPERTY(EditAnywhere, Category = "
IVSmoke | Debug", meta = (EditCondition = "bDebugEnabled"))
130 bool bShowVoxelWireframe = true;
132 UPROPERTY(EditAnywhere, Category = "
IVSmoke | Debug", meta = (EditCondition = "bDebugEnabled"))
133 bool bShowStatusText = true;
135 UPROPERTY(EditAnywhere, Category = "
IVSmoke | Debug", meta = (EditCondition = "bDebugEnabled", UIMin = 0.0, UIMax = 1.0, ClampMin = 0.0))
136 FColor DebugWireframeColor = FColor(20, 20, 20);
138 UPROPERTY(EditAnywhere, Category = "
IVSmoke | Debug", meta = (EditCondition = "bDebugEnabled", UIMin=0.0, UIMax=1.0))
139 float SliceHeight = 1.0f;
141 UPROPERTY(EditAnywhere, Category = "
IVSmoke | Debug", meta = (EditCondition = "bDebugEnabled", ClampMin=0, ClampMax=100))
142 int32 VisibleStepCountPercent = 100;
173#pragma region Lifecycle
177 virtual void Tick(
float DeltaTime)
override;
178 virtual bool ShouldTickIfViewportsOnly()
const override;
180 virtual void OnConstruction(
const FTransform& Transform)
override;
183 virtual void PostEditChangeProperty(
struct FPropertyChangedEvent& PropertyChangedEvent)
override;
184 virtual void PostEditMove(
bool bFinished)
override;
185 virtual bool CanEditChange(
const FProperty* InProperty)
const override;
186 virtual void EditorApplyRotation(
const FRotator& DeltaRotation,
bool bAltDown,
bool bShiftDown,
bool bCtrlDown)
override;
187 virtual void EditorApplyScale(
const FVector& DeltaScale,
const FVector* PivotLocation,
bool bAltDown,
bool bShiftDown,
bool bCtrlDown)
override;
188 virtual void EditorApplyTranslation(
const FVector& DeltaTranslation,
bool bAltDown,
bool bShiftDown,
bool bCtrlDown)
override;
189 virtual bool IsSelectable()
const override;
193 virtual void BeginPlay()
override;
194 virtual void EndPlay(
const EEndPlayReason::Type EndPlayReason)
override;
195 virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps)
const override;
200#pragma region Components
206 TObjectPtr<UIVSmokeHoleGeneratorComponent> GetHoleGeneratorComponent();
212 TObjectPtr<UIVSmokeCollisionComponent> GetCollisionComponent();
215 UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category =
"IVSmoke")
216 TObjectPtr<UBillboardComponent> BillboardComponent;
223 UPROPERTY(EditAnywhere, Category = "
IVSmoke")
231 UPROPERTY(EditAnywhere, Category = "
IVSmoke")
234#if WITH_EDITORONLY_DATA
240 TObjectPtr<UInstancedStaticMeshComponent> DebugMeshComponent;
246#pragma region Configuation
253 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category =
"IVSmoke | Config", meta = (ClampMin =
"1", ClampMax =
"16"))
254 FIntVector VolumeExtent = FIntVector(16, 16, 16);
262 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "
IVSmoke | Config", meta = (ClampMin = "0.1", UIMin = "0.1", UIMax = "5.0"))
263 FVector Radii = FVector(1.0f, 1.0f, 1.0f);
270 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "
IVSmoke | Config", meta = (ClampMin = "1.0", UIMin = "10.0", UIMax = "100.0"))
271 float VoxelSize = 50.0f;
278 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "
IVSmoke | Config", meta = (ClampMin = "1", UIMin = "100", UIMax = "10000"))
279 int32 MaxVoxelNum = 1000;
282 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "
IVSmoke | Config")
283 bool bAutoStart = false;
286 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "
IVSmoke | Config")
287 bool bDestroyOnFinish = false;
290 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "
IVSmoke | Config")
291 bool bIsInfinite = false;
298 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "
IVSmoke | Config")
305#pragma region Simulation
311 UFUNCTION(BlueprintCallable, Category =
"IVSmoke")
319 UFUNCTION(Server, Reliable, BlueprintCallable, Category = "
IVSmoke")
320 void StartSimulation();
327 UFUNCTION(Server, Reliable, BlueprintCallable, Category = "
IVSmoke")
328 void StopSimulation(
bool bImmediate = false);
334 UFUNCTION(Server, Reliable, BlueprintCallable, Category = "
IVSmoke")
335 void ResetSimulation();
341 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "
IVSmoke | Simulation", meta = (ClampMin = "0.0"))
342 float ExpansionDuration = 3.0f;
348 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "
IVSmoke | Simulation", meta = (ClampMin = "0.0"))
349 float SustainDuration = 5.0f;
355 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "
IVSmoke | Simulation", meta = (ClampMin = "0.0"))
356 float DissipationDuration = 2.0f;
361 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "
IVSmoke | Simulation", meta = (ClampMin = "0.0"))
362 float FadeInDuration = 2.0f;
367 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "
IVSmoke | Simulation", meta = (ClampMin = "0.0"))
368 float FadeOutDuration = 2.0f;
374 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "
IVSmoke | Simulation", meta = (ClampMin = "0.0", UIMin = "0.0", UIMax = "5000.0"))
375 float ExpansionNoise = 100.0f;
381 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "
IVSmoke | Simulation", meta = (ClampMin = "0.0", UIMin = "0.0", UIMax = "5000.0"))
382 float DissipationNoise = 100.0f;
390 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "
IVSmoke | Simulation")
391 TObjectPtr<UCurveFloat> ExpansionCurve;
399 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "
IVSmoke | Simulation")
400 TObjectPtr<UCurveFloat> DissipationCurve;
406 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "
IVSmoke | Simulation")
407 bool bEnableSimulationCollision = true;
410 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "
IVSmoke | Simulation", meta = (EditCondition = "bEnableSimulationCollision"))
411 TEnumAsByte<ECollisionChannel> VoxelCollisionChannel = ECC_WorldStatic;
415 struct FIVSmokeVoxelNode
420 bool operator<(
const FIVSmokeVoxelNode& Other)
const
422 if (FMath::IsNearlyEqual(Cost, Other.Cost))
424 return Index < Other.Index;
426 return Cost < Other.Cost;
438 FORCEINLINE
static float GetCurveValue(
float ElapsedTime,
float Duration,
const UCurveFloat* Curve)
440 if (Duration <= KINDA_SMALL_NUMBER)
445 float Alpha = FMath::Clamp(ElapsedTime / Duration, 0.0f, 1.0f);
449 return FMath::Clamp(Curve->GetFloatValue(Alpha), 0.0f, 1.0f);
457 void OnRep_ServerState();
465 void HandleStateTransition(EIVSmokeVoxelVolumeState NewState);
468 void ClearSimulationData();
478 bool IsConnectionBlocked(const UWorld* World, const FVector& BeginPos, const FVector& EndPos) const;
484 void StartSimulationInternal();
491 void StopSimulationInternal(
bool bImmediate = false);
497 void ResetSimulationInternal();
503 void FastForwardSimulation();
506 void UpdateExpansion();
509 void UpdateSustain();
512 void UpdateDissipation();
521 void ProcessExpansion(int32 SpawnNum,
float StartSimTime,
float EndSimTime);
530 void ProcessDissipation(int32 RemoveNum,
float StartSimTime,
float EndSimTime);
538 void SetVoxelBirthTime(int32 Index,
float BirthTime);
546 void SetVoxelDeathTime(int32 Index,
float DeathTime);
557 float CalculateWeightedDistance(int32 IndexA, int32 IndexB, const FVector& InvRadii) const;
560 UPROPERTY(ReplicatedUsing = OnRep_ServerState)
564 EIVSmokeVoxelVolumeState LocalState = EIVSmokeVoxelVolumeState::Idle;
567 uint8 LocalGeneration = 0;
570 FRandomStream RandomStream;
573 float SimTime = 0.0f;
576 bool bIsInitialized = false;
579 bool bIsFastForwarding = false;
582 FVector VoxelWorldAABBMin = FVector(FLT_MAX, FLT_MAX, FLT_MAX);
585 FVector VoxelWorldAABBMax = FVector(-FLT_MAX, -FLT_MAX, -FLT_MAX);
588 TArray<
float> VoxelBirthTimes;
591 TArray<
float> VoxelDeathTimes;
594 TArray<
float> VoxelCosts;
607 TArray<uint64> VoxelBits;
610 TArray<FIVSmokeVoxelNode> ExpansionHeap;
613 TArray<FIVSmokeVoxelNode> DissipationHeap;
616 TArray<int32> GeneratedVoxelIndices;
618 TBitArray<> VoxelPenetrationFlags;
624#pragma region Collision
632 void TryUpdateCollision(
bool bForce =
false);
637#pragma region DataAccess
640 FORCEINLINE EIVSmokeVoxelVolumeState
GetCurrentState()
const {
return ServerState.State; }
646 bool ShouldRender()
const;
657 FIntVector GridResolution;
658 GridResolution.X = FMath::Max(1, (VolumeExtent.X * 2) - 1);
659 GridResolution.Y = FMath::Max(1, (VolumeExtent.Y * 2) - 1);
660 GridResolution.Z = FMath::Max(1, (VolumeExtent.Z * 2) - 1);
661 return GridResolution;
665 FORCEINLINE FIntVector
GetCenterOffset()
const {
return VolumeExtent - FIntVector(1, 1, 1); }
674 FORCEINLINE
bool IsVoxelDataDirty()
const {
return DirtyLevel != EIVSmokeDirtyLevel::Clean; }
706 return IsVoxelActive(GridPos);
721 FTextureRHIRef GetHoleTexture()
const;
727 float GetSyncWorldTimeSeconds()
const;
731 int32 ActiveVoxelNum = 0;
734 EIVSmokeDirtyLevel DirtyLevel = EIVSmokeDirtyLevel::Clean;
746 UFUNCTION(CallInEditor, Category =
"IVSmoke | Debug")
747 void StartPreviewSimulation();
753 UFUNCTION(CallInEditor, Category = "
IVSmoke | Debug")
754 void StopPreviewSimulation();
757 UPROPERTY(EditAnywhere, Category = "
IVSmoke | Debug")
761 UPROPERTY(EditDefaultsOnly, Category = "
IVSmoke | Debug", AdvancedDisplay)
762 TObjectPtr<UStaticMesh> DebugVoxelMesh;
765 UPROPERTY(EditDefaultsOnly, Category = "
IVSmoke | Debug", AdvancedDisplay)
766 TObjectPtr<UMaterialInterface> DebugVoxelMaterial;
770 void DrawDebugVisualization() const;
773 void DrawDebugVolumeBounds() const;
776 void DrawDebugVoxelWireframes() const;
779 void DrawDebugVoxelMeshes() const;
782 void DrawDebugStatusText() const;
785 uint32 CalculateSimulationChecksum() const;
788 bool bIsEditorPreviewing = false;