318 lines
7.8 KiB
C++
318 lines
7.8 KiB
C++
// Copyright 2020 Phyronnaz
|
|
|
|
#include "VoxelNodes/VoxelNoiseNodes.h"
|
|
#include "VoxelGraphGenerator.h"
|
|
#include "VoxelUtilities/VoxelMathUtilities.h"
|
|
|
|
#define NOISE_SAMPLE_RANGE 10
|
|
|
|
FName UVoxelNode_NoiseNode::GetInputPinName(int32 PinIndex) const
|
|
{
|
|
if (GetDimension() == 2)
|
|
{
|
|
if (PinIndex == 0)
|
|
{
|
|
return "X";
|
|
}
|
|
else if (PinIndex == 1)
|
|
{
|
|
return "Y";
|
|
}
|
|
else if (PinIndex == 2)
|
|
{
|
|
return "Frequency";
|
|
}
|
|
else if (PinIndex == 3)
|
|
{
|
|
return "Seed";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (PinIndex == 0)
|
|
{
|
|
return "X";
|
|
}
|
|
else if (PinIndex == 1)
|
|
{
|
|
return "Y";
|
|
}
|
|
else if (PinIndex == 2)
|
|
{
|
|
return "Z";
|
|
}
|
|
else if (PinIndex == 3)
|
|
{
|
|
return "Frequency";
|
|
}
|
|
else if (PinIndex == 4)
|
|
{
|
|
return "Seed";
|
|
}
|
|
}
|
|
|
|
return CustomNoisePins.GetInputPin(PinIndex - GetBaseInputPinsCount(), false).Name;
|
|
}
|
|
|
|
FName UVoxelNode_NoiseNode::GetOutputPinName(int32 PinIndex) const
|
|
{
|
|
if (PinIndex == 0)
|
|
{
|
|
return IsDerivative() ? "Value" : "";
|
|
}
|
|
|
|
if (IsDerivative())
|
|
{
|
|
if (PinIndex == 1)
|
|
{
|
|
return "DX";
|
|
}
|
|
else if (PinIndex == 2)
|
|
{
|
|
return "DY";
|
|
}
|
|
else if (PinIndex == 3)
|
|
{
|
|
return "DZ";
|
|
}
|
|
}
|
|
|
|
return CustomNoisePins.GetOutputPin(PinIndex - GetBaseOutputPinsCount(), false).Name;
|
|
}
|
|
|
|
FString UVoxelNode_NoiseNode::GetInputPinToolTip(int32 PinIndex) const
|
|
{
|
|
if (GetDimension() == 2)
|
|
{
|
|
if (PinIndex == 0)
|
|
{
|
|
return "X";
|
|
}
|
|
else if (PinIndex == 1)
|
|
{
|
|
return "Y";
|
|
}
|
|
else if (PinIndex == 2)
|
|
{
|
|
return "The frequency of the noise";
|
|
}
|
|
else if (PinIndex == 3)
|
|
{
|
|
return "The seed to use";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (PinIndex == 0)
|
|
{
|
|
return "X";
|
|
}
|
|
else if (PinIndex == 1)
|
|
{
|
|
return "Y";
|
|
}
|
|
else if (PinIndex == 2)
|
|
{
|
|
return "Z";
|
|
}
|
|
else if (PinIndex == 3)
|
|
{
|
|
return "The frequency of the noise";
|
|
}
|
|
else if (PinIndex == 4)
|
|
{
|
|
return "The seed to use";
|
|
}
|
|
}
|
|
|
|
return CustomNoisePins.GetInputPin(PinIndex - GetBaseInputPinsCount(), false).ToolTip;
|
|
}
|
|
|
|
FString UVoxelNode_NoiseNode::GetOutputPinToolTip(int32 PinIndex) const
|
|
{
|
|
if (PinIndex == 0)
|
|
{
|
|
return "The noise value";
|
|
}
|
|
else if (PinIndex == 1)
|
|
{
|
|
return "The derivative along the X axis. Can be used to compute the slope of the noise using GetSlopeFromDerivatives.";
|
|
}
|
|
else if (PinIndex == 2)
|
|
{
|
|
return "The derivative along the Y axis. Can be used to compute the slope of the noise using GetSlopeFromDerivatives.";
|
|
}
|
|
else if (PinIndex == 3)
|
|
{
|
|
return "The derivative along the Z axis. Can be used to compute the slope of the noise using GetSlopeFromDerivatives.";
|
|
}
|
|
|
|
return CustomNoisePins.GetOutputPin(PinIndex - GetBaseOutputPinsCount(), false).ToolTip;
|
|
}
|
|
|
|
EVoxelPinCategory UVoxelNode_NoiseNode::GetInputPinCategory(int32 PinIndex) const
|
|
{
|
|
return PinIndex == GetDimension() + 1 ? EVoxelPinCategory::Seed : EVoxelPinCategory::Float;
|
|
}
|
|
|
|
EVoxelPinCategory UVoxelNode_NoiseNode::GetOutputPinCategory(int32 PinIndex) const
|
|
{
|
|
return EVoxelPinCategory::Float;
|
|
}
|
|
|
|
FString UVoxelNode_NoiseNode::GetInputPinDefaultValue(int32 PinIndex) const
|
|
{
|
|
if (PinIndex == GetDimension())
|
|
{
|
|
return FString::SanitizeFloat(Frequency);
|
|
}
|
|
|
|
return CustomNoisePins.GetInputPin(PinIndex - GetBaseInputPinsCount(), false).DefaultValue;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
#if WITH_EDITOR
|
|
void UVoxelNode_NoiseNode::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
|
|
{
|
|
Super::PostEditChangeProperty(PropertyChangedEvent);
|
|
|
|
if (PropertyChangedEvent.MemberProperty &&
|
|
PropertyChangedEvent.ChangeType != EPropertyChangeType::Interactive)
|
|
{
|
|
}
|
|
}
|
|
|
|
bool UVoxelNode_NoiseNode::CanEditChange(const FProperty* InProperty) const
|
|
{
|
|
return
|
|
Super::CanEditChange(InProperty) &&
|
|
(NeedRangeAnalysis() || InProperty->GetFName() != GET_MEMBER_NAME_STATIC(UVoxelNode_NoiseNode, NumberOfSamples));
|
|
}
|
|
#endif
|
|
|
|
void UVoxelNode_NoiseNode::PostLoad()
|
|
{
|
|
Super::PostLoad();
|
|
if (OutputRanges.Num() == 0)
|
|
{
|
|
}
|
|
}
|
|
|
|
void UVoxelNode_NoiseNode::PostInitProperties()
|
|
{
|
|
Super::PostInitProperties();
|
|
if (OutputRanges.Num() == 0 && !HasAnyFlags(RF_ClassDefaultObject | RF_NeedLoad))
|
|
{
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
FLinearColor UVoxelNode_NoiseNodeFractal::GetNodeBodyColor() const
|
|
{
|
|
return FMath::Lerp<FLinearColor>(FColorList::White, FColorList::Orange, FMath::Clamp<float>((FractalOctaves - 1.f) / 10, 0, 1));
|
|
}
|
|
|
|
FLinearColor UVoxelNode_NoiseNodeFractal::GetColor() const
|
|
{
|
|
return FMath::Lerp<FLinearColor>(FColorList::Black, FColorList::Orange, FMath::Clamp<float>((FractalOctaves - 1.f) / 10, 0, 1));
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
#if WITH_EDITOR
|
|
void UVoxelNode_NoiseNodeFractal::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
|
|
{
|
|
Super::PostEditChangeProperty(PropertyChangedEvent);
|
|
|
|
if (PropertyChangedEvent.Property && PropertyChangedEvent.ChangeType != EPropertyChangeType::Interactive)
|
|
{
|
|
LODToOctavesMap.Add("0", FractalOctaves);
|
|
int32 MaxInt = 0;
|
|
for (auto& It : LODToOctavesMap)
|
|
{
|
|
if (!It.Key.IsEmpty())
|
|
{
|
|
const int32 Int = FVoxelUtilities::ClampDepth<RENDER_CHUNK_SIZE>(TCString<TCHAR>::Atoi(*It.Key));
|
|
MaxInt = FMath::Max(MaxInt, Int);
|
|
It.Key = FString::FromInt(Int);
|
|
}
|
|
}
|
|
for (auto& It : LODToOctavesMap)
|
|
{
|
|
if (It.Key.IsEmpty())
|
|
{
|
|
if (uint8 * LOD = LODToOctavesMap.Find(FString::FromInt(MaxInt)))
|
|
{
|
|
It.Value = *LOD - 1;
|
|
}
|
|
It.Key = FString::FromInt(++MaxInt);
|
|
}
|
|
}
|
|
LODToOctavesMap.KeySort([](const FString& A, const FString& B) { return TCString<TCHAR>::Atoi(*A) < TCString<TCHAR>::Atoi(*B); });
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void UVoxelNode_NoiseNodeFractal::PostLoad()
|
|
{
|
|
LODToOctavesMap.Add("0", FractalOctaves);
|
|
Super::PostLoad(); // Make sure to call ComputeRange after
|
|
}
|
|
|
|
void UVoxelNode_NoiseNodeFractal::PostInitProperties()
|
|
{
|
|
LODToOctavesMap.Add("0", FractalOctaves);
|
|
Super::PostInitProperties(); // Make sure to call ComputeRange after
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
UVoxelNode_IQNoiseBase::UVoxelNode_IQNoiseBase()
|
|
{
|
|
bComputeDerivative = true;
|
|
FractalType = EVoxelNoiseFractalType::FBM;
|
|
FractalOctaves = 15;
|
|
Frequency = 0.001;
|
|
NumberOfSamples = 1000000;
|
|
}
|
|
|
|
#if WITH_EDITOR
|
|
bool UVoxelNode_IQNoiseBase::CanEditChange(const FProperty* InProperty) const
|
|
{
|
|
return
|
|
Super::CanEditChange(InProperty) &&
|
|
InProperty->GetFName() != GET_MEMBER_NAME_STATIC(UVoxelNode_IQNoiseBase, bComputeDerivative) &&
|
|
InProperty->GetFName() != GET_MEMBER_NAME_STATIC(UVoxelNode_IQNoiseBase, FractalType);
|
|
}
|
|
#endif
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|