Skip to content

Commit

Permalink
Add Minkowski distance function
Browse files Browse the repository at this point in the history
  • Loading branch information
Auburn committed May 4, 2024
1 parent f8fd6f8 commit fe0fd43
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 36 deletions.
25 changes: 21 additions & 4 deletions include/FastNoise/Generators/BasicGenerators.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,13 +195,28 @@ namespace FastNoise
void SetSource( SmartNodeArg<> gen ) { this->SetSourceMemberVariable( mSource, gen ); }
void SetDistanceFunction( DistanceFunction value ) { mDistanceFunction = value; }

void SetMinkowskiP( SmartNodeArg<> gen ) { this->SetSourceMemberVariable( mMinkowskiP, gen ); }
void SetMinkowskiP( float value ) { mMinkowskiP = value; }

void SetPoint( float x, float y, float z = 0, float w = 0 )
{
mPoint[0] = x;
mPoint[1] = y;
mPoint[2] = z;
mPoint[3] = w;
}

template<Dim D>
void SetScale( float value ) { mPoint[(int)D] = value; }
void SetPoint( float value ) { mPoint[(int)D] = value; }

template<Dim D>
void SetPoint( SmartNodeArg<> gen ) { this->SetSourceMemberVariable( mPoint[(int)D], gen ); }

protected:
GeneratorSource mSource;
HybridSource mMinkowskiP = 0.5f;
DistanceFunction mDistanceFunction = DistanceFunction::EuclideanSquared;
PerDimensionVariable<float> mPoint = 0.0f;
PerDimensionVariable<HybridSource> mPoint = 0.0f;

template<typename T>
friend struct MetadataT;
Expand All @@ -217,10 +232,12 @@ namespace FastNoise
{
groups.push_back( "Basic Generators" );
this->AddVariableEnum( "Distance Function", DistanceFunction::Euclidean, &DistanceToPoint::SetDistanceFunction, kDistanceFunction_Strings );
this->AddPerDimensionVariable( { "Point", "Point in current domain space" }, 0.0f, []( DistanceToPoint* p ) { return std::ref( p->mPoint ); } );
this->AddPerDimensionHybridSource( { "Point", "Point in current domain space" }, 0.0f, []( DistanceToPoint* p ) { return std::ref( p->mPoint ); } );

this->AddHybridSource( { "Minkowski P", "Only affects Minkowski distance function\n1 = Manhattan\n2 = Euclidean" }, 0.5f, &DistanceToPoint::SetMinkowskiP, &DistanceToPoint::SetMinkowskiP );

description =
"Outputs calculated distance between point and input position";
"Outputs distance between point and input position";
}
};
#endif
Expand Down
4 changes: 2 additions & 2 deletions include/FastNoise/Generators/BasicGenerators.inl
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ class FastSIMD::DispatchClass<FastNoise::DistanceToPoint, SIMD> final : public v
{
size_t pointIdx = 0;

((pos -= float32v( mPoint[pointIdx++] )), ...);
return CalcDistance( mDistanceFunction, pos... );
((pos -= this->GetSourceValue( mPoint[pointIdx++], seed, pos... ) ), ...);
return CalcDistance( mDistanceFunction, mMinkowskiP, seed, pos... );
}
};
11 changes: 9 additions & 2 deletions include/FastNoise/Generators/Cellular.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,16 @@ namespace FastNoise
class Cellular : public virtual PARENT
{
public:
void SetDistanceFunction( DistanceFunction value ) { mDistanceFunction = value; }

void SetMinkowskiP( SmartNodeArg<> gen ) { this->SetSourceMemberVariable( mMinkowskiP, gen ); }
void SetMinkowskiP( float value ) { mMinkowskiP = value; }

void SetJitterModifier( SmartNodeArg<> gen ) { this->SetSourceMemberVariable( mJitterModifier, gen ); }
void SetJitterModifier( float value ) { mJitterModifier = value; }
void SetDistanceFunction( DistanceFunction value ) { mDistanceFunction = value; }

protected:
HybridSource mMinkowskiP = 0.5f;
HybridSource mJitterModifier = 1.0f;
DistanceFunction mDistanceFunction = DistanceFunction::EuclideanSquared;
};
Expand All @@ -25,9 +30,11 @@ namespace FastNoise
MetadataT()
{
this->groups.push_back( "Coherent Noise" );
this->AddHybridSource( { "Jitter Modifier", "Above 1.0 will cause grid artifacts" }, 1.0f, &Cellular<PARENT>::SetJitterModifier, &Cellular<PARENT>::SetJitterModifier );
this->AddVariableEnum( { "Distance Function", "How distance to closest cells is calculated\nHybrid is EuclideanSquared + Manhattan" },
DistanceFunction::EuclideanSquared, &Cellular<PARENT>::SetDistanceFunction, kDistanceFunction_Strings );
this->AddHybridSource( { "Minkowski P", "Only affects Minkowski distance function\n1 = Manhattan\n2 = Euclidean" }, 0.5f, &Cellular<PARENT>::SetMinkowskiP, &Cellular<PARENT>::SetMinkowskiP );

this->AddHybridSource( { "Jitter Modifier", "Above 1.0 will cause grid artifacts" }, 1.0f, &Cellular<PARENT>::SetJitterModifier, &Cellular<PARENT>::SetJitterModifier );
}
};
#endif
Expand Down
18 changes: 9 additions & 9 deletions include/FastNoise/Generators/Cellular.inl
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class FastSIMD::DispatchClass<FastNoise::CellularValue, SIMD> final : public vir
yd = FS::FMulAdd( yd, invMag, ycf );

int32v newCellValueHash = hash;
float32v newDistance = CalcDistance<false>( mDistanceFunction, xd, yd );
float32v newDistance = CalcDistance<false>( mDistanceFunction, mMinkowskiP, seed, xd, yd );

for( int i = 0; ; i++ )
{
Expand Down Expand Up @@ -125,7 +125,7 @@ class FastSIMD::DispatchClass<FastNoise::CellularValue, SIMD> final : public vir
zd = FS::FMulAdd( zd, invMag, zcf );

int32v newCellValueHash = hash;
float32v newDistance = CalcDistance<false>( mDistanceFunction, xd, yd, zd );
float32v newDistance = CalcDistance<false>( mDistanceFunction, mMinkowskiP, seed, xd, yd, zd );

for( int i = 0; ; i++ )
{
Expand Down Expand Up @@ -211,7 +211,7 @@ class FastSIMD::DispatchClass<FastNoise::CellularValue, SIMD> final : public vir
wd = FS::FMulAdd( wd, invMag, wcf );

int32v newCellValueHash = hash;
float32v newDistance = CalcDistance<false>( mDistanceFunction, xd, yd, zd, wd );
float32v newDistance = CalcDistance<false>( mDistanceFunction, mMinkowskiP, seed, xd, yd, zd, wd );

for( int i = 0; ; i++ )
{
Expand Down Expand Up @@ -284,7 +284,7 @@ class FastSIMD::DispatchClass<FastNoise::CellularDistance, SIMD> final : public
xd = FS::FMulAdd( xd, invMag, xcf );
yd = FS::FMulAdd( yd, invMag, ycf );

float32v newDistance = CalcDistance<false>( mDistanceFunction, xd, yd );
float32v newDistance = CalcDistance<false>( mDistanceFunction, mMinkowskiP, seed, xd, yd );

for( int i = kMaxDistanceCount - 1; i > 0; i-- )
{
Expand Down Expand Up @@ -344,7 +344,7 @@ class FastSIMD::DispatchClass<FastNoise::CellularDistance, SIMD> final : public
yd = FS::FMulAdd( yd, invMag, ycf );
zd = FS::FMulAdd( zd, invMag, zcf );

float32v newDistance = CalcDistance<false>( mDistanceFunction, xd, yd, zd );
float32v newDistance = CalcDistance<false>( mDistanceFunction, mMinkowskiP, seed, xd, yd, zd );

for( int i = kMaxDistanceCount - 1; i > 0; i-- )
{
Expand Down Expand Up @@ -416,7 +416,7 @@ class FastSIMD::DispatchClass<FastNoise::CellularDistance, SIMD> final : public
zd = FS::FMulAdd( zd, invMag, zcf );
wd = FS::FMulAdd( wd, invMag, wcf );

float32v newDistance = CalcDistance<false>( mDistanceFunction, xd, yd, zd, wd );
float32v newDistance = CalcDistance<false>( mDistanceFunction, mMinkowskiP, seed, xd, yd, zd, wd );

for( int i = kMaxDistanceCount - 1; i > 0; i-- )
{
Expand Down Expand Up @@ -512,7 +512,7 @@ class FastSIMD::DispatchClass<FastNoise::CellularLookup, SIMD> final : public vi
xd = FS::FMulAdd( xd, invMag, xcf );
yd = FS::FMulAdd( yd, invMag, ycf );

float32v newDistance = CalcDistance<false>( mDistanceFunction, xd, yd );
float32v newDistance = CalcDistance<false>( mDistanceFunction, mMinkowskiP, seed, xd, yd );

mask32v closer = newDistance < distance;
distance = FS::Min( newDistance, distance );
Expand Down Expand Up @@ -570,7 +570,7 @@ class FastSIMD::DispatchClass<FastNoise::CellularLookup, SIMD> final : public vi
yd = FS::FMulAdd( yd, invMag, ycf );
zd = FS::FMulAdd( zd, invMag, zcf );

float32v newDistance = CalcDistance<false>( mDistanceFunction, xd, yd, zd );
float32v newDistance = CalcDistance<false>( mDistanceFunction, mMinkowskiP, seed, xd, yd, zd );

mask32v closer = newDistance < distance;
distance = FS::Min( newDistance, distance );
Expand Down Expand Up @@ -641,7 +641,7 @@ class FastSIMD::DispatchClass<FastNoise::CellularLookup, SIMD> final : public vi
zd = FS::FMulAdd( zd, invMag, zcf );
wd = FS::FMulAdd( wd, invMag, wcf );

float32v newDistance = CalcDistance<false>( mDistanceFunction, xd, yd, zd, wd );
float32v newDistance = CalcDistance<false>( mDistanceFunction, mMinkowskiP, seed, xd, yd, zd, wd );

mask32v closer = newDistance < distance;
distance = FS::Min( newDistance, distance );
Expand Down
8 changes: 5 additions & 3 deletions include/FastNoise/Generators/Generator.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

#include "FastNoise/Utility/Config.h"

#if !defined( FASTNOISE_METADATA ) && defined( __INTELLISENSE__ )
#if !defined( FASTNOISE_METADATA ) && ( defined( __INTELLISENSE__ ) || defined( __CLION_IDE__ ) )
#define FASTNOISE_METADATA
#endif

Expand All @@ -35,6 +35,7 @@ namespace FastNoise
Manhattan,
Hybrid,
MaxAxis,
Minkowski,
};

constexpr static const char* kDistanceFunction_Strings[] =
Expand All @@ -44,6 +45,7 @@ namespace FastNoise
"Manhattan",
"Hybrid",
"Max Axis",
"Minkowski",
};

struct OutputMinMax
Expand Down Expand Up @@ -87,7 +89,7 @@ namespace FastNoise
{
float constant;

HybridSourceT( float f = 0.0f )
constexpr HybridSourceT( float f = 0.0f )
{
constant = f;
}
Expand Down Expand Up @@ -173,7 +175,7 @@ namespace FastNoise
T varArray[(int)Dim::Count];

template<typename U = T>
PerDimensionVariable( U value = 0 )
constexpr PerDimensionVariable( U value = 0 )
{
for( T& element : varArray )
{
Expand Down
6 changes: 3 additions & 3 deletions include/FastNoise/Generators/Generator.inl
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public:
}

template<typename T, typename... POS>
FS_FORCEINLINE float32v FS_VECTORCALL GetSourceValue( const FastNoise::HybridSourceT<T>& memberVariable, int32v seed, POS... pos ) const
static FS_FORCEINLINE float32v FS_VECTORCALL GetSourceValue( const FastNoise::HybridSourceT<T>& memberVariable, int32v seed, POS... pos )
{
if( memberVariable.simdGeneratorPtr )
{
Expand All @@ -58,7 +58,7 @@ public:
}

template<typename T, typename... POS>
FS_FORCEINLINE float32v FS_VECTORCALL GetSourceValue( const FastNoise::GeneratorSourceT<T>& memberVariable, int32v seed, POS... pos ) const
static FS_FORCEINLINE float32v FS_VECTORCALL GetSourceValue( const FastNoise::GeneratorSourceT<T>& memberVariable, int32v seed, POS... pos )
{
assert( memberVariable.simdGeneratorPtr );
auto simdGen = reinterpret_cast<VoidPtrStorageType>( memberVariable.simdGeneratorPtr );
Expand All @@ -67,7 +67,7 @@ public:
}

template<typename T>
FS_FORCEINLINE const DispatchClass<T, SIMD>* GetSourceSIMD( const FastNoise::GeneratorSourceT<T>& memberVariable ) const
static FS_FORCEINLINE const DispatchClass<T, SIMD>* GetSourceSIMD( const FastNoise::GeneratorSourceT<T>& memberVariable )
{
assert( memberVariable.simdGeneratorPtr );
auto simdGen = reinterpret_cast<VoidPtrStorageType>( memberVariable.simdGeneratorPtr );
Expand Down
33 changes: 20 additions & 13 deletions include/FastNoise/Generators/Utils.inl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#include <climits>

namespace FastNoise
{
{
namespace Primes
{
static constexpr int X = 501125321;
Expand Down Expand Up @@ -240,17 +240,17 @@ namespace FastNoise
return t * t * t * FS::FMulAdd( t, FS::FMulAdd( t, float32v( 6 ), float32v( -15 )), float32v( 10 ) );
}

template<bool DO_SQRT = true, typename... P>
FS_FORCEINLINE static float32v CalcDistance( DistanceFunction distFunc, float32v dX, P... d )
template<bool DO_SQRT = true, FastSIMD::FeatureSet SIMD = FastSIMD::FeatureSetDefault(), typename... P>
FS_FORCEINLINE static float32v CalcDistance( DistanceFunction distFunc, const HybridSource& minkowskiP, int32v seed, float32v pX, P... pos )
{
switch( distFunc )
{
default:
case DistanceFunction::Euclidean:
if constexpr( DO_SQRT )
{
float32v distSqr = dX * dX;
((distSqr = FS::FMulAdd( d, d, distSqr )), ...);
float32v distSqr = pX * pX;
((distSqr = FS::FMulAdd( pos, pos, distSqr )), ...);

float32v invSqrt = FS::InvSqrt( distSqr );

Expand All @@ -259,35 +259,42 @@ namespace FastNoise

case DistanceFunction::EuclideanSquared:
{
float32v distSqr = dX * dX;
((distSqr = FS::FMulAdd( d, d, distSqr )), ...);
float32v distSqr = pX * pX;
((distSqr = FS::FMulAdd( pos, pos, distSqr )), ...);

return distSqr;
}

case DistanceFunction::Manhattan:
{
float32v dist = FS::Abs( dX );
dist += (FS::Abs( d ) + ...);
float32v dist = FS::Abs( pX );
dist += (FS::Abs( pos ) + ...);

return dist;
}

case DistanceFunction::Hybrid:
{
float32v both = FS::FMulAdd( dX, dX, FS::Abs( dX ) );
((both += FS::FMulAdd( d, d, FS::Abs( d ) )), ...);
float32v both = FS::FMulAdd( pX, pX, FS::Abs( pX ) );
((both += FS::FMulAdd( pos, pos, FS::Abs( pos ) )), ...);

return both;
}

case DistanceFunction::MaxAxis:
{
float32v max = FS::Abs( dX );
((max = FS::Max( FS::Abs(d), max )), ...);
float32v max = FS::Abs( pX );
((max = FS::Max( FS::Abs( pos ), max )), ...);

return max;
}

case DistanceFunction::Minkowski:
{
float32v minkowski = FastSIMD::DispatchClass<Generator, SIMD>::GetSourceValue( minkowskiP, seed, pX, pos... );

return FS::Pow( FS::Pow( FS::Abs( pX ), minkowski) + (FS::Pow( FS::Abs( pos ), minkowski) + ...), FS::Reciprocal( minkowski ) );
}
}
}
}

0 comments on commit fe0fd43

Please sign in to comment.